UNPKG

appium-webdriveragent-driver

Version:
258 lines (198 loc) 20.6 kB
'use strict'; var _createClass = require('babel-runtime/helpers/create-class')['default']; var _classCallCheck = require('babel-runtime/helpers/class-call-check')['default']; var _getIterator = require('babel-runtime/core-js/get-iterator')['default']; var _regeneratorRuntime = require('babel-runtime/regenerator')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; Object.defineProperty(exports, '__esModule', { value: true }); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _url = require('url'); var _url2 = _interopRequireDefault(_url); var _bluebird = require('bluebird'); var _bluebird2 = _interopRequireDefault(_bluebird); var _teen_process = require('teen_process'); var _appiumJsonwpProxy = require('appium-jsonwp-proxy'); var _appiumSupport = require('appium-support'); var _logger = require('./logger'); var _logger2 = _interopRequireDefault(_logger); var _appiumLogger = require('appium-logger'); var _simulatorManagementJs = require('./simulatorManagement.js'); var agentLog = (0, _appiumLogger.getLogger)('WebDriverAgent'); var AGENT_PATH = _path2['default'].resolve(__dirname, '..', '..', 'WebDriverAgent', 'WebDriverAgent.xcworkspace'); var REQ_ARGS = ['sim', 'platformVersion', 'host']; var AGENT_LOG_PREFIX = 'XCTStubApps['; var AGENT_STARTED_REGEX = /ServerURLHere->(.*)<-ServerURLHere/; var WebDriverAgent = (function () { // agentPath (optional): Path to WebdriverAgent Executable (inside WebDriverAgent.app) function WebDriverAgent() { var args = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; _classCallCheck(this, WebDriverAgent); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = _getIterator(REQ_ARGS), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var reqArg = _step.value; if (_lodash2['default'].isUndefined(args[reqArg])) { throw new Error('You must send in the \'' + reqArg + '\' argument'); } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } if (args.agentPath) { _logger2['default'].info('Custom agent path specified: ' + args.agentPath); } else { _logger2['default'].info('Using default agent'); } this.sim = args.sim; this.platformVersion = args.platformVersion; this.host = args.host; this.agentPath = args.agentPath || _path2['default'].resolve(AGENT_PATH); } _createClass(WebDriverAgent, [{ key: 'launch', value: function launch(sessionId) { return _regeneratorRuntime.async(function launch$(context$2$0) { var _this2 = this; while (1) switch (context$2$0.prev = context$2$0.next) { case 0: return context$2$0.abrupt('return', new _bluebird2['default'](function callee$2$0(resolve, reject) { var agentUrl, agentStartedOnDevice; 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: _logger2['default'].info("Launching WebDriverAgent on the device"); context$3$0.next = 3; return _regeneratorRuntime.awrap(_appiumSupport.fs.exists(this.agentPath)); case 3: if (context$3$0.sent) { context$3$0.next = 6; break; } reject(new Error('Trying to use WebDriverAgent project at ' + this.agentPath + ' but the ' + 'file does not exist')); return context$3$0.abrupt('return'); case 6: this.simLogs = this.createSimLogsSubProcess(); this.simLogs.on('output', function (d, e) { if (d.length && d.indexOf(AGENT_LOG_PREFIX) > -1) { agentLog.info(d); } if (e.length && d.indexOf(AGENT_LOG_PREFIX) > -1) { agentLog.error(e); } }); this.simLogs.on('exit', function (code) { reject(new Error('tailing of simulator log exited with code ' + code)); return; }); this.xcodebuild = this.createXcodeBuildSubProcess(); // this.xcodebuild.on('output', (d, e) => { // log.warn(d, e); // }); this.xcodebuild.on('exit', function (code, signal) { _logger2['default'].info('xcodebuild exited with code ' + code + ' and signal ' + signal); if (!signal && code !== 0) { reject(new Error('xcodebuild failed with code ' + code)); return; } _this.quit(); }); this.xcodebuild.start(); // we have to wait for the sim to start before we can tail the log file context$3$0.next = 14; return _regeneratorRuntime.awrap((0, _simulatorManagementJs.systemLogExists)(this.sim)); case 14: agentUrl = undefined; agentStartedOnDevice = this.simLogs.start(function (stdout) { var match = AGENT_STARTED_REGEX.exec(stdout); if (match) { agentUrl = match[1]; _logger2['default'].info('detected that WebDriverAgent is running at url ' + agentUrl); if (!agentUrl) { _logger2['default'].errorAndThrow(new Error('No url detected from WebDriverAgent')); } return true; } }); _logger2['default'].info('Waiting for WebDriverAgent to start on device'); context$3$0.next = 19; return _regeneratorRuntime.awrap(agentStartedOnDevice); case 19: _logger2['default'].info('WebDriverAgent started at url ' + agentUrl); this.url = _url2['default'].parse(agentUrl); this.jwproxy = new _appiumJsonwpProxy.JWProxy({ host: this.url.hostname, port: this.url.port, base: '' }); this.jwproxy.sessionId = sessionId; this.proxyReqRes = this.jwproxy.proxyReqRes.bind(this.jwproxy); return context$3$0.abrupt('return', resolve(_url2['default'])); case 25: case 'end': return context$3$0.stop(); } }, null, _this2); })); case 1: case 'end': return context$2$0.stop(); } }, null, this); } }, { key: 'createXcodeBuildSubProcess', value: function createXcodeBuildSubProcess() { var args = ['-workspace', this.agentPath, '-scheme', 'XCTUITestRunner', '-destination', 'id=' + this.sim.udid, 'test']; return new _teen_process.SubProcess('xcodebuild', args); } }, { key: 'createSimLogsSubProcess', value: function createSimLogsSubProcess() { var args = ['-f', '-n', '0', _path2['default'].resolve(this.sim.getLogDir(), 'system.log')]; return new _teen_process.SubProcess('tail', args); } }, { key: 'quit', value: function quit() { var stops; return _regeneratorRuntime.async(function quit$(context$2$0) { while (1) switch (context$2$0.prev = context$2$0.next) { case 0: _logger2['default'].info('Shutting down WebDriverAgent'); stops = []; if (this.xcodebuild && this.xcodebuild.proc) { stops.push(this.xcodebuild.stop()); } if (this.simLogs && this.simLogs.proc) { stops.push(this.simLogs.stop()); } this.jwproxy.sessionId = null; context$2$0.next = 7; return _regeneratorRuntime.awrap(_bluebird2['default'].all(stops)); case 7: case 'end': return context$2$0.stop(); } }, null, this); } }]); return WebDriverAgent; })(); exports['default'] = WebDriverAgent; module.exports = exports['default']; //# sourceMappingURL=data:application/json;base64,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OEIsQ0FBQyxDQUFDO0FBQ3JDLGlCQUFLLEdBQUcsRUFBRTs7QUFDZCxnQkFBSSxJQUFJLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFO0FBQzNDLG1CQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQzthQUNwQztBQUNELGdCQUFJLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUU7QUFDckMsbUJBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO2FBQ2pDOztBQUVELGdCQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7Ozs2Q0FFeEIsc0JBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQzs7Ozs7OztLQUNuQjs7O1NBbklHLGNBQWM7OztxQkFzSUwsY0FBYyIsImZpbGUiOiJsaWIvd2ViZHJpdmVyYWdlbnQuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgdXJsIGZyb20gJ3VybCc7XG5pbXBvcnQgQiBmcm9tICdibHVlYmlyZCc7XG5pbXBvcnQgeyBTdWJQcm9jZXNzIH0gZnJvbSAndGVlbl9wcm9jZXNzJztcbmltcG9ydCB7IEpXUHJveHkgfSBmcm9tICdhcHBpdW0tanNvbndwLXByb3h5JztcbmltcG9ydCB7IGZzIH0gZnJvbSAnYXBwaXVtLXN1cHBvcnQnO1xuaW1wb3J0IGxvZyBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgeyBnZXRMb2dnZXIgfSBmcm9tICdhcHBpdW0tbG9nZ2VyJztcbmltcG9ydCB7IHN5c3RlbUxvZ0V4aXN0cyB9IGZyb20gJy4vc2ltdWxhdG9yTWFuYWdlbWVudC5qcyc7XG5cbmNvbnN0IGFnZW50TG9nID0gZ2V0TG9nZ2VyKCdXZWJEcml2ZXJBZ2VudCcpO1xuY29uc3QgQUdFTlRfUEFUSCA9IHBhdGgucmVzb2x2ZShfX2Rpcm5hbWUsICcuLicsICcuLicsICdXZWJEcml2ZXJBZ2VudCcsICdXZWJEcml2ZXJBZ2VudC54Y3dvcmtzcGFjZScpO1xuY29uc3QgUkVRX0FSR1MgPSBbJ3NpbScsICdwbGF0Zm9ybVZlcnNpb24nLCAnaG9zdCddO1xuY29uc3QgQUdFTlRfTE9HX1BSRUZJWCA9ICdYQ1RTdHViQXBwc1snO1xuY29uc3QgQUdFTlRfU1RBUlRFRF9SRUdFWCA9IC9TZXJ2ZXJVUkxIZXJlLT4oLiopPC1TZXJ2ZXJVUkxIZXJlLztcblxuXG5cbmNsYXNzIFdlYkRyaXZlckFnZW50IHtcblxuICAvLyBhZ2VudFBhdGggKG9wdGlvbmFsKTogUGF0aCB0byBXZWJkcml2ZXJBZ2VudCBFeGVjdXRhYmxlIChpbnNpZGUgV2ViRHJpdmVyQWdlbnQuYXBwKVxuICBjb25zdHJ1Y3RvciAoYXJncyA9IHt9KSB7XG4gICAgZm9yIChsZXQgcmVxQXJnIG9mIFJFUV9BUkdTKSB7XG4gICAgICBpZiAoXy5pc1VuZGVmaW5lZChhcmdzW3JlcUFyZ10pKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgWW91IG11c3Qgc2VuZCBpbiB0aGUgJyR7cmVxQXJnfScgYXJndW1lbnRgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoYXJncy5hZ2VudFBhdGgpIHtcbiAgICAgIGxvZy5pbmZvKGBDdXN0b20gYWdlbnQgcGF0aCBzcGVjaWZpZWQ6ICR7YXJncy5hZ2VudFBhdGh9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZy5pbmZvKGBVc2luZyBkZWZhdWx0IGFnZW50YCk7XG4gICAgfVxuXG4gICAgdGhpcy5zaW0gPSBhcmdzLnNpbTtcbiAgICB0aGlzLnBsYXRmb3JtVmVyc2lvbiA9IGFyZ3MucGxhdGZvcm1WZXJzaW9uO1xuICAgIHRoaXMuaG9zdCA9IGFyZ3MuaG9zdDtcbiAgICB0aGlzLmFnZW50UGF0aCA9IGFyZ3MuYWdlbnRQYXRoIHx8IHBhdGgucmVzb2x2ZShBR0VOVF9QQVRIKTtcbiAgfVxuXG4gIGFzeW5jIGxhdW5jaCAoc2Vzc2lvbklkKSB7XG4gICAgcmV0dXJuIG5ldyBCKGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGxvZy5pbmZvKFwiTGF1bmNoaW5nIFdlYkRyaXZlckFnZW50IG9uIHRoZSBkZXZpY2VcIik7XG5cbiAgICAgIGlmICghYXdhaXQgZnMuZXhpc3RzKHRoaXMuYWdlbnRQYXRoKSkge1xuICAgICAgICByZWplY3QobmV3IEVycm9yKGBUcnlpbmcgdG8gdXNlIFdlYkRyaXZlckFnZW50IHByb2plY3QgYXQgJHt0aGlzLmFnZW50UGF0aH0gYnV0IHRoZSBgICtcbiAgICAgICAgICAgICAgICAgICAgICAgICBgZmlsZSBkb2VzIG5vdCBleGlzdGApKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnNpbUxvZ3MgPSB0aGlzLmNyZWF0ZVNpbUxvZ3NTdWJQcm9jZXNzKCk7XG4gICAgICB0aGlzLnNpbUxvZ3Mub24oJ291dHB1dCcsIChkLCBlKSA9PiB7XG4gICAgICAgIGlmIChkLmxlbmd0aCAmJiBkLmluZGV4T2YoQUdFTlRfTE9HX1BSRUZJWCkgPiAtMSkge1xuICAgICAgICAgIGFnZW50TG9nLmluZm8oZCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGUubGVuZ3RoICYmIGQuaW5kZXhPZihBR0VOVF9MT0dfUFJFRklYKSA+IC0xKSB7XG4gICAgICAgICAgYWdlbnRMb2cuZXJyb3IoZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdGhpcy5zaW1Mb2dzLm9uKCdleGl0JywgKGNvZGUpID0+IHtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgdGFpbGluZyBvZiBzaW11bGF0b3IgbG9nIGV4aXRlZCB3aXRoIGNvZGUgJHtjb2RlfWApKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSk7XG5cbiAgICAgIHRoaXMueGNvZGVidWlsZCA9IHRoaXMuY3JlYXRlWGNvZGVCdWlsZFN1YlByb2Nlc3MoKTtcbiAgICAgIC8vIHRoaXMueGNvZGVidWlsZC5vbignb3V0cHV0JywgKGQsIGUpID0+IHtcbiAgICAgIC8vICAgbG9nLndhcm4oZCwgZSk7XG4gICAgICAvLyB9KTtcbiAgICAgIHRoaXMueGNvZGVidWlsZC5vbignZXhpdCcsIChjb2RlLCBzaWduYWwpID0+IHtcbiAgICAgICAgbG9nLmluZm8oYHhjb2RlYnVpbGQgZXhpdGVkIHdpdGggY29kZSAke2NvZGV9IGFuZCBzaWduYWwgJHtzaWduYWx9YCk7XG4gICAgICAgIGlmICghc2lnbmFsICYmIGNvZGUgIT09IDApIHtcbiAgICAgICAgICByZWplY3QobmV3IEVycm9yKGB4Y29kZWJ1aWxkIGZhaWxlZCB3aXRoIGNvZGUgJHtjb2RlfWApKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5xdWl0KCk7XG4gICAgICB9KTtcblxuICAgICAgdGhpcy54Y29kZWJ1aWxkLnN0YXJ0KCk7XG5cbiAgICAgIC8vIHdlIGhhdmUgdG8gd2FpdCBmb3IgdGhlIHNpbSB0byBzdGFydCBiZWZvcmUgd2UgY2FuIHRhaWwgdGhlIGxvZyBmaWxlXG4gICAgICBhd2FpdCBzeXN0ZW1Mb2dFeGlzdHModGhpcy5zaW0pO1xuXG4gICAgICBsZXQgYWdlbnRVcmw7XG4gICAgICBsZXQgYWdlbnRTdGFydGVkT25EZXZpY2UgPSB0aGlzLnNpbUxvZ3Muc3RhcnQoKHN0ZG91dCkgPT4ge1xuICAgICAgICBsZXQgbWF0Y2ggPSBBR0VOVF9TVEFSVEVEX1JFR0VYLmV4ZWMoc3Rkb3V0KTtcbiAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgYWdlbnRVcmwgPSBtYXRjaFsxXTtcbiAgICAgICAgICBsb2cuaW5mbyhgZGV0ZWN0ZWQgdGhhdCBXZWJEcml2ZXJBZ2VudCBpcyBydW5uaW5nIGF0IHVybCAke2FnZW50VXJsfWApO1xuICAgICAgICAgIGlmICghYWdlbnRVcmwpIHtcbiAgICAgICAgICAgIGxvZy5lcnJvckFuZFRocm93KG5ldyBFcnJvcignTm8gdXJsIGRldGVjdGVkIGZyb20gV2ViRHJpdmVyQWdlbnQnKSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgbG9nLmluZm8oYFdhaXRpbmcgZm9yIFdlYkRyaXZlckFnZW50IHRvIHN0YXJ0IG9uIGRldmljZWApO1xuICAgICAgYXdhaXQgYWdlbnRTdGFydGVkT25EZXZpY2U7XG4gICAgICBsb2cuaW5mbyhgV2ViRHJpdmVyQWdlbnQgc3RhcnRlZCBhdCB1cmwgJHthZ2VudFVybH1gKTtcblxuICAgICAgdGhpcy51cmwgPSB1cmwucGFyc2UoYWdlbnRVcmwpO1xuXG4gICAgICB0aGlzLmp3cHJveHkgPSBuZXcgSldQcm94eSh7aG9zdDogdGhpcy51cmwuaG9zdG5hbWUsIHBvcnQ6IHRoaXMudXJsLnBvcnQsIGJhc2U6ICcnfSk7XG4gICAgICB0aGlzLmp3cHJveHkuc2Vzc2lvbklkID0gc2Vzc2lvbklkO1xuICAgICAgdGhpcy5wcm94eVJlcVJlcyA9IHRoaXMuandwcm94eS5wcm94eVJlcVJlcy5iaW5kKHRoaXMuandwcm94eSk7XG5cbiAgICAgIHJldHVybiByZXNvbHZlKHVybCk7XG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVYY29kZUJ1aWxkU3ViUHJvY2VzcyAoKSB7XG5cbiAgICBsZXQgYXJncyA9IFtcbiAgICAgICctd29ya3NwYWNlJyxcbiAgICAgIHRoaXMuYWdlbnRQYXRoLFxuICAgICAgJy1zY2hlbWUnLFxuICAgICAgJ1hDVFVJVGVzdFJ1bm5lcicsXG4gICAgICAnLWRlc3RpbmF0aW9uJyxcbiAgICAgIGBpZD0ke3RoaXMuc2ltLnVkaWR9YCxcbiAgICAgICd0ZXN0J1xuICAgIF07XG5cbiAgICByZXR1cm4gbmV3IFN1YlByb2Nlc3MoJ3hjb2RlYnVpbGQnLCBhcmdzKTtcbiAgfVxuXG4gIGNyZWF0ZVNpbUxvZ3NTdWJQcm9jZXNzICgpIHtcblxuICAgIGxldCBhcmdzID0gW1xuICAgICAgJy1mJyxcbiAgICAgICctbicsXG4gICAgICAnMCcsXG4gICAgICBwYXRoLnJlc29sdmUodGhpcy5zaW0uZ2V0TG9nRGlyKCksICdzeXN0ZW0ubG9nJylcbiAgICBdO1xuXG4gICAgcmV0dXJuIG5ldyBTdWJQcm9jZXNzKCd0YWlsJywgYXJncyk7XG4gIH1cblxuICBhc3luYyBxdWl0ICgpIHtcbiAgICBsb2cuaW5mbygnU2h1dHRpbmcgZG93biBXZWJEcml2ZXJBZ2VudCcpO1xuICAgIGxldCBzdG9wcyA9IFtdO1xuICAgIGlmICh0aGlzLnhjb2RlYnVpbGQgJiYgdGhpcy54Y29kZWJ1aWxkLnByb2MpIHtcbiAgICAgIHN0b3BzLnB1c2godGhpcy54Y29kZWJ1aWxkLnN0b3AoKSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnNpbUxvZ3MgJiYgdGhpcy5zaW1Mb2dzLnByb2MpIHtcbiAgICAgIHN0b3BzLnB1c2godGhpcy5zaW1Mb2dzLnN0b3AoKSk7XG4gICAgfVxuXG4gICAgdGhpcy5qd3Byb3h5LnNlc3Npb25JZCA9IG51bGw7XG5cbiAgICBhd2FpdCBCLmFsbChzdG9wcyk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgV2ViRHJpdmVyQWdlbnQ7XG4iXX0=