appium-ios-simulator
Version:
iOS Simulator interface for Appium.
284 lines (219 loc) • 16.6 kB
JavaScript
;
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _logger = require('./logger');
var _logger2 = _interopRequireDefault(_logger);
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _teen_process = require('teen_process');
var _asyncbox = require('asyncbox');
var _appiumXcode = require('appium-xcode');
var _nodeSimctl = require('node-simctl');
var _appiumSupport = require('appium-support');
function killAllSimulators() {
var appName, xcodeVersion, allSimsAreShutDown;
return _regeneratorRuntime.async(function killAllSimulators$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
allSimsAreShutDown = function allSimsAreShutDown() {
var devices;
return _regeneratorRuntime.async(function allSimsAreShutDown$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.next = 2;
return _regeneratorRuntime.awrap((0, _nodeSimctl.getDevices)());
case 2:
devices = context$2$0.sent;
devices = _lodash2['default'].flatten(_lodash2['default'].values(devices));
return context$2$0.abrupt('return', _lodash2['default'].every(devices, function (sim) {
return sim.state === 'Shutdown';
}));
case 5:
case 'end':
return context$2$0.stop();
}
}, null, this);
};
_logger2['default'].debug('Killing all iOS Simulators');
appName = undefined;
context$1$0.next = 5;
return _regeneratorRuntime.awrap((0, _appiumXcode.getVersion)(true));
case 5:
xcodeVersion = context$1$0.sent;
if (xcodeVersion.major === 7) {
appName = 'Simulator';
} else {
appName = 'iOS Simulator';
}
context$1$0.prev = 7;
context$1$0.next = 10;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('osascript', ['-e', 'quit app "' + appName + '"']));
case 10:
context$1$0.next = 16;
break;
case 12:
context$1$0.prev = 12;
context$1$0.t0 = context$1$0['catch'](7);
_logger2['default'].error(JSON.stringify(context$1$0.t0));
throw context$1$0.t0;
case 16:
context$1$0.next = 18;
return _regeneratorRuntime.awrap((0, _asyncbox.waitForCondition)(allSimsAreShutDown, {
waitMs: 60 * 1000,
intervalMs: 200
}));
case 18:
case 'end':
return context$1$0.stop();
}
}, null, this, [[7, 12]]);
}
function endAllSimulatorDaemons() {
var _arr, _i, servicePattern, launchCtlCommand, stopCmd, removeCmd;
return _regeneratorRuntime.async(function endAllSimulatorDaemons$(context$1$0) {
var _this = this;
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
_logger2['default'].debug('Ending all simulator daemons');
_arr = ['com.apple.iphonesimulator', 'com.apple.CoreSimulator'];
_i = 0;
case 3:
if (!(_i < _arr.length)) {
context$1$0.next = 28;
break;
}
servicePattern = _arr[_i];
_logger2['default'].debug('Killing any other ' + servicePattern + ' daemons');
launchCtlCommand = 'launchctl list | grep ' + servicePattern + ' | cut -f 3 | xargs -n 1 launchctl';
context$1$0.prev = 7;
stopCmd = launchCtlCommand + ' stop';
context$1$0.next = 11;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('bash', ['-c', stopCmd]));
case 11:
context$1$0.next = 16;
break;
case 13:
context$1$0.prev = 13;
context$1$0.t0 = context$1$0['catch'](7);
_logger2['default'].warn('Could not stop ' + servicePattern + ' daemons, carrying on anyway!');
case 16:
context$1$0.prev = 16;
removeCmd = launchCtlCommand + ' remove';
context$1$0.next = 20;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('bash', ['-c', removeCmd]));
case 20:
context$1$0.next = 25;
break;
case 22:
context$1$0.prev = 22;
context$1$0.t1 = context$1$0['catch'](16);
_logger2['default'].warn('Could not remove ' + servicePattern + ' daemons, carrying on anyway!');
case 25:
_i++;
context$1$0.next = 3;
break;
case 28:
context$1$0.prev = 28;
context$1$0.next = 31;
return _regeneratorRuntime.awrap((0, _asyncbox.waitForCondition)(function callee$1$0() {
var _ref, stdout;
return _regeneratorRuntime.async(function callee$1$0$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.next = 2;
return _regeneratorRuntime.awrap((0, _teen_process.exec)('bash', ['-c', 'ps -e | grep launchd_sim | grep -v bash | grep -v grep | awk {\'print$1\'}']));
case 2:
_ref = context$2$0.sent;
stdout = _ref.stdout;
return context$2$0.abrupt('return', stdout.trim().length === 0);
case 5:
case 'end':
return context$2$0.stop();
}
}, null, _this);
}, { waitMs: 5000, intervalMs: 500 }));
case 31:
context$1$0.next = 36;
break;
case 33:
context$1$0.prev = 33;
context$1$0.t2 = context$1$0['catch'](28);
_logger2['default'].warn('Could not end all simulator daemons, carrying on!');
case 36:
_logger2['default'].debug('Finishing ending all simulator daemons');
case 37:
case 'end':
return context$1$0.stop();
}
}, null, this, [[7, 13], [16, 22], [28, 33]]);
}
function simExists(udid) {
var devices;
return _regeneratorRuntime.async(function simExists$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.next = 2;
return _regeneratorRuntime.awrap((0, _nodeSimctl.getDevices)());
case 2:
devices = context$1$0.sent;
devices = _lodash2['default'].pairs(devices).map(function (pair) {
return pair[1];
}).reduce(function (a, b) {
return a.concat(b);
}, []);
return context$1$0.abrupt('return', !!_lodash2['default'].find(devices, function (sim) {
return sim.udid === udid;
}));
case 5:
case 'end':
return context$1$0.stop();
}
}, null, this);
}
function safeRimRaf(delPath) {
var tryNum = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
return _regeneratorRuntime.async(function safeRimRaf$(context$1$0) {
while (1) switch (context$1$0.prev = context$1$0.next) {
case 0:
context$1$0.prev = 0;
context$1$0.next = 3;
return _regeneratorRuntime.awrap(_appiumSupport.fs.rimraf(delPath));
case 3:
context$1$0.next = 16;
break;
case 5:
context$1$0.prev = 5;
context$1$0.t0 = context$1$0['catch'](0);
if (!(tryNum < 20)) {
context$1$0.next = 16;
break;
}
if (!(context$1$0.t0.message.indexOf('ENOTEMPTY') !== -1)) {
context$1$0.next = 13;
break;
}
_logger2['default'].debug('Path \'' + delPath + '\' was not empty during delete; retrying');
return context$1$0.abrupt('return', safeRimRaf(delPath, tryNum + 1));
case 13:
if (!(context$1$0.t0.message.indexOf('ENOENT') !== -1)) {
context$1$0.next = 16;
break;
}
_logger2['default'].debug('Path \'' + delPath + '\'\' did not exist when we tried to delete, ignoring');
return context$1$0.abrupt('return', safeRimRaf(delPath, tryNum + 1));
case 16:
case 'end':
return context$1$0.stop();
}
}, null, this, [[0, 5]]);
}
exports.killAllSimulators = killAllSimulators;
exports.endAllSimulatorDaemons = endAllSimulatorDaemons;
exports.safeRimRaf = safeRimRaf;
exports.simExists = simExists;
// waiting until the simulator service has died.
// see the README for github.com/appium/node-simctl for example output of getDevices()
//# sourceMappingURL=data:application/json;base64,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bG9nZ2VyJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBleGVjIH0gZnJvbSAndGVlbl9wcm9jZXNzJztcbmltcG9ydCB7IHdhaXRGb3JDb25kaXRpb24gfSBmcm9tICdhc3luY2JveCc7XG5pbXBvcnQgeyBnZXRWZXJzaW9uIH0gZnJvbSAnYXBwaXVtLXhjb2RlJztcbmltcG9ydCB7IGdldERldmljZXMgfSBmcm9tICdub2RlLXNpbWN0bCc7XG5pbXBvcnQgeyBmcyB9IGZyb20gJ2FwcGl1bS1zdXBwb3J0JztcblxuXG5hc3luYyBmdW5jdGlvbiBraWxsQWxsU2ltdWxhdG9ycyAoKSB7XG4gIGxvZy5kZWJ1ZygnS2lsbGluZyBhbGwgaU9TIFNpbXVsYXRvcnMnKTtcblxuICBsZXQgYXBwTmFtZTtcbiAgbGV0IHhjb2RlVmVyc2lvbiA9IGF3YWl0IGdldFZlcnNpb24odHJ1ZSk7XG4gIGlmICh4Y29kZVZlcnNpb24ubWFqb3IgPT09IDcpIHtcbiAgICBhcHBOYW1lID0gJ1NpbXVsYXRvcic7XG4gIH0gZWxzZSB7XG4gICAgYXBwTmFtZSA9ICdpT1MgU2ltdWxhdG9yJztcbiAgfVxuXG4gIHRyeSB7XG4gICAgYXdhaXQgZXhlYygnb3Nhc2NyaXB0JywgWyctZScsIGBxdWl0IGFwcCBcIiR7YXBwTmFtZX1cImBdKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxvZy5lcnJvcihKU09OLnN0cmluZ2lmeShlKSk7XG4gICAgdGhyb3cgZTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIGFsbFNpbXNBcmVTaHV0RG93biAoKSB7XG4gICAgbGV0IGRldmljZXMgPSBhd2FpdCBnZXREZXZpY2VzKCk7XG4gICAgZGV2aWNlcyA9IF8uZmxhdHRlbihfLnZhbHVlcyhkZXZpY2VzKSk7XG4gICAgcmV0dXJuIF8uZXZlcnkoZGV2aWNlcywgKHNpbSkgPT4ge1xuICAgICAgcmV0dXJuIHNpbS5zdGF0ZSA9PT0gJ1NodXRkb3duJztcbiAgICB9KTtcbiAgfVxuXG4gIGF3YWl0IHdhaXRGb3JDb25kaXRpb24oYWxsU2ltc0FyZVNodXREb3duLCB7XG4gICAgd2FpdE1zOiA2MCAqIDEwMDAsXG4gICAgaW50ZXJ2YWxNczogMjAwXG4gIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBlbmRBbGxTaW11bGF0b3JEYWVtb25zICgpIHtcbiAgbG9nLmRlYnVnKCdFbmRpbmcgYWxsIHNpbXVsYXRvciBkYWVtb25zJyk7XG4gIGZvciAobGV0IHNlcnZpY2VQYXR0ZXJuIG9mIFsnY29tLmFwcGxlLmlwaG9uZXNpbXVsYXRvcicsICdjb20uYXBwbGUuQ29yZVNpbXVsYXRvciddKSB7XG4gICAgbG9nLmRlYnVnKGBLaWxsaW5nIGFueSBvdGhlciAke3NlcnZpY2VQYXR0ZXJufSBkYWVtb25zYCk7XG4gICAgbGV0IGxhdW5jaEN0bENvbW1hbmQgPSBgbGF1bmNoY3RsIGxpc3QgfCBncmVwICR7c2VydmljZVBhdHRlcm59IHwgY3V0IC1mIDMgfCB4YXJncyAtbiAxIGxhdW5jaGN0bGA7XG4gICAgdHJ5IHtcbiAgICAgIGxldCBzdG9wQ21kID0gYCR7bGF1bmNoQ3RsQ29tbWFuZH0gc3RvcGA7XG4gICAgICBhd2FpdCBleGVjKCdiYXNoJywgWyctYycsIHN0b3BDbWRdKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGxvZy53YXJuKGBDb3VsZCBub3Qgc3RvcCAke3NlcnZpY2VQYXR0ZXJufSBkYWVtb25zLCBjYXJyeWluZyBvbiBhbnl3YXkhYCk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBsZXQgcmVtb3ZlQ21kID0gYCR7bGF1bmNoQ3RsQ29tbWFuZH0gcmVtb3ZlYDtcbiAgICAgIGF3YWl0IGV4ZWMoJ2Jhc2gnLCBbJy1jJywgcmVtb3ZlQ21kXSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2cud2FybihgQ291bGQgbm90IHJlbW92ZSAke3NlcnZpY2VQYXR0ZXJufSBkYWVtb25zLCBjYXJyeWluZyBvbiBhbnl3YXkhYCk7XG4gICAgfVxuICB9XG4gIC8vIHdhaXRpbmcgdW50aWwgdGhlIHNpbXVsYXRvciBzZXJ2aWNlIGhhcyBkaWVkLlxuICB0cnkge1xuICAgIGF3YWl0IHdhaXRGb3JDb25kaXRpb24oYXN5bmMgKCkgPT4ge1xuICAgICAgbGV0IHtzdGRvdXR9ID0gYXdhaXQgZXhlYygnYmFzaCcsIFsnLWMnLFxuICAgICAgICBgcHMgLWUgIHwgZ3JlcCBsYXVuY2hkX3NpbSB8IGdyZXAgLXYgYmFzaCB8IGdyZXAgLXYgZ3JlcCB8IGF3ayB7J3ByaW50JDEnfWBdKTtcbiAgICAgIHJldHVybiBzdGRvdXQudHJpbSgpLmxlbmd0aCA9PT0gMDtcbiAgICB9LCB7d2FpdE1zOiA1MDAwLCBpbnRlcnZhbE1zOiA1MDB9KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nLndhcm4oYENvdWxkIG5vdCBlbmQgYWxsIHNpbXVsYXRvciBkYWVtb25zLCBjYXJyeWluZyBvbiFgKTtcbiAgfVxuICBsb2cuZGVidWcoJ0ZpbmlzaGluZyBlbmRpbmcgYWxsIHNpbXVsYXRvciBkYWVtb25zJyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNpbUV4aXN0cyAodWRpZCkge1xuICAvLyBzZWUgdGhlIFJFQURNRSBmb3IgZ2l0aHViLmNvbS9hcHBpdW0vbm9kZS1zaW1jdGwgZm9yIGV4YW1wbGUgb3V0cHV0IG9mIGdldERldmljZXMoKVxuICBsZXQgZGV2aWNlcyA9IGF3YWl0IGdldERldmljZXMoKTtcblxuICBkZXZpY2VzID0gXy5wYWlycyhkZXZpY2VzKS5tYXAoKHBhaXIpID0+IHtcbiAgICByZXR1cm4gcGFpclsxXTtcbiAgfSkucmVkdWNlKChhLCBiKSA9PiB7XG4gICAgcmV0dXJuIGEuY29uY2F0KGIpO1xuICB9LCBbXSk7XG4gIHJldHVybiAhIV8uZmluZChkZXZpY2VzLCAoc2ltKSA9PiB7XG4gICAgcmV0dXJuIHNpbS51ZGlkID09PSB1ZGlkO1xuICB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2FmZVJpbVJhZiAoZGVsUGF0aCwgdHJ5TnVtID0gMCkge1xuICB0cnkge1xuICAgIGF3YWl0IGZzLnJpbXJhZihkZWxQYXRoKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKHRyeU51bSA8IDIwKSB7XG4gICAgICBpZiAoZXJyLm1lc3NhZ2UuaW5kZXhPZignRU5PVEVNUFRZJykgIT09IC0xKSB7XG4gICAgICAgIGxvZy5kZWJ1ZyhgUGF0aCAnJHtkZWxQYXRofScgd2FzIG5vdCBlbXB0eSBkdXJpbmcgZGVsZXRlOyByZXRyeWluZ2ApO1xuICAgICAgICByZXR1cm4gc2FmZVJpbVJhZihkZWxQYXRoLCB0cnlOdW0gKyAxKTtcbiAgICAgIH0gZWxzZSBpZiAoZXJyLm1lc3NhZ2UuaW5kZXhPZignRU5PRU5UJykgIT09IC0xKSB7XG4gICAgICAgIGxvZy5kZWJ1ZyhgUGF0aCAnJHtkZWxQYXRofScnIGRpZCBub3QgZXhpc3Qgd2hlbiB3ZSB0cmllZCB0byBkZWxldGUsIGlnbm9yaW5nYCk7XG4gICAgICAgIHJldHVybiBzYWZlUmltUmFmKGRlbFBhdGgsIHRyeU51bSArIDEpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgeyBraWxsQWxsU2ltdWxhdG9ycywgZW5kQWxsU2ltdWxhdG9yRGFlbW9ucywgc2FmZVJpbVJhZiwgc2ltRXhpc3RzIH07XG4iXX0=