appium-uiautomator
Version:
Appium Android UI Automator interface
224 lines (175 loc) • 15.7 kB
JavaScript
;
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 _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
Object.defineProperty(exports, '__esModule', {
value: true
});
var _events = require('events');
var _events2 = _interopRequireDefault(_events);
var _appiumSupport = require('appium-support');
var log = _appiumSupport.logger.getLogger('UiAutomator');
var UiAutomator = (function (_events$EventEmitter) {
_inherits(UiAutomator, _events$EventEmitter);
function UiAutomator(adb) {
_classCallCheck(this, UiAutomator);
if (!adb) {
log.errorAndThrow("adb is required to instantiate UiAutomator");
}
_get(Object.getPrototypeOf(UiAutomator.prototype), 'constructor', this).call(this);
this.adb = adb;
this.tempPath = "/data/local/tmp/";
}
_createClass(UiAutomator, [{
key: 'start',
value: function start(uiAutomatorBinaryPath, className, startDetector) {
var processIsAlive,
jarName,
_len,
extraParams,
_key,
args,
args$2$0 = arguments;
return _regeneratorRuntime.async(function start$(context$2$0) {
var _this = this;
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
processIsAlive = undefined;
context$2$0.prev = 1;
log.debug("Starting UiAutomator");
this.changeState(UiAutomator.STATE_STARTING);
log.debug("Parsing uiautomator jar");
// expecting a path like /ads/ads/foo.jar or \asd\asd\foo.jar
jarName = this.parseJarNameFromPath(uiAutomatorBinaryPath);
context$2$0.next = 8;
return _regeneratorRuntime.awrap(this.adb.push(uiAutomatorBinaryPath, this.tempPath));
case 8:
context$2$0.next = 10;
return _regeneratorRuntime.awrap(this.killUiAutomatorOnDevice());
case 10:
log.debug('Starting UIAutomator');
for (_len = args$2$0.length, extraParams = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
extraParams[_key - 3] = args$2$0[_key];
}
args = ["shell", "uiautomator", "runtest", jarName, "-c", className].concat(extraParams);
this.proc = this.adb.createSubProcess(args);
// handle out-of-bound exit by simply emitting a stopped state
this.proc.on('exit', function (code, signal) {
processIsAlive = false;
// cleanup
if (_this.state !== UiAutomator.STATE_STOPPED && _this.state !== UiAutomator.STATE_STOPPING) {
var msg = 'UiAutomator exited unexpectedly with code ' + code + ', ' + ('signal ' + signal);
log.error(msg);
} else if (_this.state === UiAutomator.STATE_STOPPING) {
log.debug("UiAutomator shut down normally");
}
_this.changeState(UiAutomator.STATE_STOPPED);
});
context$2$0.next = 17;
return _regeneratorRuntime.awrap(this.proc.start(startDetector));
case 17:
processIsAlive = true;
this.changeState(UiAutomator.STATE_ONLINE);
return context$2$0.abrupt('return', this.proc);
case 22:
context$2$0.prev = 22;
context$2$0.t0 = context$2$0['catch'](1);
this.emit(UiAutomator.EVENT_ERROR, context$2$0.t0);
if (!processIsAlive) {
context$2$0.next = 30;
break;
}
context$2$0.next = 28;
return _regeneratorRuntime.awrap(this.killUiAutomatorOnDevice());
case 28:
context$2$0.next = 30;
return _regeneratorRuntime.awrap(this.proc.stop());
case 30:
log.errorAndThrow(context$2$0.t0);
case 31:
case 'end':
return context$2$0.stop();
}
}, null, this, [[1, 22]]);
}
}, {
key: 'shutdown',
value: function shutdown() {
return _regeneratorRuntime.async(function shutdown$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
log.debug('Shutting down UiAutomator');
if (!(this.state !== UiAutomator.STATE_STOPPED)) {
context$2$0.next = 5;
break;
}
this.changeState(UiAutomator.STATE_STOPPING);
context$2$0.next = 5;
return _regeneratorRuntime.awrap(this.proc.stop());
case 5:
context$2$0.next = 7;
return _regeneratorRuntime.awrap(this.killUiAutomatorOnDevice());
case 7:
this.changeState(UiAutomator.STATE_STOPPED);
case 8:
case 'end':
return context$2$0.stop();
}
}, null, this);
}
}, {
key: 'parseJarNameFromPath',
value: function parseJarNameFromPath(binaryPath) {
var reTest = /.*(\/|\\)(.*\.jar)/.exec(binaryPath);
if (!reTest) {
throw new Error('Unable to parse jar name from ' + binaryPath);
}
var jarName = reTest[2];
log.debug('Found jar name: \'' + jarName + '\'');
return jarName;
}
}, {
key: 'changeState',
value: function changeState(state) {
log.debug('Moving to state \'' + state + '\'');
this.state = state;
this.emit(UiAutomator.EVENT_CHANGED, { state: state });
}
}, {
key: 'killUiAutomatorOnDevice',
value: function killUiAutomatorOnDevice() {
return _regeneratorRuntime.async(function killUiAutomatorOnDevice$(context$2$0) {
while (1) switch (context$2$0.prev = context$2$0.next) {
case 0:
context$2$0.prev = 0;
context$2$0.next = 3;
return _regeneratorRuntime.awrap(this.adb.killProcessesByName('uiautomator'));
case 3:
context$2$0.next = 8;
break;
case 5:
context$2$0.prev = 5;
context$2$0.t0 = context$2$0['catch'](0);
log.warn('Error while killing uiAutomator: ' + context$2$0.t0);
case 8:
case 'end':
return context$2$0.stop();
}
}, null, this, [[0, 5]]);
}
}]);
return UiAutomator;
})(_events2['default'].EventEmitter);
UiAutomator.EVENT_ERROR = 'uiautomator_error';
UiAutomator.EVENT_CHANGED = 'stateChanged';
UiAutomator.STATE_STOPPED = 'stopped';
UiAutomator.STATE_STARTING = 'starting';
UiAutomator.STATE_ONLINE = 'online';
UiAutomator.STATE_STOPPING = 'stopping';
exports['default'] = UiAutomator;
module.exports = exports['default'];
// killing any uiautomator existing processes
//# sourceMappingURL=data:application/json;charset=utf8;base64,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QXpGRyxXQUFXO0dBQVMsb0JBQU8sWUFBWTs7QUE2RjdDLFdBQVcsQ0FBQyxXQUFXLEdBQUcsbUJBQW1CLENBQUM7QUFDOUMsV0FBVyxDQUFDLGFBQWEsR0FBRyxjQUFjLENBQUM7QUFDM0MsV0FBVyxDQUFDLGFBQWEsR0FBRyxTQUFTLENBQUM7QUFDdEMsV0FBVyxDQUFDLGNBQWMsR0FBRyxVQUFVLENBQUM7QUFDeEMsV0FBVyxDQUFDLFlBQVksR0FBRyxRQUFRLENBQUM7QUFDcEMsV0FBVyxDQUFDLGNBQWMsR0FBRyxVQUFVLENBQUM7O3FCQUV6QixXQUFXIiwiZmlsZSI6ImxpYi91aWF1dG9tYXRvci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBldmVudHMgZnJvbSAnZXZlbnRzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJ2FwcGl1bS1zdXBwb3J0JztcblxuXG5jb25zdCBsb2cgPSBsb2dnZXIuZ2V0TG9nZ2VyKCdVaUF1dG9tYXRvcicpO1xuXG5jbGFzcyBVaUF1dG9tYXRvciBleHRlbmRzIGV2ZW50cy5FdmVudEVtaXR0ZXIge1xuICBjb25zdHJ1Y3RvciAoYWRiKSB7XG4gICAgaWYgKCFhZGIpIHtcbiAgICAgIGxvZy5lcnJvckFuZFRocm93KFwiYWRiIGlzIHJlcXVpcmVkIHRvIGluc3RhbnRpYXRlIFVpQXV0b21hdG9yXCIpO1xuICAgIH1cbiAgICBzdXBlcigpO1xuICAgIHRoaXMuYWRiID0gYWRiO1xuICAgIHRoaXMudGVtcFBhdGggPSBcIi9kYXRhL2xvY2FsL3RtcC9cIjtcbiAgfVxuXG4gIGFzeW5jIHN0YXJ0ICh1aUF1dG9tYXRvckJpbmFyeVBhdGgsIGNsYXNzTmFtZSwgc3RhcnREZXRlY3RvciwgLi4uZXh0cmFQYXJhbXMpIHtcbiAgICBsZXQgcHJvY2Vzc0lzQWxpdmU7XG4gICAgdHJ5IHtcbiAgICAgIGxvZy5kZWJ1ZyhcIlN0YXJ0aW5nIFVpQXV0b21hdG9yXCIpO1xuICAgICAgdGhpcy5jaGFuZ2VTdGF0ZShVaUF1dG9tYXRvci5TVEFURV9TVEFSVElORyk7XG5cbiAgICAgIGxvZy5kZWJ1ZyhcIlBhcnNpbmcgdWlhdXRvbWF0b3IgamFyXCIpO1xuICAgICAgLy8gZXhwZWN0aW5nIGEgcGF0aCBsaWtlIC9hZHMvYWRzL2Zvby5qYXIgb3IgXFxhc2RcXGFzZFxcZm9vLmphclxuICAgICAgbGV0IGphck5hbWUgPSB0aGlzLnBhcnNlSmFyTmFtZUZyb21QYXRoKHVpQXV0b21hdG9yQmluYXJ5UGF0aCk7XG4gICAgICBhd2FpdCB0aGlzLmFkYi5wdXNoKHVpQXV0b21hdG9yQmluYXJ5UGF0aCwgdGhpcy50ZW1wUGF0aCk7XG5cbiAgICAgIC8vIGtpbGxpbmcgYW55IHVpYXV0b21hdG9yIGV4aXN0aW5nIHByb2Nlc3Nlc1xuICAgICAgYXdhaXQgdGhpcy5raWxsVWlBdXRvbWF0b3JPbkRldmljZSgpO1xuXG4gICAgICBsb2cuZGVidWcoJ1N0YXJ0aW5nIFVJQXV0b21hdG9yJyk7XG4gICAgICBsZXQgYXJncyA9IFtcInNoZWxsXCIsIFwidWlhdXRvbWF0b3JcIiwgXCJydW50ZXN0XCIsIGphck5hbWUsIFwiLWNcIiwgY2xhc3NOYW1lLCAuLi5leHRyYVBhcmFtc107XG4gICAgICB0aGlzLnByb2MgPSB0aGlzLmFkYi5jcmVhdGVTdWJQcm9jZXNzKGFyZ3MpO1xuXG4gICAgICAvLyBoYW5kbGUgb3V0LW9mLWJvdW5kIGV4aXQgYnkgc2ltcGx5IGVtaXR0aW5nIGEgc3RvcHBlZCBzdGF0ZVxuICAgICAgdGhpcy5wcm9jLm9uKCdleGl0JywgKGNvZGUsIHNpZ25hbCkgPT4ge1xuICAgICAgICBwcm9jZXNzSXNBbGl2ZSA9IGZhbHNlO1xuICAgICAgICAvLyBjbGVhbnVwXG4gICAgICAgIGlmICh0aGlzLnN0YXRlICE9PSBVaUF1dG9tYXRvci5TVEFURV9TVE9QUEVEICYmXG4gICAgICAgICAgICB0aGlzLnN0YXRlICE9PSBVaUF1dG9tYXRvci5TVEFURV9TVE9QUElORykge1xuICAgICAgICAgIGxldCBtc2cgPSBgVWlBdXRvbWF0b3IgZXhpdGVkIHVuZXhwZWN0ZWRseSB3aXRoIGNvZGUgJHtjb2RlfSwgYCArXG4gICAgICAgICAgICAgICAgICAgIGBzaWduYWwgJHtzaWduYWx9YDtcbiAgICAgICAgICBsb2cuZXJyb3IobXNnKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnN0YXRlID09PSBVaUF1dG9tYXRvci5TVEFURV9TVE9QUElORykge1xuICAgICAgICAgIGxvZy5kZWJ1ZyhcIlVpQXV0b21hdG9yIHNodXQgZG93biBub3JtYWxseVwiKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNoYW5nZVN0YXRlKFVpQXV0b21hdG9yLlNUQVRFX1NUT1BQRUQpO1xuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHRoaXMucHJvYy5zdGFydChzdGFydERldGVjdG9yKTtcbiAgICAgIHByb2Nlc3NJc0FsaXZlID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2hhbmdlU3RhdGUoVWlBdXRvbWF0b3IuU1RBVEVfT05MSU5FKTtcbiAgICAgIHJldHVybiB0aGlzLnByb2M7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5lbWl0KFVpQXV0b21hdG9yLkVWRU5UX0VSUk9SLCBlKTtcbiAgICAgIGlmIChwcm9jZXNzSXNBbGl2ZSkge1xuICAgICAgICBhd2FpdCB0aGlzLmtpbGxVaUF1dG9tYXRvck9uRGV2aWNlKCk7XG4gICAgICAgIGF3YWl0IHRoaXMucHJvYy5zdG9wKCk7XG4gICAgICB9XG4gICAgICBsb2cuZXJyb3JBbmRUaHJvdyhlKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBzaHV0ZG93biAoKSB7XG4gICAgbG9nLmRlYnVnKCdTaHV0dGluZyBkb3duIFVpQXV0b21hdG9yJyk7XG4gICAgaWYgKHRoaXMuc3RhdGUgIT09IFVpQXV0b21hdG9yLlNUQVRFX1NUT1BQRUQpIHtcbiAgICAgIHRoaXMuY2hhbmdlU3RhdGUoVWlBdXRvbWF0b3IuU1RBVEVfU1RPUFBJTkcpO1xuICAgICAgYXdhaXQgdGhpcy5wcm9jLnN0b3AoKTtcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5raWxsVWlBdXRvbWF0b3JPbkRldmljZSgpO1xuICAgIHRoaXMuY2hhbmdlU3RhdGUoVWlBdXRvbWF0b3IuU1RBVEVfU1RPUFBFRCk7XG4gIH1cblxuICBwYXJzZUphck5hbWVGcm9tUGF0aCAoYmluYXJ5UGF0aCkge1xuICAgIGxldCByZVRlc3QgPSAvLiooXFwvfFxcXFwpKC4qXFwuamFyKS8uZXhlYyhiaW5hcnlQYXRoKTtcbiAgICBpZiAoIXJlVGVzdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gcGFyc2UgamFyIG5hbWUgZnJvbSAke2JpbmFyeVBhdGh9YCk7XG4gICAgfVxuICAgIGxldCBqYXJOYW1lID0gcmVUZXN0WzJdO1xuICAgIGxvZy5kZWJ1ZyhgRm91bmQgamFyIG5hbWU6ICcke2phck5hbWV9J2ApO1xuICAgIHJldHVybiBqYXJOYW1lO1xuICB9XG5cbiAgY2hhbmdlU3RhdGUgKHN0YXRlKSB7XG4gICAgbG9nLmRlYnVnKGBNb3ZpbmcgdG8gc3RhdGUgJyR7c3RhdGV9J2ApO1xuICAgIHRoaXMuc3RhdGUgPSBzdGF0ZTtcbiAgICB0aGlzLmVtaXQoVWlBdXRvbWF0b3IuRVZFTlRfQ0hBTkdFRCwge3N0YXRlfSk7XG4gIH1cblxuICBhc3luYyBraWxsVWlBdXRvbWF0b3JPbkRldmljZSAoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuYWRiLmtpbGxQcm9jZXNzZXNCeU5hbWUoJ3VpYXV0b21hdG9yJyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbG9nLndhcm4oYEVycm9yIHdoaWxlIGtpbGxpbmcgdWlBdXRvbWF0b3I6ICR7ZX1gKTtcbiAgICB9XG4gIH1cblxufVxuXG5VaUF1dG9tYXRvci5FVkVOVF9FUlJPUiA9ICd1aWF1dG9tYXRvcl9lcnJvcic7XG5VaUF1dG9tYXRvci5FVkVOVF9DSEFOR0VEID0gJ3N0YXRlQ2hhbmdlZCc7XG5VaUF1dG9tYXRvci5TVEFURV9TVE9QUEVEID0gJ3N0b3BwZWQnO1xuVWlBdXRvbWF0b3IuU1RBVEVfU1RBUlRJTkcgPSAnc3RhcnRpbmcnO1xuVWlBdXRvbWF0b3IuU1RBVEVfT05MSU5FID0gJ29ubGluZSc7XG5VaUF1dG9tYXRvci5TVEFURV9TVE9QUElORyA9ICdzdG9wcGluZyc7XG5cbmV4cG9ydCBkZWZhdWx0IFVpQXV0b21hdG9yO1xuIl0sInNvdXJjZVJvb3QiOiIuLi8uLiJ9