testcafe
Version:
Automated browser testing for the modern web development stack.
496 lines • 75.1 kB
JavaScript
"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