UNPKG

appium-ios-simulator

Version:
165 lines 6.32 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MIN_SUPPORTED_XCODE_VERSION = exports.SIMULATOR_APP_NAME = exports.MOBILE_SAFARI_BUNDLE_ID = exports.SAFARI_STARTUP_TIMEOUT_MS = void 0; exports.killAllSimulators = killAllSimulators; exports.getSimulatorInfo = getSimulatorInfo; exports.simExists = simExists; exports.getDeveloperRoot = getDeveloperRoot; exports.assertXcodeVersion = assertXcodeVersion; const logger_1 = require("./logger"); const lodash_1 = __importDefault(require("lodash")); const teen_process_1 = require("teen_process"); const asyncbox_1 = require("asyncbox"); const appium_xcode_1 = require("appium-xcode"); const path_1 = __importDefault(require("path")); const device_utils_1 = require("./device-utils"); const DEFAULT_SIM_SHUTDOWN_TIMEOUT_MS = 30000; exports.SAFARI_STARTUP_TIMEOUT_MS = 25 * 1000; exports.MOBILE_SAFARI_BUNDLE_ID = 'com.apple.mobilesafari'; exports.SIMULATOR_APP_NAME = 'Simulator.app'; exports.MIN_SUPPORTED_XCODE_VERSION = 10; /** * @param {string} appName * @param {boolean} [forceKill=false] * @returns {Promise<number>} */ async function pkill(appName, forceKill = false) { let args = forceKill ? ['-9'] : []; args.push('-x', appName); try { await (0, teen_process_1.exec)('pkill', args); return 0; } catch (err) { // pgrep/pkill exit codes: // 0 One or more processes were matched. // 1 No processes were matched. // 2 Invalid options were specified on the command line. // 3 An internal error occurred. if (!lodash_1.default.isUndefined(err.code)) { throw new Error(`Cannot forcefully terminate ${appName}. pkill error code: ${err.code}`); } logger_1.log.error(`Received unexpected error while trying to kill ${appName}: ${err.message}`); throw err; } } /** * @param {number} [timeout=DEFAULT_SIM_SHUTDOWN_TIMEOUT_MS] * @returns {Promise<void>} */ async function killAllSimulators(timeout = DEFAULT_SIM_SHUTDOWN_TIMEOUT_MS) { logger_1.log.debug('Killing all iOS Simulators'); const xcodeVersion = await (0, appium_xcode_1.getVersion)(true); if (lodash_1.default.isString(xcodeVersion)) { return; } const appName = path_1.default.parse(exports.SIMULATOR_APP_NAME).name; // later versions are slower to close timeout = timeout * (xcodeVersion.major >= 8 ? 2 : 1); try { await (0, teen_process_1.exec)('xcrun', ['simctl', 'shutdown', xcodeVersion.major > 8 ? 'all' : 'booted'], { timeout }); } catch { } const pids = []; try { const { stdout } = await (0, teen_process_1.exec)('pgrep', ['-f', `${appName}.app/Contents/MacOS/`]); if (stdout.trim()) { pids.push(...(stdout.trim().split(/\s+/))); } } catch (e) { if (e.code === 1) { logger_1.log.debug(`${appName} is not running. Continuing...`); return; } if (lodash_1.default.isEmpty(pids)) { logger_1.log.warn(`pgrep error ${e.code} while detecting whether ${appName} is running. Trying to kill anyway.`); } } if (!lodash_1.default.isEmpty(pids)) { logger_1.log.debug(`Killing processes: ${pids.join(', ')}`); try { await (0, teen_process_1.exec)('kill', ['-9', ...(pids.map((pid) => `${pid}`))]); } catch { } } logger_1.log.debug(`Using pkill to kill application: ${appName}`); try { await pkill(appName, true); } catch { } // wait for all the devices to be shutdown before Continuing // but only print out the failed ones when they are actually fully failed let remainingDevices = []; async function allSimsAreDown() { remainingDevices = []; let devices = await (0, device_utils_1.getDevices)(); devices = lodash_1.default.flatten(lodash_1.default.values(devices)); return lodash_1.default.every(devices, (sim) => { const state = sim.state.toLowerCase(); const done = ['shutdown', 'unavailable', 'disconnected'].includes(state); if (!done) { remainingDevices.push(`${sim.name} (${sim.sdk}, udid: ${sim.udid}) is still in state '${state}'`); } return done; }); } try { await (0, asyncbox_1.waitForCondition)(allSimsAreDown, { waitMs: timeout, intervalMs: 200 }); } catch (err) { if (remainingDevices.length > 0) { logger_1.log.warn(`The following devices are still not in the correct state after ${timeout} ms:`); for (let device of remainingDevices) { logger_1.log.warn(` ${device}`); } } throw err; } } /** * @param {string} udid * @param {{devicesSetPath?: string|null}} [opts={}] * @returns {Promise<any>} */ async function getSimulatorInfo(udid, opts = {}) { const { devicesSetPath } = opts; // see the README for github.com/appium/node-simctl for example output of getDevices() const devices = lodash_1.default.toPairs(await (0, device_utils_1.getDevices)({ devicesSetPath })) .map((pair) => pair[1]) .reduce((a, b) => a.concat(b), []); return lodash_1.default.find(devices, (sim) => sim.udid === udid); } /** * @param {string} udid * @returns {Promise<boolean>} */ async function simExists(udid) { return !!(await getSimulatorInfo(udid)); } /** * @returns {Promise<string>} */ async function getDeveloperRoot() { const { stdout } = await (0, teen_process_1.exec)('xcode-select', ['-p']); return stdout.trim(); } /** * @template {import('appium-xcode').XcodeVersion} V * @param {V} xcodeVersion * @returns {V} */ function assertXcodeVersion(xcodeVersion) { if (xcodeVersion.major < exports.MIN_SUPPORTED_XCODE_VERSION) { throw new Error(`Tried to use an iOS simulator with xcode version ${xcodeVersion.versionString} but only Xcode version ` + `${exports.MIN_SUPPORTED_XCODE_VERSION} and up are supported`); } return xcodeVersion; } //# sourceMappingURL=utils.js.map