UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

449 lines 71.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const debug_1 = __importDefault(require("debug")); const time_limit_promise_1 = __importDefault(require("time-limit-promise")); const events_1 = require("events"); const mustache_1 = __importDefault(require("mustache")); const lodash_1 = require("lodash"); const parse_user_agent_1 = require("../../utils/parse-user-agent"); const read_file_relative_1 = require("read-file-relative"); const promisify_event_1 = __importDefault(require("promisify-event")); const nanoid_1 = require("nanoid"); const command_1 = __importDefault(require("./command")); const status_1 = __importDefault(require("./status")); const heartbeat_status_1 = __importDefault(require("./heartbeat-status")); const runtime_1 = require("../../errors/runtime"); const types_1 = require("../../errors/types"); const warning_log_1 = __importDefault(require("../../notifications/warning-log")); const service_routes_1 = __importDefault(require("./service-routes")); const browser_connection_timeouts_1 = require("../../utils/browser-connection-timeouts"); const tracker_1 = __importDefault(require("./tracker")); const getBrowserConnectionDebugScope = (id) => `testcafe:browser:connection:${id}`; const IDLE_PAGE_TEMPLATE = (0, read_file_relative_1.readSync)('../../client/browser/idle-page/index.html.mustache'); const DEFAULT_BROWSER_CONNECTION_OPTIONS = { disableMultipleWindows: false, developmentMode: false, nativeAutomation: false, }; class BrowserConnection extends events_1.EventEmitter { constructor(gateway, browserInfo, permanent, options = {}, messageBus) { super(); this._currentTestRun = null; this.url = ''; this.idleUrl = ''; this.forcedIdleUrl = ''; this.initScriptUrl = ''; this.heartbeatUrl = ''; this.statusUrl = ''; this.activeWindowIdUrl = ''; this.ensureWindowInNativeAutomationUrl = ''; this.closeWindowUrl = ''; this.statusDoneUrl = ''; this.heartbeatRelativeUrl = ''; this.statusRelativeUrl = ''; this.statusDoneRelativeUrl = ''; this.idleRelativeUrl = ''; this.openFileProtocolRelativeUrl = ''; this.openFileProtocolUrl = ''; this.dispatchNativeAutomationEventRelativeUrl = ''; this.dispatchNativeAutomationEventSequenceRelativeUrl = ''; this.parseSelectorRelativeUrl = ''; this.HEARTBEAT_TIMEOUT = browser_connection_timeouts_1.HEARTBEAT_TIMEOUT; this.BROWSER_CLOSE_TIMEOUT = browser_connection_timeouts_1.BROWSER_CLOSE_TIMEOUT; this.BROWSER_RESTART_TIMEOUT = browser_connection_timeouts_1.BROWSER_RESTART_TIMEOUT; this.id = BrowserConnection._generateId(); this.jobQueue = []; this.initScriptsQueue = []; this.browserConnectionGateway = gateway; this.disconnectionPromise = null; this.testRunAborted = false; this.warningLog = new warning_log_1.default(null, warning_log_1.default.createAddWarningCallback(messageBus)); this.debugLogger = (0, debug_1.default)(getBrowserConnectionDebugScope(this.id)); if (messageBus) { this.messageBus = messageBus; this.initMessageBus(); } this.browserInfo = browserInfo; this.browserInfo.userAgentProviderMetaInfo = ''; this.provider = browserInfo.provider; this.permanent = permanent; this.status = status_1.default.uninitialized; this.idle = true; this.heartbeatTimeout = null; this.pendingTestRunInfo = null; this._options = this._calculateResultOptions(options); this._setEventHandlers(); tracker_1.default.add(this); this.previousActiveWindowId = null; this.browserConnectionGateway.startServingConnection(this); } _calculateResultOptions(options) { return Object.assign({}, DEFAULT_BROWSER_CONNECTION_OPTIONS, options); } _buildCommunicationUrls(proxy) { this.url = proxy.resolveRelativeServiceUrl(`${service_routes_1.default.connect}/${this.id}`); this.forcedIdleUrl = proxy.resolveRelativeServiceUrl(`${service_routes_1.default.idleForced}/${this.id}`); this.initScriptUrl = proxy.resolveRelativeServiceUrl(`${service_routes_1.default.initScript}/${this.id}`); this.heartbeatRelativeUrl = `${service_routes_1.default.heartbeat}/${this.id}`; this.statusRelativeUrl = `${service_routes_1.default.status}/${this.id}`; this.statusDoneRelativeUrl = `${service_routes_1.default.statusDone}/${this.id}`; this.idleRelativeUrl = `${service_routes_1.default.idle}/${this.id}`; this.activeWindowIdUrl = `${service_routes_1.default.activeWindowId}/${this.id}`; this.ensureWindowInNativeAutomationUrl = `${service_routes_1.default.ensureWindowInNativeAutomation}/${this.id}`; this.closeWindowUrl = `${service_routes_1.default.closeWindow}/${this.id}`; this.openFileProtocolRelativeUrl = `${service_routes_1.default.openFileProtocol}/${this.id}`; this.dispatchNativeAutomationEventRelativeUrl = `${service_routes_1.default.dispatchNativeAutomationEvent}/${this.id}`; this.dispatchNativeAutomationEventSequenceRelativeUrl = `${service_routes_1.default.dispatchNativeAutomationEventSequence}/${this.id}`; this.parseSelectorRelativeUrl = `${service_routes_1.default.parseSelector}/${this.id}`; this.idleUrl = proxy.resolveRelativeServiceUrl(this.idleRelativeUrl); this.heartbeatUrl = proxy.resolveRelativeServiceUrl(this.heartbeatRelativeUrl); this.statusUrl = proxy.resolveRelativeServiceUrl(this.statusRelativeUrl); this.statusDoneUrl = proxy.resolveRelativeServiceUrl(this.statusDoneRelativeUrl); this.openFileProtocolUrl = proxy.resolveRelativeServiceUrl(this.openFileProtocolRelativeUrl); } initMessageBus() { this.warningLog.callback = warning_log_1.default.createAddWarningCallback(this._messageBus); this.assignTestRunStartEventListener(); this.emit('message-bus-initialized', this._messageBus); } assignTestRunStartEventListener() { if (!this._messageBus) return; this._messageBus.on('test-run-start', testRun => { if (testRun.browserConnection.id === this.id) this._currentTestRun = testRun; }); } set messageBus(messageBus) { this._messageBus = messageBus; } get messageBus() { return this._messageBus; } _setEventHandlers() { this.on('error', e => { this.debugLogger(e); this._forceIdle(); this.close(); }); for (const name in status_1.default) { const status = status_1.default[name]; this.on(status, () => { this.debugLogger(`status changed to '${status}'`); }); } } static _generateId() { return (0, nanoid_1.nanoid)(7); } _getAdditionalBrowserOptions() { return { disableMultipleWindows: this._options.disableMultipleWindows, nativeAutomation: this._options.nativeAutomation, developmentMode: this._options.developmentMode, serviceDomains: [ this.browserConnectionGateway.proxy.server1Info.domain, this.browserConnectionGateway.proxy.server2Info.domain, ], }; } async _runBrowser() { try { const additionalOptions = this._getAdditionalBrowserOptions(); await this.provider.openBrowser(this.id, this.url, this.browserInfo.browserOption, additionalOptions); if (this.status !== status_1.default.ready) await (0, promisify_event_1.default)(this, 'ready'); this.status = status_1.default.opened; this.emit('opened'); } catch (err) { this.emit('error', new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.unableToOpenBrowser, this.browserInfo.providerName + ':' + this.browserInfo.browserName, err.stack)); } } async _closeBrowser(data = {}) { if (!this.idle) await (0, promisify_event_1.default)(this, 'idle'); try { await this.provider.closeBrowser(this.id, data); } catch (err) { // NOTE: A warning would be really nice here, but it can't be done while log is stored in a task. this.debugLogger(err); } } _forceIdle() { if (!this.idle) { this.idle = true; this.emit('idle'); } } _createBrowserDisconnectedError() { return new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.browserDisconnected, this.userAgent); } _waitForHeartbeat() { if (this._options.developmentMode) return; this.heartbeatTimeout = setTimeout(() => { const err = this._createBrowserDisconnectedError(); this.status = status_1.default.disconnected; this.testRunAborted = true; this.emit('disconnected', err); this._restartBrowserOnDisconnect(err); }, this.HEARTBEAT_TIMEOUT); } async _getTestRunInfo(needPopNext) { if (needPopNext || !this.pendingTestRunInfo) this.pendingTestRunInfo = await this._popNextTestRunInfo(); return this.pendingTestRunInfo; } async _popNextTestRunInfo() { while (this.hasQueuedJobs && !this.currentJob.hasQueuedTestRuns) this.jobQueue.shift(); return this.hasQueuedJobs ? await this.currentJob.popNextTestRunInfo(this) : null; } getCurrentTestRun() { return this._currentTestRun; } static getById(id) { return tracker_1.default.activeBrowserConnections[id] || null; } async _restartBrowser() { this.status = status_1.default.uninitialized; this._forceIdle(); let resolveTimeout = null; let isTimeoutExpired = false; let timeout = null; const restartPromise = (0, time_limit_promise_1.default)(this._closeBrowser({ isRestarting: true }), this.BROWSER_CLOSE_TIMEOUT, { rejectWith: new runtime_1.TimeoutError() }) .catch(err => this.debugLogger(err)) .then(() => this._runBrowser()); const timeoutPromise = new Promise(resolve => { resolveTimeout = resolve; timeout = setTimeout(() => { isTimeoutExpired = true; resolve(); }, this.BROWSER_RESTART_TIMEOUT); }); return Promise.race([restartPromise, timeoutPromise]) .then(() => { clearTimeout(timeout); if (isTimeoutExpired) this.emit('error', this._createBrowserDisconnectedError()); else resolveTimeout(); }); } _restartBrowserOnDisconnect(err) { let resolveFn = null; let rejectFn = null; this.disconnectionPromise = new Promise((resolve, reject) => { resolveFn = resolve; rejectFn = () => { reject(err); }; setTimeout(() => { rejectFn(); }); }) .then(() => { return this._restartBrowser(); }) .catch(e => { this.emit('error', e); }); this.disconnectionPromise.resolve = resolveFn; this.disconnectionPromise.reject = rejectFn; } async getDefaultBrowserInitTimeout() { const isLocalBrowser = await this.provider.isLocalBrowser(this.id, this.browserInfo.browserName); return isLocalBrowser ? browser_connection_timeouts_1.LOCAL_BROWSER_INIT_TIMEOUT : browser_connection_timeouts_1.REMOTE_BROWSER_INIT_TIMEOUT; } async processDisconnection(disconnectionThresholdExceeded) { const { resolve, reject } = this.disconnectionPromise; if (disconnectionThresholdExceeded) reject(); else resolve(); } addWarning(message, ...args) { if (this.currentJob) this.currentJob.warningLog.addWarning(message, ...args); else this.warningLog.addWarning(message, ...args); } _appendToPrettyUserAgent(str) { this.browserInfo.parsedUserAgent.prettyUserAgent += ` (${str})`; } _moveWarningLogToJob(job) { job.warningLog.copyFrom(this.warningLog); this.warningLog.clear(); } setProviderMetaInfo(str, options) { const appendToUserAgent = options === null || options === void 0 ? void 0 : options.appendToUserAgent; if (appendToUserAgent) { // NOTE: // change prettyUserAgent only when connection already was established if (this.isReady()) this._appendToPrettyUserAgent(str); else this.on('ready', () => this._appendToPrettyUserAgent(str)); return; } this.browserInfo.userAgentProviderMetaInfo = str; } get userAgent() { let userAgent = this.browserInfo.parsedUserAgent.prettyUserAgent; if (this.browserInfo.userAgentProviderMetaInfo) userAgent += ` (${this.browserInfo.userAgentProviderMetaInfo})`; return userAgent; } get retryTestPages() { return this.browserConnectionGateway.retryTestPages; } get hasQueuedJobs() { return !!this.jobQueue.length; } get currentJob() { return this.jobQueue[0]; } // API runInitScript(code) { return new Promise(resolve => this.initScriptsQueue.push({ code, resolve })); } addJob(job) { this.jobQueue.push(job); this._moveWarningLogToJob(job); } removeJob(job) { (0, lodash_1.pull)(this.jobQueue, job); } async close() { if (this.status === status_1.default.closing || this.status === status_1.default.closed) return; this.status = status_1.default.closing; this.emit(status_1.default.closing); await this._closeBrowser(); this.browserConnectionGateway.stopServingConnection(this); if (this.heartbeatTimeout) clearTimeout(this.heartbeatTimeout); tracker_1.default.remove(this); this.status = status_1.default.closed; this.emit(status_1.default.closed); } async establish(userAgent) { const osInfo = await this.provider.getOSInfo(this.id); this.status = status_1.default.ready; this.browserInfo.parsedUserAgent = (0, parse_user_agent_1.parseUserAgent)(userAgent, osInfo); this._waitForHeartbeat(); this.emit('ready'); } heartbeat() { if (this.heartbeatTimeout) clearTimeout(this.heartbeatTimeout); this._waitForHeartbeat(); return { code: this.status === status_1.default.closing ? heartbeat_status_1.default.closing : heartbeat_status_1.default.ok, url: this.status === status_1.default.closing ? this.idleUrl : '', }; } renderIdlePage() { return mustache_1.default.render(IDLE_PAGE_TEMPLATE, { userAgent: this.userAgent, statusUrl: this.statusUrl, heartbeatUrl: this.heartbeatUrl, initScriptUrl: this.initScriptUrl, openFileProtocolUrl: this.openFileProtocolUrl, retryTestPages: !!this.browserConnectionGateway.retryTestPages, nativeAutomation: this._options.nativeAutomation, }); } getInitScript() { const initScriptPromise = this.initScriptsQueue[0]; return { code: initScriptPromise ? initScriptPromise.code : null }; } handleInitScriptResult(data) { const initScriptPromise = this.initScriptsQueue.shift(); if (initScriptPromise) initScriptPromise.resolve(JSON.parse(data)); } isHeadlessBrowser() { return this.provider.isHeadlessBrowser(this.id); } async reportJobResult(status, data) { await this.provider.reportJobResult(this.id, status, data); } async getStatus(isTestDone) { if (!this.idle && !isTestDone) { this.idle = true; this.emit('idle'); } if (this.status === status_1.default.opened) { const nextTestRunInfo = await this._getTestRunInfo(isTestDone || this.testRunAborted); this.testRunAborted = false; if (nextTestRunInfo) { this.idle = false; return { cmd: command_1.default.run, testRunId: nextTestRunInfo.testRunId, url: nextTestRunInfo.url, }; } } return { cmd: command_1.default.idle, url: this.idleUrl, testRunId: null, }; } get activeWindowId() { return this.provider.getActiveWindowId(this.id); } set activeWindowId(val) { this.previousActiveWindowId = this.activeWindowId; this.provider.setActiveWindowId(this.id, val); } async openFileProtocol(url) { return this.provider.openFileProtocol(this.id, url); } async dispatchNativeAutomationEvent(type, options) { return this.provider.dispatchNativeAutomationEvent(this.id, type, options); } async dispatchNativeAutomationEventSequence(eventSequence) { return this.provider.dispatchNativeAutomationEventSequence(this.id, eventSequence); } async canUseDefaultWindowActions() { return this.provider.canUseDefaultWindowActions(this.id); } isReady() { return this.status === status_1.default.ready || this.status === status_1.default.opened || this.status === status_1.default.closing; } initialize() { this._buildCommunicationUrls(this.browserConnectionGateway.proxy); process.nextTick(() => this._runBrowser()); } supportNativeAutomation() { return this.provider.supportNativeAutomation(); } getNativeAutomation() { return this.provider.getNativeAutomation(this.id); } isNativeAutomationEnabled() { return this._options.nativeAutomation; } async getNewWindowIdInNativeAutomation(windowId) { return this.provider.getNewWindowIdInNativeAutomation(this.id, windowId); } async getCurrentCDPSession() { return this.provider.getCurrentCDPSession(this.id); } resetActiveWindowId() { this.provider.resetActiveWindowId(this.id); } } exports.default = BrowserConnection; module.exports = exports.default; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYnJvd3Nlci9jb25uZWN0aW9uL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsa0RBQTBCO0FBQzFCLDRFQUEyQztBQUMzQyxtQ0FBc0M7QUFDdEMsd0RBQWdDO0FBQ2hDLG1DQUF3QztBQUN4QyxtRUFHc0M7QUFDdEMsMkRBQXNEO0FBQ3RELHNFQUE2QztBQUM3QyxtQ0FBZ0M7QUFDaEMsd0RBQWdDO0FBQ2hDLHNEQUErQztBQUMvQywwRUFBaUQ7QUFDakQsa0RBQWtFO0FBQ2xFLDhDQUFvRDtBQUdwRCxrRkFBeUQ7QUFFekQsc0VBQThDO0FBQzlDLHlGQU1pRDtBQUVqRCx3REFBaUQ7QUFVakQsTUFBTSw4QkFBOEIsR0FBRyxDQUFDLEVBQVUsRUFBVSxFQUFFLENBQUMsK0JBQStCLEVBQUUsRUFBRSxDQUFDO0FBRW5HLE1BQU0sa0JBQWtCLEdBQUcsSUFBQSw2QkFBSSxFQUFDLG9EQUFvRCxDQUFDLENBQUM7QUFtRHRGLE1BQU0sa0NBQWtDLEdBQUc7SUFDdkMsc0JBQXNCLEVBQUUsS0FBSztJQUM3QixlQUFlLEVBQVMsS0FBSztJQUM3QixnQkFBZ0IsRUFBUSxLQUFLO0NBQ2hDLENBQUM7QUFFRixNQUFxQixpQkFBa0IsU0FBUSxxQkFBWTtJQTZDdkQsWUFDSSxPQUFpQyxFQUNqQyxXQUF3QixFQUN4QixTQUFrQixFQUNsQixVQUE2QyxFQUFFLEVBQy9DLFVBQXVCO1FBQ3ZCLEtBQUssRUFBRSxDQUFDO1FBNUNKLG9CQUFlLEdBQW1CLElBQUksQ0FBQztRQVN4QyxRQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ1QsWUFBTyxHQUFHLEVBQUUsQ0FBQztRQUNaLGtCQUFhLEdBQUcsRUFBRSxDQUFDO1FBQ25CLGtCQUFhLEdBQUcsRUFBRSxDQUFDO1FBQ3BCLGlCQUFZLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLGNBQVMsR0FBRyxFQUFFLENBQUM7UUFD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Q0FBQztJQUVELEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBRSxRQUFnQjtRQUNwRCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsZ0NBQWdDLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM3RSxDQUFDO0lBRU0sS0FBSyxDQUFDLG9CQUFvQjtRQUM3QixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFTSxtQkFBbUI7UUFDdEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0MsQ0FBQztDQUNKO0FBM2pCRCxvQ0EyakJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGRlYnVnIGZyb20gJ2RlYnVnJztcbmltcG9ydCB0aW1lTGltaXQgZnJvbSAndGltZS1saW1pdC1wcm9taXNlJztcbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ2V2ZW50cyc7XG5pbXBvcnQgTXVzdGFjaGUgZnJvbSAnbXVzdGFjaGUnO1xuaW1wb3J0IHsgcHVsbCBhcyByZW1vdmUgfSBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHtcbiAgICBQYXJzZWRVc2VyQWdlbnQsXG4gICAgcGFyc2VVc2VyQWdlbnQsXG59IGZyb20gJy4uLy4uL3V0aWxzL3BhcnNlLXVzZXItYWdlbnQnO1xuaW1wb3J0IHsgcmVhZFN5bmMgYXMgcmVhZCB9IGZyb20gJ3JlYWQtZmlsZS1yZWxhdGl2ZSc7XG5pbXBvcnQgcHJvbWlzaWZ5RXZlbnQgZnJvbSAncHJvbWlzaWZ5LWV2ZW50JztcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZCc7XG5pbXBvcnQgQ09NTUFORCBmcm9tICcuL2NvbW1hbmQnO1xuaW1wb3J0IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzIGZyb20gJy4vc3RhdHVzJztcbmltcG9ydCBIZWFydGJlYXRTdGF0dXMgZnJvbSAnLi9oZWFydGJlYXQtc3RhdHVzJztcbmltcG9ydCB7IEdlbmVyYWxFcnJvciwgVGltZW91dEVycm9yIH0gZnJvbSAnLi4vLi4vZXJyb3JzL3J1bnRpbWUnO1xuaW1wb3J0IHsgUlVOVElNRV9FUlJPUlMgfSBmcm9tICcuLi8uLi9lcnJvcnMvdHlwZXMnO1xuaW1wb3J0IEJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheSBmcm9tICcuL2dhdGV3YXknO1xuaW1wb3J0IEJyb3dzZXJKb2IgZnJvbSAnLi4vLi4vcnVubmVyL2Jyb3dzZXItam9iJztcbmltcG9ydCBXYXJuaW5nTG9nIGZyb20gJy4uLy4uL25vdGlmaWNhdGlvbnMvd2FybmluZy1sb2cnO1xuaW1wb3J0IEJyb3dzZXJQcm92aWRlciBmcm9tICcuLi9wcm92aWRlcic7XG5pbXBvcnQgU0VSVklDRV9ST1VURVMgZnJvbSAnLi9zZXJ2aWNlLXJvdXRlcyc7XG5pbXBvcnQge1xuICAgIEJST1dTRVJfUkVTVEFSVF9USU1FT1VULFxuICAgIEJST1dTRVJfQ0xPU0VfVElNRU9VVCxcbiAgICBIRUFSVEJFQVRfVElNRU9VVCxcbiAgICBMT0NBTF9CUk9XU0VSX0lOSVRfVElNRU9VVCxcbiAgICBSRU1PVEVfQlJPV1NFUl9JTklUX1RJTUVPVVQsXG59IGZyb20gJy4uLy4uL3V0aWxzL2Jyb3dzZXItY29ubmVjdGlvbi10aW1lb3V0cyc7XG5pbXBvcnQgTWVzc2FnZUJ1cyBmcm9tICcuLi8uLi91dGlscy9tZXNzYWdlLWJ1cyc7XG5pbXBvcnQgQnJvd3NlckNvbm5lY3Rpb25UcmFja2VyIGZyb20gJy4vdHJhY2tlcic7XG5pbXBvcnQgVGVzdFJ1biBmcm9tICcuLi8uLi90ZXN0LXJ1bic7XG4vLyBAdHMtaWdub3JlXG5pbXBvcnQgeyBUZXN0UnVuIGFzIExlZ2FjeVRlc3RSdW4gfSBmcm9tICd0ZXN0Y2FmZS1sZWdhY3ktYXBpJztcbmltcG9ydCB7IFByb3h5IH0gZnJvbSAndGVzdGNhZmUtaGFtbWVyaGVhZCc7XG5pbXBvcnQgeyBOZXh0VGVzdFJ1bkluZm8sIE9wZW5Ccm93c2VyQWRkaXRpb25hbE9wdGlvbnMgfSBmcm9tICcuLi8uLi9zaGFyZWQvdHlwZXMnO1xuaW1wb3J0IHsgRXZlbnRUeXBlIH0gZnJvbSAnLi4vLi4vbmF0aXZlLWF1dG9tYXRpb24vdHlwZXMnO1xuaW1wb3J0IHsgTmF0aXZlQXV0b21hdGlvbkJhc2UgfSBmcm9tICcuLi8uLi9uYXRpdmUtYXV0b21hdGlvbic7XG5pbXBvcnQgcmVtb3RlQ2hyb21lIGZyb20gJ2Nocm9tZS1yZW1vdGUtaW50ZXJmYWNlJztcblxuY29uc3QgZ2V0QnJvd3NlckNvbm5lY3Rpb25EZWJ1Z1Njb3BlID0gKGlkOiBzdHJpbmcpOiBzdHJpbmcgPT4gYHRlc3RjYWZlOmJyb3dzZXI6Y29ubmVjdGlvbjoke2lkfWA7XG5cbmNvbnN0IElETEVfUEFHRV9URU1QTEFURSA9IHJlYWQoJy4uLy4uL2NsaWVudC9icm93c2VyL2lkbGUtcGFnZS9pbmRleC5odG1sLm11c3RhY2hlJyk7XG5cblxuaW50ZXJmYWNlIERpc2Nvbm5lY3Rpb25Qcm9taXNlPFQ+IGV4dGVuZHMgUHJvbWlzZTxUPiB7XG4gICAgcmVzb2x2ZTogRnVuY3Rpb247XG4gICAgcmVqZWN0OiBGdW5jdGlvbjtcbn1cblxuaW50ZXJmYWNlIEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzUmVzdWx0IHtcbiAgICBjbWQ6IHN0cmluZztcbiAgICB1cmw6IHN0cmluZztcbiAgICB0ZXN0UnVuSWQ6IHN0cmluZyB8IG51bGw7XG59XG5cbmludGVyZmFjZSBIZWFydGJlYXRTdGF0dXNSZXN1bHQge1xuICAgIGNvZGU6IEhlYXJ0YmVhdFN0YXR1cztcbiAgICB1cmw6IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIEluaXRTY3JpcHQge1xuICAgIGNvZGU6IHN0cmluZyB8IG51bGw7XG59XG5cbmludGVyZmFjZSBJbml0U2NyaXB0VGFzayBleHRlbmRzIEluaXRTY3JpcHQge1xuICAgIHJlc29sdmU6IEZ1bmN0aW9uO1xufVxuXG5pbnRlcmZhY2UgUHJvdmlkZXJNZXRhSW5mb09wdGlvbnMge1xuICAgIGFwcGVuZFRvVXNlckFnZW50PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCcm93c2VyQ2xvc2luZ0luZm8ge1xuICAgIGlzUmVzdGFydGluZz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQnJvd3NlckluZm8ge1xuICAgIGFsaWFzOiBzdHJpbmc7XG4gICAgYnJvd3Nlck5hbWU6IHN0cmluZztcbiAgICBicm93c2VyT3B0aW9uOiB1bmtub3duO1xuICAgIHByb3ZpZGVyTmFtZTogc3RyaW5nO1xuICAgIHByb3ZpZGVyOiBCcm93c2VyUHJvdmlkZXI7XG4gICAgdXNlckFnZW50UHJvdmlkZXJNZXRhSW5mbzogc3RyaW5nO1xuICAgIHBhcnNlZFVzZXJBZ2VudDogUGFyc2VkVXNlckFnZW50O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEJyb3dzZXJDb25uZWN0aW9uT3B0aW9ucyB7XG4gICAgZGlzYWJsZU11bHRpcGxlV2luZG93czogYm9vbGVhbjtcbiAgICBkZXZlbG9wbWVudE1vZGU6IGJvb2xlYW47XG4gICAgbmF0aXZlQXV0b21hdGlvbjogYm9vbGVhbjtcbn1cblxuY29uc3QgREVGQVVMVF9CUk9XU0VSX0NPTk5FQ1RJT05fT1BUSU9OUyA9IHtcbiAgICBkaXNhYmxlTXVsdGlwbGVXaW5kb3dzOiBmYWxzZSxcbiAgICBkZXZlbG9wbWVudE1vZGU6ICAgICAgICBmYWxzZSxcbiAgICBuYXRpdmVBdXRvbWF0aW9uOiAgICAgICBmYWxzZSxcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJyb3dzZXJDb25uZWN0aW9uIGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcbiAgICBwdWJsaWMgcGVybWFuZW50OiBib29sZWFuO1xuICAgIHB1YmxpYyBwcmV2aW91c0FjdGl2ZVdpbmRvd0lkOiBzdHJpbmcgfCBudWxsO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgSEVBUlRCRUFUX1RJTUVPVVQ6IG51bWJlcjtcbiAgICBwcml2YXRlIHJlYWRvbmx5IEJST1dTRVJfQ0xPU0VfVElNRU9VVDogbnVtYmVyO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgQlJPV1NFUl9SRVNUQVJUX1RJTUVPVVQ6IG51bWJlcjtcbiAgICBwdWJsaWMgcmVhZG9ubHkgaWQ6IHN0cmluZztcbiAgICBwcml2YXRlIF9jdXJyZW50VGVzdFJ1bjogVGVzdFJ1biB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgam9iUXVldWU6IEJyb3dzZXJKb2JbXTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGluaXRTY3JpcHRzUXVldWU6IEluaXRTY3JpcHRUYXNrW107XG4gICAgcHVibGljIGJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheTogQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5O1xuICAgIHByaXZhdGUgZGlzY29ubmVjdGlvblByb21pc2U6IERpc2Nvbm5lY3Rpb25Qcm9taXNlPHZvaWQ+IHwgbnVsbDtcbiAgICBwcml2YXRlIHRlc3RSdW5BYm9ydGVkOiBib29sZWFuO1xuICAgIHB1YmxpYyBzdGF0dXM6IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzO1xuICAgIHByaXZhdGUgaGVhcnRiZWF0VGltZW91dDogTm9kZUpTLlRpbWVvdXQgfCBudWxsO1xuICAgIHByaXZhdGUgcGVuZGluZ1Rlc3RSdW5JbmZvOiBOZXh0VGVzdFJ1bkluZm8gfCBudWxsO1xuICAgIHB1YmxpYyB1cmwgPSAnJztcbiAgICBwdWJsaWMgaWRsZVVybCA9ICcnO1xuICAgIHByaXZhdGUgZm9yY2VkSWRsZVVybCA9ICcnO1xuICAgIHByaXZhdGUgaW5pdFNjcmlwdFVybCA9ICcnO1xuICAgIHB1YmxpYyBoZWFydGJlYXRVcmwgPSAnJztcbiAgICBwdWJsaWMgc3RhdHVzVXJsID0gJyc7XG4gICAgcHVibGljIGFjdGl2ZVdpbmRvd0lkVXJsID0gJyc7XG4gICAgcHVibGljIGVuc3VyZVdpbmRvd0luTmF0aXZlQXV0b21hdGlvblVybCA9ICcnO1xuICAgIHB1YmxpYyBjbG9zZVdpbmRvd1VybCA9ICcnO1xuICAgIHB1YmxpYyBzdGF0dXNEb25lVXJsID0gJyc7XG4gICAgcHVibGljIGhlYXJ0YmVhdFJlbGF0aXZlVXJsID0gJyc7XG4gICAgcHVibGljIHN0YXR1c1JlbGF0aXZlVXJsID0gJyc7XG4gICAgcHVibGljIHN0YXR1c0RvbmVSZWxhdGl2ZVVybCA9ICcnO1xuICAgIHB1YmxpYyBpZGxlUmVsYXRpdmVVcmwgPSAnJztcbiAgICBwdWJsaWMgb3BlbkZpbGVQcm90b2NvbFJlbGF0aXZlVXJsID0gJyc7XG4gICAgcHVibGljIG9wZW5GaWxlUHJvdG9jb2xVcmwgPSAnJztcbiAgICBwdWJsaWMgZGlzcGF0Y2hOYXRpdmVBdXRvbWF0aW9uRXZlbnRSZWxhdGl2ZVVybCA9ICcnO1xuICAgIHB1YmxpYyBkaXNwYXRjaE5hdGl2ZUF1dG9tYXRpb25FdmVudFNlcXVlbmNlUmVsYXRpdmVVcmwgPSAnJztcbiAgICBwdWJsaWMgcGFyc2VTZWxlY3RvclJlbGF0aXZlVXJsID0gJyc7XG4gICAgcHJpdmF0ZSByZWFkb25seSBkZWJ1Z0xvZ2dlcjogZGVidWcuRGVidWdnZXI7XG4gICAgcHVibGljIHJlYWRvbmx5IHdhcm5pbmdMb2c6IFdhcm5pbmdMb2c7XG4gICAgcHJpdmF0ZSBfbWVzc2FnZUJ1cz86IE1lc3NhZ2VCdXM7XG4gICAgcHJpdmF0ZSByZWFkb25seSBfb3B0aW9uczogQnJvd3NlckNvbm5lY3Rpb25PcHRpb25zO1xuXG4gICAgcHVibGljIGlkbGU6IGJvb2xlYW47XG5cbiAgICBwdWJsaWMgYnJvd3NlckluZm86IEJyb3dzZXJJbmZvO1xuICAgIHB1YmxpYyBwcm92aWRlcjogYW55O1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yIChcbiAgICAgICAgZ2F0ZXdheTogQnJvd3NlckNvbm5lY3Rpb25HYXRld2F5LFxuICAgICAgICBicm93c2VySW5mbzogQnJvd3NlckluZm8sXG4gICAgICAgIHBlcm1hbmVudDogYm9vbGVhbixcbiAgICAgICAgb3B0aW9uczogUGFydGlhbDxCcm93c2VyQ29ubmVjdGlvbk9wdGlvbnM+ID0ge30sXG4gICAgICAgIG1lc3NhZ2VCdXM/OiBNZXNzYWdlQnVzKSB7XG4gICAgICAgIHN1cGVyKCk7XG5cbiAgICAgICAgdGhpcy5IRUFSVEJFQVRfVElNRU9VVCAgICAgICA9IEhFQVJUQkVBVF9USU1FT1VUO1xuICAgICAgICB0aGlzLkJST1dTRVJfQ0xPU0VfVElNRU9VVCAgID0gQlJPV1NFUl9DTE9TRV9USU1FT1VUO1xuICAgICAgICB0aGlzLkJST1dTRVJfUkVTVEFSVF9USU1FT1VUID0gQlJPV1NFUl9SRVNUQVJUX1RJTUVPVVQ7XG5cbiAgICAgICAgdGhpcy5pZCAgICAgICAgICAgICAgICAgICAgICAgPSBCcm93c2VyQ29ubmVjdGlvbi5fZ2VuZXJhdGVJZCgpO1xuICAgICAgICB0aGlzLmpvYlF1ZXVlICAgICAgICAgICAgICAgICA9IFtdO1xuICAgICAgICB0aGlzLmluaXRTY3JpcHRzUXVldWUgICAgICAgICA9IFtdO1xuICAgICAgICB0aGlzLmJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheSA9IGdhdGV3YXk7XG4gICAgICAgIHRoaXMuZGlzY29ubmVjdGlvblByb21pc2UgICAgID0gbnVsbDtcbiAgICAgICAgdGhpcy50ZXN0UnVuQWJvcnRlZCAgICAgICAgICAgPSBmYWxzZTtcbiAgICAgICAgdGhpcy53YXJuaW5nTG9nICAgICAgICAgICAgICAgPSBuZXcgV2FybmluZ0xvZyhudWxsLCBXYXJuaW5nTG9nLmNyZWF0ZUFkZFdhcm5pbmdDYWxsYmFjayhtZXNzYWdlQnVzKSk7XG4gICAgICAgIHRoaXMuZGVidWdMb2dnZXIgICAgICAgICAgICAgID0gZGVidWcoZ2V0QnJvd3NlckNvbm5lY3Rpb25EZWJ1Z1Njb3BlKHRoaXMuaWQpKTtcblxuICAgICAgICBpZiAobWVzc2FnZUJ1cykge1xuICAgICAgICAgICAgdGhpcy5tZXNzYWdlQnVzID0gbWVzc2FnZUJ1cztcblxuICAgICAgICAgICAgdGhpcy5pbml0TWVzc2FnZUJ1cygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5icm93c2VySW5mbyAgICAgICAgICAgICAgICAgICAgICAgICAgID0gYnJvd3NlckluZm87XG4gICAgICAgIHRoaXMuYnJvd3NlckluZm8udXNlckFnZW50UHJvdmlkZXJNZXRhSW5mbyA9ICcnO1xuXG4gICAgICAgIHRoaXMucHJvdmlkZXIgPSBicm93c2VySW5mby5wcm92aWRlcjtcblxuICAgICAgICB0aGlzLnBlcm1hbmVudCAgICAgICAgICAgICAgPSBwZXJtYW5lbnQ7XG4gICAgICAgIHRoaXMuc3RhdHVzICAgICAgICAgICAgICAgICA9IEJyb3dzZXJDb25uZWN0aW9uU3RhdHVzLnVuaW5pdGlhbGl6ZWQ7XG4gICAgICAgIHRoaXMuaWRsZSAgICAgICAgICAgICAgICAgICA9IHRydWU7XG4gICAgICAgIHRoaXMuaGVhcnRiZWF0VGltZW91dCAgICAgICA9IG51bGw7XG4gICAgICAgIHRoaXMucGVuZGluZ1Rlc3RSdW5JbmZvICAgICA9IG51bGw7XG4gICAgICAgIHRoaXMuX29wdGlvbnMgICAgICAgICAgICAgICA9IHRoaXMuX2NhbGN1bGF0ZVJlc3VsdE9wdGlvbnMob3B0aW9ucyk7XG5cbiAgICAgICAgdGhpcy5fc2V0RXZlbnRIYW5kbGVycygpO1xuXG4gICAgICAgIEJyb3dzZXJDb25uZWN0aW9uVHJhY2tlci5hZGQodGhpcyk7XG5cbiAgICAgICAgdGhpcy5wcmV2aW91c0FjdGl2ZVdpbmRvd0lkID0gbnVsbDtcblxuICAgICAgICB0aGlzLmJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheS5zdGFydFNlcnZpbmdDb25uZWN0aW9uKHRoaXMpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2NhbGN1bGF0ZVJlc3VsdE9wdGlvbnMgKG9wdGlvbnM6IFBhcnRpYWw8QnJvd3NlckNvbm5lY3Rpb25PcHRpb25zPik6IEJyb3dzZXJDb25uZWN0aW9uT3B0aW9ucyB7XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCBERUZBVUxUX0JST1dTRVJfQ09OTkVDVElPTl9PUFRJT05TLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9idWlsZENvbW11bmljYXRpb25VcmxzIChwcm94eTogUHJveHkpOiB2b2lkIHtcbiAgICAgICAgdGhpcy51cmwgICAgICAgICAgID0gcHJveHkucmVzb2x2ZVJlbGF0aXZlU2VydmljZVVybChgJHtTRVJWSUNFX1JPVVRFUy5jb25uZWN0fS8ke3RoaXMuaWR9YCk7XG4gICAgICAgIHRoaXMuZm9yY2VkSWRsZVVybCA9IHByb3h5LnJlc29sdmVSZWxhdGl2ZVNlcnZpY2VVcmwoYCR7U0VSVklDRV9ST1VURVMuaWRsZUZvcmNlZH0vJHt0aGlzLmlkfWApO1xuICAgICAgICB0aGlzLmluaXRTY3JpcHRVcmwgPSBwcm94eS5yZXNvbHZlUmVsYXRpdmVTZXJ2aWNlVXJsKGAke1NFUlZJQ0VfUk9VVEVTLmluaXRTY3JpcHR9LyR7dGhpcy5pZH1gKTtcblxuICAgICAgICB0aGlzLmhlYXJ0YmVhdFJlbGF0aXZlVXJsICAgICAgICAgICAgICAgICAgICAgID0gYCR7U0VSVklDRV9ST1VURVMuaGVhcnRiZWF0fS8ke3RoaXMuaWR9YDtcbiAgICAgICAgdGhpcy5zdGF0dXNSZWxhdGl2ZVVybCAgICAgICAgICAgICAgICAgICAgICAgICA9IGAke1NFUlZJQ0VfUk9VVEVTLnN0YXR1c30vJHt0aGlzLmlkfWA7XG4gICAgICAgIHRoaXMuc3RhdHVzRG9uZVJlbGF0aXZlVXJsICAgICAgICAgICAgICAgICAgICAgPSBgJHtTRVJWSUNFX1JPVVRFUy5zdGF0dXNEb25lfS8ke3RoaXMuaWR9YDtcbiAgICAgICAgdGhpcy5pZGxlUmVsYXRpdmVVcmwgICAgICAgICAgICAgICAgICAgICAgICAgICA9IGAke1NFUlZJQ0VfUk9VVEVTLmlkbGV9LyR7dGhpcy5pZH1gO1xuICAgICAgICB0aGlzLmFjdGl2ZVdpbmRvd0lkVXJsICAgICAgICAgICAgICAgICAgICAgIC