UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

204 lines 29.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const net_1 = require("net"); const promisify_event_1 = __importDefault(require("promisify-event")); const events_1 = __importDefault(require("events")); const delay_1 = __importDefault(require("../../../../../../utils/delay")); const client_functions_1 = require("../../../../utils/client-functions"); const commands_1 = __importDefault(require("./commands")); const CONNECTION_TIMEOUT = 30000; const CONNECTION_RETRY_DELAY = 300; const MAX_RESIZE_RETRY_COUNT = 2; const HEADER_SEPARATOR = ':'; module.exports = class MarionetteClient { constructor(port = 2828, runtimeInfo, host = '127.0.0.1') { this.currentPacketNumber = 1; this.events = new events_1.default(); this.port = port; this.host = host; this.socket = new net_1.Socket(); this.buffer = Buffer.alloc(0); this.getPacketPromise = Promise.resolve(); this.sendPacketPromise = Promise.resolve(); this._runtimeInfo = runtimeInfo; this._windowHandles = {}; this.protocolInfo = { applicationType: '', marionetteProtocol: '', }; this.sessionInfo = null; } get activeWindowId() { return this._runtimeInfo.activeWindowId; } async _attemptToConnect(port, host) { this.socket.connect(port, host); const connectionPromise = Promise.race([ (0, promisify_event_1.default)(this.socket, 'connect'), (0, promisify_event_1.default)(this.socket, 'error'), ]); return await connectionPromise .then(() => true) .catch(() => { this.socket.removeAllListeners('connect'); return (0, delay_1.default)(CONNECTION_RETRY_DELAY); }); } async _connectSocket(port, host) { const connectionStartTime = Date.now(); let connected = await this._attemptToConnect(port, host); while (!connected && Date.now() - connectionStartTime < CONNECTION_TIMEOUT) connected = await this._attemptToConnect(port, host); if (!connected) throw new Error('Unable to connect'); this.socket.on('data', data => this._handleNewData(data)); } async _writeSocket(message) { if (!this.socket.write(message)) await (0, promisify_event_1.default)(this.socket, 'drain'); } _handleNewData(data) { if (!data) return; this.buffer = Buffer.concat([this.buffer, data]); this.events.emit('new-data'); } _getPacket() { this.getPacketPromise = this.getPacketPromise.then(async () => { let headerEndIndex = this.buffer.indexOf(HEADER_SEPARATOR); while (headerEndIndex < 0) { await (0, promisify_event_1.default)(this.events, 'new-data'); headerEndIndex = this.buffer.indexOf(HEADER_SEPARATOR); } const packet = { length: NaN, body: null, }; packet.length = parseInt(this.buffer.toString('utf8', 0, headerEndIndex), 10) || 0; const bodyStartIndex = headerEndIndex + HEADER_SEPARATOR.length; const bodyEndIndex = bodyStartIndex + packet.length; if (packet.length) { while (this.buffer.length < bodyEndIndex) await (0, promisify_event_1.default)(this.events, 'new-data'); packet.body = JSON.parse(this.buffer.toString('utf8', bodyStartIndex, bodyEndIndex)); } this.buffer = this.buffer.slice(bodyEndIndex); return packet; }); return this.getPacketPromise; } _sendPacket(payload) { this.sendPacketPromise = this.sendPacketPromise.then(async () => { const body = [0, this.currentPacketNumber++, payload.command, payload.parameters]; const serialized = JSON.stringify(body); const message = Buffer.byteLength(serialized, 'utf8') + HEADER_SEPARATOR + serialized; this._writeSocket(message); }); return this.sendPacketPromise; } _throwMarionetteError(error) { throw new Error(`${error.error}${error.message ? ': ' + error.message : ''}`); } async _switchToWindow(windowHandle) { await this._getResponse({ command: commands_1.default.switchToWindow, parameters: { handle: windowHandle }, }); } async _getActiveWindowHandle() { const windowHandles = await this._getResponse({ command: commands_1.default.getWindowHandles, }); for (const handle of windowHandles) { await this._switchToWindow(handle); const title = await this._getResponse({ command: commands_1.default.getTitle }); if (title.value.includes(this.activeWindowId)) return handle; } return null; } async _ensureActiveWindow() { let handle = this._windowHandles[this.activeWindowId]; if (handle) { await this._switchToWindow(handle); return; } handle = await this._getActiveWindowHandle(); if (handle) this._windowHandles[this.activeWindowId] = handle; } async _request(packet) { await this._ensureActiveWindow(); return this._getResponse(packet); } async _getResponse(packet) { const packetNumber = this.currentPacketNumber; await this._sendPacket(packet); let responsePacket = await this._getPacket(); while (!responsePacket.body || responsePacket.body[1] !== packetNumber) responsePacket = await this._getPacket(); if (responsePacket.body[2]) this._throwMarionetteError(responsePacket.body[2]); return responsePacket.body[3]; } async _getScreenshotRawData(fullPage = false) { return await this._request({ command: commands_1.default.takeScreenshot, parameters: { full: fullPage, hash: false, scroll: false, }, }); } async connect() { await this._connectSocket(this.port, this.host); const infoPacket = await this._getPacket(); this.protocolInfo = { applicationType: infoPacket.body.applicationType, marionetteProtocol: infoPacket.body.marionetteProtocol, }; this.sessionInfo = await this._getResponse({ command: commands_1.default.newSession }); } dispose() { this.socket.end(); this.buffer = null; } async executeScript(code) { return await this._request({ command: commands_1.default.executeScript, parameters: { script: `return (${code})()` }, }); } async getScreenshotData(fullPage) { const frameData = await this._getScreenshotRawData(fullPage); return Buffer.from(frameData.value, 'base64'); } async setWindowSize(width, height) { let { value: pageRect } = await this.executeScript(client_functions_1.GET_WINDOW_DIMENSIONS_INFO_SCRIPT); let attemptCounter = 0; while (attemptCounter++ < MAX_RESIZE_RETRY_COUNT && (pageRect.width !== width || pageRect.height !== height)) { const currentRect = await this._request({ command: commands_1.default.getWindowRect }); await this._request({ command: commands_1.default.setWindowRect, parameters: { x: currentRect.x, y: currentRect.y, width: width + (currentRect.width - pageRect.width), height: height + (currentRect.height - pageRect.height), }, }); ({ value: pageRect } = await this.executeScript(client_functions_1.GET_WINDOW_DIMENSIONS_INFO_SCRIPT)); } } async quit() { await this._request({ command: commands_1.default.quit }); } // NOTE: This method is empty because of the code structure async closeBrowserChildWindow() { } }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYnJvd3Nlci9wcm92aWRlci9idWlsdC1pbi9kZWRpY2F0ZWQvZmlyZWZveC9tYXJpb25ldHRlLWNsaWVudC9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZCQUE2QjtBQUM3QixzRUFBNkM7QUFDN0Msb0RBQWtDO0FBQ2xDLDBFQUFrRDtBQUNsRCx5RUFBdUY7QUFDdkYsMERBQWtDO0FBR2xDLE1BQU0sa0JBQWtCLEdBQU8sS0FBSyxDQUFDO0FBQ3JDLE1BQU0sc0JBQXNCLEdBQUcsR0FBRyxDQUFDO0FBQ25DLE1BQU0sc0JBQXNCLEdBQUcsQ0FBQyxDQUFDO0FBQ2pDLE1BQU0sZ0JBQWdCLEdBQVMsR0FBRyxDQUFDO0FBRW5DLE1BQU0sQ0FBQyxPQUFPLEdBQUcsTUFBTSxnQkFBZ0I7SUFDbkMsWUFBYSxJQUFJLEdBQUcsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEdBQUcsV0FBVztRQUNyRCxJQUFJLENBQUMsbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxNQUFNLEdBQWdCLElBQUksZ0JBQVksRUFBRSxDQUFDO1FBQzlDLElBQUksQ0FBQyxJQUFJLEdBQWtCLElBQUksQ0FBQztRQUNoQyxJQUFJLENBQUMsSUFBSSxHQUFrQixJQUFJLENBQUM7UUFDaEMsSUFBSSxDQUFDLE1BQU0sR0FBZ0IsSUFBSSxZQUFNLEVBQUUsQ0FBQztRQUN4QyxJQUFJLENBQUMsTUFBTSxHQUFnQixNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxnQkFBZ0IsR0FBTSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDN0MsSUFBSSxDQUFDLGlCQUFpQixHQUFLLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUU3QyxJQUFJLENBQUMsWUFBWSxHQUFLLFdBQVcsQ0FBQztR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TSxHQUFHLENBQUMsV0FBVyxDQUFDLE1BQU0sR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDO2lCQUMxRDthQUNKLENBQUMsQ0FBQztZQUVILENBQUMsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLG9EQUFpQyxDQUFDLENBQUMsQ0FBQztTQUN2RjtJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsSUFBSTtRQUNOLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLE9BQU8sRUFBRSxrQkFBUSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUVELDJEQUEyRDtJQUMzRCxLQUFLLENBQUMsdUJBQXVCO0lBQzdCLENBQUM7Q0FDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU29ja2V0IH0gZnJvbSAnbmV0JztcbmltcG9ydCBwcm9taXNpZnlFdmVudCBmcm9tICdwcm9taXNpZnktZXZlbnQnO1xuaW1wb3J0IEV2ZW50RW1pdHRlciBmcm9tICdldmVudHMnO1xuaW1wb3J0IGRlbGF5IGZyb20gJy4uLy4uLy4uLy4uLy4uLy4uL3V0aWxzL2RlbGF5JztcbmltcG9ydCB7IEdFVF9XSU5ET1dfRElNRU5TSU9OU19JTkZPX1NDUklQVCB9IGZyb20gJy4uLy4uLy4uLy4uL3V0aWxzL2NsaWVudC1mdW5jdGlvbnMnO1xuaW1wb3J0IENPTU1BTkRTIGZyb20gJy4vY29tbWFuZHMnO1xuXG5cbmNvbnN0IENPTk5FQ1RJT05fVElNRU9VVCAgICAgPSAzMDAwMDtcbmNvbnN0IENPTk5FQ1RJT05fUkVUUllfREVMQVkgPSAzMDA7XG5jb25zdCBNQVhfUkVTSVpFX1JFVFJZX0NPVU5UID0gMjtcbmNvbnN0IEhFQURFUl9TRVBBUkFUT1IgICAgICAgPSAnOic7XG5cbm1vZHVsZS5leHBvcnRzID0gY2xhc3MgTWFyaW9uZXR0ZUNsaWVudCB7XG4gICAgY29uc3RydWN0b3IgKHBvcnQgPSAyODI4LCBydW50aW1lSW5mbywgaG9zdCA9ICcxMjcuMC4wLjEnKSB7XG4gICAgICAgIHRoaXMuY3VycmVudFBhY2tldE51bWJlciA9IDE7XG4gICAgICAgIHRoaXMuZXZlbnRzICAgICAgICAgICAgICA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAgICAgdGhpcy5wb3J0ICAgICAgICAgICAgICAgID0gcG9ydDtcbiAgICAgICAgdGhpcy5ob3N0ICAgICAgICAgICAgICAgID0gaG9zdDtcbiAgICAgICAgdGhpcy5zb2NrZXQgICAgICAgICAgICAgID0gbmV3IFNvY2tldCgpO1xuICAgICAgICB0aGlzLmJ1ZmZlciAgICAgICAgICAgICAgPSBCdWZmZXIuYWxsb2MoMCk7XG4gICAgICAgIHRoaXMuZ2V0UGFja2V0UHJvbWlzZSAgICA9IFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB0aGlzLnNlbmRQYWNrZXRQcm9taXNlICAgPSBQcm9taXNlLnJlc29sdmUoKTtcblxuICAgICAgICB0aGlzLl9ydW50aW1lSW5mbyAgID0gcnVudGltZUluZm87XG4gICAgICAgIHRoaXMuX3dpbmRvd0hhbmRsZXMgPSB7fTtcblxuICAgICAgICB0aGlzLnByb3RvY29sSW5mbyA9IHtcbiAgICAgICAgICAgIGFwcGxpY2F0aW9uVHlwZTogICAgJycsXG4gICAgICAgICAgICBtYXJpb25ldHRlUHJvdG9jb2w6ICcnLFxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMuc2Vzc2lvbkluZm8gPSBudWxsO1xuICAgIH1cblxuICAgIGdldCBhY3RpdmVXaW5kb3dJZCAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ydW50aW1lSW5mby5hY3RpdmVXaW5kb3dJZDtcbiAgICB9XG5cbiAgICBhc3luYyBfYXR0ZW1wdFRvQ29ubmVjdCAocG9ydCwgaG9zdCkge1xuICAgICAgICB0aGlzLnNvY2tldC5jb25uZWN0KHBvcnQsIGhvc3QpO1xuXG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25Qcm9taXNlID0gUHJvbWlzZS5yYWNlKFtcbiAgICAgICAgICAgIHByb21pc2lmeUV2ZW50KHRoaXMuc29ja2V0LCAnY29ubmVjdCcpLFxuICAgICAgICAgICAgcHJvbWlzaWZ5RXZlbnQodGhpcy5zb2NrZXQsICdlcnJvcicpLFxuICAgICAgICBdKTtcblxuICAgICAgICByZXR1cm4gYXdhaXQgY29ubmVjdGlvblByb21pc2VcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHRydWUpXG4gICAgICAgICAgICAuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc29ja2V0LnJlbW92ZUFsbExpc3RlbmVycygnY29ubmVjdCcpO1xuICAgICAgICAgICAgICAgIHJldHVybiBkZWxheShDT05ORUNUSU9OX1JFVFJZX0RFTEFZKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFzeW5jIF9jb25uZWN0U29ja2V0IChwb3J0LCBob3N0KSB7XG4gICAgICAgIGNvbnN0IGNvbm5lY3Rpb25TdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIGxldCBjb25uZWN0ZWQgPSBhd2FpdCB0aGlzLl9hdHRlbXB0VG9Db25uZWN0KHBvcnQsIGhvc3QpO1xuXG4gICAgICAgIHdoaWxlICghY29ubmVjdGVkICYmIERhdGUubm93KCkgLSBjb25uZWN0aW9uU3RhcnRUaW1lIDwgQ09OTkVDVElPTl9USU1FT1VUKVxuICAgICAgICAgICAgY29ubmVjdGVkID0gYXdhaXQgdGhpcy5fYXR0ZW1wdFRvQ29ubmVjdChwb3J0LCBob3N0KTtcblxuICAgICAgICBpZiAoIWNvbm5lY3RlZClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGNvbm5lY3QnKTtcblxuICAgICAgICB0aGlzLnNvY2tldC5vbignZGF0YScsIGRhdGEgPT4gdGhpcy5faGFuZGxlTmV3RGF0YShkYXRhKSk7XG4gICAgfVxuXG4gICAgYXN5bmMgX3dyaXRlU29ja2V0IChtZXNzYWdlKSB7XG4gICAgICAgIGlmICghdGhpcy5zb2NrZXQud3JpdGUobWVzc2FnZSkpXG4gICAgICAgICAgICBhd2FpdCBwcm9taXNpZnlFdmVudCh0aGlzLnNvY2tldCwgJ2RyYWluJyk7XG4gICAgfVxuXG4gICAgX2hhbmRsZU5ld0RhdGEgKGRhdGEpIHtcbiAgICAgICAgaWYgKCFkYXRhKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIHRoaXMuYnVmZmVyID0gQnVmZmVyLmNvbmNhdChbdGhpcy5idWZmZXIsIGRhdGFdKTtcblxuICAgICAgICB0aGlzLmV2ZW50cy5lbWl0KCduZXctZGF0YScpO1xuICAgIH1cblxuICAgIF9nZXRQYWNrZXQgKCkge1xuICAgICAgICB0aGlzLmdldFBhY2tldFByb21pc2UgPSB0aGlzLmdldFBhY2tldFByb21pc2UudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBsZXQgaGVhZGVyRW5kSW5kZXggPSB0aGlzLmJ1ZmZlci5pbmRleE9mKEhFQURFUl9TRVBBUkFUT1IpO1xuXG4gICAgICAgICAgICB3aGlsZSAoaGVhZGVyRW5kSW5kZXggPCAwKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgcHJvbWlzaWZ5RXZlbnQodGhpcy5ldmVudHMsICduZXctZGF0YScpO1xuXG4gICAgICAgICAgICAgICAgaGVhZGVyRW5kSW5kZXggPSB0aGlzLmJ1ZmZlci5pbmRleE9mKEhFQURFUl9TRVBBUkFUT1IpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBwYWNrZXQgPSB7XG4gICAgICAgICAgICAgICAgbGVuZ3RoOiBOYU4sXG4gICAgICAgICAgICAgICAgYm9keTogICBudWxsLFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcGFja2V0Lmxlbmd0aCA9IHBhcnNlSW50KHRoaXMuYnVmZmVyLnRvU3RyaW5nKCd1dGY4JywgMCwgaGVhZGVyRW5kSW5kZXgpLCAxMCkgfHwgMDtcblxuICAgICAgICAgICAgY29uc3QgYm9keVN0YXJ0SW5kZXggPSBoZWFkZXJFbmRJbmRleCArIEhFQURFUl9TRVBBUkFUT1IubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgYm9keUVuZEluZGV4ICAgPSBib2R5U3RhcnRJbmRleCArIHBhY2tldC5sZW5ndGg7XG5cbiAgICAgICAgICAgIGlmIChwYWNrZXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHRoaXMuYnVmZmVyLmxlbmd0aCA8IGJvZHlFbmRJbmRleClcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgcHJvbWlzaWZ5RXZlbnQodGhpcy5ldmVudHMsICduZXctZGF0YScpO1xuXG4gICAgICAgICAgICAgICAgcGFja2V0LmJvZHkgPSBKU09OLnBhcnNlKHRoaXMuYnVmZmVyLnRvU3RyaW5nKCd1dGY4JywgYm9keVN0YXJ0SW5kZXgsIGJvZHlFbmRJbmRleCkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IHRoaXMuYnVmZmVyLnNsaWNlKGJvZHlFbmRJbmRleCk7XG5cbiAgICAgICAgICAgIHJldHVybiBwYWNrZXQ7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmdldFBhY2tldFByb21pc2U7XG4gICAgfVxuXG4gICAgX3NlbmRQYWNrZXQgKHBheWxvYWQpIHtcbiAgICAgICAgdGhpcy5zZW5kUGFja2V0UHJvbWlzZSA9IHRoaXMuc2VuZFBhY2tldFByb21pc2UudGhlbihhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBib2R5ICAgICAgID0gWzAsIHRoaXMuY3VycmVudFBhY2tldE51bWJlcisrLCBwYXlsb2FkLmNvbW1hbmQsIHBheWxvYWQucGFyYW1ldGVyc107XG4gICAgICAgICAgICBjb25zdCBzZXJpYWxpemVkID0gSlNPTi5zdHJpbmdpZnkoYm9keSk7XG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlICAgID0gQnVmZmVyLmJ5dGVMZW5ndGgoc2VyaWFsaXplZCwgJ3V0ZjgnKSArIEhFQURFUl9TRVBBUkFUT1IgKyBzZXJpYWxpemVkO1xuXG4gICAgICAgICAgICB0aGlzLl93cml0ZVNvY2tldChtZXNzYWdlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc2VuZFBhY2tldFByb21pc2U7XG4gICAgfVxuXG4gICAgX3Rocm93TWFyaW9uZXR0ZUVycm9yIChlcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXJyb3IuZXJyb3J9JHtlcnJvci5tZXNzYWdlID8gJzogJyArIGVycm9yLm1lc3NhZ2UgOiAnJ31gKTtcbiAgICB9XG5cbiAgICBhc3luYyBfc3dpdGNoVG9XaW5kb3cgKHdpbmRvd0hhbmRsZSkge1xuICAgICAgICBhd2FpdCB0aGlzLl9nZXRSZXNwb25zZSh7XG4gICAgICAgICAgICBjb21tYW5kOiAgICBDT01NQU5EUy5zd2l0Y2hUb1dpbmRvdyxcbiAgICAgICAgICAgIHBhcmFtZXRlcnM6IHsgaGFuZGxlOiB3aW5kb3dIYW5kbGUgfSxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYXN5bmMgX2dldEFjdGl2ZVdpbmRvd0hhbmRsZSAoKSB7XG4gICAgICAgIGNvbnN0IHdpbmRvd0hhbmRsZXMgPSBhd2FpdCB0aGlzLl9nZXRSZXNwb25zZSh7XG4gICAgICAgICAgICBjb21tYW5kOiBDT01NQU5EUy5nZXRXaW5kb3dIYW5kbGVzLFxuICAgICAgICB9KTtcblxuICAgICAgICBmb3IgKGNvbnN0IGhhbmRsZSBvZiB3aW5kb3dIYW5kbGVzKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9zd2l0Y2hUb1dpbmRvdyhoYW5kbGUpO1xuXG4gICAgICAgICAgICBjb25zdCB0aXRsZSA9IGF3YWl0IHRoaXMuX2dldFJlc3BvbnNlKHsgY29tbWFuZDogQ09NTUFORFMuZ2V0VGl0bGUgfSk7XG5cbiAgICAgICAgICAgIGlmICh0aXRsZS52YWx1ZS5pbmNsdWRlcyh0aGlzLmFjdGl2ZVdpbmRvd0lkKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgYXN5bmMgX2Vuc3VyZUFjdGl2ZVdpbmRvdyAoKSB7XG4gICAgICAgIGxldCBoYW5kbGUgPSB0aGlzLl93aW5kb3dIYW5kbGVzW3RoaXMuYWN0aXZlV2luZG93SWRdO1xuXG4gICAgICAgIGlmIChoYW5kbGUpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX3N3aXRjaFRvV2luZG93KGhhbmRsZSk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGhhbmRsZSA9IGF3YWl0IHRoaXMuX2dldEFjdGl2ZVdpbmRvd0hhbmRsZSgpO1xuXG4gICAgICAgIGlmIChoYW5kbGUpXG4gICAgICAgICAgICB0aGlzLl93aW5kb3dIYW5kbGVzW3RoaXMuYWN0aXZlV2luZG93SWRdID0gaGFuZGxlO1xuICAgIH1cblxuICAgIGFzeW5jIF9yZXF1ZXN0IChwYWNrZXQpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5fZW5zdXJlQWN0aXZlV2luZG93KCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldFJlc3BvbnNlKHBhY2tldCk7XG4gICAgfVxuXG4gICAgYXN5bmMgX2dldFJlc3BvbnNlIChwYWNrZXQpIHtcbiAgICAgICAgY29uc3QgcGFja2V0TnVtYmVyID0gdGhpcy5jdXJyZW50UGFja2V0TnVtYmVyO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuX3NlbmRQYWNrZXQocGFja2V0KTtcblxuICAgICAgICBsZXQgcmVzcG9uc2VQYWNrZXQgPSBhd2FpdCB0aGlzLl9nZXRQYWNrZXQoKTtcblxuICAgICAgICB3aGlsZSAoIXJlc3BvbnNlUGFja2V0LmJvZHkgfHwgcmVzcG9uc2VQYWNrZXQuYm9keVsxXSAhPT0gcGFja2V0TnVtYmVyKVxuICAgICAgICAgICAgcmVzcG9uc2VQYWNrZXQgPSBhd2FpdCB0aGlzLl9nZXRQYWNrZXQoKTtcblxuICAgICAgICBpZiAocmVzcG9uc2VQYWNrZXQuYm9keVsyXSlcbiAgICAgICAgICAgIHRoaXMuX3Rocm93TWFyaW9uZXR0ZUVycm9yKHJlc3BvbnNlUGFja2V0LmJvZHlbMl0pO1xuXG4gICAgICAgIHJldHVybiByZXNwb25zZVBhY2tldC5ib2R5WzNdO1xuICAgIH1cblxuICAgIGFzeW5jIF9nZXRTY3JlZW5zaG90UmF3RGF0YSAoZnVsbFBhZ2UgPSBmYWxzZSkge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5fcmVxdWVzdCh7XG4gICAgICAgICAgICBjb21tYW5kOiAgICBDT01NQU5EUy50YWtlU2NyZWVuc2hvdCxcbiAgICAgICAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgICAgICBmdWxsOiAgIGZ1bGxQYWdlLFxuICAgICAgICAgICAgICAgIGhhc2g6ICAgZmFsc2UsXG4gICAgICAgICAgICAgICAgc2Nyb2xsOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFzeW5jIGNvbm5lY3QgKCkge1xuICAgICAgICBhd2FpdCB0aGlzLl9jb25uZWN0U29ja2V0KHRoaXMucG9ydCwgdGhpcy5ob3N0KTtcblxuICAgICAgICBjb25zdCBpbmZvUGFja2V0ID0gYXdhaXQgdGhpcy5fZ2V0UGFja2V0KCk7XG5cbiAgICAgICAgdGhpcy5wcm90b2NvbEluZm8gPSB7XG4gICAgICAgICAgICBhcHBsaWNhdGlvblR5cGU6ICAgIGluZm9QYWNrZXQuYm9keS5hcHBsaWNhdGlvblR5cGUsXG4gICAgICAgICAgICBtYXJpb25ldHRlUHJvdG9jb2w6IGluZm9QYWNrZXQuYm9keS5tYXJpb25ldHRlUHJvdG9jb2wsXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5zZXNzaW9uSW5mbyA9IGF3YWl0IHRoaXMuX2dldFJlc3BvbnNlKHsgY29tbWFuZDogQ09NTUFORFMubmV3U2Vzc2lvbiB9KTtcbiAgICB9XG5cbiAgICBkaXNwb3NlICgpIHtcbiAgICAgICAgdGhpcy5zb2NrZXQuZW5kKCk7XG4gICAgICAgIHRoaXMuYnVmZmVyID0gbnVsbDtcbiAgICB9XG5cbiAgICBhc3luYyBleGVjdXRlU2NyaXB0IChjb2RlKSB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLl9yZXF1ZXN0KHtcbiAgICAgICAgICAgIGNvbW1hbmQ6ICAgIENPTU1BTkRTLmV4ZWN1dGVTY3JpcHQsXG4gICAgICAgICAgICBwYXJhbWV0ZXJzOiB7IHNjcmlwdDogYHJldHVybiAoJHtjb2RlfSkoKWAgfSxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYXN5bmMgZ2V0U2NyZWVuc2hvdERhdGEgKGZ1bGxQYWdlKSB7XG4gICAgICAgIGNvbnN0IGZyYW1lRGF0YSA9IGF3YWl0IHRoaXMuX2dldFNjcmVlbnNob3RSYXdEYXRhKGZ1bGxQYWdlKTtcblxuICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oZnJhbWVEYXRhLnZhbHVlLCAnYmFzZTY0Jyk7XG4gICAgfVxuXG4gICAgYXN5bmMgc2V0V2luZG93U2l6ZSAod2lkdGgsIGhlaWdodCkge1xuICAgICAgICBsZXQgeyB2YWx1ZTogcGFnZVJlY3QgfSA9IGF3YWl0IHRoaXMuZXhlY3V0ZVNjcmlwdChHRVRfV0lORE9XX0RJTUVOU0lPTlNfSU5GT19TQ1JJUFQpO1xuICAgICAgICBsZXQgYXR0ZW1wdENvdW50ZXIgICAgICA9IDA7XG5cbiAgICAgICAgd2hpbGUgKGF0dGVtcHRDb3VudGVyKysgPCBNQVhfUkVTSVpFX1JFVFJZX0NPVU5UICYmIChwYWdlUmVjdC53aWR0aCAhPT0gd2lkdGggfHwgcGFnZVJlY3QuaGVpZ2h0ICE9PSBoZWlnaHQpKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50UmVjdCA9IGF3YWl0IHRoaXMuX3JlcXVlc3QoeyBjb21tYW5kOiBDT01NQU5EUy5nZXRXaW5kb3dSZWN0IH0pO1xuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9yZXF1ZXN0KHtcbiAgICAgICAgICAgICAgICBjb21tYW5kOiBDT01NQU5EUy5zZXRXaW5kb3dSZWN0LFxuXG4gICAgICAgICAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgICAgICAgICAgICB4OiAgICAgIGN1cnJlbnRSZWN0LngsXG4gICAgICAgICAgICAgICAgICAgIHk6ICAgICAgY3VycmVudFJlY3QueSxcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6ICB3aWR0aCArIChjdXJyZW50UmVjdC53aWR0aCAtIHBhZ2VSZWN0LndpZHRoKSxcbiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiBoZWlnaHQgKyAoY3VycmVudFJlY3QuaGVpZ2h0IC0gcGFnZVJlY3QuaGVpZ2h0KSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICh7IHZhbHVlOiBwYWdlUmVjdCB9ID0gYXdhaXQgdGhpcy5leGVjdXRlU2NyaXB0KEdFVF9XSU5ET1dfRElNRU5TSU9OU19JTkZPX1NDUklQVCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgcXVpdCAoKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX3JlcXVlc3QoeyBjb21tYW5kOiBDT01NQU5EUy5xdWl0IH0pO1xuICAgIH1cblxuICAgIC8vIE5PVEU6IFRoaXMgbWV0aG9kIGlzIGVtcHR5IGJlY2F1c2Ugb2YgdGhlIGNvZGUgc3RydWN0dXJlXG4gICAgYXN5bmMgY2xvc2VCcm93c2VyQ2hpbGRXaW5kb3cgKCkge1xuICAgIH1cbn07XG5cbiJdfQ==