UNPKG

webdriverio-automation

Version:

WebdriverIO-Automation android ios project

499 lines (468 loc) 59.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; require("source-map-support/register"); var _lodash = _interopRequireDefault(require("lodash")); var _2 = require("../.."); var _protocol = require("../../lib/protocol/protocol"); var _requestPromise = _interopRequireDefault(require("request-promise")); var _chai = _interopRequireDefault(require("chai")); var _chaiAsPromised = _interopRequireDefault(require("chai-as-promised")); var _bluebird = _interopRequireDefault(require("bluebird")); const should = _chai.default.should(); const DEFAULT_ARGS = { address: 'localhost', port: 8181 }; _chai.default.use(_chaiAsPromised.default); function baseDriverE2ETests(DriverClass, defaultCaps = {}) { describe('BaseDriver (e2e)', function () { let baseServer, d = new DriverClass(DEFAULT_ARGS); before(async function () { baseServer = await (0, _2.server)((0, _2.routeConfiguringFunction)(d), DEFAULT_ARGS.port); }); after(async function () { await baseServer.close(); }); function startSession(caps) { return (0, _requestPromise.default)({ url: 'http://localhost:8181/wd/hub/session', method: 'POST', json: { desiredCapabilities: caps, requiredCapabilities: {} } }); } function endSession(id) { return (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${id}`, method: 'DELETE', json: true, simple: false }); } function getSession(id) { return (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${id}`, method: 'GET', json: true, simple: false }); } describe('session handling', function () { it('should create session and retrieve a session id, then delete it', async function () { let res = await (0, _requestPromise.default)({ url: 'http://localhost:8181/wd/hub/session', method: 'POST', json: { desiredCapabilities: defaultCaps, requiredCapabilities: {} }, simple: false, resolveWithFullResponse: true }); res.statusCode.should.equal(200); res.body.status.should.equal(0); should.exist(res.body.sessionId); res.body.value.should.eql(defaultCaps); res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}`, method: 'DELETE', json: true, simple: false, resolveWithFullResponse: true }); res.statusCode.should.equal(200); res.body.status.should.equal(0); should.equal(d.sessionId, null); }); }); it.skip('should throw NYI for commands not implemented', async function () {}); describe('command timeouts', function () { let originalFindElement, originalFindElements; function startTimeoutSession(timeout) { let caps = _lodash.default.clone(defaultCaps); caps.newCommandTimeout = timeout; return startSession(caps); } before(function () { originalFindElement = d.findElement; d.findElement = function () { return 'foo'; }.bind(d); originalFindElements = d.findElements; d.findElements = async function () { await _bluebird.default.delay(200); return ['foo']; }.bind(d); }); after(function () { d.findElement = originalFindElement; d.findElements = originalFindElements; }); it('should set a default commandTimeout', async function () { let newSession = await startTimeoutSession(); d.newCommandTimeoutMs.should.be.above(0); await endSession(newSession.sessionId); }); it('should timeout on commands using commandTimeout cap', async function () { let newSession = await startTimeoutSession(0.25); await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}/element`, method: 'POST', json: { using: 'name', value: 'foo' } }); await _bluebird.default.delay(400); let res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}`, method: 'GET', json: true, simple: false }); res.status.should.equal(6); should.equal(d.sessionId, null); res = await endSession(newSession.sessionId); res.status.should.equal(6); }); it('should not timeout with commandTimeout of false', async function () { let newSession = await startTimeoutSession(0.1); let start = Date.now(); let res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}/elements`, method: 'POST', json: { using: 'name', value: 'foo' } }); (Date.now() - start).should.be.above(150); res.value.should.eql(['foo']); await endSession(newSession.sessionId); }); it('should not timeout with commandTimeout of 0', async function () { d.newCommandTimeoutMs = 2; let newSession = await startTimeoutSession(0); await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}/element`, method: 'POST', json: { using: 'name', value: 'foo' } }); await _bluebird.default.delay(400); let res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}`, method: 'GET', json: true, simple: false }); res.status.should.equal(0); res = await endSession(newSession.sessionId); res.status.should.equal(0); d.newCommandTimeoutMs = 60 * 1000; }); it('should not timeout if its just the command taking awhile', async function () { let newSession = await startTimeoutSession(0.25); await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}/element`, method: 'POST', json: { using: 'name', value: 'foo' } }); await _bluebird.default.delay(400); let res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${d.sessionId}`, method: 'GET', json: true, simple: false }); res.status.should.equal(6); should.equal(d.sessionId, null); res = await endSession(newSession.sessionId); res.status.should.equal(6); }); it('should not have a timer running before or after a session', async function () { should.not.exist(d.noCommandTimer); let newSession = await startTimeoutSession(0.25); newSession.sessionId.should.equal(d.sessionId); should.exist(d.noCommandTimer); await endSession(newSession.sessionId); should.not.exist(d.noCommandTimer); }); }); describe('settings api', function () { before(function () { d.settings = new _2.DeviceSettings({ ignoreUnimportantViews: false }); }); it('should be able to get settings object', function () { d.settings.getSettings().ignoreUnimportantViews.should.be.false; }); it('should throw error when updateSettings method is not defined', async function () { await d.settings.update({ ignoreUnimportantViews: true }).should.eventually.be.rejectedWith('onSettingsUpdate'); }); it('should throw error for invalid update object', async function () { await d.settings.update('invalid json').should.eventually.be.rejectedWith('JSON'); }); }); describe('unexpected exits', function () { it('should reject a current command when the driver crashes', async function () { d._oldGetStatus = d.getStatus; d.getStatus = async function () { await _bluebird.default.delay(5000); }.bind(d); let p = (0, _requestPromise.default)({ url: 'http://localhost:8181/wd/hub/status', method: 'GET', json: true, simple: false }); await _bluebird.default.delay(100); d.startUnexpectedShutdown(new Error('Crashytimes')); let res = await p; res.status.should.equal(13); res.value.message.should.contain('Crashytimes'); await d.onUnexpectedShutdown.should.be.rejectedWith('Crashytimes'); d.getStatus = d._oldGetStatus; }); }); describe('event timings', function () { it('should not add timings if not using opt-in cap', async function () { let session = await startSession(defaultCaps); let res = await getSession(session.sessionId); should.not.exist(res.events); await endSession(session.sessionId); }); it('should add start session timings', async function () { let caps = Object.assign({}, defaultCaps, { eventTimings: true }); let session = await startSession(caps); let res = (await getSession(session.sessionId)).value; should.exist(res.events); should.exist(res.events.newSessionRequested); should.exist(res.events.newSessionStarted); res.events.newSessionRequested[0].should.be.a('number'); res.events.newSessionStarted[0].should.be.a('number'); await endSession(session.sessionId); }); }); describe('execute driver script', function () { let originalFindElement, sessionId; before(function () { d.allowInsecure = ['execute_driver_script']; originalFindElement = d.findElement; d.findElement = function (strategy, selector) { if (strategy === 'accessibility id' && selector === 'amazing') { return { [_protocol.W3C_ELEMENT_KEY]: 'element-id-1' }; } throw new _2.errors.NoSuchElementError('not found'); }.bind(d); }); beforeEach(async function () { ({ sessionId } = await startSession(defaultCaps)); }); after(function () { d.findElement = originalFindElement; }); afterEach(async function () { await endSession(sessionId); }); it('should not work unless the allowInsecure feature flag is set', async function () { d._allowInsecure = d.allowInsecure; d.allowInsecure = []; const script = `return 'foo'`; await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: { script, type: 'wd' } }).should.eventually.be.rejectedWith(/allow-insecure/); await endSession(sessionId); d.allowInsecure = d._allowInsecure; }); it('should execute a webdriverio script in the context of session', async function () { const script = ` const timeouts = await driver.getTimeouts(); const status = await driver.status(); return [timeouts, status]; `; const res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: { script, type: 'webdriverio' } }); const expectedTimeouts = { command: 250, implicit: 0 }; const expectedStatus = {}; res.value.result.should.eql([expectedTimeouts, expectedStatus]); }); it('should fail with any script type other than webdriverio currently', async function () { const script = `return 'foo'`; await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: { script, type: 'wd' } }).should.eventually.be.rejectedWith(/script type/); }); it('should execute a webdriverio script that returns elements correctly', async function () { const script = ` return await driver.$("~amazing"); `; const res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: { script } }); res.value.result.should.eql({ [_protocol.W3C_ELEMENT_KEY]: 'element-id-1', [_protocol.MJSONWP_ELEMENT_KEY]: 'element-id-1' }); }); it('should execute a webdriverio script that returns elements in deep structure', async function () { const script = ` const el = await driver.$("~amazing"); return {element: el, elements: [el, el]}; `; const res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: { script } }); const elObj = { [_protocol.W3C_ELEMENT_KEY]: 'element-id-1', [_protocol.MJSONWP_ELEMENT_KEY]: 'element-id-1' }; res.value.result.should.eql({ element: elObj, elements: [elObj, elObj] }); }); it('should store and return logs to the user', async function () { const script = ` console.log("foo"); console.log("foo2"); console.warn("bar"); console.error("baz"); return null; `; const res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: { script } }); res.value.logs.should.eql({ log: ['foo', 'foo2'], warn: ['bar'], error: ['baz'] }); }); it('should have appium specific commands available', async function () { const script = ` return typeof driver.lock; `; const res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: { script } }); res.value.result.should.eql('function'); }); it('should correctly handle errors that happen in a webdriverio script', async function () { const script = ` return await driver.$("~notfound"); `; const res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: { script }, simple: false }); res.should.eql({ sessionId, status: 13, value: { message: 'An unknown server-side error occurred while processing the command. Original error: Could not execute driver script. Original error was: Error: not found' } }); }); it('should correctly handle errors that happen when a script cannot be compiled', async function () { const script = ` return {; `; const res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: { script }, simple: false }); res.should.eql({ sessionId, status: 13, value: { message: 'An unknown server-side error occurred while processing the command. Original error: Could not execute driver script. Original error was: Error: Unexpected token ;' } }); }); it('should be able to set a timeout on a driver script', async function () { const script = ` await Promise.delay(1000); return true; `; const res = await (0, _requestPromise.default)({ url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`, method: 'POST', json: { script, timeout: 50 }, simple: false }); res.value.message.should.match(/.+50.+timeout.+/); }); }); }); } var _default = baseDriverE2ETests; exports.default = _default;require('source-map-support').install(); //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvYmFzZWRyaXZlci9kcml2ZXItZTJlLXRlc3RzLmpzIl0sIm5hbWVzIjpbInNob3VsZCIsImNoYWkiLCJERUZBVUxUX0FSR1MiLCJhZGRyZXNzIiwicG9ydCIsInVzZSIsImNoYWlBc1Byb21pc2VkIiwiYmFzZURyaXZlckUyRVRlc3RzIiwiRHJpdmVyQ2xhc3MiLCJkZWZhdWx0Q2FwcyIsImRlc2NyaWJlIiwiYmFzZVNlcnZlciIsImQiLCJiZWZvcmUiLCJhZnRlciIsImNsb3NlIiwic3RhcnRTZXNzaW9uIiwiY2FwcyIsInVybCIsIm1ldGhvZCIsImpzb24iLCJkZXNpcmVkQ2FwYWJpbGl0aWVzIiwicmVxdWlyZWRDYXBhYmlsaXRpZXMiLCJlbmRTZXNzaW9uIiwiaWQiLCJzaW1wbGUiLCJnZXRTZXNzaW9uIiwiaXQiLCJyZXMiLCJyZXNvbHZlV2l0aEZ1bGxSZXNwb25zZSIsInN0YXR1c0NvZGUiLCJlcXVhbCIsImJvZHkiLCJzdGF0dXMiLCJleGlzdCIsInNlc3Npb25JZCIsInZhbHVlIiwiZXFsIiwic2tpcCIsIm9yaWdpbmFsRmluZEVsZW1lbnQiLCJvcmlnaW5hbEZpbmRFbGVtZW50cyIsInN0YXJ0VGltZW91dFNlc3Npb24iLCJ0aW1lb3V0IiwiXyIsImNsb25lIiwibmV3Q29tbWFuZFRpbWVvdXQiLCJmaW5kRWxlbWVudCIsImJpbmQiLCJmaW5kRWxlbWVudHMiLCJCIiwiZGVsYXkiLCJuZXdTZXNzaW9uIiwibmV3Q29tbWFuZFRpbWVvdXRNcyIsImJlIiwiYWJvdmUiLCJ1c2luZyIsInN0YXJ0IiwiRGF0ZSIsIm5vdyIsIm5vdCIsIm5vQ29tbWFuZFRpbWVyIiwic2V0dGluZ3MiLCJEZXZpY2VTZXR0aW5ncyIsImlnbm9yZVVuaW1wb3J0YW50Vmlld3MiLCJnZXRTZXR0aW5ncyIsImZhbHNlIiwidXBkYXRlIiwiZXZlbnR1YWxseSIsInJlamVjdGVkV2l0aCIsIl9vbGRHZXRTdGF0dXMiLCJnZXRTdGF0dXMiLCJwIiwic3RhcnRVbmV4cGVjdGVkU2h1dGRvd24iLCJFcnJvciIsIm1lc3NhZ2UiLCJjb250YWluIiwib25VbmV4cGVjdGVkU2h1dGRvd24iLCJzZXNzaW9uIiwiZXZlbnRzIiwiT2JqZWN0IiwiYXNzaWduIiwiZXZlbnRUaW1pbmdzIiwibmV3U2Vzc2lvblJlcXVlc3RlZCIsIm5ld1Nlc3Npb25TdGFydGVkIiwiYSIsImFsbG93SW5zZWN1cmUiLCJzdHJhdGVneSIsInNlbGVjdG9yIiwiVzNDX0VMRU1FTlRfS0VZIiwiZXJyb3JzIiwiTm9TdWNoRWxlbWVudEVycm9yIiwiYmVmb3JlRWFjaCIsImFmdGVyRWFjaCIsIl9hbGxvd0luc2VjdXJlIiwic2NyaXB0IiwidHlwZSIsImV4cGVjdGVkVGltZW91dHMiLCJjb21tYW5kIiwiaW1wbGljaXQiLCJleHBlY3RlZFN0YXR1cyIsInJlc3VsdCIsIk1KU09OV1BfRUxFTUVOVF9LRVkiLCJlbE9iaiIsImVsZW1lbnQiLCJlbGVtZW50cyIsImxvZ3MiLCJsb2ciLCJ3YXJuIiwiZXJyb3IiLCJtYXRjaCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFQSxNQUFNQSxNQUFNLEdBQUdDLGNBQUtELE1BQUwsRUFBZjs7QUFDQSxNQUFNRSxZQUFZLEdBQUc7QUFDbkJDLEVBQUFBLE9BQU8sRUFBRSxXQURVO0FBRW5CQyxFQUFBQSxJQUFJLEVBQUU7QUFGYSxDQUFyQjs7QUFJQUgsY0FBS0ksR0FBTCxDQUFTQyx1QkFBVDs7QUFFQSxTQUFTQyxrQkFBVCxDQUE2QkMsV0FBN0IsRUFBMENDLFdBQVcsR0FBRyxFQUF4RCxFQUE0RDtBQUMxREMsRUFBQUEsUUFBUSxDQUFDLGtCQUFELEVBQXFCLFlBQVk7QUFDdkMsUUFBSUMsVUFBSjtBQUFBLFFBQWdCQyxDQUFDLEdBQUcsSUFBSUosV0FBSixDQUFnQk4sWUFBaEIsQ0FBcEI7QUFDQVcsSUFBQUEsTUFBTSxDQUFDLGtCQUFrQjtBQUN2QkYsTUFBQUEsVUFBVSxHQUFH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QUUsRUFGSztBQUdiRyxVQUFBQSxLQUFLLEVBQUU7QUFBQ3NDLFlBQUFBLE9BQU8sRUFBRTtBQUFWO0FBSE0sU0FBZjtBQUtELE9BZkMsQ0FBRjtBQWlCQS9DLE1BQUFBLEVBQUUsQ0FBQyxvREFBRCxFQUF1RCxrQkFBa0I7QUFDekUsY0FBTW1FLE1BQU0sR0FBSTs7O1NBQWhCO0FBSUEsY0FBTWxFLEdBQUcsR0FBRyxNQUFNLDZCQUFRO0FBQ3hCVixVQUFBQSxHQUFHLEVBQUcsd0NBQXVDaUIsU0FBVSx3QkFEL0I7QUFFeEJoQixVQUFBQSxNQUFNLEVBQUUsTUFGZ0I7QUFHeEJDLFVBQUFBLElBQUksRUFBRTtBQUFDMEUsWUFBQUEsTUFBRDtBQUFTcEQsWUFBQUEsT0FBTyxFQUFFO0FBQWxCLFdBSGtCO0FBSXhCakIsVUFBQUEsTUFBTSxFQUFFO0FBSmdCLFNBQVIsQ0FBbEI7QUFNQUcsUUFBQUEsR0FBRyxDQUFDUSxLQUFKLENBQVVzQyxPQUFWLENBQWtCMUUsTUFBbEIsQ0FBeUI2RyxLQUF6QixDQUErQixpQkFBL0I7QUFDRCxPQVpDLENBQUY7QUFhRCxLQTdLTyxDQUFSO0FBOEtELEdBdGFPLENBQVI7QUF1YUQ7O2VBRWN0RyxrQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBzZXJ2ZXIsIHJvdXRlQ29uZmlndXJpbmdGdW5jdGlvbiwgRGV2aWNlU2V0dGluZ3MsIGVycm9ycyB9IGZyb20gJy4uLy4uJztcbmltcG9ydCB7IFczQ19FTEVNRU5UX0tFWSwgTUpTT05XUF9FTEVNRU5UX0tFWSB9IGZyb20gJy4uLy4uL2xpYi9wcm90b2NvbC9wcm90b2NvbCc7XG5pbXBvcnQgcmVxdWVzdCBmcm9tICdyZXF1ZXN0LXByb21pc2UnO1xuaW1wb3J0IGNoYWkgZnJvbSAnY2hhaSc7XG5pbXBvcnQgY2hhaUFzUHJvbWlzZWQgZnJvbSAnY2hhaS1hcy1wcm9taXNlZCc7XG5pbXBvcnQgQiBmcm9tICdibHVlYmlyZCc7XG5cbmNvbnN0IHNob3VsZCA9IGNoYWkuc2hvdWxkKCk7XG5jb25zdCBERUZBVUxUX0FSR1MgPSB7XG4gIGFkZHJlc3M6ICdsb2NhbGhvc3QnLFxuICBwb3J0OiA4MTgxXG59O1xuY2hhaS51c2UoY2hhaUFzUHJvbWlzZWQpO1xuXG5mdW5jdGlvbiBiYXNlRHJpdmVyRTJFVGVzdHMgKERyaXZlckNsYXNzLCBkZWZhdWx0Q2FwcyA9IHt9KSB7XG4gIGRlc2NyaWJlKCdCYXNlRHJpdmVyIChlMmUpJywgZnVuY3Rpb24gKCkge1xuICAgIGxldCBiYXNlU2VydmVyLCBkID0gbmV3IERyaXZlckNsYXNzKERFRkFVTFRfQVJHUyk7XG4gICAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGJhc2VTZXJ2ZXIgPSBhd2FpdCBzZXJ2ZXIocm91dGVDb25maWd1cmluZ0Z1bmN0aW9uKGQpLCBERUZBVUxUX0FSR1MucG9ydCk7XG4gICAgfSk7XG4gICAgYWZ0ZXIoYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgYmFzZVNlcnZlci5jbG9zZSgpO1xuICAgIH0pO1xuXG4gICAgZnVuY3Rpb24gc3RhcnRTZXNzaW9uIChjYXBzKSB7XG4gICAgICByZXR1cm4gcmVxdWVzdCh7XG4gICAgICAgIHVybDogJ2h0dHA6Ly9sb2NhbGhvc3Q6ODE4MS93ZC9odWIvc2Vzc2lvbicsXG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICBqc29uOiB7ZGVzaXJlZENhcGFiaWxpdGllczogY2FwcywgcmVxdWlyZWRDYXBhYmlsaXRpZXM6IHt9fSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVuZFNlc3Npb24gKGlkKSB7XG4gICAgICByZXR1cm4gcmVxdWVzdCh7XG4gICAgICAgIHVybDogYGh0dHA6Ly9sb2NhbGhvc3Q6ODE4MS93ZC9odWIvc2Vzc2lvbi8ke2lkfWAsXG4gICAgICAgIG1ldGhvZDogJ0RFTEVURScsXG4gICAgICAgIGpzb246IHRydWUsXG4gICAgICAgIHNpbXBsZTogZmFsc2VcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFNlc3Npb24gKGlkKSB7XG4gICAgICByZXR1cm4gcmVxdWVzdCh7XG4gICAgICAgIHVybDogYGh0dHA6Ly9sb2NhbGhvc3Q6ODE4MS93ZC9odWIvc2Vzc2lvbi8ke2lkfWAsXG4gICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgIGpzb246IHRydWUsXG4gICAgICAgIHNpbXBsZTogZmFsc2VcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGRlc2NyaWJlKCdzZXNzaW9uIGhhbmRsaW5nJywgZnVuY3Rpb24gKCkge1xuICAgICAgaXQoJ3Nob3VsZCBjcmVhdGUgc2Vzc2lvbiBhbmQgcmV0cmlldmUgYSBzZXNzaW9uIGlkLCB0aGVuIGRlbGV0ZSBpdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgbGV0IHJlcyA9IGF3YWl0IHJlcXVlc3Qoe1xuICAgICAgICAgIHVybDogJ2h0dHA6Ly9sb2NhbGhvc3Q6ODE4MS93ZC9odWIvc2Vzc2lvbicsXG4gICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAganNvbjoge2Rlc2lyZWRDYXBhYmlsaXRpZXM6IGRlZmF1bHRDYXBzLCByZXF1aXJlZENhcGFiaWxpdGllczoge319LFxuICAgICAgICAgIHNpbXBsZTogZmFsc2UsXG4gICAgICAgICAgcmVzb2x2ZVdpdGhGdWxsUmVzcG9uc2U6IHRydWVcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmVzLnN0YXR1c0NvZGUuc2hvdWxkLmVxdWFsKDIwMCk7XG4gICAgICAgIHJlcy5ib2R5LnN0YXR1cy5zaG91bGQuZXF1YWwoMCk7XG4gICAgICAgIHNob3VsZC5leGlzdChyZXMuYm9keS5zZXNzaW9uSWQpO1xuICAgICAgICByZXMuYm9keS52YWx1ZS5zaG91bGQuZXFsKGRlZmF1bHRDYXBzKTtcblxuICAgICAgICByZXMgPSBhd2FpdCByZXF1ZXN0KHtcbiAgICAgICAgICB1cmw6IGBodHRwOi8vbG9jYWxob3N0OjgxODEvd2QvaHViL3Nlc3Npb24vJHtkLnNlc3Npb25JZH1gLFxuICAgICAgICAgIG1ldGhvZDogJ0RFTEVURScsXG4gICAgICAgICAganNvbjogdHJ1ZSxcbiAgICAgICAgICBzaW1wbGU6IGZhbHNlLFxuICAgICAgICAgIHJlc29sdmVXaXRoRnVsbFJlc3BvbnNlOiB0cnVlXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJlcy5zdGF0dXNDb2RlLnNob3VsZC5lcXVhbCgyMDApO1xuICAgICAgICByZXMuYm9keS5zdGF0dXMuc2hvdWxkLmVxdWFsKDApO1xuICAgICAgICBzaG91bGQuZXF1YWwoZC5zZXNzaW9uSWQsIG51bGwpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdC5za2lwKCdzaG91bGQgdGhyb3cgTllJIGZvciBjb21tYW5kcyBub3QgaW1wbGVtZW50ZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnY29tbWFuZCB0aW1lb3V0cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBvcmlnaW5hbEZpbmRFbGVtZW50LCBvcmlnaW5hbEZpbmRFbGVtZW50cztcbiAgICAgIGZ1bmN0aW9uIHN0YXJ0VGltZW91dFNlc3Npb24gKHRpbWVvdXQpIHtcbiAgICAgICAgbGV0IGNhcHMgPSBfLmNsb25lKGRlZmF1bHRDYXBzKTtcbiAgICAgICAgY2Fwcy5uZXdDb21tYW5kVGltZW91dCA9IHRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBzdGFydFNlc3Npb24oY2Fwcyk7XG4gICAgICB9XG5cbiAgICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIG9yaWdpbmFsRmluZEVsZW1lbnQgPSBkLmZpbmRFbGVtZW50O1xuICAgICAgICBkLmZpbmRFbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJldHVybiAnZm9vJztcbiAgICAgICAgfS5iaW5kKGQpO1xuXG4gICAgICAgIG9yaWdpbmFsRmluZEVsZW1lbnRzID0gZC5maW5kRWxlbWVudHM7XG4gICAgICAgIGQuZmluZEVsZW1lbnRzID0gYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGF3YWl0IEIuZGVsYXkoMjAwKTtcbiAgICAgICAgICByZXR1cm4gWydmb28nXTtcbiAgICAgICAgfS5iaW5kKGQpO1xuICAgICAgfSk7XG5cbiAgICAgIGFmdGVyKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZC5maW5kRWxlbWVudCA9IG9yaWdpbmFsRmluZEVsZW1lbnQ7XG4gICAgICAgIGQuZmluZEVsZW1lbnRzID0gb3JpZ2luYWxGaW5kRWxlbWVudHM7XG4gICAgICB9KTtcblxuXG4gICAgICBpdCgnc2hvdWxkIHNldCBhIGRlZmF1bHQgY29tbWFuZFRpbWVvdXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBuZXdTZXNzaW9uID0gYXdhaXQgc3RhcnRUaW1lb3V0U2Vzc2lvbigpO1xuICAgICAgICBkLm5ld0NvbW1hbmRUaW1lb3V0TXMuc2hvdWxkLmJlLmFib3ZlKDApO1xuICAgICAgICBhd2FpdCBlbmRTZXNzaW9uKG5ld1Nlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHRpbWVvdXQgb24gY29tbWFuZHMgdXNpbmcgY29tbWFuZFRpbWVvdXQgY2FwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBsZXQgbmV3U2Vzc2lvbiA9IGF3YWl0IHN0YXJ0VGltZW91dFNlc3Npb24oMC4yNSk7XG5cbiAgICAgICAgYXdhaXQgcmVxdWVzdCh7XG4gICAgICAgICAgdXJsOiBgaHR0cDovL2xvY2FsaG9zdDo4MTgxL3dkL2h1Yi9zZXNzaW9uLyR7ZC5zZXNzaW9uSWR9L2VsZW1lbnRgLFxuICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgIGpzb246IHt1c2luZzogJ25hbWUnLCB2YWx1ZTogJ2Zvbyd9LFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgQi5kZWxheSg0MDApO1xuICAgICAgICBsZXQgcmVzID0gYXdhaXQgcmVxdWVzdCh7XG4gICAgICAgICAgdXJsOiBgaHR0cDovL2xvY2FsaG9zdDo4MTgxL3dkL2h1Yi9zZXNzaW9uLyR7ZC5zZXNzaW9uSWR9YCxcbiAgICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICAgIGpzb246IHRydWUsXG4gICAgICAgICAgc2ltcGxlOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICAgICAgcmVzLnN0YXR1cy5zaG91bGQuZXF1YWwoNik7XG4gICAgICAgIHNob3VsZC5lcXVhbChkLnNlc3Npb25JZCwgbnVsbCk7XG4gICAgICAgIHJlcyA9IGF3YWl0IGVuZFNlc3Npb24obmV3U2Vzc2lvbi5zZXNzaW9uSWQpO1xuICAgICAgICByZXMuc3RhdHVzLnNob3VsZC5lcXVhbCg2KTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG5vdCB0aW1lb3V0IHdpdGggY29tbWFuZFRpbWVvdXQgb2YgZmFsc2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBuZXdTZXNzaW9uID0gYXdhaXQgc3RhcnRUaW1lb3V0U2Vzc2lvbigwLjEpO1xuICAgICAgICBsZXQgc3RhcnQgPSBEYXRlLm5vdygpO1xuICAgICAgICBsZXQgcmVzID0gYXdhaXQgcmVxdWVzdCh7XG4gICAgICAgICAgdXJsOiBgaHR0cDovL2xvY2FsaG9zdDo4MTgxL3dkL2h1Yi9zZXNzaW9uLyR7ZC5zZXNzaW9uSWR9L2VsZW1lbnRzYCxcbiAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICBqc29uOiB7dXNpbmc6ICduYW1lJywgdmFsdWU6ICdmb28nfSxcbiAgICAgICAgfSk7XG4gICAgICAgIChEYXRlLm5vdygpIC0gc3RhcnQpLnNob3VsZC5iZS5hYm92ZSgxNTApO1xuICAgICAgICByZXMudmFsdWUuc2hvdWxkLmVxbChbJ2ZvbyddKTtcbiAgICAgICAgYXdhaXQgZW5kU2Vzc2lvbihuZXdTZXNzaW9uLnNlc3Npb25JZCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCBub3QgdGltZW91dCB3aXRoIGNvbW1hbmRUaW1lb3V0IG9mIDAnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGQubmV3Q29tbWFuZFRpbWVvdXRNcyA9IDI7XG4gICAgICAgIGxldCBuZXdTZXNzaW9uID0gYXdhaXQgc3RhcnRUaW1lb3V0U2Vzc2lvbigwKTtcblxuICAgICAgICBhd2FpdCByZXF1ZXN0KHtcbiAgICAgICAgICB1cmw6IGBodHRwOi8vbG9jYWxob3N0OjgxODEvd2QvaHViL3Nlc3Npb24vJHtkLnNlc3Npb25JZH0vZWxlbWVudGAsXG4gICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAganNvbjoge3VzaW5nOiAnbmFtZScsIHZhbHVlOiAnZm9vJ30sXG4gICAgICAgIH0pO1xuICAgICAgICBhd2FpdCBCLmRlbGF5KDQwMCk7XG4gICAgICAgIGxldCByZXMgPSBhd2FpdCByZXF1ZXN0KHtcbiAgICAgICAgICB1cmw6IGBodHRwOi8vbG9jYWxob3N0OjgxODEvd2QvaHViL3Nlc3Npb24vJHtkLnNlc3Npb25JZH1gLFxuICAgICAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICAgICAganNvbjogdHJ1ZSxcbiAgICAgICAgICBzaW1wbGU6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgICAgICByZXMuc3RhdHVzLnNob3VsZC5lcXVhbCgwKTtcbiAgICAgICAgcmVzID0gYXdhaXQgZW5kU2Vzc2lvbihuZXdTZXNzaW9uLnNlc3Npb25JZCk7XG4gICAgICAgIHJlcy5zdGF0dXMuc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICAgIGQubmV3Q29tbWFuZFRpbWVvdXRNcyA9IDYwICogMTAwMDtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG5vdCB0aW1lb3V0IGlmIGl0cyBqdXN0IHRoZSBjb21tYW5kIHRha2luZyBhd2hpbGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxldCBuZXdTZXNzaW9uID0gYXdhaXQgc3RhcnRUaW1lb3V0U2Vzc2lvbigwLjI1KTtcbiAgICAgICAgYXdhaXQgcmVxdWVzdCh7XG4gICAgICAgICAgdXJsOiBgaHR0cDovL2xvY2FsaG9zdDo4MTgxL3dkL2h1Yi9zZXNzaW9uLyR7ZC5zZXNzaW9uSWR9L2VsZW1lbnRgLFxuICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgIGpzb246IHt1c2luZzogJ25hbWUnLCB2YWx1ZTogJ2Zvbyd9LFxuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgQi5kZWxheSg0MDApO1xuICAgICAgICBsZXQgcmVzID0gYXdhaXQgcmVxdWVzdCh7XG4gICAgICAgICAgdXJsOiBgaHR0cDovL2xvY2FsaG9zdDo4MTgxL3dkL2h1Yi9zZXNzaW9uLyR7ZC5zZXNzaW9uSWR9YCxcbiAgICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICAgIGpzb246IHRydWUsXG4gICAgICAgICAgc2ltcGxlOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICAgICAgcmVzLnN0YXR1cy5zaG91bGQuZXF1YWwoNik7XG4gICAgICAgIHNob3VsZC5lcXVhbChkLnNlc3Npb25JZCwgbnVsbCk7XG4gICAgICAgIHJlcyA9IGF3YWl0IGVuZFNlc3Npb24obmV3U2Vzc2lvbi5zZXNzaW9uSWQpO1xuICAgICAgICByZXMuc3RhdHVzLnNob3VsZC5lcXVhbCg2KTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIG5vdCBoYXZlIGEgdGltZXIgcnVubmluZyBiZWZvcmUgb3IgYWZ0ZXIgYSBzZXNzaW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBzaG91bGQubm90LmV4aXN0KGQubm9Db21tYW5kVGltZXIpO1xuICAgICAgICBsZXQgbmV3U2Vzc2lvbiA9IGF3YWl0IHN0YXJ0VGltZW91dFNlc3Npb24oMC4yNSk7XG4gICAgICAgIG5ld1Nlc3Npb24uc2Vzc2lvbklkLnNob3VsZC5lcXVhbChkLnNlc3Npb25JZCk7XG4gICAgICAgIHNob3VsZC5leGlzdChkLm5vQ29tbWFuZFRpbWVyKTtcbiAgICAgICAgYXdhaXQgZW5kU2Vzc2lvbihuZXdTZXNzaW9uLnNlc3Npb25JZCk7XG4gICAgICAgIHNob3VsZC5ub3QuZXhpc3QoZC5ub0NvbW1hbmRUaW1lcik7XG4gICAgICB9KTtcblxuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ3NldHRpbmdzIGFwaScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIGQuc2V0dGluZ3MgPSBuZXcgRGV2aWNlU2V0dGluZ3Moe2lnbm9yZVVuaW1wb3J0YW50Vmlld3M6IGZhbHNlfSk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgYmUgYWJsZSB0byBnZXQgc2V0dGluZ3Mgb2JqZWN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgICBkLnNldHRpbmdzLmdldFNldHRpbmdzKCkuaWdub3JlVW5pbXBvcnRhbnRWaWV3cy5zaG91bGQuYmUuZmFsc2U7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3Igd2hlbiB1cGRhdGVTZXR0aW5ncyBtZXRob2QgaXMgbm90IGRlZmluZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGF3YWl0IGQuc2V0dGluZ3MudXBkYXRlKHtpZ25vcmVVbmltcG9ydGFudFZpZXdzOiB0cnVlfSkuc2hvdWxkLmV2ZW50dWFsbHlcbiAgICAgICAgICAgICAgICAuYmUucmVqZWN0ZWRXaXRoKCdvblNldHRpbmdzVXBkYXRlJyk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgdGhyb3cgZXJyb3IgZm9yIGludmFsaWQgdXBkYXRlIG9iamVjdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgYXdhaXQgZC5zZXR0aW5ncy51cGRhdGUoJ2ludmFsaWQganNvbicpLnNob3VsZC5ldmVudHVhbGx5XG4gICAgICAgICAgICAgICAgLmJlLnJlamVjdGVkV2l0aCgnSlNPTicpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgndW5leHBlY3RlZCBleGl0cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGl0KCdzaG91bGQgcmVqZWN0IGEgY3VycmVudCBjb21tYW5kIHdoZW4gdGhlIGRyaXZlciBjcmFzaGVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBkLl9vbGRHZXRTdGF0dXMgPSBkLmdldFN0YXR1cztcbiAgICAgICAgZC5nZXRTdGF0dXMgPSBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgYXdhaXQgQi5kZWxheSg1MDAwKTtcbiAgICAgICAgfS5iaW5kKGQpO1xuICAgICAgICBsZXQgcCA9IHJlcXVlc3Qoe1xuICAgICAgICAgIHVybDogJ2h0dHA6Ly9sb2NhbGhvc3Q6ODE4MS93ZC9odWIvc3RhdHVzJyxcbiAgICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICAgIGpzb246IHRydWUsXG4gICAgICAgICAgc2ltcGxlOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gbWFrZSBzdXJlIHRoYXQgdGhlIHJlcXVlc3QgZ2V0cyB0byB0aGUgc2VydmVyIGJlZm9yZSBvdXIgc2h1dGRvd25cbiAgICAgICAgYXdhaXQgQi5kZWxheSgxMDApO1xuICAgICAgICBkLnN0YXJ0VW5leHBlY3RlZFNodXRkb3duKG5ldyBFcnJvcignQ3Jhc2h5dGltZXMnKSk7XG4gICAgICAgIGxldCByZXMgPSBhd2FpdCBwO1xuICAgICAgICByZXMuc3RhdHVzLnNob3VsZC5lcXVhbCgxMyk7XG4gICAgICAgIHJlcy52YWx1ZS5tZXNzYWdlLnNob3VsZC5jb250YWluKCdDcmFzaHl0aW1lcycpO1xuICAgICAgICBhd2FpdCBkLm9uVW5leHBlY3RlZFNodXRkb3duLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0NyYXNoeXRpbWVzJyk7XG4gICAgICAgIGQuZ2V0U3RhdHVzID0gZC5fb2xkR2V0U3RhdHVzO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnZXZlbnQgdGltaW5ncycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGl0KCdzaG91bGQgbm90IGFkZCB0aW1pbmdzIGlmIG5vdCB1c2luZyBvcHQtaW4gY2FwJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICBsZXQgc2Vzc2lvbiA9IGF3YWl0IHN0YXJ0U2Vzc2lvbihkZWZhdWx0Q2Fwcyk7XG4gICAgICAgIGxldCByZXMgPSBhd2FpdCBnZXRTZXNzaW9uKHNlc3Npb24uc2Vzc2lvbklkKTtcbiAgICAgICAgc2hvdWxkLm5vdC5leGlzdChyZXMuZXZlbnRzKTtcbiAgICAgICAgYXdhaXQgZW5kU2Vzc2lvbihzZXNzaW9uLnNlc3Npb25JZCk7XG4gICAgICB9KTtcbiAgICAgIGl0KCdzaG91bGQgYWRkIHN0YXJ0IHNlc3Npb24gdGltaW5ncycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgI