Skip to content

Commit

Permalink
chore(ci): Add unit tests for run and Catalyst stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
dpogue committed Aug 29, 2024
1 parent ca5bd0c commit 88d46a5
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 82 deletions.
28 changes: 20 additions & 8 deletions lib/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ module.exports.run = function (runOptions) {
return Promise.resolve()
.then(() => {
if (!runOptions.emulator && !useCatalyst) {
return require('./listDevices').run().then(devices => {
return module.exports.execListDevices().then(devices => {
if (devices.length > 0) {
useDevice = true;

Expand Down Expand Up @@ -84,13 +84,12 @@ module.exports.run = function (runOptions) {
.then(() => {
// Uncompress IPA (zip file)
const appFileInflated = path.join(buildOutputDir, 'Payload', `${projectName}.app`);
const appFile = path.join(buildOutputDir, `${projectName}.app`);
const payloadFolder = path.join(buildOutputDir, 'Payload');

// delete the existing platform/ios/build/device/appname.app
fs.rmSync(appFile, { recursive: true, force: true });
fs.rmSync(appPath, { recursive: true, force: true });
// move the platform/ios/build/device/Payload/appname.app to parent
fs.renameSync(appFileInflated, appFile);
fs.renameSync(appFileInflated, appPath);
// delete the platform/ios/build/device/Payload folder
fs.rmSync(payloadFolder, { recursive: true, force: true });

Expand All @@ -106,6 +105,7 @@ module.exports.run = function (runOptions) {
return module.exports.deployToDevice(appPath, runOptions.target, extraArgs);
},
// if device connection check failed use emulator then
// This might fail due to being the wrong type of app bundle
() => module.exports.deployToSim(appPath, runOptions.target)
);
} else if (useCatalyst) {
Expand All @@ -127,6 +127,8 @@ module.exports.deployToSim = deployToSim;
module.exports.startSim = startSim;
module.exports.listDevices = listDevices;
module.exports.listEmulators = listEmulators;
module.exports.execListDevices = execListDevices;
module.exports.execListEmulatorTargets = execListEmulatorTargets;

/**
* Filters the args array and removes supported args for the 'run' command.
Expand Down Expand Up @@ -195,13 +197,13 @@ async function deployToSim (appPath, target) {

if (!target) {
// Select target device for emulator (preferring iPhone Emulators)
const emulators = await require('./listEmulatorImages').run();
const emulators = await module.exports.execListEmulatorTargets();
const iPhoneEmus = emulators.filter(emulator => emulator.startsWith('iPhone'));
target = iPhoneEmus.concat(emulators)[0];
events.emit('log', `No target specified for emulator. Deploying to "${target}" simulator.`);
}

return startSim(appPath, target);
return module.exports.startSim(appPath, target);
}

function startSim (appPath, target) {
Expand Down Expand Up @@ -230,8 +232,18 @@ function startSim (appPath, target) {
return subprocess;
}

/* istanbul ignore next */
function execListDevices () {
return require('./listDevices').run();
}

/* istanbul ignore next */
function execListEmulatorTargets () {
return require('./listEmulatorTargets').run();
}

function listDevices () {
return require('./listDevices').run()
return module.exports.execListDevices()
.then(devices => {
events.emit('log', 'Available iOS Devices:');
devices.forEach(device => {
Expand All @@ -241,7 +253,7 @@ function listDevices () {
}

function listEmulators () {
return require('./listEmulatorImages').run()
return module.exports.execListEmulatorTargets()
.then(emulators => {
events.emit('log', 'Available iOS Simulators:');
emulators.forEach(emulator => {
Expand Down
21 changes: 21 additions & 0 deletions tests/spec/unit/build.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,27 @@ describe('build', () => {
]);
expect(args.length).toEqual(18);
});

it('should generate appropriate args for Catalyst macOS builds', () => {
const buildOpts = {
catalyst: true
};

const args = getXcodeBuildArgs('TestProjectName', testProjectPath, 'TestConfiguration', '', buildOpts);
expect(args).toEqual([
'-workspace',
'TestProjectName.xcworkspace',
'-scheme',
'TestProjectName',
'-configuration',
'TestConfiguration',
'-destination',
'generic/platform=macOS,variant=Mac Catalyst',
'build',
`SYMROOT=${path.join(testProjectPath, 'build')}`
]);
expect(args.length).toEqual(10);
});
});

describe('getXcodeArchiveArgs method', () => {
Expand Down
74 changes: 0 additions & 74 deletions tests/spec/unit/lib/run.spec.js

This file was deleted.

153 changes: 153 additions & 0 deletions tests/spec/unit/run.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/

const path = require('node:path');
const { CordovaError, events } = require('cordova-common');
const build = require('../../../lib/build');
const run = require('../../../lib/run');

describe('cordova/lib/run', () => {
const testProjectPath = path.join('/test', 'project', 'path');

beforeEach(() => {
run.root = testProjectPath;
});

describe('runListDevices method', () => {
beforeEach(() => {
spyOn(events, 'emit');
spyOn(run, 'execListDevices').and.returnValue(Promise.resolve(["iPhone Xs"]));

Check failure on line 35 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-14

Strings must use singlequote

Check failure on line 35 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

Strings must use singlequote

Check failure on line 35 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-14

Strings must use singlequote

Check failure on line 35 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 22.x on macos-14

Strings must use singlequote

Check failure on line 35 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

Strings must use singlequote

Check failure on line 35 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 22.x on ubuntu-latest

Strings must use singlequote
spyOn(run, 'execListEmulatorTargets').and.returnValue(Promise.resolve(["iPhone 15 Simulator"]));

Check failure on line 36 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-14

Strings must use singlequote

Check failure on line 36 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

Strings must use singlequote

Check failure on line 36 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-14

Strings must use singlequote

Check failure on line 36 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 22.x on macos-14

Strings must use singlequote

Check failure on line 36 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

Strings must use singlequote

Check failure on line 36 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 22.x on ubuntu-latest

Strings must use singlequote
});

it('should delegate to "listDevices" when the "runListDevices" method options param contains "options.device".', () => {
return run.runListDevices({ options: { device: true } }).then(() => {
expect(run.execListDevices).toHaveBeenCalled();
expect(run.execListEmulatorTargets).not.toHaveBeenCalled();

expect(events.emit).toHaveBeenCalledWith('log', '\tiPhone Xs');
});
});

it('should delegate to "listDevices" when the "runListDevices" method options param contains "options.emulator".', () => {
return run.runListDevices({ options: { emulator: true } }).then(() => {
expect(run.execListDevices).not.toHaveBeenCalled();
expect(run.execListEmulatorTargets).toHaveBeenCalled();

expect(events.emit).toHaveBeenCalledWith('log', '\tiPhone 15 Simulator');
});
});

it('should delegate to both "listEmulators" and "listDevices" when the "runListDevices" method does not contain "options.device" or "options.emulator".', () => {
return run.runListDevices().then(() => {
expect(run.execListDevices).toHaveBeenCalled();
expect(run.execListEmulatorTargets).toHaveBeenCalled();

expect(events.emit).toHaveBeenCalledWith('log', '\tiPhone Xs');
expect(events.emit).toHaveBeenCalledWith('log', '\tiPhone 15 Simulator');
});
});
});

describe('run method', () => {
beforeEach(() => {
spyOn(build, 'run').and.returnValue(Promise.resolve());
spyOn(build, 'findXCodeProjectIn').and.returnValue('ProjectName');
spyOn(run, 'execListDevices').and.resolveTo([]);
spyOn(run, 'execListEmulatorTargets').and.resolveTo([]);
spyOn(run, 'listDevices').and.resolveTo();
spyOn(run, 'deployToMac').and.resolveTo();
spyOn(run, 'deployToSim').and.resolveTo();
spyOn(run, 'checkDeviceConnected').and.rejectWith(new Error('No Device Connected'));
});

describe('--list option', () => {
beforeEach(() => {
spyOn(run, 'listEmulators').and.returnValue(Promise.resolve());
});

it('should delegate to listDevices method if `options.device` specified', () => {
return run.run({ list: true, device: true }).then(() => {
expect(run.listDevices).toHaveBeenCalled();
expect(run.listEmulators).not.toHaveBeenCalled();
});
});

it('should delegate to listEmulators method if `options.device` specified', () => {
return run.run({ list: true, emulator: true }).then(() => {
expect(run.listDevices).not.toHaveBeenCalled();
expect(run.listEmulators).toHaveBeenCalled();
});
});

it('should delegate to both listEmulators and listDevices methods if neither `options.device` nor `options.emulator` are specified', () => {
return run.run({ list: true }).then(() => {
expect(run.listDevices).toHaveBeenCalled();
expect(run.listEmulators).toHaveBeenCalled();
});
});
});

it('should not accept device and emulator options together', () => {
spyOn(Promise, 'reject');

run.run({
device: true,
emulator: true
});

expect(Promise.reject).toHaveBeenCalledWith(new CordovaError('Only one of "device"/"emulator" options should be specified'));
});

it('should run on a simulator if --device is not specified and no device is connected', () => {
return run.run({ }).then(() => {
expect(run.deployToSim).toHaveBeenCalled();
expect(build.run).toHaveBeenCalled();
});
});

it('should try to run on a device if --device is not specified and a device is connected', () => {
run.execListDevices.and.resolveTo(["iPhone 12 Plus"]);

Check failure on line 126 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-14

Strings must use singlequote

Check failure on line 126 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

Strings must use singlequote

Check failure on line 126 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-14

Strings must use singlequote

Check failure on line 126 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 22.x on macos-14

Strings must use singlequote

Check failure on line 126 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

Strings must use singlequote

Check failure on line 126 in tests/spec/unit/run.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 22.x on ubuntu-latest

Strings must use singlequote

return run.run({ }).then(() => {
expect(run.checkDeviceConnected).toHaveBeenCalled();
expect(build.run).toHaveBeenCalledWith(jasmine.objectContaining({ device: true }));
});
});

it('should try to run on a device if --device is specified', () => {
return run.run({ device: true }).then(() => {
expect(run.checkDeviceConnected).toHaveBeenCalled();
expect(build.run).toHaveBeenCalledWith(jasmine.objectContaining({ device: true }));
});
});

it('should not run a build if --noBuild is passed', () => {
return run.run({ emulator: true, nobuild: true }).then(() => {
expect(build.run).not.toHaveBeenCalled();
});
});

it('should try to launch the macOS Catalyst app bundle', () => {
return run.run({ device: true, target: 'mac', release: true }).then(() => {
expect(run.deployToMac).toHaveBeenCalledWith(path.join(testProjectPath, 'build', 'Release-maccatalyst', 'ProjectName.app'));
});
});
});
});

0 comments on commit 88d46a5

Please sign in to comment.