UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

496 lines 75.1 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const lodash_1 = require("lodash"); const is_stream_1 = require("is-stream"); const plugin_host_1 = __importDefault(require("./plugin-host")); const plugin_methods_1 = __importDefault(require("./plugin-methods")); const format_command_1 = __importDefault(require("./command/format-command")); const runtime_1 = require("../errors/runtime"); const reporter_1 = require("../utils/reporter"); const resolve_path_relatively_cwd_1 = __importDefault(require("../utils/resolve-path-relatively-cwd")); const make_dir_1 = __importDefault(require("make-dir")); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const debug_loggers_1 = require("../utils/debug-loggers"); const get_testcafe_version_1 = __importDefault(require("../utils/get-testcafe-version")); class Reporter { constructor({ name, plugin, outStream, messageBus, reporterPluginHooks }) { this.plugin = new plugin_host_1.default(plugin, outStream, name, reporterPluginHooks); this.messageBus = messageBus; this.disposed = false; this.taskInfo = null; this.outStream = outStream; this._assignMessageBusEventHandlers(); } static _isSpecialStream(stream) { return stream.isTTY || stream === process.stdout || stream === process.stderr; } static _createPendingPromise() { let resolver = null; const promise = new Promise(resolve => { resolver = resolve; }); promise.resolve = resolver; return promise; } async init() { const testcafeVersion = (0, get_testcafe_version_1.default)(); await this.dispatchToPlugin({ method: plugin_methods_1.default.init, initialObject: null, args: [testcafeVersion], }); } async dispatchToPlugin({ method, initialObject, args = [] }) { (0, debug_loggers_1.reporterLogger)('begin dispatchToPlugin method: %s\n%O', method, args); try { // @ts-ignore await this.plugin[method](...args); } catch (originalError) { const uncaughtError = new runtime_1.ReporterPluginError({ name: this.plugin.name, method, originalError, }); (0, debug_loggers_1.reporterLogger)('Plugin error: %O', uncaughtError); (0, debug_loggers_1.reporterLogger)('Plugin error: initialObject: %O', initialObject); if (initialObject) await initialObject.emit('error', uncaughtError); else throw uncaughtError; } (0, debug_loggers_1.reporterLogger)('end dispatchToPlugin method: %s', method); } _assignMessageBusEventHandlers() { const messageBus = this.messageBus; messageBus.on('warning-add', async (e) => await this._onWarningAddHandler(e)); messageBus.on('report-data', async (e) => await this._onReportDataHandler(e)); messageBus.once('start', async (task) => await this._onceTaskStartHandler(task)); messageBus.on('test-run-start', async (testRun) => await this._onTaskTestRunStartHandler(testRun)); messageBus.on('test-run-done', async (testRun) => await this._onTaskTestRunDoneHandler(testRun)); messageBus.on('test-action-start', async (e) => await this._onTaskTestActionStart(e)); messageBus.on('test-action-done', async (e) => await this._onTaskTestActionDone(e)); messageBus.once('done', async () => await this._onceTaskDoneHandler()); messageBus.once('unhandled-rejection', async () => await this._onceTaskDoneHandler()); } async dispose() { var _a; if (this.disposed) return Promise.resolve(); this.disposed = true; if (!(0, lodash_1.isFunction)((_a = this === null || this === void 0 ? void 0 : this.outStream) === null || _a === void 0 ? void 0 : _a.once) || Reporter._isSpecialStream(this.outStream) || !(0, is_stream_1.writable)(this.outStream)) return Promise.resolve(); const streamFinishedPromise = new Promise(resolve => { this.outStream.once('finish', resolve); this.outStream.once('error', resolve); }); this.outStream.end(); return streamFinishedPromise; } static async _ensureOutStream(outStream) { if (typeof outStream !== 'string') return outStream; const fullReporterOutputPath = (0, resolve_path_relatively_cwd_1.default)(outStream); await (0, make_dir_1.default)(path_1.default.dirname(fullReporterOutputPath)); return fs_1.default.createWriteStream(fullReporterOutputPath); } static _addDefaultReporter(reporters) { reporters.push({ name: 'spec', output: process.stdout, }); } static async getReporterPlugins(reporters = []) { if (!reporters.length) Reporter._addDefaultReporter(reporters); return Promise.all(reporters.map(async ({ name, output, options }) => { const pluginFactory = (0, reporter_1.getPluginFactory)(name); const processedName = (0, reporter_1.processReporterName)(name); const outStream = output ? await Reporter._ensureOutStream(output) : void 0; try { return { plugin: pluginFactory(options), name: processedName, outStream, }; } catch (err) { throw new runtime_1.LoadReporterError(err, processedName); } })); } async _onWarningAddHandler({ message, testRun, actionId }) { await this.dispatchToPlugin({ method: plugin_methods_1.default.reportWarnings, initialObject: this.messageBus, args: [ { message, testRunId: testRun === null || testRun === void 0 ? void 0 : testRun.id, actionId, }, ], }); } //Task static _createTestItem(test, runsPerTest) { return { fixture: test.fixture, test: test, testRunIds: [], screenshotPath: null, screenshots: [], videos: [], quarantine: null, errs: [], warnings: [], unstable: false, startTime: null, finishTime: null, testRunInfo: null, pendingRuns: runsPerTest, pendingStarts: runsPerTest, pendingTestRunDonePromise: Reporter._createPendingPromise(), pendingTestRunStartPromise: Reporter._createPendingPromise(), browsers: [], reportData: {}, }; } static _createTestQueue(task) { const runsPerTest = task.browserConnectionGroups.length; return task.tests.map(test => Reporter._createTestItem(test, runsPerTest)); } static _getTestDuration(reportItem) { if (reportItem.test.skip) return 0; const finishTime = reportItem.finishTime || +new Date(); return finishTime - reportItem.startTime; } static _createTestRunInfo(reportItem) { return { errs: (0, lodash_1.sortBy)(reportItem.errs, ['userAgent', 'code']), warnings: reportItem.warnings, reportData: reportItem.reportData, durationMs: Reporter._getTestDuration(reportItem), unstable: reportItem.unstable, screenshotPath: reportItem.screenshotPath, screenshots: reportItem.screenshots, videos: reportItem.videos, quarantine: reportItem.quarantine, skipped: reportItem.test.skip, browsers: reportItem.browsers, testId: reportItem.test.id, fixture: { id: reportItem.fixture.id, name: reportItem.fixture.name, path: reportItem.fixture.path, meta: reportItem.fixture.meta, }, }; } _getTestItemForTestRun(taskInfo, testRun) { return (0, lodash_1.find)(taskInfo.testQueue, i => i.test === testRun.test); } async _shiftTestQueue() { if (!this.taskInfo) return; let currentFixture = null; let nextReportItem = null; let testItem = null; const testQueue = this.taskInfo.testQueue; while (testQueue.length && testQueue[0].testRunInfo) { testItem = testQueue.shift(); currentFixture = testItem.fixture; // NOTE: here we assume that tests are sorted by fixture. // Therefore, if the next report item has a different // fixture, we can report this fixture start. nextReportItem = testQueue[0]; await this.dispatchToPlugin({ method: plugin_methods_1.default.reportTestDone, initialObject: this.taskInfo.task, args: [ testItem.test.name, testItem.testRunInfo, testItem.test.meta, ], }); if (!nextReportItem || nextReportItem.fixture === currentFixture) continue; await this.dispatchToPlugin({ method: plugin_methods_1.default.reportFixtureStart, initialObject: this.taskInfo.task, args: [ nextReportItem.fixture.name, nextReportItem.fixture.path, nextReportItem.fixture.meta, ], }); } } async _resolveTestItem(taskInfo, testItem, testRun) { var _a; if (!taskInfo.task) return; if (taskInfo.task.screenshots.hasCapturedFor(testRun.test)) { testItem.screenshotPath = taskInfo.task.screenshots.getPathFor(testRun.test); testItem.screenshots = taskInfo.task.screenshots.getScreenshotsInfo(testRun.test); } if (taskInfo.task.videos) testItem.videos = taskInfo.task.videos.getTestVideos(testItem.test.id); if (testRun.quarantine) { const testItemQuarantine = testRun.quarantine.attempts.reduce((result, { errors }, index) => { const passed = !errors.length; const quarantineAttempt = index + 1; result[quarantineAttempt] = { passed }; return result; }, {}); Object.assign(testItem.quarantine, testItemQuarantine); } if (!testItem.finishTime) testItem.finishTime = ((_a = testRun.finishTime) === null || _a === void 0 ? void 0 : _a.getTime()) || null; if (!testItem.testRunInfo) { testItem.testRunInfo = Reporter._createTestRunInfo(testItem); if (testItem.test.skip) taskInfo.skipped++; else if (testItem.errs.length) taskInfo.failed++; else taskInfo.passed++; } await this._shiftTestQueue(); testItem.pendingTestRunDonePromise.resolve(); } _prepareReportTestActionEventArgs({ command, duration, result, testRun, err }) { const args = {}; if (err) args.err = err; if (typeof duration === 'number') args.duration = duration; const testFixture = testRun.test.fixture; return Object.assign(args, { testRunId: testRun.id, test: { id: testRun.test.id, name: testRun.test.name, phase: testRun.phase, }, fixture: { name: testFixture.name, id: testFixture.id, }, command: (0, format_command_1.default)(command, result), browser: testRun.browser, }); } async _onceTaskStartHandler(task) { this.taskInfo = { task: task, passed: 0, failed: 0, skipped: 0, testCount: task.tests.filter(test => !test.skip).length, testQueue: Reporter._createTestQueue(task), stopOnFirstFail: task.opts.stopOnFirstFail, pendingTaskDonePromise: Reporter._createPendingPromise(), }; const startTime = task.startTime; const browserConnectionsInfo = [] .concat(...task.browserConnectionGroups) .map(connection => connection.userAgent); const first = this.taskInfo.testQueue[0]; const taskProperties = { configuration: task.opts, }; await this.dispatchToPlugin({ method: plugin_methods_1.default.reportTaskStart, initialObject: task, args: [ startTime, browserConnectionsInfo, this.taskInfo.testCount, task.testStructure, taskProperties, ], }); if (first) { await this.dispatchToPlugin({ method: plugin_methods_1.default.reportFixtureStart, initialObject: task, args: [ first.fixture.name, first.fixture.path, first.fixture.meta, ], }); } } async _onTaskTestRunStartHandler(testRun) { if (!this.taskInfo) return void 0; const testItem = this._getTestItemForTestRun(this.taskInfo, testRun); testItem.testRunIds.push(testRun.id); if (!testItem.startTime) testItem.startTime = +new Date(); testItem.pendingStarts--; if (!testItem.pendingStarts) { // @ts-ignore if (this.plugin.reportTestStart) { const testStartInfo = { testRunIds: testItem.testRunIds, testId: testItem.test.id, startTime: new Date(testItem.startTime), skipped: testItem.test.skip, }; await this.dispatchToPlugin({ method: plugin_methods_1.default.reportTestStart, initialObject: this.taskInfo.task, args: [ testItem.test.name, testItem.test.meta, testStartInfo, ], }); } testItem.pendingTestRunStartPromise.resolve(); } return testItem.pendingTestRunStartPromise; } async _onTaskTestRunDoneHandler(testRun) { if (!this.taskInfo) return; const reportItem = this._getTestItemForTestRun(this.taskInfo, testRun); const isTestRunStoppedTaskExecution = !!testRun.errs.length && this.taskInfo.stopOnFirstFail; const browser = Object.assign({ testRunId: testRun.id }, testRun.browser); reportItem.browsers.push(browser); reportItem.pendingRuns = isTestRunStoppedTaskExecution ? 0 : reportItem.pendingRuns - 1; reportItem.unstable = reportItem.unstable || testRun.unstable; reportItem.errs = reportItem.errs.concat(testRun.errs); reportItem.warnings = testRun.warningLog ? (0, lodash_1.union)(reportItem.warnings, testRun.warningLog.messages) : []; reportItem.reportData = reportItem.reportData || {}; reportItem.reportData[testRun.id] = testRun.reportDataLog ? testRun.reportDataLog.data : []; if (testRun.quarantine) { reportItem.quarantine = reportItem.quarantine || {}; const reportItemQuarantine = testRun.quarantine.attempts.reduce((result, { errors, testRunId }) => { const passed = !errors.length; result[testRunId] = { passed, errors }; browser.quarantineAttemptsTestRunIds = browser.quarantineAttemptsTestRunIds || []; browser.quarantineAttemptsTestRunIds.push(testRunId); return result; }, {}); Object.assign(reportItem.quarantine, reportItemQuarantine); } if (!reportItem.pendingRuns) await this._resolveTestItem(this.taskInfo, reportItem, testRun); await reportItem.pendingTestRunDonePromise; } async _onTaskTestActionStart(_a) { var { apiActionName } = _a, restArgs = __rest(_a, ["apiActionName"]); if (!this.taskInfo) return; // @ts-ignore if (this.plugin.reportTestActionStart) { restArgs = this._prepareReportTestActionEventArgs(restArgs); await this.dispatchToPlugin({ method: plugin_methods_1.default.reportTestActionStart, initialObject: this.taskInfo.task, args: [ apiActionName, restArgs, ], }); } } async _onTaskTestActionDone(_a) { var { apiActionName } = _a, restArgs = __rest(_a, ["apiActionName"]); if (!this.taskInfo) return; // @ts-ignore if (this.plugin.reportTestActionDone) { restArgs = this._prepareReportTestActionEventArgs(restArgs); await this.dispatchToPlugin({ method: plugin_methods_1.default.reportTestActionDone, initialObject: this.taskInfo.task, args: [ apiActionName, restArgs, ], }); } } async _onceTaskDoneHandler() { var _a; if (!this.taskInfo) return; const endTime = new Date(); const result = { passedCount: this.taskInfo.passed, failedCount: this.taskInfo.failed, skippedCount: this.taskInfo.skipped, }; await this.dispatchToPlugin({ method: plugin_methods_1.default.reportTaskDone, initialObject: this.taskInfo.task, args: [ endTime, this.taskInfo.passed, (_a = this.taskInfo.task) === null || _a === void 0 ? void 0 : _a.warningLog.messages, result, ], }); this.taskInfo.pendingTaskDonePromise.resolve(); } _prepareReportDataEventArgs(testRun) { const { test, browser, id } = testRun; const fixture = test.fixture; const testInfo = { name: test.name, id: test.id, meta: test.meta, }; const fixtureInfo = { name: fixture === null || fixture === void 0 ? void 0 : fixture.name, id: fixture === null || fixture === void 0 ? void 0 : fixture.id, meta: fixture === null || fixture === void 0 ? void 0 : fixture.meta, path: fixture === null || fixture === void 0 ? void 0 : fixture.path, }; return { test: testInfo, fixture: fixtureInfo, testRunId: id, browser, }; } async _onReportDataHandler({ testRun, data }) { if (!this.taskInfo) return; const testRunInfo = this._prepareReportDataEventArgs(testRun); await this.dispatchToPlugin({ method: plugin_methods_1.default.reportData, initialObject: this.taskInfo.task, args: [ testRunInfo, ...data, ], }); } } exports.default = Reporter; module.exports = exports.default; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwb3J0ZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1DQUtnQjtBQUVoQix5Q0FBeUQ7QUFDekQsZ0VBQStDO0FBQy9DLHNFQUFvRDtBQUNwRCw4RUFBcUQ7QUFDckQsK0NBQTJFO0FBZ0IzRSxnREFBMEU7QUFDMUUsdUdBQTRFO0FBQzVFLHdEQUErQjtBQUMvQixnREFBd0I7QUFDeEIsNENBQW9CO0FBSXBCLDBEQUF3RDtBQUN4RCx5RkFBK0Q7QUF3SC9ELE1BQXFCLFFBQVE7SUFPekIsWUFBb0IsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsbUJBQW1CLEVBQW1CO1FBQzdGLElBQUksQ0FBQyxNQUFNLEdBQU8sSUFBSSxxQkFBa0IsQ0FBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1FBQ3ZGLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO1FBQzdCLElBQUksQ0FBQyxRQUFRLEdBQUssS0FBSyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxRQUFRLEdBQUssSUFBSSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxTQUFTLEdBQUksU0FBUyxDQUFDO1FBRTVCLElBQUksQ0FBQyw4QkFBOEIsRUFBRSxDQUFDO0lBQzFDLENBQUM7SUFFTyxNQUFNLENBQUMsZ0JBQWdCLENBQUUsTUFBZ0I7UUFDN0MsT0FBUSxNQUFzQixDQUFDLEtBQUssSUFBSSxNQUFNLEtBQUssT0FBTyxDQUFDLE1BQU0sSUFBSSxNQUFNLEtBQUssT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUNuRyxDQUFDO0lBRU8sTUFBTSxDQUFDLHFCQUFxQjtRQUNoQyxJQUFJLFFBQVEsR0FBRyxJQUFJLENBQUM7UUFFcEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVB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LE9BQU8sdUJBQVAsT0FBTyxDQUFFLEVBQUU7WUFDakIsSUFBSSxFQUFFLE9BQU8sYUFBUCxPQUFPLHVCQUFQLE9BQU8sQ0FBRSxJQUFJO1lBQ25CLElBQUksRUFBRSxPQUFPLGFBQVAsT0FBTyx1QkFBUCxPQUFPLENBQUUsSUFBSTtTQUN0QixDQUFDO1FBRUYsT0FBTztZQUNILElBQUksRUFBTyxRQUFRO1lBQ25CLE9BQU8sRUFBSSxXQUFXO1lBQ3RCLFNBQVMsRUFBRSxFQUFFO1lBQ2IsT0FBTztTQUNWLENBQUM7SUFDTixDQUFDO0lBRU8sS0FBSyxDQUFDLG9CQUFvQixDQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBdUI7UUFDdEUsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRO1lBQ2QsT0FBTztRQUVYLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUU5RCxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztZQUN4QixNQUFNLEVBQVMsd0JBQW9CLENBQUMsVUFBb0I7WUFDeEQsYUFBYSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSTtZQUNqQyxJQUFJLEVBQVc7Z0JBQ1gsV0FBVztnQkFDWCxHQUFHLElBQUk7YUFDVjtTQUNKLENBQUMsQ0FBQztJQUNQLENBQUM7Q0FDSjtBQW5rQkQsMkJBbWtCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gICAgZmluZCxcbiAgICBzb3J0QnksXG4gICAgdW5pb24sXG4gICAgaXNGdW5jdGlvbixcbn0gZnJvbSAnbG9kYXNoJztcblxuaW1wb3J0IHsgd3JpdGFibGUgYXMgaXNXcml0YWJsZVN0cmVhbSB9IGZyb20gJ2lzLXN0cmVhbSc7XG5pbXBvcnQgUmVwb3J0ZXJQbHVnaW5Ib3N0IGZyb20gJy4vcGx1Z2luLWhvc3QnO1xuaW1wb3J0IFJlcG9ydGVyUGx1Z2luTWV0aG9kIGZyb20gJy4vcGx1Z2luLW1ldGhvZHMnO1xuaW1wb3J0IGZvcm1hdENvbW1hbmQgZnJvbSAnLi9jb21tYW5kL2Zvcm1hdC1jb21tYW5kJztcbmltcG9ydCB7IFJlcG9ydGVyUGx1Z2luRXJyb3IsIExvYWRSZXBvcnRlckVycm9yIH0gZnJvbSAnLi4vZXJyb3JzL3J1bnRpbWUnO1xuaW1wb3J0IFRhc2sgZnJvbSAnLi4vcnVubmVyL3Rhc2snO1xuaW1wb3J0IHsgV3JpdGFibGUgYXMgV3JpdGFibGVTdHJlYW0sIFdyaXRhYmxlIH0gZnJvbSAnc3RyZWFtJztcbmltcG9ydCB7IFdyaXRlU3RyZWFtIH0gZnJvbSAndHR5JztcbmltcG9ydCBUZXN0UnVuIGZyb20gJy4uL3Rlc3QtcnVuJztcbmltcG9ydCBUZXN0IGZyb20gJy4uL2FwaS9zdHJ1Y3R1cmUvdGVzdCc7XG5pbXBvcnQgRml4dHVyZSBmcm9tICcuLi9hcGkvc3RydWN0dXJlL2ZpeHR1cmUnO1xuaW1wb3J0IFRlc3RSdW5FcnJvckZvcm1hdHRhYmxlQWRhcHRlciBmcm9tICcuLi9lcnJvcnMvdGVzdC1ydW4vZm9ybWF0dGFibGUtYWRhcHRlcic7XG5pbXBvcnQgeyBDb21tYW5kQmFzZSB9IGZyb20gJy4uL3Rlc3QtcnVuL2NvbW1hbmRzL2Jhc2UnO1xuXG5pbXBvcnQge1xuICAgIFJlcG9ydGVyUGx1Z2luLFxuICAgIFJlcG9ydGVyUGx1Z2luU291cmNlLFxuICAgIFJlcG9ydGVyU291cmNlLFxufSBmcm9tICcuL2ludGVyZmFjZXMnO1xuXG5pbXBvcnQgeyBnZXRQbHVnaW5GYWN0b3J5LCBwcm9jZXNzUmVwb3J0ZXJOYW1lIH0gZnJvbSAnLi4vdXRpbHMvcmVwb3J0ZXInO1xuaW1wb3J0IHJlc29sdmVQYXRoUmVsYXRpdmVseUN3ZCBmcm9tICcuLi91dGlscy9yZXNvbHZlLXBhdGgtcmVsYXRpdmVseS1jd2QnO1xuaW1wb3J0IG1ha2VEaXIgZnJvbSAnbWFrZS1kaXInO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IE1lc3NhZ2VCdXMgZnJvbSAnLi4vdXRpbHMvbWVzc2FnZS1idXMnO1xuaW1wb3J0IEJyb3dzZXJDb25uZWN0aW9uIGZyb20gJy4uL2Jyb3dzZXIvY29ubmVjdGlvbic7XG5pbXBvcnQgeyBEaWN0aW9uYXJ5IH0gZnJvbSAnLi4vY29uZmlndXJhdGlvbi9pbnRlcmZhY2VzJztcbmltcG9ydCB7IHJlcG9ydGVyTG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvZGVidWctbG9nZ2Vycyc7XG5pbXBvcnQgZ2V0VGVzdENhZmVWZXJzaW9uIGZyb20gJy4uL3V0aWxzL2dldC10ZXN0Y2FmZS12ZXJzaW9uJztcblxuaW50ZXJmYWNlIFBlbmRpbmdQcm9taXNlIHtcbiAgICByZXNvbHZlOiBGdW5jdGlvbiB8IG51bGw7XG4gICAgdGhlbjogRnVuY3Rpb247XG59XG5cbmludGVyZmFjZSBUYXNrSW5mbyB7XG4gICAgdGFzazogVGFzayB8IG51bGw7XG4gICAgcGFzc2VkOiBudW1iZXI7XG4gICAgZmFpbGVkOiBudW1iZXI7XG4gICAgc2tpcHBlZDogbnVtYmVyO1xuICAgIHRlc3RDb3VudDogbnVtYmVyO1xuICAgIHRlc3RRdWV1ZTogVGVzdEluZm9bXTtcbiAgICByZWFkb25seSBzdG9wT25GaXJzdEZhaWw6IGJvb2xlYW47XG4gICAgcmVhZG9ubHkgcGVuZGluZ1Rhc2tEb25lUHJvbWlzZTogUGVuZGluZ1Byb21pc2U7XG59XG5cbmludGVyZmFjZSBUZXN0SW5mbyB7XG4gICAgcmVwb3J0RGF0YTogRGljdGlvbmFyeTxhbnlbXT47XG4gICAgZml4dHVyZTogRml4dHVyZTtcbiAgICB0ZXN0OiBUZXN0O1xuICAgIHRlc3RSdW5JZHM6IHN0cmluZ1tdO1xuICAgIHNjcmVlbnNob3RQYXRoOiBudWxsIHwgc3RyaW5nO1xuICAgIHNjcmVlbnNob3RzOiB1bmtub3duW107XG4gICAgdmlkZW9zOiB1bmtub3duW107XG4gICAgcXVhcmFudGluZTogbnVsbCB8IFJlY29yZDxzdHJpbmcsIG9iamVjdD47XG4gICAgZXJyczogVGVzdFJ1bkVycm9yRm9ybWF0dGFibGVBZGFwdGVyW107XG4gICAgd2FybmluZ3M6IHN0cmluZ1tdO1xuICAgIHVuc3RhYmxlOiBib29sZWFuO1xuICAgIHN0YXJ0VGltZTogbnVsbCB8IG51bWJlcjtcbiAgICBmaW5pc2hUaW1lOiBudWxsIHwgbnVtYmVyO1xuICAgIHRlc3RSdW5JbmZvOiBudWxsIHwgVGVzdFJ1bkluZm87XG4gICAgcGVuZGluZ1J1bnM6IG51bWJlcjtcbiAgICBwZW5kaW5nU3RhcnRzOiBudW1iZXI7XG4gICAgcGVuZGluZ1Rlc3RSdW5Eb25lUHJvbWlzZTogUGVuZGluZ1Byb21pc2U7XG4gICAgcGVuZGluZ1Rlc3RSdW5TdGFydFByb21pc2U6IFBlbmRpbmdQcm9taXNlO1xuICAgIGJyb3dzZXJzOiBCcm93c2VyUnVuSW5mb1tdO1xufVxuXG5pbnRlcmZhY2UgRml4dHVyZUluZm8ge1xuICAgIGlkOiBzdHJpbmc7XG4gICAgbmFtZTogc3RyaW5nIHwgbnVsbDtcbiAgICBwYXRoOiBzdHJpbmc7XG4gICAgbWV0YTogTWV0YWRhdGE7XG59XG5cbmludGVyZmFjZSBCcm93c2VyUnVuSW5mbyBleHRlbmRzIEJyb3dzZXIge1xuICAgIHRlc3RSdW5JZDogc3RyaW5nO1xuICAgIHF1YXJhbnRpbmVBdHRlbXB0c1Rlc3RSdW5JZHM/OiBzdHJpbmdbXTtcbn1cblxuaW50ZXJmYWNlIFRlc3RSdW5JbmZvIHtcbiAgICBlcnJzOiBUZXN0UnVuRXJyb3JGb3JtYXR0YWJsZUFkYXB0ZXJbXTtcbiAgICB3YXJuaW5nczogc3RyaW5nW107XG4gICAgcmVwb3J0RGF0YTogRGljdGlvbmFyeTxhbnlbXT47XG4gICAgZHVyYXRpb25NczogbnVtYmVyO1xuICAgIHVuc3RhYmxlOiBib29sZWFuO1xuICAgIHNjcmVlbnNob3RQYXRoOiBzdHJpbmc7XG4gICAgc2NyZWVuc2hvdHM6IHVua25vd247XG4gICAgdmlkZW9zOiB1bmtub3duO1xuICAgIHF1YXJhbnRpbmU6IHVua25vd247XG4gICAgc2tpcHBlZDogYm9vbGVhbjtcbiAgICBicm93c2VyczogdW5rbm93bltdO1xuICAgIHRlc3RJZDogc3RyaW5nO1xuICAgIGZpeHR1cmU6IEZpeHR1cmVJbmZvO1xufVxuXG5pbnRlcmZhY2UgUGx1Z2luTWV0aG9kQXJndW1lbnRzIHtcbiAgICBpbml0aWFsT2JqZWN0OiBUYXNrIHwgTWVzc2FnZUJ1cyB8IG51bGw7XG4gICAgbWV0aG9kOiBzdHJpbmc7XG4gICAgYXJnczogdW5rbm93bltdO1xufVxuXG5pbnRlcmZhY2UgUmVwb3J0VGVzdEFjdGlvbkV2ZW50QXJndW1lbnRzIHtcbiAgICBjb21tYW5kOiBDb21tYW5kQmFzZTtcbiAgICBkdXJhdGlvbjogbnVtYmVyO1xuICAgIHJlc3VsdDogdW5rbm93bjtcbiAgICB0ZXN0UnVuOiBUZXN0UnVuO1xuICAgIGVycjogVGVzdFJ1bkVycm9yRm9ybWF0dGFibGVBZGFwdGVyO1xufVxuXG5pbnRlcmZhY2UgUmVwb3J0VGFza0FjdGlvbkV2ZW50QXJndW1lbnRzIHtcbiAgICBhcGlBY3Rpb25OYW1lOiBzdHJpbmc7XG4gICAgcmVzdEFyZ3M6IG9iamVjdDtcbn1cblxuaW50ZXJmYWNlIFJlcG9ydFdhcm5pbmdFdmVudEFyZ3VtZW50cyB7XG4gICAgbWVzc2FnZTogc3RyaW5nO1xuICAgIHRlc3RSdW4/OiBUZXN0UnVuO1xuICAgIGFjdGlvbklkPzogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgUmVwb3J0RGF0YUV2ZW50QXJncyB7XG4gICAgZGF0YTogYW55W107XG4gICAgdGVzdFJ1bjogVGVzdFJ1blxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFdyaXRlSW5mbyB7XG4gICAgaW5pdGlhdG9yOiBzdHJpbmc7XG4gICAgZm9ybWF0dGVkVGV4dDogc3RyaW5nO1xuICAgIGZvcm1hdE9wdGlvbnM6IHtcbiAgICAgICAgdXNlV29yZFdyYXA6IGJvb2xlYW47XG4gICAgICAgIGluZGVudDogbnVtYmVyO1xuICAgIH1cbiAgICBkYXRhOiB1bmRlZmluZWQgfCBvYmplY3Q7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVwb3J0ZXJQbHVnaW5Ib29rcyB7XG4gICAgb25CZWZvcmVXcml0ZT86IEZ1bmN0aW9uO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlcG9ydGVyT3B0aW9ucyB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIHBsdWdpbjogUmVwb3J0ZXJQbHVnaW47XG4gICAgbWVzc2FnZUJ1czogTWVzc2FnZUJ1cztcbiAgICBvdXRTdHJlYW06IFdyaXRhYmxlO1xuICAgIHJlcG9ydGVyUGx1Z2luSG9va3M/OiBSZXBvcnRlclBsdWdpbkhvb2tzXG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlcG9ydGVyIHtcbiAgICBwdWJsaWMgcmVhZG9ubHkgcGx1Z2luOiBSZXBvcnRlclBsdWdpbkhvc3Q7XG4gICAgcHVibGljIHJlYWRvbmx5IG1lc3NhZ2VCdXM6IE1lc3NhZ2VCdXM7XG4gICAgcHVibGljIGRpc3Bvc2VkOiBib29sZWFuO1xuICAgIHB1YmxpYyB0YXNrSW5mbzogVGFza0luZm8gfCBudWxsO1xuICAgIHB1YmxpYyByZWFkb25seSBvdXRTdHJlYW06IFdyaXRhYmxlO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yICh7IG5hbWUsIHBsdWdpbiwgb3V0U3RyZWFtLCBtZXNzYWdlQnVzLCByZXBvcnRlclBsdWdpbkhvb2tzIH06IFJlcG9ydGVyT3B0aW9ucykge1xuICAgICAgICB0aGlzLnBsdWdpbiAgICAgPSBuZXcgUmVwb3J0ZXJQbHVnaW5Ib3N0KHBsdWdpbiwgb3V0U3RyZWFtLCBuYW1lLCByZXBvcnRlclBsdWdpbkhvb2tzKTtcbiAgICAgICAgdGhpcy5tZXNzYWdlQnVzID0gbWVzc2FnZUJ1cztcbiAgICAgICAgdGhpcy5kaXNwb3NlZCAgID0gZmFsc2U7XG4gICAgICAgIHRoaXMudGFza0luZm8gICA9IG51bGw7XG4gICAgICAgIHRoaXMub3V0U3RyZWFtICA9IG91dFN0cmVhbTtcblxuICAgICAgICB0aGlzLl9hc3NpZ25NZXNzYWdlQnVzRXZlbnRIYW5kbGVycygpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc3RhdGljIF9pc1NwZWNpYWxTdHJlYW0gKHN0cmVhbTogV3JpdGFibGUpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIChzdHJlYW0gYXMgV3JpdGVTdHJlYW0pLmlzVFRZIHx8IHN0cmVhbSA9PT0gcHJvY2Vzcy5zdGRvdXQgfHwgc3RyZWFtID09PSBwcm9jZXNzLnN0ZGVycjtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBfY3JlYXRlUGVuZGluZ1Byb21pc2UgKCk6IFBlbmRpbmdQcm9taXNlIHtcbiAgICAgICAgbGV0IHJlc29sdmVyID0gbnVsbDtcblxuICAgICAgICBjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlciA9IHJlc29sdmU7XG4gICAgICAgIH0pIGFzIHVua25vd24gYXMgUGVuZGluZ1Byb21pc2U7XG5cbiAgICAgICAgcHJvbWlzZS5yZXNvbHZlID0gcmVzb2x2ZXI7XG5cbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGluaXQgKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCB0ZXN0Y2FmZVZlcnNpb24gPSBnZXRUZXN0Q2FmZVZlcnNpb24oKTtcblxuICAgICAgICBhd2FpdCB0aGlzLmRpc3BhdGNoVG9QbHVnaW4oe1xuICAgICAgICAgICAgbWV0aG9kOiAgICAgICAgUmVwb3J0ZXJQbHVnaW5NZXRob2QuaW5pdCxcbiAgICAgICAgICAgIGluaXRpYWxPYmplY3Q6IG51bGwsXG4gICAgICAgICAgICBhcmdzOiAgICAgICAgICBbdGVzdGNhZmVWZXJzaW9uXSxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGRpc3BhdGNoVG9QbHVnaW4gKHsgbWV0aG9kLCBpbml0aWFsT2JqZWN0LCBhcmdzID0gW10gfTogUGx1Z2luTWV0aG9kQXJndW1lbnRzKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJlcG9ydGVyTG9nZ2VyKCdiZWdpbiBkaXNwYXRjaFRvUGx1Z2luIG1ldGhvZDogJXNcXG4lTycsIG1ldGhvZCwgYXJncyk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luW21ldGhvZF0oLi4uYXJncyk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKG9yaWdpbmFsRXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnN0IHVuY2F1Z2h0RXJyb3IgPSBuZXcgUmVwb3J0ZXJQbHVnaW5FcnJvcih7XG4gICAgICAgICAgICAgICAgbmFtZTogdGhpcy5wbHVnaW4ubmFtZSxcbiAgICAgICAgICAgICAgICBtZXRob2QsXG4gICAgICAgICAgICAgICAgb3JpZ2luYWxFcnJvcixcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICByZXBvcnRlckxvZ2dlcignUGx1Z2luIGVycm9yOiAlTycsIHVuY2F1Z2h0RXJyb3IpO1xuICAgICAgICAgICAgcmVwb3J0ZXJMb2dnZXIoJ1BsdWdpbiBlcnJvcjogaW5pdGlhbE9iamVjdDogJU8nLCBpbml0aWFsT2JqZWN0KTtcblxuICAgICAgICAgICAgaWYgKGluaXRpYWxPYmplY3QpXG4gICAgICAgICAgICAgICAgYXdhaXQgaW5pdGlhbE9iamVjdC5lbWl0KCdlcnJvcicsIHVuY2F1Z2h0RXJyb3IpO1xuICAgICAgICAgICAgZWxzZVxuICAgICAgIC