appium
Version:
Automation for Apps.
688 lines (561 loc) • 53.6 kB
JavaScript
require('source-map-support').install();
'use strict';
var _slicedToArray = require('babel-runtime/helpers/sliced-to-array')['default'];
var _regeneratorRuntime = require('babel-runtime/regenerator')['default'];
var _getIterator = require('babel-runtime/core-js/get-iterator')['default'];
var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
var _this = this;
var _libAppium = require('../lib/appium');
var _appiumFakeDriver = require('appium-fake-driver');
var _helpers = require('./helpers');
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _sinon = require('sinon');
var _sinon2 = _interopRequireDefault(_sinon);
var _chai = require('chai');
var _chai2 = _interopRequireDefault(_chai);
var _chaiAsPromised = require('chai-as-promised');
var _chaiAsPromised2 = _interopRequireDefault(_chaiAsPromised);
var _appiumXcuitestDriver = require('appium-xcuitest-driver');
var _appiumIosDriver = require('appium-ios-driver');
var _asyncbox = require('asyncbox');
_chai2['default'].should();
_chai2['default'].use(_chaiAsPromised2['default']);
var BASE_CAPS = { platformName: 'Fake', deviceName: 'Fake', app: _helpers.TEST_FAKE_APP };
var SESSION_ID = 1;
describe('AppiumDriver', function () {
describe('getAppiumRouter', function () {
it('should return a route configuring function', function callee$2$0() {
var routeConfiguringFunction;
return _regeneratorRuntime.async(function callee$2$0$(context$3$0) {
while (1) switch (context$3$0.prev = context$3$0.next) {
case 0:
routeConfiguringFunction = (0, _libAppium.getAppiumRouter)({});
routeConfiguringFunction.should.be.a['function'];
case 2:
case 'end':
return context$3$0.stop();
}
}, null, _this);
});
});
describe('AppiumDriver', function () {
function getDriverAndFakeDriver() {
var appium = new _libAppium.AppiumDriver({});
var fakeDriver = new _appiumFakeDriver.FakeDriver();
var mockFakeDriver = _sinon2['default'].mock(fakeDriver);
appium.getDriverForCaps = function () /*args*/{
return function () {
return fakeDriver;
};
};
return [appium, mockFakeDriver];
}
describe('createSession', function () {
var appium = undefined;
var mockFakeDriver = undefined;
beforeEach(function () {
var _getDriverAndFakeDriver = getDriverAndFakeDriver();
var _getDriverAndFakeDriver2 = _slicedToArray(_getDriverAndFakeDriver, 2);
appium = _getDriverAndFakeDriver2[0];
mockFakeDriver = _getDriverAndFakeDriver2[1];
});
afterEach(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:
mockFakeDriver.restore();
context$4$0.next = 3;
return _regeneratorRuntime.awrap(appium.deleteSession(SESSION_ID));
case 3:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
it('should call inner driver\'s createSession with desired capabilities', 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:
mockFakeDriver.expects("createSession").once().withExactArgs(BASE_CAPS, undefined, []).returns([SESSION_ID, BASE_CAPS]);
context$4$0.next = 3;
return _regeneratorRuntime.awrap(appium.createSession(BASE_CAPS));
case 3:
mockFakeDriver.verify();
case 4:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
it('should call inner driver\'s createSession with desired and default capabilities', function callee$3$0() {
var defaultCaps, allCaps;
return _regeneratorRuntime.async(function callee$3$0$(context$4$0) {
while (1) switch (context$4$0.prev = context$4$0.next) {
case 0:
defaultCaps = { deviceName: 'Emulator' }, allCaps = _lodash2['default'].extend(_lodash2['default'].clone(defaultCaps), BASE_CAPS);
appium.args.defaultCapabilities = defaultCaps;
mockFakeDriver.expects("createSession").once().withArgs(allCaps).returns([SESSION_ID, allCaps]);
context$4$0.next = 5;
return _regeneratorRuntime.awrap(appium.createSession(BASE_CAPS));
case 5:
mockFakeDriver.verify();
case 6:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
it('should call inner driver\'s createSession with desired and default capabilities without overriding caps', function callee$3$0() {
var defaultCaps;
return _regeneratorRuntime.async(function callee$3$0$(context$4$0) {
while (1) switch (context$4$0.prev = context$4$0.next) {
case 0:
defaultCaps = { platformName: 'Ersatz' };
appium.args.defaultCapabilities = defaultCaps;
mockFakeDriver.expects("createSession").once().withArgs(BASE_CAPS).returns([SESSION_ID, BASE_CAPS]);
context$4$0.next = 5;
return _regeneratorRuntime.awrap(appium.createSession(BASE_CAPS));
case 5:
mockFakeDriver.verify();
case 6:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
it('should kill all other sessions if sessionOverride is on', function callee$3$0() {
var fakeDrivers, mockFakeDrivers, sessions, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, mfd;
return _regeneratorRuntime.async(function callee$3$0$(context$4$0) {
while (1) switch (context$4$0.prev = context$4$0.next) {
case 0:
appium.args.sessionOverride = true;
// mock three sessions that should be removed when the new one is created
fakeDrivers = [new _appiumFakeDriver.FakeDriver(), new _appiumFakeDriver.FakeDriver(), new _appiumFakeDriver.FakeDriver()];
mockFakeDrivers = _lodash2['default'].map(fakeDrivers, function (fd) {
return _sinon2['default'].mock(fd);
});
mockFakeDrivers[0].expects('deleteSession').once();
mockFakeDrivers[1].expects('deleteSession').once().throws('Cannot shut down Android driver; it has already shut down');
mockFakeDrivers[2].expects('deleteSession').once();
appium.sessions['abc-123-xyz'] = fakeDrivers[0];
appium.sessions['xyz-321-abc'] = fakeDrivers[1];
appium.sessions['123-abc-xyz'] = fakeDrivers[2];
context$4$0.next = 11;
return _regeneratorRuntime.awrap(appium.getSessions());
case 11:
sessions = context$4$0.sent;
sessions.should.have.length(3);
mockFakeDriver.expects("createSession").once().withExactArgs(BASE_CAPS, undefined, []).returns([SESSION_ID, BASE_CAPS]);
context$4$0.next = 16;
return _regeneratorRuntime.awrap(appium.createSession(BASE_CAPS));
case 16:
context$4$0.next = 18;
return _regeneratorRuntime.awrap(appium.getSessions());
case 18:
sessions = context$4$0.sent;
sessions.should.have.length(1);
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
context$4$0.prev = 23;
for (_iterator = _getIterator(mockFakeDrivers); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
mfd = _step.value;
mfd.verify();
}
context$4$0.next = 31;
break;
case 27:
context$4$0.prev = 27;
context$4$0.t0 = context$4$0['catch'](23);
_didIteratorError = true;
_iteratorError = context$4$0.t0;
case 31:
context$4$0.prev = 31;
context$4$0.prev = 32;
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
case 34:
context$4$0.prev = 34;
if (!_didIteratorError) {
context$4$0.next = 37;
break;
}
throw _iteratorError;
case 37:
return context$4$0.finish(34);
case 38:
return context$4$0.finish(31);
case 39:
mockFakeDriver.verify();
case 40:
case 'end':
return context$4$0.stop();
}
}, null, _this, [[23, 27, 31, 39], [32,, 34, 38]]);
});
});
describe('deleteSession', function () {
var appium = undefined;
var mockFakeDriver = undefined;
beforeEach(function () {
var _getDriverAndFakeDriver3 = getDriverAndFakeDriver();
var _getDriverAndFakeDriver32 = _slicedToArray(_getDriverAndFakeDriver3, 2);
appium = _getDriverAndFakeDriver32[0];
mockFakeDriver = _getDriverAndFakeDriver32[1];
});
afterEach(function () {
mockFakeDriver.restore();
});
it('should remove the session if it is found', function callee$3$0() {
var _ref, _ref2, sessionId, sessions;
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.next = 2;
return _regeneratorRuntime.awrap(appium.createSession(BASE_CAPS));
case 2:
_ref = context$4$0.sent;
_ref2 = _slicedToArray(_ref, 1);
sessionId = _ref2[0];
context$4$0.next = 7;
return _regeneratorRuntime.awrap(appium.getSessions());
case 7:
sessions = context$4$0.sent;
sessions.should.have.length(1);
context$4$0.next = 11;
return _regeneratorRuntime.awrap(appium.deleteSession(sessionId));
case 11:
context$4$0.next = 13;
return _regeneratorRuntime.awrap(appium.getSessions());
case 13:
sessions = context$4$0.sent;
sessions.should.have.length(0);
case 15:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
it('should call inner driver\'s deleteSession method', function callee$3$0() {
var _ref3, _ref32, sessionId;
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.next = 2;
return _regeneratorRuntime.awrap(appium.createSession(BASE_CAPS));
case 2:
_ref3 = context$4$0.sent;
_ref32 = _slicedToArray(_ref3, 1);
sessionId = _ref32[0];
mockFakeDriver.expects("deleteSession").once().withExactArgs(sessionId, []).returns();
context$4$0.next = 8;
return _regeneratorRuntime.awrap(appium.deleteSession(sessionId));
case 8:
mockFakeDriver.verify();
// cleanup, since we faked the delete session call
context$4$0.next = 11;
return _regeneratorRuntime.awrap(mockFakeDriver.object.deleteSession());
case 11:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
});
describe('getSessions', function () {
var appium = undefined;
var sessions = undefined;
before(function () {
appium = new _libAppium.AppiumDriver({});
});
afterEach(function callee$3$0() {
var _iteratorNormalCompletion2, _didIteratorError2, _iteratorError2, _iterator2, _step2, session;
return _regeneratorRuntime.async(function callee$3$0$(context$4$0) {
while (1) switch (context$4$0.prev = context$4$0.next) {
case 0:
_iteratorNormalCompletion2 = true;
_didIteratorError2 = false;
_iteratorError2 = undefined;
context$4$0.prev = 3;
_iterator2 = _getIterator(sessions);
case 5:
if (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done) {
context$4$0.next = 12;
break;
}
session = _step2.value;
context$4$0.next = 9;
return _regeneratorRuntime.awrap(appium.deleteSession(session.id));
case 9:
_iteratorNormalCompletion2 = true;
context$4$0.next = 5;
break;
case 12:
context$4$0.next = 18;
break;
case 14:
context$4$0.prev = 14;
context$4$0.t0 = context$4$0['catch'](3);
_didIteratorError2 = true;
_iteratorError2 = context$4$0.t0;
case 18:
context$4$0.prev = 18;
context$4$0.prev = 19;
if (!_iteratorNormalCompletion2 && _iterator2['return']) {
_iterator2['return']();
}
case 21:
context$4$0.prev = 21;
if (!_didIteratorError2) {
context$4$0.next = 24;
break;
}
throw _iteratorError2;
case 24:
return context$4$0.finish(21);
case 25:
return context$4$0.finish(18);
case 26:
case 'end':
return context$4$0.stop();
}
}, null, _this, [[3, 14, 18, 26], [19,, 21, 25]]);
});
it('should return an empty array of sessions', 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.next = 2;
return _regeneratorRuntime.awrap(appium.getSessions());
case 2:
sessions = context$4$0.sent;
sessions.should.be.an.array;
sessions.should.be.empty;
case 5:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
it('should return sessions created', function callee$3$0() {
var session1, session2;
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.next = 2;
return _regeneratorRuntime.awrap(appium.createSession(_lodash2['default'].extend(_lodash2['default'].clone(BASE_CAPS), { cap: 'value' })));
case 2:
session1 = context$4$0.sent;
context$4$0.next = 5;
return _regeneratorRuntime.awrap(appium.createSession(_lodash2['default'].extend(_lodash2['default'].clone(BASE_CAPS), { cap: 'other value' })));
case 5:
session2 = context$4$0.sent;
context$4$0.next = 8;
return _regeneratorRuntime.awrap(appium.getSessions());
case 8:
sessions = context$4$0.sent;
sessions.should.be.an.array;
sessions.should.have.length(2);
sessions[0].id.should.equal(session1[0]);
sessions[0].capabilities.should.eql(session1[1]);
sessions[1].id.should.equal(session2[0]);
sessions[1].capabilities.should.eql(session2[1]);
case 15:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
});
describe('getStatus', function () {
var appium = undefined;
before(function () {
appium = new _libAppium.AppiumDriver({});
});
it('should return a status', function callee$3$0() {
var status;
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.next = 2;
return _regeneratorRuntime.awrap(appium.getStatus());
case 2:
status = context$4$0.sent;
status.build.should.exist;
status.build.version.should.exist;
case 5:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
});
describe('sessionExists', function () {});
describe('attachUnexpectedShutdownHandler', function () {
var appium = undefined,
mockFakeDriver = undefined;
beforeEach(function () {
var _getDriverAndFakeDriver4 = getDriverAndFakeDriver();
var _getDriverAndFakeDriver42 = _slicedToArray(_getDriverAndFakeDriver4, 2);
appium = _getDriverAndFakeDriver42[0];
mockFakeDriver = _getDriverAndFakeDriver42[1];
});
afterEach(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.next = 2;
return _regeneratorRuntime.awrap(mockFakeDriver.object.deleteSession());
case 2:
mockFakeDriver.restore();
appium.args.defaultCapabilities = {};
case 4:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
it('should remove session if inner driver unexpectedly exits with an error', function callee$3$0() {
var _ref4, _ref42, sessionId;
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.next = 2;
return _regeneratorRuntime.awrap(appium.createSession(_lodash2['default'].clone(BASE_CAPS)));
case 2:
_ref4 = context$4$0.sent;
_ref42 = _slicedToArray(_ref4, 1);
sessionId = _ref42[0];
// eslint-disable-line comma-spacing
_lodash2['default'].keys(appium.sessions).should.contain(sessionId);
appium.sessions[sessionId].unexpectedShutdownDeferred.reject(new Error("Oops"));
// let event loop spin so rejection is handled
context$4$0.next = 9;
return _regeneratorRuntime.awrap((0, _asyncbox.sleep)(1));
case 9:
_lodash2['default'].keys(appium.sessions).should.not.contain(sessionId);
case 10:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
it('should remove session if inner driver unexpectedly exits with no error', function callee$3$0() {
var _ref5, _ref52, sessionId;
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.next = 2;
return _regeneratorRuntime.awrap(appium.createSession(_lodash2['default'].clone(BASE_CAPS)));
case 2:
_ref5 = context$4$0.sent;
_ref52 = _slicedToArray(_ref5, 1);
sessionId = _ref52[0];
// eslint-disable-line comma-spacing
_lodash2['default'].keys(appium.sessions).should.contain(sessionId);
appium.sessions[sessionId].unexpectedShutdownDeferred.resolve();
// let event loop spin so rejection is handled
context$4$0.next = 9;
return _regeneratorRuntime.awrap((0, _asyncbox.sleep)(1));
case 9:
_lodash2['default'].keys(appium.sessions).should.not.contain(sessionId);
case 10:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
it('should not remove session if inner driver cancels unexpected exit', function callee$3$0() {
var _ref6, _ref62, sessionId;
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.next = 2;
return _regeneratorRuntime.awrap(appium.createSession(_lodash2['default'].clone(BASE_CAPS)));
case 2:
_ref6 = context$4$0.sent;
_ref62 = _slicedToArray(_ref6, 1);
sessionId = _ref62[0];
// eslint-disable-line comma-spacing
_lodash2['default'].keys(appium.sessions).should.contain(sessionId);
appium.sessions[sessionId].onUnexpectedShutdown.cancel();
// let event loop spin so rejection is handled
context$4$0.next = 9;
return _regeneratorRuntime.awrap((0, _asyncbox.sleep)(1));
case 9:
_lodash2['default'].keys(appium.sessions).should.contain(sessionId);
case 10:
case 'end':
return context$4$0.stop();
}
}, null, _this);
});
});
describe('getDriverForCaps', function () {
it('should not blow up if user does not provide platformName', function () {
var appium = new _libAppium.AppiumDriver({});
(function () {
appium.getDriverForCaps({});
}).should['throw'](/platformName/);
});
it('should get XCUITestDriver driver for automationName of XCUITest', function () {
var appium = new _libAppium.AppiumDriver({});
var driver = appium.getDriverForCaps({
platformName: 'iOS',
automationName: 'XCUITest'
});
driver.should.be.an['instanceof'](Function);
driver.should.equal(_appiumXcuitestDriver.XCUITestDriver);
});
it('should get iosdriver for ios < 10', function () {
var appium = new _libAppium.AppiumDriver({});
var caps = {
platformName: 'iOS',
platformVersion: '8.0'
};
var driver = appium.getDriverForCaps(caps);
driver.should.be.an['instanceof'](Function);
driver.should.equal(_appiumIosDriver.IosDriver);
caps.platformVersion = '8.1';
driver = appium.getDriverForCaps(caps);
driver.should.equal(_appiumIosDriver.IosDriver);
caps.platformVersion = '9.4';
driver = appium.getDriverForCaps(caps);
driver.should.equal(_appiumIosDriver.IosDriver);
caps.platformVersion = '';
driver = appium.getDriverForCaps(caps);
driver.should.equal(_appiumIosDriver.IosDriver);
caps.platformVersion = 'foo';
driver = appium.getDriverForCaps(caps);
driver.should.equal(_appiumIosDriver.IosDriver);
delete caps.platformVersion;
driver = appium.getDriverForCaps(caps);
driver.should.equal(_appiumIosDriver.IosDriver);
});
it('should get xcuitestdriver for ios >= 10', function () {
var appium = new _libAppium.AppiumDriver({});
var caps = {
platformName: 'iOS',
platformVersion: '10'
};
var driver = appium.getDriverForCaps(caps);
driver.should.be.an['instanceof'](Function);
driver.should.equal(_appiumXcuitestDriver.XCUITestDriver);
caps.platformVersion = '10.0';
driver = appium.getDriverForCaps(caps);
driver.should.equal(_appiumXcuitestDriver.XCUITestDriver);
caps.platformVersion = '10.1';
driver = appium.getDriverForCaps(caps);
driver.should.equal(_appiumXcuitestDriver.XCUITestDriver);
caps.platformVersion = '12.14';
driver = appium.getDriverForCaps(caps);
driver.should.equal(_appiumXcuitestDriver.XCUITestDriver);
});
});
});
});
// a default capability with the same key as a desired capability
// should do nothing
//# sourceMappingURL=data:application/json;charset=utf8;base64,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WUFBSSxDQUFDLGVBQWUsR0FBRyxNQUFNLENBQUM7QUFDOUIsY0FBTSxHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUN2QyxjQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssc0NBQWdCLENBQUM7O0FBRXBDLFlBQUksQ0FBQyxlQUFlLEdBQUcsT0FBTyxDQUFDO0FBQy9CLGNBQU0sR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDdkMsY0FBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLHNDQUFnQixDQUFDO09BQ3JDLENBQUMsQ0FBQztLQUNKLENBQUMsQ0FBQztHQUNKLENBQUMsQ0FBQztDQUNKLENBQUMsQ0FBQyIsImZpbGUiOiJ0ZXN0L2RyaXZlci1zcGVjcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIHRyYW5zcGlsZTptb2NoYVxuXG5pbXBvcnQgeyBBcHBpdW1Ecml2ZXIsIGdldEFwcGl1bVJvdXRlciB9IGZyb20gJy4uL2xpYi9hcHBpdW0nO1xuaW1wb3J0IHsgRmFrZURyaXZlciB9IGZyb20gJ2FwcGl1bS1mYWtlLWRyaXZlcic7XG5pbXBvcnQgeyBURVNUX0ZBS0VfQVBQIH0gZnJvbSAnLi9oZWxwZXJzJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgc2lub24gZnJvbSAnc2lub24nO1xuaW1wb3J0IGNoYWkgZnJvbSAnY2hhaSc7XG5pbXBvcnQgY2hhaUFzUHJvbWlzZWQgZnJvbSAnY2hhaS1hcy1wcm9taXNlZCc7XG5pbXBvcnQgeyBYQ1VJVGVzdERyaXZlciB9IGZyb20gJ2FwcGl1bS14Y3VpdGVzdC1kcml2ZXInO1xuaW1wb3J0IHsgSW9zRHJpdmVyIH0gZnJvbSAnYXBwaXVtLWlvcy1kcml2ZXInO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tICdhc3luY2JveCc7XG5cbmNoYWkuc2hvdWxkKCk7XG5jaGFpLnVzZShjaGFpQXNQcm9taXNlZCk7XG5cbmNvbnN0IEJBU0VfQ0FQUyA9IHtwbGF0Zm9ybU5hbWU6ICdGYWtlJywgZGV2aWNlTmFtZTogJ0Zha2UnLCBhcHA6IFRFU1RfRkFLRV9BUFB9O1xuY29uc3QgU0VTU0lPTl9JRCA9IDE7XG5cbmRlc2NyaWJlKCdBcHBpdW1Ecml2ZXInLCAoKSA9PiB7XG4gIGRlc2NyaWJlKCdnZXRBcHBpdW1Sb3V0ZXInLCAoKSA9PiB7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gYSByb3V0ZSBjb25maWd1cmluZyBmdW5jdGlvbicsIGFzeW5jICgpID0+IHtcbiAgICAgIGxldCByb3V0ZUNvbmZpZ3VyaW5nRnVuY3Rpb24gPSBnZXRBcHBpdW1Sb3V0ZXIoe30pO1xuICAgICAgcm91dGVDb25maWd1cmluZ0Z1bmN0aW9uLnNob3VsZC5iZS5hLmZ1bmN0aW9uO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQXBwaXVtRHJpdmVyJywgKCkgPT4ge1xuICAgIGZ1bmN0aW9uIGdldERyaXZlckFuZEZha2VEcml2ZXIgKCkge1xuICAgICAgbGV0IGFwcGl1bSA9IG5ldyBBcHBpdW1Ecml2ZXIoe30pO1xuICAgICAgbGV0IGZha2VEcml2ZXIgPSBuZXcgRmFrZURyaXZlcigpO1xuICAgICAgbGV0IG1vY2tGYWtlRHJpdmVyID0gc2lub24ubW9jayhmYWtlRHJpdmVyKTtcbiAgICAgIGFwcGl1bS5nZXREcml2ZXJGb3JDYXBzID0gZnVuY3Rpb24gKC8qYXJncyovKSB7XG4gICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGZha2VEcml2ZXI7XG4gICAgICAgIH07XG4gICAgICB9O1xuICAgICAgcmV0dXJuIFthcHBpdW0sIG1vY2tGYWtlRHJpdmVyXTtcbiAgICB9XG4gICAgZGVzY3JpYmUoJ2NyZWF0ZVNlc3Npb24nLCAoKSA9PiB7XG4gICAgICBsZXQgYXBwaXVtO1xuICAgICAgbGV0IG1vY2tGYWtlRHJpdmVyO1xuICAgICAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgICAgIFthcHBpdW0sIG1vY2tGYWtlRHJpdmVyXSA9IGdldERyaXZlckFuZEZha2VEcml2ZXIoKTtcbiAgICAgIH0pO1xuICAgICAgYWZ0ZXJFYWNoKGFzeW5jICgpID0+IHtcbiAgICAgICAgbW9ja0Zha2VEcml2ZXIucmVzdG9yZSgpO1xuICAgICAgICBhd2FpdCBhcHBpdW0uZGVsZXRlU2Vzc2lvbihTRVNTSU9OX0lEKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIGNhbGwgaW5uZXIgZHJpdmVyXFwncyBjcmVhdGVTZXNzaW9uIHdpdGggZGVzaXJlZCBjYXBhYmlsaXRpZXMnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLmV4cGVjdHMoXCJjcmVhdGVTZXNzaW9uXCIpXG4gICAgICAgICAgLm9uY2UoKS53aXRoRXhhY3RBcmdzKEJBU0VfQ0FQUywgdW5kZWZpbmVkLCBbXSlcbiAgICAgICAgICAucmV0dXJucyhbU0VTU0lPTl9JRCwgQkFTRV9DQVBTXSk7XG4gICAgICAgIGF3YWl0IGFwcGl1bS5jcmVhdGVTZXNzaW9uKEJBU0VfQ0FQUyk7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLnZlcmlmeSgpO1xuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIGNhbGwgaW5uZXIgZHJpdmVyXFwncyBjcmVhdGVTZXNzaW9uIHdpdGggZGVzaXJlZCBhbmQgZGVmYXVsdCBjYXBhYmlsaXRpZXMnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGxldCBkZWZhdWx0Q2FwcyA9IHtkZXZpY2VOYW1lOiAnRW11bGF0b3InfVxuICAgICAgICAgICwgYWxsQ2FwcyA9IF8uZXh0ZW5kKF8uY2xvbmUoZGVmYXVsdENhcHMpLCBCQVNFX0NBUFMpO1xuICAgICAgICBhcHBpdW0uYXJncy5kZWZhdWx0Q2FwYWJpbGl0aWVzID0gZGVmYXVsdENhcHM7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLmV4cGVjdHMoXCJjcmVhdGVTZXNzaW9uXCIpXG4gICAgICAgICAgLm9uY2UoKS53aXRoQXJncyhhbGxDYXBzKVxuICAgICAgICAgIC5yZXR1cm5zKFtTRVNTSU9OX0lELCBhbGxDYXBzXSk7XG4gICAgICAgIGF3YWl0IGFwcGl1bS5jcmVhdGVTZXNzaW9uKEJBU0VfQ0FQUyk7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLnZlcmlmeSgpO1xuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIGNhbGwgaW5uZXIgZHJpdmVyXFwncyBjcmVhdGVTZXNzaW9uIHdpdGggZGVzaXJlZCBhbmQgZGVmYXVsdCBjYXBhYmlsaXRpZXMgd2l0aG91dCBvdmVycmlkaW5nIGNhcHMnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIC8vIGEgZGVmYXVsdCBjYXBhYmlsaXR5IHdpdGggdGhlIHNhbWUga2V5IGFzIGEgZGVzaXJlZCBjYXBhYmlsaXR5XG4gICAgICAgIC8vIHNob3VsZCBkbyBub3RoaW5nXG4gICAgICAgIGxldCBkZWZhdWx0Q2FwcyA9IHtwbGF0Zm9ybU5hbWU6ICdFcnNhdHonfTtcbiAgICAgICAgYXBwaXVtLmFyZ3MuZGVmYXVsdENhcGFiaWxpdGllcyA9IGRlZmF1bHRDYXBzO1xuICAgICAgICBtb2NrRmFrZURyaXZlci5leHBlY3RzKFwiY3JlYXRlU2Vzc2lvblwiKVxuICAgICAgICAgIC5vbmNlKCkud2l0aEFyZ3MoQkFTRV9DQVBTKVxuICAgICAgICAgIC5yZXR1cm5zKFtTRVNTSU9OX0lELCBCQVNFX0NBUFNdKTtcbiAgICAgICAgYXdhaXQgYXBwaXVtLmNyZWF0ZVNlc3Npb24oQkFTRV9DQVBTKTtcbiAgICAgICAgbW9ja0Zha2VEcml2ZXIudmVyaWZ5KCk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQga2lsbCBhbGwgb3RoZXIgc2Vzc2lvbnMgaWYgc2Vzc2lvbk92ZXJyaWRlIGlzIG9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBhcHBpdW0uYXJncy5zZXNzaW9uT3ZlcnJpZGUgPSB0cnVlO1xuXG4gICAgICAgIC8vIG1vY2sgdGhyZWUgc2Vzc2lvbnMgdGhhdCBzaG91bGQgYmUgcmVtb3ZlZCB3aGVuIHRoZSBuZXcgb25lIGlzIGNyZWF0ZWRcbiAgICAgICAgbGV0IGZha2VEcml2ZXJzID0gW25ldyBGYWtlRHJpdmVyKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgRmFrZURyaXZlcigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3IEZha2VEcml2ZXIoKV07XG4gICAgICAgIGxldCBtb2NrRmFrZURyaXZlcnMgPSBfLm1hcChmYWtlRHJpdmVycywgKGZkKSA9PiB7cmV0dXJuIHNpbm9uLm1vY2soZmQpO30pO1xuICAgICAgICBtb2NrRmFrZURyaXZlcnNbMF0uZXhwZWN0cygnZGVsZXRlU2Vzc2lvbicpXG4gICAgICAgICAgLm9uY2UoKTtcbiAgICAgICAgbW9ja0Zha2VEcml2ZXJzWzFdLmV4cGVjdHMoJ2RlbGV0ZVNlc3Npb24nKVxuICAgICAgICAgIC5vbmNlKClcbiAgICAgICAgICAudGhyb3dzKCdDYW5ub3Qgc2h1dCBkb3duIEFuZHJvaWQgZHJpdmVyOyBpdCBoYXMgYWxyZWFkeSBzaHV0IGRvd24nKTtcbiAgICAgICAgbW9ja0Zha2VEcml2ZXJzWzJdLmV4cGVjdHMoJ2RlbGV0ZVNlc3Npb24nKVxuICAgICAgICAgIC5vbmNlKCk7XG4gICAgICAgIGFwcGl1bS5zZXNzaW9uc1snYWJjLTEyMy14eXonXSA9IGZha2VEcml2ZXJzWzBdO1xuICAgICAgICBhcHBpdW0uc2Vzc2lvbnNbJ3h5ei0zMjEtYWJjJ10gPSBmYWtlRHJpdmVyc1sxXTtcbiAgICAgICAgYXBwaXVtLnNlc3Npb25zWycxMjMtYWJjLXh5eiddID0gZmFrZURyaXZlcnNbMl07XG5cbiAgICAgICAgbGV0IHNlc3Npb25zID0gYXdhaXQgYXBwaXVtLmdldFNlc3Npb25zKCk7XG4gICAgICAgIHNlc3Npb25zLnNob3VsZC5oYXZlLmxlbmd0aCgzKTtcblxuICAgICAgICBtb2NrRmFrZURyaXZlci5leHBlY3RzKFwiY3JlYXRlU2Vzc2lvblwiKVxuICAgICAgICAgIC5vbmNlKCkud2l0aEV4YWN0QXJncyhCQVNFX0NBUFMsIHVuZGVmaW5lZCwgW10pXG4gICAgICAgICAgLnJldHVybnMoW1NFU1NJT05fSUQsIEJBU0VfQ0FQU10pO1xuICAgICAgICBhd2FpdCBhcHBpdW0uY3JlYXRlU2Vzc2lvbihCQVNFX0NBUFMpO1xuXG4gICAgICAgIHNlc3Npb25zID0gYXdhaXQgYXBwaXVtLmdldFNlc3Npb25zKCk7XG4gICAgICAgIHNlc3Npb25zLnNob3VsZC5oYXZlLmxlbmd0aCgxKTtcblxuICAgICAgICBmb3IgKGxldCBtZmQgb2YgbW9ja0Zha2VEcml2ZXJzKSB7XG4gICAgICAgICAgbWZkLnZlcmlmeSgpO1xuICAgICAgICB9XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLnZlcmlmeSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgZGVzY3JpYmUoJ2RlbGV0ZVNlc3Npb24nLCAoKSA9PiB7XG4gICAgICBsZXQgYXBwaXVtO1xuICAgICAgbGV0IG1vY2tGYWtlRHJpdmVyO1xuICAgICAgYmVmb3JlRWFjaCgoKSA9PiB7XG4gICAgICAgIFthcHBpdW0sIG1vY2tGYWtlRHJpdmVyXSA9IGdldERyaXZlckFuZEZha2VEcml2ZXIoKTtcbiAgICAgIH0pO1xuICAgICAgYWZ0ZXJFYWNoKCgpID0+IHtcbiAgICAgICAgbW9ja0Zha2VEcml2ZXIucmVzdG9yZSgpO1xuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIHJlbW92ZSB0aGUgc2Vzc2lvbiBpZiBpdCBpcyBmb3VuZCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbGV0IFtzZXNzaW9uSWRdID0gYXdhaXQgYXBwaXVtLmNyZWF0ZVNlc3Npb24oQkFTRV9DQVBTKTtcbiAgICAgICAgbGV0IHNlc3Npb25zID0gYXdhaXQgYXBwaXVtLmdldFNlc3Npb25zKCk7XG4gICAgICAgIHNlc3Npb25zLnNob3VsZC5oYXZlLmxlbmd0aCgxKTtcbiAgICAgICAgYXdhaXQgYXBwaXVtLmRlbGV0ZVNlc3Npb24oc2Vzc2lvbklkKTtcbiAgICAgICAgc2Vzc2lvbnMgPSBhd2FpdCBhcHBpdW0uZ2V0U2Vzc2lvbnMoKTtcbiAgICAgICAgc2Vzc2lvbnMuc2hvdWxkLmhhdmUubGVuZ3RoKDApO1xuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIGNhbGwgaW5uZXIgZHJpdmVyXFwncyBkZWxldGVTZXNzaW9uIG1ldGhvZCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgW3Nlc3Npb25JZF0gPSBhd2FpdCBhcHBpdW0uY3JlYXRlU2Vzc2lvbihCQVNFX0NBUFMpO1xuICAgICAgICBtb2NrRmFrZURyaXZlci5leHBlY3RzKFwiZGVsZXRlU2Vzc2lvblwiKVxuICAgICAgICAgIC5vbmNlKCkud2l0aEV4YWN0QXJncyhzZXNzaW9uSWQsIFtdKVxuICAgICAgICAgIC5yZXR1cm5zKCk7XG4gICAgICAgIGF3YWl0IGFwcGl1bS5kZWxldGVTZXNzaW9uKHNlc3Npb25JZCk7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLnZlcmlmeSgpO1xuXG4gICAgICAgIC8vIGNsZWFudXAsIHNpbmNlIHdlIGZha2VkIHRoZSBkZWxldGUgc2Vzc2lvbiBjYWxsXG4gICAgICAgIGF3YWl0IG1vY2tGYWtlRHJpdmVyLm9iamVjdC5kZWxldGVTZXNzaW9uKCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBkZXNjcmliZSgnZ2V0U2Vzc2lvbnMnLCAoKSA9PiB7XG4gICAgICBsZXQgYXBwaXVtO1xuICAgICAgbGV0IHNlc3Npb25zO1xuICAgICAgYmVmb3JlKCgpID0+IHtcbiAgICAgICAgYXBwaXVtID0gbmV3IEFwcGl1bURyaXZlcih7fSk7XG4gICAgICB9KTtcbiAgICAgIGFmdGVyRWFjaChhc3luYyAoKSA9PiB7XG4gICAgICAgIGZvciAobGV0IHNlc3Npb24gb2Ygc2Vzc2lvbnMpIHtcbiAgICAgICAgICBhd2FpdCBhcHBpdW0uZGVsZXRlU2Vzc2lvbihzZXNzaW9uLmlkKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBpdCgnc2hvdWxkIHJldHVybiBhbiBlbXB0eSBhcnJheSBvZiBzZXNzaW9ucycsIGFzeW5jICgpID0+IHtcbiAgICAgICAgc2Vzc2lvbnMgPSBhd2FpdCBhcHBpdW0uZ2V0U2Vzc2lvbnMoKTtcbiAgICAgICAgc2Vzc2lvbnMuc2hvdWxkLmJlLmFuLmFycmF5O1xuICAgICAgICBzZXNzaW9ucy5zaG91bGQuYmUuZW1wdHk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgcmV0dXJuIHNlc3Npb25zIGNyZWF0ZWQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGxldCBzZXNzaW9uMSA9IGF3YWl0IGFwcGl1bS5jcmVhdGVTZXNzaW9uKF8uZXh0ZW5kKF8uY2xvbmUoQkFTRV9DQVBTKSwge2NhcDogJ3ZhbHVlJ30pKTtcbiAgICAgICAgbGV0IHNlc3Npb24yID0gYXdhaXQgYXBwaXVtLmNyZWF0ZVNlc3Npb24oXy5leHRlbmQoXy5jbG9uZShCQVNFX0NBUFMpLCB7Y2FwOiAnb3RoZXIgdmFsdWUnfSkpO1xuXG4gICAgICAgIHNlc3Npb25zID0gYXdhaXQgYXBwaXVtLmdldFNlc3Npb25zKCk7XG4gICAgICAgIHNlc3Npb25zLnNob3VsZC5iZS5hbi5hcnJheTtcbiAgICAgICAgc2Vzc2lvbnMuc2hvdWxkLmhhdmUubGVuZ3RoKDIpO1xuICAgICAgICBzZXNzaW9uc1swXS5pZC5zaG91bGQuZXF1YWwoc2Vzc2lvbjFbMF0pO1xuICAgICAgICBzZXNzaW9uc1swXS5jYXBhYmlsaXRpZXMuc2hvdWxkLmVxbChzZXNzaW9uMVsxXSk7XG4gICAgICAgIHNlc3Npb25zWzFdLmlkLnNob3VsZC5lcXVhbChzZXNzaW9uMlswXSk7XG4gICAgICAgIHNlc3Npb25zWzFdLmNhcGFiaWxpdGllcy5zaG91bGQuZXFsKHNlc3Npb24yWzFdKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICAgIGRlc2NyaWJlKCdnZXRTdGF0dXMnLCAoKSA9PiB7XG4gICAgICBsZXQgYXBwaXVtO1xuICAgICAgYmVmb3JlKCgpID0+IHtcbiAgICAgICAgYXBwaXVtID0gbmV3IEFwcGl1bURyaXZlcih7fSk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgcmV0dXJuIGEgc3RhdHVzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBsZXQgc3RhdHVzID0gYXdhaXQgYXBwaXVtLmdldFN0YXR1cygpO1xuICAgICAgICBzdGF0dXMuYnVpbGQuc2hvdWxkLmV4aXN0O1xuICAgICAgICBzdGF0dXMuYnVpbGQudmVyc2lvbi5zaG91bGQuZXhpc3Q7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICBkZXNjcmliZSgnc2Vzc2lvbkV4aXN0cycsICgpID0+IHtcbiAgICB9KTtcbiAgICBkZXNjcmliZSgnYXR0YWNoVW5leHBlY3RlZFNodXRkb3duSGFuZGxlcicsICgpID0+IHtcbiAgICAgIGxldCBhcHBpdW1cbiAgICAgICAgLCBtb2NrRmFrZURyaXZlcjtcbiAgICAgIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgICAgICBbYXBwaXVtLCBtb2NrRmFrZURyaXZlcl0gPSBnZXREcml2ZXJBbmRGYWtlRHJpdmVyKCk7XG4gICAgICB9KTtcbiAgICAgIGFmdGVyRWFjaChhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IG1vY2tGYWtlRHJpdmVyLm9iamVjdC5kZWxldGVTZXNzaW9uKCk7XG4gICAgICAgIG1vY2tGYWtlRHJpdmVyLnJlc3RvcmUoKTtcbiAgICAgICAgYXBwaXVtLmFyZ3MuZGVmYXVsdENhcGFiaWxpdGllcyA9IHt9O1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcmVtb3ZlIHNlc3Npb24gaWYgaW5uZXIgZHJpdmVyIHVuZXhwZWN0ZWRseSBleGl0cyB3aXRoIGFuIGVycm9yJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBsZXQgW3Nlc3Npb25JZCxdID0gYXdhaXQgYXBwaXVtLmNyZWF0ZVNlc3Npb24oXy5jbG9uZShCQVNFX0NBUFMpKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBjb21tYS1zcGFjaW5nXG4gICAgICAgIF8ua2V5cyhhcHBpdW0uc2Vzc2lvbnMpLnNob3VsZC5jb250YWluKHNlc3Npb25JZCk7XG4gICAgICAgIGFwcGl1bS5zZXNzaW9uc1tzZXNzaW9uSWRdLnVuZXhwZWN0ZWRTaHV0ZG93bkRlZmVycmVkLnJlamVjdChuZXcgRXJyb3IoXCJPb3BzXCIpKTtcbiAgICAgICAgLy8gbGV0IGV2ZW50IGxvb3Agc3BpbiBzbyByZWplY3Rpb24gaXMgaGFuZGxlZFxuICAgICAgICBhd2FpdCBzbGVlcCgxKTtcbiAgICAgICAgXy5rZXlzKGFwcGl1bS5zZXNzaW9ucykuc2hvdWxkLm5vdC5jb250YWluKHNlc3Npb25JZCk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgcmVtb3ZlIHNlc3Npb24gaWYgaW5uZXIgZHJpdmVyIHVuZXhwZWN0ZWRseSBleGl0cyB3aXRoIG5vIGVycm9yJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBsZXQgW3Nlc3Npb25JZCxdID0gYXdhaXQgYXBwaXVtLmNyZWF0ZVNlc3Npb24oXy5jbG9uZShCQVNFX0NBUFMpKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBjb21tYS1zcGFjaW5nXG4gICAgICAgIF8ua2V5cyhhcHBpdW0uc2Vzc2lvbnMpLnNob3VsZC5jb250YWluKHNlc3Npb25JZCk7XG4gICAgICAgIGFwcGl1bS5zZXNzaW9uc1tzZXNzaW9uSWRdLnVuZXhwZWN0ZWRTaHV0ZG93bkRlZmVycmVkLnJlc29sdmUoKTtcbiAgICAgICAgLy8gbGV0IGV2ZW50IGxvb3Agc3BpbiBzbyByZWplY3Rpb24gaXMgaGFuZGxlZFxuICAgICAgICBhd2FpdCBzbGVlcCgxKTtcbiAgICAgICAgXy5rZXlzKGFwcGl1bS5zZXNzaW9ucykuc2hvdWxkLm5vdC5jb250YWluKHNlc3Npb25JZCk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgbm90IHJlbW92ZSBzZXNzaW9uIGlmIGlubmVyIGRyaXZlciBjYW5jZWxzIHVuZXhwZWN0ZWQgZXhpdCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbGV0IFtzZXNzaW9uSWQsXSA9IGF3YWl0IGFwcGl1bS5jcmVhdGVTZXNzaW9uKF8uY2xvbmUoQkFTRV9DQVBTKSk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgY29tbWEtc3BhY2luZ1xuICAgICAgICBfLm