UNPKG

ti-appium

Version:

An Appium wrapper to test Titanium applications

326 lines (258 loc) 10.9 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: src/device.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: src/device.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>'use strict'; const ps = require('ps-list'), output = require('./output.js'), childProcess = require('child_process'); /** * @class Device_Helper * @desc * Devices handling class, used to make shortcuts around the launching and * shutting down of emulators. Also has functions for finding iOS certificates * and provisioning profiles. */ class Device_Helper { /** * Kill the iOS simulator using it's UDID, and then repeatedly check whether * it has fully shut down * * @param {String} simName - The name of the iOS device to find * @param {String} simVersion - The version of the iOS device to find * @param {Object} opts - Optional arguments * @param {Int} opts.initialWait - How long to wait for the first boot check * @param {Int} opts.intervalWait - How long to wait between each check following the first */ static async killSim(simName, simVersion, { initialWait = 10000, intervalWait = 5000 } = {}) { if (!simName) { throw new Error('Empty simulator name argument passed'); } if (!simVersion) { throw new Error('Empty simulator version passed'); } output.debug(`Shutting Down the iOS Simulator: ${simName} (${simVersion})`); const udid = getUdid(simName, simVersion); output.debug(`Found UDID for Simulator: ${udid}`); childProcess.execSync(`xcrun simctl shutdown ${udid}`); await isShutdown(simName, simVersion, initialWait, intervalWait); // The simulator process hangs around even after the sim itself is shut down childProcess.spawn('killall', [ 'Simulator' ]); } /** * Get the boot status of an iOS simulator via its UDID * * @param {String} simName - The name of the iOS device to find * @param {String} simVersion - The version of the iOS device to find */ static getSimState(simName, simVersion) { if (!simName) { throw new Error('Empty simulator name argument passed'); } if (!simVersion) { throw new Error('Empty simulator version passed'); } return getState(simName, simVersion); } /** * Kill all the Android emulators. * * @param {String} deviceName - The name of the Android device to kill */ static async killEmu(deviceName) { const devicePID = await getAndroidPID(deviceName); output.debug(`Found Android emulator PID: ${devicePID}`); if (process.platform === 'win32') { output.debug('Detected Windows, killing emulator with taskkill command'); await childProcess.execSync(`taskkill /F /PID ${devicePID}`); } else { output.debug('Presuming UNIX, killing emulator with kill command'); await childProcess.execSync(`kill -9 ${devicePID}`); } } /** * Use ioslib to probe the machine for a particular iOS certificate, then * return the certificate object. * * @param {String} type - The type of operation the cert is defined for * @param {String} search - Part of the cert name, used to help locate it */ static async getCert(type, search) { if (process.platform !== 'darwin') { return undefined; } const ioslib = require('ioslib'); const certs = await ioslib.certs.getCerts(), subCerts = certs[type], valid = [ 'developer', 'distribution' ]; if (!valid.includes(type)) { throw Error(`Argument '${type}' is not a valid type of certificate`); } let foundCert; subCerts.forEach(cert => { if (cert.name.includes(search)) { foundCert = cert; } }); if (!foundCert) { throw Error(`No certificate found with a name including '${search}'`); } return foundCert; } /** * Use ioslib to probe the machine for a particular iOS provisioning profile, * then return the provisioning profile object. * * @param {String} type - The type of operation the pp is defined for * @param {String} search - Part of the pp name, used to help locate it */ static async getProfile(type, search) { if (process.platform !== 'darwin') { return undefined; } const ioslib = require('ioslib'); const profiles = await ioslib.provisioning.getProvisioningProfiles(), subProfiles = profiles[type], valid = [ 'adhoc', 'development', 'distribution' ]; if (!valid.includes(type)) { throw Error(`Argument '${type}' is not a valid type of provisioning profile`); } let foundProfile; subProfiles.forEach(profile => { if (profile.name === search) { foundProfile = profile; } }); if (!foundProfile) { throw Error(`No provisioning profile found with a name matching '${search}'`); } return foundProfile; } } /** * Use the status of the simulator to determine whether the device is shutdown. The * initial wait value is used because a simulator will sometimes show as shutdown * before it really is and then change it's mind back to booted. So we use a long * wait to allow it to get past this phase * @private * * @param {String} simName - The name of the iOS device to find * @param {String} simVersion - The version of the iOS device to find * @param {Int} initialWait - How long to wait for the first boot check * @param {Int} intervalWait - How long to wait between each check following the first */ function isShutdown(simName, simVersion, initialWait, intervalWait) { return new Promise((resolve, reject) => { output.debug(`Starting Check for Simulator Shutdown, Waiting ${initialWait}ms for First Check Then Every ${intervalWait}ms`); setTimeout(() => { let count = 0; const interval = setInterval(() => { let state = getState(simName, simVersion); count++; output.debug(`${simName} (${simVersion}) is Currently ${state}`); if (state === 'Shutdown') { clearInterval(interval); return resolve(); } else if (count >= 20) { clearInterval(interval); return reject('iOS simulator didn\'t shutdown in expected time, you may expierience instability'); } }, intervalWait); }, initialWait); }); } /** * Get the boot status of an iOS simulator via its UDID * @private * * @param {String} simName - The name of the iOS device to find * @param {String} simVersion - The version of the iOS device to find */ function getState(simName, simVersion) { const versionParts = simVersion.split('.'), major = versionParts[0], minor = versionParts[1]; const udid = getUdid(simName, simVersion); const xcrunOut = childProcess.execSync('xcrun simctl list --json'); const xcrunSims = JSON.parse(xcrunOut).devices[`com.apple.CoreSimulator.SimRuntime.iOS-${major}-${minor}`]; try { for (const xcrunSim of xcrunSims) { if (xcrunSim.udid === udid) { return xcrunSim.state; } } } catch (e) { throw new Error(`An issue occured trying to get the boot status of iOS simulator "${simName} (${simVersion})", do you have this simulator configured?`); } throw new Error(`Cannot retrieve a status for simulator ${simName} (${simVersion})`); } /** * Get the UDID of an iOS simulator using the Titanium CLI * @private * * @param {String} simName - The name of the iOS device to find * @param {String} simVersion - The version of the iOS device to find */ function getUdid(simName, simVersion) { const tiOut = childProcess.execSync('ti info -t ios -o json'); const tiSims = JSON.parse(tiOut).ios.simulators.ios[simVersion]; try { for (const tiSim of tiSims) { if (tiSim.name === simName) { return tiSim.udid; } } } catch (e) { throw new Error(`An issue occured trying to find the UDID of iOS simulator "${simName} (${simVersion})", do you have this simulator configured?`); } throw new Error(`Cannot find a UDID for simulator ${simName} (${simVersion})`); } /** * Search the running processes on the system, and look for one with the * Android device name that we booted for testing. * @private * * @param {String} deviceName - The name of the Android device to find */ async function getAndroidPID(deviceName) { try { const list = await ps(); let pid; if (process.platform === 'win32') { const proc = list.find(x => x.name.includes('qemu-system-x86_64')); pid = proc.pid; } else { const proc = list.find(x => x.cmd.includes(deviceName)); pid = proc.pid; } return pid; } catch (err) { throw Error(`Cannot find an Android PID for ${deviceName}`); } } module.exports = Device_Helper; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Namespaces</h3><ul><li><a href="WebDriverCommands.html">WebDriverCommands</a></li></ul><h3>Classes</h3><ul><li><a href="Appc_Helper.html">Appc_Helper</a></li><li><a href="Appium_Helper.html">Appium_Helper</a></li><li><a href="Device_Helper.html">Device_Helper</a></li><li><a href="Mocha_Helper.html">Mocha_Helper</a></li><li><a href="Output_Helper.html">Output_Helper</a></li><li><a href="Webdriver_Helper.html">Webdriver_Helper</a></li></ul><h3>Global</h3><ul><li><a href="global.html#appcRun">appcRun</a></li><li><a href="global.html#appcSetup">appcSetup</a></li><li><a href="global.html#banner">banner</a></li><li><a href="global.html#buildApp">buildApp</a></li><li><a href="global.html#createAppPath">createAppPath</a></li><li><a href="global.html#debug">debug</a></li><li><a href="global.html#error">error</a></li><li><a href="global.html#finish">finish</a></li><li><a href="global.html#getCert">getCert</a></li><li><a href="global.html#getProfile">getProfile</a></li><li><a href="global.html#getSimState">getSimState</a></li><li><a href="global.html#info">info</a></li><li><a href="global.html#killEmulator">killEmulator</a></li><li><a href="global.html#killSimulator">killSimulator</a></li><li><a href="global.html#parseSDK">parseSDK</a></li><li><a href="global.html#skip">skip</a></li><li><a href="global.html#startAppium">startAppium</a></li><li><a href="global.html#startClient">startClient</a></li><li><a href="global.html#step">step</a></li><li><a href="global.html#stopAppium">stopAppium</a></li><li><a href="global.html#stopClient">stopClient</a></li><li><a href="global.html#test">test</a></li><li><a href="global.html#warn">warn</a></li></ul> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.3</a> on Fri Aug 28 2020 10:09:07 GMT+0100 (British Summer Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>