appium-webdriveragent-driver
Version:
Appium driver for WebDriverAgent
258 lines (198 loc) • 20.6 kB
JavaScript
;
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=