Skip to content

Commit

Permalink
refactor: Tune temporary simulator creation logic (#1790)
Browse files Browse the repository at this point in the history
  • Loading branch information
mykola-mokhnach committed Jun 29, 2023
1 parent 15016dc commit 9ac2f6a
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 43 deletions.
33 changes: 7 additions & 26 deletions lib/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
verifyApplicationPlatform,
} from './app-utils';
import commands from './commands';
import {PLATFORM_NAME_IOS, PLATFORM_NAME_TVOS, desiredCapConstraints} from './desired-caps';
import {desiredCapConstraints} from './desired-caps';
import DEVICE_CONNECTIONS_FACTORY from './device-connections-factory';
import {executeMethodMap} from './execute-method-map';
import {newMethodMap} from './method-map';
Expand Down Expand Up @@ -55,6 +55,7 @@ import {
getAndCheckXcodeVersion,
getDriverInfo,
isLocalHost,
isTvOs,
markSystemFilesForCleanup,
normalizeCommandTimeouts,
normalizePlatformVersion,
Expand Down Expand Up @@ -1250,6 +1251,8 @@ class XCUITestDriver extends BaseDriver {
this.log.warn(
`Cannot detect any connected real devices. Falling back to Simulator. Original error: ${err.message}`
);
await setupVersionCaps();

// @ts-expect-error - do not assign arbitrary properties to `this.opts`
const device = await getExistingSim(this.opts);
if (!device) {
Expand All @@ -1258,17 +1261,7 @@ class XCUITestDriver extends BaseDriver {
`Cannot detect udid for ${this.opts.deviceName} Simulator running iOS ${this.opts.platformVersion}`
);
}

// Matching Simulator exists and is found. Use it
this.opts.udid = device.udid;
const devicePlatform = normalizePlatformVersion(await device.getPlatformVersion());
if (this.opts.platformVersion !== devicePlatform) {
this.opts.platformVersion = devicePlatform;
this.log.info(
`Set platformVersion to '${devicePlatform}' to match the device with given UDID`
);
}
await setupVersionCaps();
return {device, realDevice: false, udid: device.udid};
}
} else {
Expand All @@ -1289,7 +1282,7 @@ class XCUITestDriver extends BaseDriver {
}
}

const device = await getRealDeviceObj(this.opts.udid);
const device = getRealDeviceObj(this.opts.udid);
return {device, realDevice: true, udid: this.opts.udid};
}

Expand All @@ -1303,13 +1296,10 @@ class XCUITestDriver extends BaseDriver {
// figure out the correct simulator to use, given the desired capabilities
// @ts-expect-error - do not assign arbitrary properties to `this.opts`
const device = await getExistingSim(this.opts);

// check for an existing simulator
if (device) {
return {device, realDevice: false, udid: device.udid};
}

this.log.info('Simulator udid not provided');
}

// no device of this type exists, or they request new sim, so create one
Expand Down Expand Up @@ -1359,14 +1349,9 @@ class XCUITestDriver extends BaseDriver {

async createSim() {
this.lifecycleData.createSim = true;

// Get platform name from const since it must be case sensitive to create a new simulator
const platformName = this.isTvOS() ? PLATFORM_NAME_TVOS : PLATFORM_NAME_IOS;

// create sim for caps
const sim = await createSim(this.opts, platformName);
const sim = await createSim(this.opts);
this.log.info(`Created simulator with udid '${sim.udid}'.`);

return sim;
}

Expand Down Expand Up @@ -1474,10 +1459,6 @@ class XCUITestDriver extends BaseDriver {
return !this.opts.realDevice;
}

isTvOS() {
return _.toLower(this.opts.platformName) === _.toLower(PLATFORM_NAME_TVOS);
}

validateLocatorStrategy(strategy) {
super.validateLocatorStrategy(strategy, this.isWebContext());
}
Expand Down Expand Up @@ -1703,7 +1684,7 @@ class XCUITestDriver extends BaseDriver {

await verifyApplicationPlatform.bind(this)(this.opts.app, {
isSimulator: this.isSimulator(),
isTvOS: this.isTvOS(),
isTvOS: isTvOs(this.opts.platformName),
});

const {install, skipUninstall} = await this.checkAutInstallationState();
Expand Down
51 changes: 34 additions & 17 deletions lib/simulator-management.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { resetTestProcesses } from 'appium-webdriveragent';
import _ from 'lodash';
import log from './logger';
import { util } from 'appium/support';
import { PLATFORM_NAME_IOS } from './desired-caps';
import { UDID_AUTO } from './utils';
import { UDID_AUTO, normalizePlatformName } from './utils';


const APPIUM_SIM_PREFIX = 'appiumTest';
Expand All @@ -25,24 +24,42 @@ const SAFARI_OPTS_ALIASES_MAP = /** @type {const} */({
});

/**
* Capability set by a user
*
* @typedef {Object} SimulatorCreationOptions
* @property {string} deviceName - A name for the device
* @property {string} platformVersion - The version of iOS to use
* @property {string} [simulatorDevicesSetPath]
* @property {string} [platformName]
*/
/**
* Create a new simulator with `appiumTest-` prefix and return the object.
*
* @param {object} caps - Capability set by a user. The options available are:
* @property {string} platform [iOS] - Platform name in order to specify runtime such as 'iOS', 'tvOS', 'watchOS'
* @param {Partial<SimulatorCreationOptions>} caps - Capability set by a user. The options available are:
* @returns {Promise<object>} Simulator object associated with the udid passed in.
*/
async function createSim (caps, platform = PLATFORM_NAME_IOS) {
const devicesSetPath = caps.simulatorDevicesSetPath;
const udid = await new Simctl({devicesSetPath}).createDevice(
`${APPIUM_SIM_PREFIX}-${util.uuidV4().toUpperCase()}-${caps.deviceName}`,
caps.deviceName,
caps.platformVersion,
async function createSim (caps) {
const {
simulatorDevicesSetPath: devicesSetPath,
deviceName,
platformVersion,
} = caps;
const platform = normalizePlatformName(caps.platformName);
const simctl = new Simctl({devicesSetPath});
if (!deviceName) {
let deviceNames = 'none';
try {
deviceNames = await simctl.getDevices(platformVersion, platform)
.map(({deviceName}) => deviceName);
} catch (ign) {}
throw new Error(
`'deviceName' must be provided in order to create a new Simulator for ${platform} platform. ` +
`Currently available device names: ${deviceNames}`);
}
const simName = `${APPIUM_SIM_PREFIX}-${util.uuidV4().toUpperCase()}-${deviceName}`;
log.debug(`Creating a temporary Simulator device '${simName}'`);
const udid = await simctl.createDevice(
simName,
deviceName,
platformVersion,
{platform},
);
return await getSimulator(udid, {
Expand Down Expand Up @@ -70,15 +87,15 @@ async function createSim (caps, platform = PLATFORM_NAME_IOS) {
async function getExistingSim (opts = /** @type {SimulatorLookupOptions} */({})) {
const {
platformVersion,
platformName = PLATFORM_NAME_IOS,
deviceName,
udid,
simulatorDevicesSetPath: devicesSetPath,
} = opts;

const platform = normalizePlatformName(opts.platformName);
const selectSim = async (/** @type {{ udid: string; platform: string; }} */ dev) => await getSimulator(
dev.udid, {
platform: dev.platform,
platform,
checkExistence: false,
devicesSetPath,
}
Expand All @@ -88,7 +105,7 @@ async function getExistingSim (opts = /** @type {SimulatorLookupOptions} */({}))
let devicesMap;
if (udid && _.toLower(udid) !== UDID_AUTO) {
log.debug(`Looking for an existing Simulator with UDID '${udid}'`);
devicesMap = await simctl.getDevices(null, platformName);
devicesMap = await simctl.getDevices(null, platform);
for (const device of _.flatMap(_.values(devicesMap))) {
if (device.udid === udid) {
return await selectSim(device);
Expand All @@ -102,9 +119,9 @@ async function getExistingSim (opts = /** @type {SimulatorLookupOptions} */({}))
return null;
}

const devices = devicesMap?.[platformVersion] ?? await simctl.getDevices(platformVersion, platformName);
const devices = devicesMap?.[platformVersion] ?? await simctl.getDevices(platformVersion, platform);
log.debug(
`Looking for an existing Simulator with platformName: ${platformName}, ` +
`Looking for an existing Simulator with platformName: ${platform}, ` +
`platformVersion: ${platformVersion}, deviceName: ${deviceName}`
);
for (const device of devices) {
Expand Down
21 changes: 21 additions & 0 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import semver from 'semver';
import {exec} from 'teen_process';
import iosGenericSimulators from './ios-generic-simulators';
import log from './logger';
import {PLATFORM_NAME_TVOS, PLATFORM_NAME_IOS} from './desired-caps';

export const UDID_AUTO = 'auto';
const DEFAULT_TIMEOUT_KEY = 'default';
Expand Down Expand Up @@ -457,6 +458,26 @@ export function assertSimulator(action, driver) {
}
}

/**
* Check if platform name is the TV OS one.
*
* @param {string|null|undefined} platformName
* @returns {boolean}
*/
export function isTvOs (platformName) {
return _.toLower(platformName ?? '') === _.toLower(PLATFORM_NAME_TVOS);
}

/**
* Return normalized platform name.
*
* @param {string|null|undefined} platformName
* @returns {string}
*/
export function normalizePlatformName (platformName) {
return isTvOs(platformName) ? PLATFORM_NAME_TVOS : PLATFORM_NAME_IOS;
}

export {
detectUdid,
getAndCheckXcodeVersion,
Expand Down

0 comments on commit 9ac2f6a

Please sign in to comment.