UNPKG

appium-xcuitest-driver-conan

Version:

Appium driver for iOS using XCUITest for backend

1,404 lines (1,104 loc) 138 kB
'use strict'; var _get = require('babel-runtime/helpers/get')['default']; var _inherits = require('babel-runtime/helpers/inherits')['default']; var _createClass = require('babel-runtime/helpers/create-class')['default']; var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default']; var _slicedToArray = require('babel-runtime/helpers/sliced-to-array')['default']; var _getIterator = require('babel-runtime/core-js/get-iterator')['default']; var _regeneratorRuntime = require('babel-runtime/regenerator')['default']; var _Object$assign = require('babel-runtime/core-js/object/assign')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; Object.defineProperty(exports, '__esModule', { value: true }); var _appiumBaseDriver = require('appium-base-driver'); var _appiumSupport = require('appium-support'); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _nodeSimctl = require('node-simctl'); var _webdriveragent = require('./webdriveragent'); var _webdriveragent2 = _interopRequireDefault(_webdriveragent); var _logger = require('./logger'); var _logger2 = _interopRequireDefault(_logger); var _simulatorManagement = require('./simulator-management'); var _appiumIosSimulator = require('appium-ios-simulator'); var _asyncbox = require('asyncbox'); var _appiumIosDriver = require('appium-ios-driver'); var _desiredCaps = require('./desired-caps'); var _desiredCaps2 = _interopRequireDefault(_desiredCaps); var _commandsIndex = require('./commands/index'); var _commandsIndex2 = _interopRequireDefault(_commandsIndex); var _utils = require('./utils'); var _realDeviceManagement = require('./real-device-management'); var _bluebird = require('bluebird'); var _bluebird2 = _interopRequireDefault(_bluebird); var _packageJson = require('../../package.json'); // eslint-disable-line import/no-unresolved var SAFARI_BUNDLE_ID = 'com.apple.mobilesafari'; var WDA_STARTUP_RETRIES = 2; var DEFAULT_TIMEOUT_KEY = 'default'; var WDA_STARTUP_RETRY_INTERVAL = 10000; var NO_PROXY_NATIVE_LIST = [['GET', /^\/session\/[^\/]+$/], ['GET', /context/], ['POST', /context/], ['GET', /window/], ['POST', /window/], ['DELETE', /window/], ['POST', /execute/], ['POST', /element$/], ['POST', /elements$/], ['POST', /timeouts/], ['GET', /alert_text/], ['POST', /alert_text/], ['POST', /accept_alert/], ['POST', /dismiss_alert/], ['GET', /source/], ['GET', /screenshot/], ['POST', /appium/], ['GET', /appium/], ['POST', /touch/], ['GET', /log/], ['POST', /log/], ['POST', /moveto/], ['POST', /receive_async_response/], // always, in case context switches while waiting ['GET', /location/], ['GET', /size/], ['POST', /value/], ['POST', /keys/], ['POST', /back/], ['POST', /session\/[^\/]+\/location/], // geo location, but not element location ['POST', /appium\/device\/lock/], ['POST', /shake/], ['POST', /clear/]]; var NO_PROXY_WEB_LIST = [['GET', /title/], ['GET', /url/], ['POST', /url/], ['POST', /element/], ['POST', /forward/], ['GET', /attribute/], ['GET', /text/], ['POST', /clear/], ['GET', /element/], ['POST', /click/], ['POST', /refresh/], ['GET', /cookie/], ['POST', /cookie/], ['DELETE', /cookie/], ['POST', /frame/], ['POST', /keys/]].concat(NO_PROXY_NATIVE_LIST); function normalizeCommandTimeouts(value) { // The value is normalized already if (typeof value !== 'string') { return value; } var result = {}; // Use as default timeout for all commands if a single integer value is provided if (!isNaN(value)) { result[DEFAULT_TIMEOUT_KEY] = _lodash2['default'].toInteger(value); return result; } // JSON object has been provided. Let's parse it try { result = JSON.parse(value); if (!_lodash2['default'].isPlainObject(result)) { throw new Error(); } } catch (err) { _logger2['default'].errorAndThrow('"commandTimeouts" capability should be a valid JSON object. "' + value + '" was given instead'); } var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = _getIterator(_lodash2['default'].toPairs(result)), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var _step$value = _slicedToArray(_step.value, 2); var cmd = _step$value[0]; var timeout = _step$value[1]; if (!_lodash2['default'].isInteger(timeout) || timeout <= 0) { _logger2['default'].errorAndThrow('The timeout for "' + cmd + '" should be a valid natural number of milliseconds. "' + timeout + '" was given instead'); } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } return result; } var XCUITestDriver = (function (_BaseDriver) { _inherits(XCUITestDriver, _BaseDriver); function XCUITestDriver() { var opts = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; var shouldValidateCaps = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1]; _classCallCheck(this, XCUITestDriver); _get(Object.getPrototypeOf(XCUITestDriver.prototype), 'constructor', this).call(this, opts, shouldValidateCaps); _logger2['default'].debug('XCUITestDriver version: ' + _packageJson.version); this.desiredCapConstraints = _desiredCaps2['default']; this.locatorStrategies = ['xpath', 'id', 'name', 'class name', '-ios predicate string', '-ios class chain', 'accessibility id']; this.webLocatorStrategies = ['link text', 'css selector', 'tag name', 'link text', 'partial link text']; this.resetIos(); } _createClass(XCUITestDriver, [{ key: 'resetIos', value: function resetIos() { this.opts = this.opts || {}; this.wda = null; this.opts.device = null; this.jwpProxyActive = false; this.proxyReqRes = null; this.jwpProxyAvoid = []; this.safari = false; this.cachedWdaStatus = null; // some things that commands imported from appium-ios-driver need this.curWebFrames = []; this.webElementIds = []; this._currentUrl = null; this.curContext = null; this.xcodeVersion = null; this.iosSdkVersion = null; this.contexts = []; this.implicitWaitMs = 0; this.asynclibWaitMs = 0; this.pageLoadMs = 6000; } }, { key: 'getStatus', value: function getStatus() { var status; return _regeneratorRuntime.async(function getStatus$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: if (!(typeof this.driverInfo === 'undefined')) { context$2$0.next = 4; break; } context$2$0.next = 3; return _regeneratorRuntime.awrap((0, _utils.getDriverInfo)()); case 3: this.driverInfo = context$2$0.sent; case 4: status = { build: { version: this.driverInfo.version } }; if (this.cachedWdaStatus) { status.wda = this.cachedWdaStatus; } return context$2$0.abrupt('return', status); case 7: case 'end': return context$2$0.stop(); } }, null, this); } }, { key: 'createSession', value: function createSession(caps) { var _ref, _ref2, sessionId; return _regeneratorRuntime.async(function createSession$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: this.lifecycleData = {}; // this is used for keeping track of the state we start so when we delete the session we can put things back context$2$0.prev = 1; context$2$0.next = 4; return _regeneratorRuntime.awrap(_get(Object.getPrototypeOf(XCUITestDriver.prototype), 'createSession', this).call(this, caps)); case 4: _ref = context$2$0.sent; _ref2 = _slicedToArray(_ref, 1); sessionId = _ref2[0]; this.opts.sessionId = sessionId; context$2$0.next = 10; return _regeneratorRuntime.awrap(this.start()); case 10: // merge server capabilities + desired capabilities caps = _Object$assign({}, _appiumIosDriver.defaultServerCaps, caps); // update the udid with what is actually used caps.udid = this.opts.udid; return context$2$0.abrupt('return', [sessionId, caps]); case 15: context$2$0.prev = 15; context$2$0.t0 = context$2$0['catch'](1); _logger2['default'].error(context$2$0.t0); context$2$0.next = 20; return _regeneratorRuntime.awrap(this.deleteSession()); case 20: throw context$2$0.t0; case 21: case 'end': return context$2$0.stop(); } }, null, this, [[1, 15]]); } }, { key: 'start', value: function start() { var tools, _ref3, device, udid, realDevice, installAppPromise; return _regeneratorRuntime.async(function start$(context$2$0) { var _this2 = this; while (1) switch (context$2$0.prev = context$2$0.next) { case 0: this.opts.noReset = !!this.opts.noReset; this.opts.fullReset = !!this.opts.fullReset; if (this.xcodeVersion) { context$2$0.next = 8; break; } context$2$0.next = 5; return _regeneratorRuntime.awrap((0, _utils.getAndCheckXcodeVersion)()); case 5: this.xcodeVersion = context$2$0.sent; tools = !this.xcodeVersion.toolsVersion ? '' : '(tools v' + this.xcodeVersion.toolsVersion + ')'; _logger2['default'].debug('Xcode version set to \'' + this.xcodeVersion.versionString + '\' ' + tools); case 8: context$2$0.next = 10; return _regeneratorRuntime.awrap((0, _utils.getAndCheckIosSdkVersion)()); case 10: this.iosSdkVersion = context$2$0.sent; _logger2['default'].debug('iOS SDK Version set to \'' + this.iosSdkVersion + '\''); if (!(this.opts.platformVersion && parseFloat(this.opts.platformVersion) < 9.0)) { context$2$0.next = 14; break; } throw Error('Platform version must be 9.0 or above. \'' + this.opts.platformVersion + '\' is not supported.'); case 14: this.logEvent('xcodeDetailsRetrieved'); context$2$0.next = 17; return _regeneratorRuntime.awrap(this.determineDevice()); case 17: _ref3 = context$2$0.sent; device = _ref3.device; udid = _ref3.udid; realDevice = _ref3.realDevice; _logger2['default'].info('Determining device to run tests on: udid: \'' + udid + '\', real device: ' + realDevice); this.opts.device = device; this.opts.udid = udid; this.opts.realDevice = realDevice; if (!(this.isSimulator() && this.opts.customSSLCert)) { context$2$0.next = 29; break; } context$2$0.next = 28; return _regeneratorRuntime.awrap((0, _appiumIosSimulator.installSSLCert)(this.opts.customSSLCert, this.opts.udid)); case 28: this.logEvent('customCertInstalled'); case 29: if (this.opts.platformVersion) { context$2$0.next = 37; break; } if (!(this.opts.device && _lodash2['default'].isFunction(this.opts.device.getPlatformVersion))) { context$2$0.next = 37; break; } context$2$0.next = 33; return _regeneratorRuntime.awrap(this.opts.device.getPlatformVersion()); case 33: this.opts.platformVersion = context$2$0.sent; _logger2['default'].info('No platformVersion specified. Using device version: \'' + this.opts.platformVersion + '\''); context$2$0.next = 37; break; case 37: if (!((this.opts.browserName || '').toLowerCase() === 'safari')) { context$2$0.next = 47; break; } _logger2['default'].info('Safari test requested'); this.safari = true; this.opts.app = undefined; this.opts.processArguments = this.opts.processArguments || {}; this.opts.bundleId = SAFARI_BUNDLE_ID; this._currentUrl = this.opts.safariInitialUrl || (this.isRealDevice() ? 'http://appium.io' : 'http://' + this.opts.address + ':' + this.opts.port + '/welcome'); this.opts.processArguments.args = ['-u', this._currentUrl]; context$2$0.next = 49; break; case 47: context$2$0.next = 49; return _regeneratorRuntime.awrap(this.configureApp()); case 49: this.logEvent('appConfigured'); // fail very early if the app doesn't actually exist // or if bundle id doesn't point to an installed app if (!this.opts.app) { context$2$0.next = 55; break; } context$2$0.next = 53; return _regeneratorRuntime.awrap((0, _utils.checkAppPresent)(this.opts.app)); case 53: context$2$0.next = 60; break; case 55: if (!(this.opts.bundleId && !this.safari)) { context$2$0.next = 60; break; } context$2$0.next = 58; return _regeneratorRuntime.awrap(this.opts.device.isAppInstalled(this.opts.bundleId)); case 58: if (context$2$0.sent) { context$2$0.next = 60; break; } _logger2['default'].errorAndThrow('App with bundle identifier \'' + this.opts.bundleId + '\' unknown'); case 60: if (this.opts.bundleId) { context$2$0.next = 64; break; } context$2$0.next = 63; return _regeneratorRuntime.awrap(this.extractBundleId(this.opts.app)); case 63: this.opts.bundleId = context$2$0.sent; case 64: if (!this.opts.realDevice) { if (typeof this.opts.scaleFactor !== 'undefined') { _logger2['default'].info('Setting non-default Simulator scale factor to \'' + this.opts.scaleFactor + '\''); device.setScaleFactor(this.opts.scaleFactor); } if (typeof this.opts.connectHardwareKeyboard !== 'undefined') { _logger2['default'].info('Setting \'connectHardwareKeyboard\' Simulator option to \'' + (this.opts.connectHardwareKeyboard ? 'on' : 'off') + '\''); device.setConnectHardwareKeyboard(this.opts.connectHardwareKeyboard); } } context$2$0.next = 67; return _regeneratorRuntime.awrap(this.runReset()); case 67: context$2$0.next = 69; return _regeneratorRuntime.awrap(this.startLogCapture()); case 69: this.logEvent('logCaptureStarted'); _logger2['default'].info('Setting up ' + (this.isRealDevice() ? 'real device' : 'simulator')); if (!this.isRealDevice()) { context$2$0.next = 78; break; } if (!this.opts.app) { context$2$0.next = 76; break; } context$2$0.next = 75; return _regeneratorRuntime.awrap(this.installApp()); case 75: this.logEvent('appInstalled'); case 76: context$2$0.next = 98; break; case 78: context$2$0.next = 80; return _regeneratorRuntime.awrap(_appiumIosDriver.settings.setLocale(this.opts.device, this.opts, {}, this.isSafari())); case 80: this.localeConfig = context$2$0.sent; context$2$0.next = 83; return _regeneratorRuntime.awrap(_appiumIosDriver.settings.setPreferences(this.opts.device, this.opts, this.isSafari())); case 83: installAppPromise = null; if (!this.opts.app) { context$2$0.next = 92; break; } context$2$0.next = 87; return _regeneratorRuntime.awrap((0, _simulatorManagement.simBooted)(this.opts.device)); case 87: if (!context$2$0.sent) { context$2$0.next = 91; break; } installAppPromise = this.installApp(); context$2$0.next = 92; break; case 91: installAppPromise = new _bluebird2['default'](function callee$2$0(resolve, reject) { return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { var _this = this; while (1) switch (context$3$0.prev = context$3$0.next) { case 0: this.opts.device.on(_appiumIosSimulator.BOOT_COMPLETED_EVENT, function callee$3$0() { return _regeneratorRuntime.async(function callee$3$0$(context$4$0) { while (1) switch (context$4$0.prev = context$4$0.next) { case 0: context$4$0.prev = 0; context$4$0.next = 3; return _regeneratorRuntime.awrap(this.installApp()); case 3: resolve(); context$4$0.next = 9; break; case 6: context$4$0.prev = 6; context$4$0.t0 = context$4$0['catch'](0); reject(context$4$0.t0); case 9: case 'end': return context$4$0.stop(); } }, null, _this, [[0, 6]]); }); case 1: case 'end': return context$3$0.stop(); } }, null, _this2); }); case 92: context$2$0.next = 94; return _regeneratorRuntime.awrap(this.startSim()); case 94: this.logEvent('simStarted'); context$2$0.next = 97; return _regeneratorRuntime.awrap(installAppPromise); case 97: this.logEvent('appInstalled'); case 98: context$2$0.next = 100; return _regeneratorRuntime.awrap(this.startWda(this.opts.sessionId, realDevice)); case 100: context$2$0.next = 102; return _regeneratorRuntime.awrap(this.setInitialOrientation(this.opts.orientation)); case 102: this.logEvent('orientationSet'); if (!(this.isRealDevice() && this.opts.startIWDP)) { context$2$0.next = 113; break; } context$2$0.prev = 104; context$2$0.next = 107; return _regeneratorRuntime.awrap(this.startIWDP()); case 107: _logger2['default'].debug('Started ios_webkit_debug proxy server at: ' + this.iwdpServer.endpoint); context$2$0.next = 113; break; case 110: context$2$0.prev = 110; context$2$0.t0 = context$2$0['catch'](104); _logger2['default'].errorAndThrow('Could not start ios_webkit_debug_proxy server: ' + context$2$0.t0.message); case 113: if (!(this.isSafari() || this.opts.autoWebview)) { context$2$0.next = 118; break; } _logger2['default'].debug('Waiting for initial webview'); context$2$0.next = 117; return _regeneratorRuntime.awrap(this.navToInitialWebview()); case 117: this.logEvent('initialWebviewNavigated'); case 118: if (this.isRealDevice()) { context$2$0.next = 127; break; } if (!this.opts.calendarAccessAuthorized) { context$2$0.next = 124; break; } context$2$0.next = 122; return _regeneratorRuntime.awrap(this.opts.device.enableCalendarAccess(this.opts.bundleId)); case 122: context$2$0.next = 127; break; case 124: if (!(this.opts.calendarAccessAuthorized === false)) { context$2$0.next = 127; break; } context$2$0.next = 127; return _regeneratorRuntime.awrap(this.opts.device.disableCalendarAccess(this.opts.bundleId)); case 127: case 'end': return context$2$0.stop(); } }, null, this, [[104, 110]]); } }, { key: 'startWda', value: function startWda(sessionId, realDevice) { var startupRetries, startupRetryInterval; return _regeneratorRuntime.async(function startWda$(context$2$0) { var _this4 = this; while (1) switch (context$2$0.prev = context$2$0.next) { case 0: startupRetries = this.opts.wdaStartupRetries || WDA_STARTUP_RETRIES; startupRetryInterval = this.opts.wdaStartupRetryInterval || WDA_STARTUP_RETRY_INTERVAL; context$2$0.next = 4; return _regeneratorRuntime.awrap((0, _asyncbox.retryInterval)(startupRetries, startupRetryInterval, function callee$2$0() { var quitAndUninstall, wdaStatus; return _regeneratorRuntime.async(function callee$2$0$(context$3$0) { var _this3 = this; while (1) switch (context$3$0.prev = context$3$0.next) { case 0: this.logEvent('wdaStartAttempted'); this.wda = new _webdriveragent2['default'](this.xcodeVersion, this.opts); if (!this.opts.useNewWDA) { context$3$0.next = 7; break; } _logger2['default'].debug('Capability \'useNewWDA\' set, so uninstalling WDA before proceeding'); context$3$0.next = 6; return _regeneratorRuntime.awrap(this.wda.uninstall()); case 6: this.logEvent('wdaUninstalled'); case 7: quitAndUninstall = function quitAndUninstall(msg) { return _regeneratorRuntime.async(function quitAndUninstall$(context$4$0) { while (1) switch (context$4$0.prev = context$4$0.next) { case 0: _logger2['default'].debug(msg); _logger2['default'].debug('Quitting and uninstalling WebDriverAgent, then retrying'); context$4$0.next = 4; return _regeneratorRuntime.awrap(this.wda.quit()); case 4: context$4$0.next = 6; return _regeneratorRuntime.awrap(this.wda.uninstall()); case 6: throw new Error(msg); case 7: case 'end': return context$4$0.stop(); } }, null, _this3); }; wdaStatus = null; context$3$0.prev = 9; context$3$0.next = 12; return _regeneratorRuntime.awrap(this.wda.launch(sessionId, realDevice)); case 12: wdaStatus = context$3$0.sent; context$3$0.next = 20; break; case 15: context$3$0.prev = 15; context$3$0.t0 = context$3$0['catch'](9); this.logEvent('wdaStartFailed'); context$3$0.next = 20; return _regeneratorRuntime.awrap(quitAndUninstall('Unable to launch WebDriverAgent because of xcodebuild failure: ' + context$3$0.t0.message)); case 20: this.proxyReqRes = this.wda.proxyReqRes.bind(this.wda); this.jwpProxyActive = true; context$3$0.prev = 22; context$3$0.next = 25; return _regeneratorRuntime.awrap((0, _asyncbox.retryInterval)(15, 1000, function callee$3$0() { return _regeneratorRuntime.async(function callee$3$0$(context$4$0) { while (1) switch (context$4$0.prev = context$4$0.next) { case 0: this.logEvent('wdaSessionAttempted'); _logger2['default'].debug('Sending createSession command to WDA'); context$4$0.prev = 2; if (!wdaStatus) { context$4$0.next = 7; break; } this.cachedWdaStatus = wdaStatus; context$4$0.next = 9; break; case 7: context$4$0.next = 9; return _regeneratorRuntime.awrap(this.proxyCommand('/status', 'GET')); case 9: context$4$0.next = 11; return _regeneratorRuntime.awrap(this.startWdaSession(this.opts.bundleId, this.opts.processArguments)); case 11: context$4$0.next = 17; break; case 13: context$4$0.prev = 13; context$4$0.t0 = context$4$0['catch'](2); _logger2['default'].debug('Failed to create WDA session. Retrying...'); throw context$4$0.t0; case 17: case 'end': return context$4$0.stop(); } }, null, _this3, [[2, 13]]); })); case 25: this.logEvent('wdaSessionStarted'); context$3$0.next = 33; break; case 28: context$3$0.prev = 28; context$3$0.t1 = context$3$0['catch'](22); context$3$0.next = 32; return _regeneratorRuntime.awrap(quitAndUninstall('Unable to start WebDriverAgent session: ' + context$3$0.t1.message)); case 32: return context$3$0.abrupt('return', context$3$0.sent); case 33: this.opts.preventWDAAttachments = !_appiumSupport.util.hasValue(this.opts.preventWDAAttachments) || this.opts.preventWDAAttachments; context$3$0.next = 36; return _regeneratorRuntime.awrap((0, _utils.adjustWDAAttachmentsPermissions)(this.opts.preventWDAAttachments ? '555' : '755')); case 36: this.logEvent('wdaPermsAdjusted'); // we expect certain socket errors until this point, but now // mark things as fully working this.wda.fullyStarted = true; this.logEvent('wdaStarted'); case 39: case 'end': return context$3$0.stop(); } }, null, _this4, [[9, 15], [22, 28]]); })); case 4: case 'end': return context$2$0.stop(); } }, null, this); } // create an alias so we can actually unit test createSession by stubbing // this }, { key: 'extractBundleId', value: function extractBundleId(app) { return _regeneratorRuntime.async(function extractBundleId$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return _regeneratorRuntime.awrap(_appiumIosDriver.appUtils.extractBundleId(app)); case 2: return context$2$0.abrupt('return', context$2$0.sent); case 3: case 'end': return context$2$0.stop(); } }, null, this); } }, { key: 'runReset', value: function runReset() { var opts = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0]; return _regeneratorRuntime.async(function runReset$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: this.logEvent('resetStarted'); if (!this.isRealDevice()) { context$2$0.next = 6; break; } context$2$0.next = 4; return _regeneratorRuntime.awrap((0, _realDeviceManagement.runRealDeviceReset)(this.opts.device, opts || this.opts)); case 4: context$2$0.next = 8; break; case 6: context$2$0.next = 8; return _regeneratorRuntime.awrap((0, _simulatorManagement.runSimulatorReset)(this.opts.device, opts || this.opts)); case 8: this.logEvent('resetComplete'); case 9: case 'end': return context$2$0.stop(); } }, null, this); } }, { key: 'deleteSession', value: function deleteSession() { return _regeneratorRuntime.async(function deleteSession$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: context$2$0.next = 2; return _regeneratorRuntime.awrap(this.stop()); case 2: if (!this.opts.preventWDAAttachments) { context$2$0.next = 5; break; } context$2$0.next = 5; return _regeneratorRuntime.awrap((0, _utils.adjustWDAAttachmentsPermissions)('755')); case 5: if (!this.opts.clearSystemFiles) { context$2$0.next = 10; break; } context$2$0.next = 8; return _regeneratorRuntime.awrap((0, _utils.clearSystemFiles)(this.wda, !!this.opts.showXcodeLog)); case 8: context$2$0.next = 11; break; case 10: _logger2['default'].debug('Not clearing log files. Use `clearSystemFiles` capability to turn on.'); case 11: if (!this.isWebContext()) { context$2$0.next = 15; break; } _logger2['default'].debug('In a web session. Removing remote debugger'); context$2$0.next = 15; return _regeneratorRuntime.awrap(this.stopRemote()); case 15: if (!(this.opts.resetOnSessionStartOnly === false)) { context$2$0.next = 18; break; } context$2$0.next = 18; return _regeneratorRuntime.awrap(this.runReset()); case 18: if (!(this.isSimulator() && this.opts.udid && this.opts.customSSLCert)) { context$2$0.next = 21; break; } context$2$0.next = 21; return _regeneratorRuntime.awrap((0, _appiumIosSimulator.uninstallSSLCert)(this.opts.customSSLCert, this.opts.udid)); case 21: if (!(this.isSimulator() && !this.opts.noReset && !!this.opts.device)) { context$2$0.next = 28; break; } if (!this.lifecycleData.createSim) { context$2$0.next = 28; break; } _logger2['default'].debug('Deleting simulator created for this run'); context$2$0.next = 26; return _regeneratorRuntime.awrap(this.opts.device.shutdown()); case 26: context$2$0.next = 28; return _regeneratorRuntime.awrap(this.opts.device['delete']()); case 28: if (!_lodash2['default'].isEmpty(this.logs)) { this.logs.syslog.stopCapture(); this.logs = {}; } if (this.iwdpServer) { this.stopIWDP(); } this.resetIos(); context$2$0.next = 33; return _regeneratorRuntime.awrap(_get(Object.getPrototypeOf(XCUITestDriver.prototype), 'deleteSession', this).call(this)); case 33: case 'end': return context$2$0.stop(); } }, null, this); } }, { key: 'stop', value: function stop() { return _regeneratorRuntime.async(function stop$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: this.jwpProxyActive = false; this.proxyReqRes = null; if (!(this.wda && this.wda.fullyStarted)) { context$2$0.next = 14; break; } if (!this.wda.jwproxy) { context$2$0.next = 12; break; } context$2$0.prev = 4; context$2$0.next = 7; return _regeneratorRuntime.awrap(this.proxyCommand('/session/' + this.sessionId, 'DELETE')); case 7: context$2$0.next = 12; break; case 9: context$2$0.prev = 9; context$2$0.t0 = context$2$0['catch'](4); // an error here should not short-circuit the rest of clean up _logger2['default'].debug('Unable to DELETE session on WDA: \'' + context$2$0.t0.message + '\'. Continuing shutdown.'); case 12: context$2$0.next = 14; return _regeneratorRuntime.awrap(this.wda.quit()); case 14: case 'end': return context$2$0.stop(); } }, null, this, [[4, 9]]); } }, { key: 'executeCommand', value: function executeCommand(cmd) { var _get2; for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } return _regeneratorRuntime.async(function executeCommand$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: _logger2['default'].debug('Executing command \'' + cmd + '\''); if (!(cmd === 'receiveAsyncResponse')) { context$2$0.next = 5; break; } context$2$0.next = 4; return _regeneratorRuntime.awrap(this.receiveAsyncResponse.apply(this, args)); case 4: return context$2$0.abrupt('return', context$2$0.sent); case 5: if (!(cmd === 'getStatus')) { context$2$0.next = 9; break; } context$2$0.next = 8; return _regeneratorRuntime.awrap(this.getStatus()); case 8: return context$2$0.abrupt('return', context$2$0.sent); case 9: context$2$0.next = 11; return _regeneratorRuntime.awrap((_get2 = _get(Object.getPrototypeOf(XCUITestDriver.prototype), 'executeCommand', this)).call.apply(_get2, [this, cmd].concat(args))); case 11: return context$2$0.abrupt('return', context$2$0.sent); case 12: case 'end': return context$2$0.stop(); } }, null, this); } }, { key: 'configureApp', value: function configureApp() { var appIsPackageOrBundle; return _regeneratorRuntime.async(function configureApp$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: appIsPackageOrBundle = function appIsPackageOrBundle(app) { return (/^([a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+)+$/.test(app) ); }; // the app name is a bundleId assign it to the bundleId property if (!this.opts.bundleId && appIsPackageOrBundle(this.opts.app)) { this.opts.bundleId = this.opts.app; this.opts.app = ''; } // we have a bundle ID, but no app, or app is also a bundle if (!(this.opts.bundleId && appIsPackageOrBundle(this.opts.bundleId) && (this.opts.app === '' || appIsPackageOrBundle(this.opts.app)))) { context$2$0.next = 5; break; } _logger2['default'].debug('App is an iOS bundle, will attempt to run as pre-existing'); return context$2$0.abrupt('return'); case 5: if (!(this.opts.app && this.opts.app.toLowerCase() === 'settings')) { context$2$0.next = 11; break; } this.opts.bundleId = 'com.apple.Preferences'; this.opts.app = null; return context$2$0.abrupt('return'); case 11: if (!(this.opts.app && this.opts.app.toLowerCase() === 'calendar')) { context$2$0.next = 15; break; } this.opts.bundleId = 'com.apple.mobilecal'; this.opts.app = null; return context$2$0.abrupt('return'); case 15: context$2$0.prev = 15; context$2$0.next = 18; return _regeneratorRuntime.awrap(this.helpers.configureApp(this.opts.app, '.app', this.opts.mountRoot, this.opts.windowsShareUserName, this.opts.windowsSharePassword)); case 18: this.opts.app = context$2$0.sent; context$2$0.next = 25; break; case 21: context$2$0.prev = 21; context$2$0.t0 = context$2$0['catch'](15); _logger2['default'].error(context$2$0.t0); throw new Error('Bad app: ' + this.opts.app + '. App paths need to be absolute, or relative to the appium ' + 'server install dir, or a URL to compressed file, or a special app name.'); case 25: case 'end': return context$2$0.stop(); } }, null, this, [[15, 21]]); } }, { key: 'determineDevice', value: function determineDevice() { var _device, devices, _device2, device; return _regeneratorRuntime.async(function determineDevice$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: // in the one case where we create a sim, we will set this state this.lifecycleData.createSim = false; // if we get generic names, translate them this.opts.deviceName = (function translateDeviceName() { var dn = arguments.length <= 0 || arguments[0] === undefined ? '' : arguments[0]; var deviceName = dn; if (dn.toLowerCase() === 'iphone simulator') { deviceName = 'iPhone 6'; } else if (dn.toLowerCase() === 'ipad simulator') { deviceName = 'iPad Retina'; } if (deviceName !== dn) { _logger2['default'].debug('Changing deviceName from \'' + dn + '\' to \'' + deviceName + '\''); } return deviceName; })(this.opts.deviceName); // check for a particular simulator context$2$0.t0 = this.opts.udid; if (!context$2$0.t0) { context$2$0.next = 7; break; } context$2$0.next = 6; return _regeneratorRuntime.awrap((0, _appiumIosSimulator.simExists)(this.opts.udid)); case 6: context$2$0.t0 = context$2$0.sent; case 7: if (!context$2$0.t0) { context$2$0.next = 12; break; } context$2$0.next = 10; return _regeneratorRuntime.awrap((0, _appiumIosSimulator.getSimulator)(this.opts.udid)); case 10: _device = context$2$0.sent; return context$2$0.abrupt('return', { device: _device, realDevice: false, udid: this.opts.udid }); case 12: if (!this.opts.udid) { context$2$0.next = 29; break; } if (!(this.opts.udid.toLowerCase() === 'auto')) { context$2$0.next = 19; break; } context$2$0.next = 16; return _regeneratorRuntime.awrap((0, _utils.detectUdid)()); case 16: this.opts.udid = context$2$0.sent; context$2$0.next = 25; break; case 19: context$2$0.next = 21; return _regeneratorRuntime.awrap((0, _realDeviceManagement.getConnectedDevices)()); case 21: devices = context$2$0.sent; _logger2['default'].debug('Available devices: ' + devices.join(', ')); if (!(devices.indexOf(this.opts.udid) === -1)) { context$2$0.next = 25; break; } throw new Error('Unknown device or simulator UDID: \'' + this.opts.udid + '\''); case 25: context$2$0.next = 27; return _regeneratorRuntime.awrap((0, _realDeviceManagement.getRealDeviceObj)(this.opts.udid)); case 27: _device2 = context$2$0.sent; return context$2$0.abrupt('return', { device: _device2, realDevice: true, udid: this.opts.udid }); case 29: context$2$0.next = 31; return _regeneratorRuntime.awrap((0, _simulatorManagement.getExistingSim)(this.opts.deviceName, this.opts.platformVersion)); case 31: device = context$2$0.sent; if (!device) { context$2$0.next = 34; break; } return context$2$0.abrupt('return', { device: device, realDevice: false, udid: device.udid }); case 34: // no device of this type exists, so create one _logger2['default'].info('Simulator udid not provided, using desired caps to create a new simulator'); if (!this.opts.platformVersion) { _logger2['default'].info('No platformVersion specified. Using latest version Xcode supports: \'' + this.iosSdkVersion + '\' ' + 'This may cause problems if a simulator does not exist for this platform version.'); this.opts.platformVersion = this.iosSdkVersion; } context$2$0.next = 38; return _regeneratorRuntime.awrap(this.createSim()); case 38: device = context$2$0.sent; return context$2$0.abrupt('return', { device: device, realDevice: false, udid: device.udid }); case 40: case 'end': return context$2$0.stop(); } }, null, this); } }, { key: 'startSim', value: function startSim() { return _regeneratorRuntime.async(function startSim$(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, _simulatorManagement.simBooted)(this.opts.device)); case 2: if (!context$2$0.sent) { context$2$0.next = 5; break; } _logger2['default'].info('Simulator with udid \'' + this.opts.udid + '\' already booted'); return context$2$0.abrupt('return'); case 5: _logger2['default'].info('Simulator with udid \'' + this.opts.udid + '\' not booted. Booting up now'); context$2$0.next = 8; return _regeneratorRuntime.awrap((0, _appiumIosSimulator.killAllSimulators)()); case 8: context$2$0.next = 10; return _regeneratorRuntime.awrap(this.opts.device.run(undefined, this.opts.allowTouchIdEnroll)); case 10: case 'end': return context$2$0.stop(); } }, null, this); } }, { key: 'createSim', value: function createSim() { var sim; return _regeneratorRuntime.async(function createSim$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: this.lifecycleData.createSim = true; // create sim for caps context$2$0.next = 3; return _regeneratorRuntime.awrap((0, _simulatorManagement.createSim)(this.opts, this.sessionId)); case 3: sim = context$2$0.sent; _logger2['default'].info('Created simulator with udid \'' + sim.udid + '\'.'); return context$2$0.abrupt('return', sim); case 6: case 'end': return context$2$0.stop(); } }, null, this); } }, { key: 'launchApp', value: function launchApp() { var APP_LAUNCH_TIMEOUT, checkStatus, retries; return _regeneratorRuntime.async(function launchApp$(context$2$0) { var _this5 = this; while (1) switch (context$2$0.prev = context$2$0.next) { case 0: APP_LAUNCH_TIMEOUT = 20 * 1000; this.logEvent('appLaunchAttempted'); context$2$0.next = 4; return _regeneratorRuntime.awrap((0, _nodeSimctl.launch)(this.opts.device.udid, this.opts.bundleId)); case 4: checkStatus = function checkStatus() { var response, currentApp; return _regeneratorRuntime.async(function checkStatus$(context$3$0) { while (1) switch (context$3$0.prev = context$3$0.next) { case 0: context$3$0.next = 2; return _regeneratorRuntime.awrap(this.proxyCommand('/status', 'GET')); case 2: response = context$3$0.sent; currentApp = response.currentApp.bundleID; if (!(currentApp !== this.opts.bundleId)) { context$3$0.next = 6; break; } throw new Error(this.opts.bundleId + ' not in foreground. ' + currentApp + ' is in foreground'); case 6: case 'end': return context$3$0.stop(); } }, null, _this5); }; _logger2['default'].info('Waiting for \'' + this.opts.bundleId + '\' to be in foreground'); retries = parseInt(APP_LAUNCH_TIMEOUT / 200, 10); context$2$0.next = 9; return _regeneratorRuntime.awrap((0, _asyncbox.retryInterval)(retries, 200, checkStatus)); case 9: _logger2['default'].info(this.opts.bundleId + ' is in foreground'); this.logEvent('appLaunched'); case 11: case 'end': return context$2$0.stop(); } }, null, this); } }, { key: 'startWdaSession', value: function startWdaSession(bundleId, processArguments) { var args, env, shouldWaitForQuiescence, maxTypingFrequency, shouldUseSingletonTestManager, shouldUseTestManagerForVisibilityDetection, desired; return _regeneratorRuntime.async(function startWdaSession$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: args = processArguments ? processArguments.args : []; env = processArguments ? processArguments.env : {}; shouldWaitForQuiescence = _appiumSupport.util.hasValue(this.opts.waitForQuiescence) ? this.opts.waitForQuiescence : true; maxTypingFrequency = _appiumSupport.util.hasValue(this.opts.maxTypingFrequency) ? this.opts.maxTypingFrequency : 60; shouldUseSingletonTestManager = _appiumSupport.util.hasValue(this.opts.shouldUseSingletonTestManager) ? this.opts.shouldUseSingletonTestManager : true; shouldUseTestManagerForVisibilityDetection = false; if (_appiumSupport.util.hasValue(this.opts.simpleIsVisibleCheck)) { shouldUseTestManagerForVisibilityDetection = this.opts.simpleIsVisibleCheck; } if ((this.opts.platformVersion || '').indexOf('9') === 0) { shouldUseTestManagerForVisibilityDetection = true; } desired = { desiredCapabilities: { bundleId: bundleId, arguments: args, environment: env, shouldWaitForQuiescence: shouldWaitForQuiescence, shouldUseTestManagerForVisibilityDetection: shouldUseTestManagerForVisibilityDetection, maxTypingFrequency: maxTypingFrequency, shouldUseSingletonTestManager: shouldUseSingletonTestManager } }; context$2$0.next = 11; return _regeneratorRuntime.awrap(this.proxyCommand('/session', 'POST', desired)); case 11: case 'end': return context$2$0.stop(); } }, null, this); } // Override Proxy methods