@browserstack/testcafe
Version:
Automated browser testing for the modern web development stack.
229 lines • 34.8 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 format_command_1 = __importDefault(require("./command/format-command"));
class Reporter {
constructor(plugin, task, outStream, name) {
this.plugin = new plugin_host_1.default(plugin, outStream, name);
this.task = task;
this.disposed = false;
this.passed = 0;
this.failed = 0;
this.skipped = 0;
this.testCount = task.tests.filter(test => !test.skip).length;
this.reportQueue = Reporter._createReportQueue(task);
this.stopOnFirstFail = task.opts.stopOnFirstFail;
this.outStream = outStream;
this.pendingTaskDonePromise = Reporter._createPendingPromise();
this._assignTaskEventHandlers();
}
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;
}
static _createReportItem(test, runsPerTest) {
return {
fixture: test.fixture,
test: test,
testRunIds: [],
screenshotPath: null,
screenshots: [],
videos: [],
quarantine: null,
errs: [],
warnings: [],
unstable: false,
startTime: null,
testRunInfo: null,
pendingRuns: runsPerTest,
pendingStarts: runsPerTest,
pendingTestRunDonePromise: Reporter._createPendingPromise(),
pendingTestRunStartPromise: Reporter._createPendingPromise()
};
}
static _createReportQueue(task) {
const runsPerTest = task.browserConnectionGroups.length;
return task.tests.map(test => Reporter._createReportItem(test, runsPerTest));
}
static _createTestRunInfo(reportItem) {
return {
errs: lodash_1.sortBy(reportItem.errs, ['userAgent', 'code']),
warnings: reportItem.warnings,
durationMs: new Date() - reportItem.startTime,
unstable: reportItem.unstable,
screenshotPath: reportItem.screenshotPath,
screenshots: reportItem.screenshots,
videos: reportItem.videos,
quarantine: reportItem.quarantine,
skipped: reportItem.test.skip
};
}
_getReportItemForTestRun(testRun) {
return lodash_1.find(this.reportQueue, i => i.test === testRun.test);
}
async _shiftReportQueue(reportItem) {
let currentFixture = null;
let nextReportItem = null;
while (this.reportQueue.length && this.reportQueue[0].testRunInfo) {
reportItem = this.reportQueue.shift();
currentFixture = reportItem.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 = this.reportQueue[0];
await this.plugin.reportTestDone(reportItem.test.name, reportItem.testRunInfo, reportItem.test.meta);
if (nextReportItem && nextReportItem.fixture !== currentFixture)
await this.plugin.reportFixtureStart(nextReportItem.fixture.name, nextReportItem.fixture.path, nextReportItem.fixture.meta);
}
}
async _resolveReportItem(reportItem, testRun) {
if (this.task.screenshots.hasCapturedFor(testRun.test)) {
reportItem.screenshotPath = this.task.screenshots.getPathFor(testRun.test);
reportItem.screenshots = this.task.screenshots.getScreenshotsInfo(testRun.test);
}
if (this.task.videos)
reportItem.videos = this.task.videos.getTestVideos(reportItem.test.id);
if (testRun.quarantine) {
reportItem.quarantine = testRun.quarantine.attempts.reduce((result, errors, index) => {
const passed = !errors.length;
const quarantineAttempt = index + 1;
result[quarantineAttempt] = { passed };
return result;
}, {});
}
if (!reportItem.testRunInfo) {
reportItem.testRunInfo = Reporter._createTestRunInfo(reportItem);
if (reportItem.test.skip)
this.skipped++;
else if (reportItem.errs.length)
this.failed++;
else
this.passed++;
}
await this._shiftReportQueue(reportItem);
reportItem.pendingTestRunDonePromise.resolve();
}
_prepareReportTestActionEventArgs({ command, duration, result, testRun, err }) {
const args = {};
if (err)
args.err = err;
if (typeof duration === 'number')
args.duration = duration;
return Object.assign(args, {
testRunId: testRun.id,
test: {
id: testRun.test.id,
name: testRun.test.name,
phase: testRun.phase,
},
fixture: {
name: testRun.test.fixture.name,
id: testRun.test.fixture.id
},
command: format_command_1.default(command, result),
browser: testRun.controller.browser,
});
}
_assignTaskEventHandlers() {
const task = this.task;
task.once('start', async () => {
const startTime = new Date();
const userAgents = task.browserConnectionGroups.map(group => group[0].userAgent);
const first = this.reportQueue[0];
const taskProperties = {
configuration: task.opts
};
await this.plugin.reportTaskStart(startTime, userAgents, this.testCount, task.testStructure, taskProperties);
await this.plugin.reportFixtureStart(first.fixture.name, first.fixture.path, first.fixture.meta);
});
task.on('test-run-start', async (testRun) => {
const reportItem = this._getReportItemForTestRun(testRun);
reportItem.testRunIds.push(testRun.id);
if (!reportItem.startTime)
reportItem.startTime = new Date();
reportItem.pendingStarts--;
if (!reportItem.pendingStarts) {
if (this.plugin.reportTestStart) {
const testStartInfo = { testRunIds: reportItem.testRunIds };
await this.plugin.reportTestStart(reportItem.test.name, reportItem.test.meta, testStartInfo);
}
reportItem.pendingTestRunStartPromise.resolve();
}
return reportItem.pendingTestRunStartPromise;
});
task.on('test-run-done', async (testRun) => {
const reportItem = this._getReportItemForTestRun(testRun);
const isTestRunStoppedTaskExecution = !!testRun.errs.length && this.stopOnFirstFail;
reportItem.pendingRuns = isTestRunStoppedTaskExecution ? 0 : reportItem.pendingRuns - 1;
reportItem.unstable = reportItem.unstable || testRun.unstable;
reportItem.errs = reportItem.errs.concat(testRun.errs);
reportItem.warnings = testRun.warningLog ? lodash_1.union(reportItem.warnings, testRun.warningLog.messages) : [];
if (!reportItem.pendingRuns)
await this._resolveReportItem(reportItem, testRun);
await reportItem.pendingTestRunDonePromise;
});
task.on('test-action-start', async (_a) => {
var { apiActionName } = _a, args = __rest(_a, ["apiActionName"]);
if (this.plugin.reportTestActionStart) {
args = this._prepareReportTestActionEventArgs(args);
await this.plugin.reportTestActionStart(apiActionName, args);
}
});
task.on('test-action-done', async (_a) => {
var { apiActionName } = _a, args = __rest(_a, ["apiActionName"]);
if (this.plugin.reportTestActionDone) {
args = this._prepareReportTestActionEventArgs(args);
await this.plugin.reportTestActionDone(apiActionName, args);
}
});
task.once('done', async () => {
const endTime = new Date();
const result = {
passedCount: this.passed,
failedCount: this.failed,
skippedCount: this.skipped
};
await this.plugin.reportTaskDone(endTime, this.passed, task.warningLog.messages, result);
this.pendingTaskDonePromise.resolve();
});
}
async dispose() {
if (this.disposed)
return Promise.resolve();
this.disposed = true;
if (!this.outStream || Reporter._isSpecialStream(this.outStream) || !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;
}
}
exports.default = Reporter;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwb3J0ZXIvaW5kZXguanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1DQUE2QztBQUM3Qyx5Q0FBeUQ7QUFDekQsZ0VBQStDO0FBQy9DLDhFQUFxRDtBQUVyRCxNQUFxQixRQUFRO0lBQ3pCLFlBQWEsTUFBTSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSTtRQUN0QyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUkscUJBQWtCLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM5RCxJQUFJLENBQUMsSUFBSSxHQUFLLElBQUksQ0FBQztRQUVuQixJQUFJLENBQUMsUUFBUSxHQUFVLEtBQUssQ0FBQztRQUM3QixJQUFJLENBQUMsTUFBTSxHQUFZLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsTUFBTSxHQUFZLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsT0FBTyxHQUFXLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsU0FBUyxHQUFTLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDO1FBQ3BFLElBQUksQ0FBQyxXQUFXLEdBQU8sUUFBUSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pELElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUM7UUFDakQsSUFBSSxDQUFDLFNBQVMsR0FBUyxTQUFTLENBQUM7UUFFakMsSUFBSSxDQUFDLHNCQUFzQixHQUFHLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBRS9ELElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxNQUFNLENBQUMsZ0JBQWdCLENBQUUsTUFB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QUM7UUFFckIsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksUUFBUSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLG9CQUFnQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDakcsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFN0IsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNoRCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDdkMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzFDLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUVyQixPQUFPLHFCQUFxQixDQUFDO0lBQ2pDLENBQUM7Q0FDSjtBQXZRRCwyQkF1UUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmaW5kLCBzb3J0QnksIHVuaW9uIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IHdyaXRhYmxlIGFzIGlzV3JpdGFibGVTdHJlYW0gfSBmcm9tICdpcy1zdHJlYW0nO1xuaW1wb3J0IFJlcG9ydGVyUGx1Z2luSG9zdCBmcm9tICcuL3BsdWdpbi1ob3N0JztcbmltcG9ydCBmb3JtYXRDb21tYW5kIGZyb20gJy4vY29tbWFuZC9mb3JtYXQtY29tbWFuZCc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlcG9ydGVyIHtcbiAgICBjb25zdHJ1Y3RvciAocGx1Z2luLCB0YXNrLCBvdXRTdHJlYW0sIG5hbWUpIHtcbiAgICAgICAgdGhpcy5wbHVnaW4gPSBuZXcgUmVwb3J0ZXJQbHVnaW5Ib3N0KHBsdWdpbiwgb3V0U3RyZWFtLCBuYW1lKTtcbiAgICAgICAgdGhpcy50YXNrICAgPSB0YXNrO1xuXG4gICAgICAgIHRoaXMuZGlzcG9zZWQgICAgICAgID0gZmFsc2U7XG4gICAgICAgIHRoaXMucGFzc2VkICAgICAgICAgID0gMDtcbiAgICAgICAgdGhpcy5mYWlsZWQgICAgICAgICAgPSAwO1xuICAgICAgICB0aGlzLnNraXBwZWQgICAgICAgICA9IDA7XG4gICAgICAgIHRoaXMudGVzdENvdW50ICAgICAgID0gdGFzay50ZXN0cy5maWx0ZXIodGVzdCA9PiAhdGVzdC5za2lwKS5sZW5ndGg7XG4gICAgICAgIHRoaXMucmVwb3J0UXVldWUgICAgID0gUmVwb3J0ZXIuX2NyZWF0ZVJlcG9ydFF1ZXVlKHRhc2spO1xuICAgICAgICB0aGlzLnN0b3BPbkZpcnN0RmFpbCA9IHRhc2sub3B0cy5zdG9wT25GaXJzdEZhaWw7XG4gICAgICAgIHRoaXMub3V0U3RyZWFtICAgICAgID0gb3V0U3RyZWFtO1xuXG4gICAgICAgIHRoaXMucGVuZGluZ1Rhc2tEb25lUHJvbWlzZSA9IFJlcG9ydGVyLl9jcmVhdGVQZW5kaW5nUHJvbWlzZSgpO1xuXG4gICAgICAgIHRoaXMuX2Fzc2lnblRhc2tFdmVudEhhbmRsZXJzKCk7XG4gICAgfVxuXG4gICAgc3RhdGljIF9pc1NwZWNpYWxTdHJlYW0gKHN0cmVhbSkge1xuICAgICAgICByZXR1cm4gc3RyZWFtLmlzVFRZIHx8IHN0cmVhbSA9PT0gcHJvY2Vzcy5zdGRvdXQgfHwgc3RyZWFtID09PSBwcm9jZXNzLnN0ZGVycjtcbiAgICB9XG5cbiAgICBzdGF0aWMgX2NyZWF0ZVBlbmRpbmdQcm9taXNlICgpIHtcbiAgICAgICAgbGV0IHJlc29sdmVyID0gbnVsbDtcblxuICAgICAgICBjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlciA9IHJlc29sdmU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHByb21pc2UucmVzb2x2ZSA9IHJlc29sdmVyO1xuXG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIHN0YXRpYyBfY3JlYXRlUmVwb3J0SXRlbSAodGVzdCwgcnVuc1BlclRlc3QpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGZpeHR1cmU6ICAgICAgICAgICAgICAgICAgICB0ZXN0LmZpeHR1cmUsXG4gICAgICAgICAgICB0ZXN0OiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCxcbiAgICAgICAgICAgIHRlc3RSdW5JZHM6ICAgICAgICAgICAgICAgICBbXSxcbiAgICAgICAgICAgIHNjcmVlbnNob3RQYXRoOiAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgc2NyZWVuc2hvdHM6ICAgICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgdmlkZW9zOiAgICAgICAgICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgcXVhcmFudGluZTogICAgICAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICBlcnJzOiAgICAgICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICB3YXJuaW5nczogICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICB1bnN0YWJsZTogICAgICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICBzdGFydFRpbWU6ICAgICAgICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgIHRlc3RSdW5JbmZvOiAgICAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgcGVuZGluZ1J1bnM6ICAgICAgICAgICAgICAgIHJ1bnNQZXJUZXN0LFxuICAgICAgICAgICAgcGVuZGluZ1N0YXJ0czogICAgICAgICAgICAgIHJ1bnNQZXJUZXN0LFxuICAgICAgICAgICAgcGVuZGluZ1Rlc3RSdW5Eb25lUHJvbWlzZTogIFJlcG9ydGVyLl9jcmVhdGVQZW5kaW5nUHJvbWlzZSgpLFxuICAgICAgICAgICAgcGVuZGluZ1Rlc3RSdW5TdGFydFByb21pc2U6IFJlcG9ydGVyLl9jcmVhdGVQZW5kaW5nUHJvbWlzZSgpXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgc3RhdGljIF9jcmVhdGVSZXBvcnRRdWV1ZSAodGFzaykge1xuICAgICAgICBjb25zdCBydW5zUGVyVGVzdCA9IHRhc2suYnJvd3NlckNvbm5lY3Rpb25Hcm91cHMubGVuZ3RoO1xuXG4gICAgICAgIHJldHVybiB0YXNrLnRlc3RzLm1hcCh0ZXN0ID0+IFJlcG9ydGVyLl9jcmVhdGVSZXBvcnRJdGVtKHRlc3QsIHJ1bnNQZXJUZXN0KSk7XG4gICAgfVxuXG4gICAgc3RhdGljIF9jcmVhdGVUZXN0UnVuSW5mbyAocmVwb3J0SXRlbSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZXJyczogICAgICAgICAgIHNvcnRCeShyZXBvcnRJdGVtLmVycnMsIFsndXNlckFnZW50JywgJ2NvZGUnXSksXG4gICAgICAgICAgICB3YXJuaW5nczogICAgICAgcmVwb3J0SXRlbS53YXJuaW5ncyxcbiAgICAgICAgICAgIGR1cmF0aW9uTXM6ICAgICBuZXcgRGF0ZSgpIC0gcmVwb3J0SXRlbS5zdGFydFRpbWUsXG4gICAgICAgICAgICB1bnN0YWJsZTogICAgICAgcmVwb3J0SXRlbS51bnN0YWJsZSxcbiAgICAgICAgICAgIHNjcmVlbnNob3RQYXRoOiByZXBvcnRJdGVtLnNjcmVlbnNob3RQYXRoLFxuICAgICAgICAgICAgc2NyZWVuc2hvdHM6ICAgIHJlcG9ydEl0ZW0uc2NyZWVuc2hvdHMsXG4gICAgICAgICAgICB2aWRlb3M6ICAgICAgICAgcmVwb3J0SXRlbS52aWRlb3MsXG4gICAgICAgICAgICBxdWFyYW50aW5lOiAgICAgcmVwb3J0SXRlbS5xdWFyYW50aW5lLFxuICAgICAgICAgICAgc2tpcHBlZDogICAgICAgIHJlcG9ydEl0ZW0udGVzdC5za2lwXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgX2dldFJlcG9ydEl0ZW1Gb3JUZXN0UnVuICh0ZXN0UnVuKSB7XG4gICAgICAgIHJldHVybiBmaW5kKHRoaXMucmVwb3J0UXVldWUsIGkgPT4gaS50ZXN0ID09PSB0ZXN0UnVuLnRlc3QpO1xuICAgIH1cblxuICAgIGFzeW5jIF9zaGlmdFJlcG9ydFF1ZXVlIChyZXBvcnRJdGVtKSB7XG4gICAgICAgIGxldCBjdXJyZW50Rml4dHVyZSA9IG51bGw7XG4gICAgICAgIGxldCBuZXh0UmVwb3J0SXRlbSA9IG51bGw7XG5cbiAgICAgICAgd2hpbGUgKHRoaXMucmVwb3J0UXVldWUubGVuZ3RoICYmIHRoaXMucmVwb3J0UXVldWVbMF0udGVzdFJ1bkluZm8pIHtcbiAgICAgICAgICAgIHJlcG9ydEl0ZW0gICAgID0gdGhpcy5yZXBvcnRRdWV1ZS5zaGlmdCgpO1xuICAgICAgICAgICAgY3VycmVudEZpeHR1cmUgPSByZXBvcnRJdGVtLmZpeHR1cmU7XG5cbiAgICAgICAgICAgIC8vIE5PVEU6IGhlcmUgd2UgYXNzdW1lIHRoYXQgdGVzdHMgYXJlIHNvcnRlZCBieSBmaXh0dXJlLlxuICAgICAgICAgICAgLy8gVGhlcmVmb3JlLCBpZiB0aGUgbmV4dCByZXBvcnQgaXRlbSBoYXMgYSBkaWZmZXJlbnRcbiAgICAgICAgICAgIC8vIGZpeHR1cmUsIHdlIGNhbiByZXBvcnQgdGhpcyBmaXh0dXJlIHN0YXJ0LlxuICAgICAgICAgICAgbmV4dFJlcG9ydEl0ZW0gPSB0aGlzLnJlcG9ydFF1ZXVlWzBdO1xuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5yZXBvcnRUZXN0RG9uZShyZXBvcnRJdGVtLnRlc3QubmFtZSwgcmVwb3J0SXRlbS50ZXN0UnVuSW5mbywgcmVwb3J0SXRlbS50ZXN0Lm1ldGEpO1xuXG4gICAgICAgICAgICBpZiAobmV4dFJlcG9ydEl0ZW0gJiYgbmV4dFJlcG9ydEl0ZW0uZml4dHVyZSAhPT0gY3VycmVudEZpeHR1cmUpXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4ucmVwb3J0Rml4dHVyZVN0YXJ0KG5leHRSZXBvcnRJdGVtLmZpeHR1cmUubmFtZSwgbmV4dFJlcG9ydEl0ZW0uZml4dHVyZS5wYXRoLCBuZXh0UmVwb3J0SXRlbS5maXh0dXJlLm1ldGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgX3Jlc29sdmVSZXBvcnRJdGVtIChyZXBvcnRJdGVtLCB0ZXN0UnVuKSB7XG4gICAgICAgIGlmICh0aGlzLnRhc2suc2NyZWVuc2hvdHMuaGFzQ2FwdHVyZWRGb3IodGVzdFJ1bi50ZXN0KSkge1xuICAgICAgICAgICAgcmVwb3J0SXRlbS5zY3JlZW5zaG90UGF0aCA9IHRoaXMudGFzay5zY3JlZW5zaG90cy5nZXRQYXRoRm9yKHRlc3RSdW4udGVzdCk7XG4gICAgICAgICAgICByZXBvcnRJdGVtLnNjcmVlbnNob3RzICAgID0gdGhpcy50YXNrLnNjcmVlbnNob3RzLmdldFNjcmVlbnNob3RzSW5mbyh0ZXN0UnVuLnRlc3QpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMudGFzay52aWRlb3MpXG4gICAgICAgICAgICByZXBvcnRJdGVtLnZpZGVvcyA9IHRoaXMudGFzay52aWRlb3MuZ2V0VGVzdFZpZGVvcyhyZXBvcnRJdGVtLnRlc3QuaWQpO1xuXG4gICAgICAgIGlmICh0ZXN0UnVuLnF1YXJhbnRpbmUpIHtcbiAgICAgICAgICAgIHJlcG9ydEl0ZW0ucXVhcmFudGluZSA9IHRlc3RSdW4ucXVhcmFudGluZS5hdHRlbXB0cy5yZWR1Y2UoKHJlc3VsdCwgZXJyb3JzLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhc3NlZCAgICAgICAgICAgID0gIWVycm9ycy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgY29uc3QgcXVhcmFudGluZUF0dGVtcHQgPSBpbmRleCArIDE7XG5cbiAgICAgICAgICAgICAgICByZXN1bHRbcXVhcmFudGluZUF0dGVtcHRdID0geyBwYXNzZWQgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9LCB7fSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXJlcG9ydEl0ZW0udGVzdFJ1bkluZm8pIHtcbiAgICAgICAgICAgIHJlcG9ydEl0ZW0udGVzdFJ1bkluZm8gPSBSZXBvcnRlci5fY3JlYXRlVGVzdFJ1bkluZm8ocmVwb3J0SXRlbSk7XG5cbiAgICAgICAgICAgIGlmIChyZXBvcnRJdGVtLnRlc3Quc2tpcClcbiAgICAgICAgICAgICAgICB0aGlzLnNraXBwZWQrKztcbiAgICAgICAgICAgIGVsc2UgaWYgKHJlcG9ydEl0ZW0uZXJycy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhpcy5mYWlsZWQrKztcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICB0aGlzLnBhc3NlZCsrO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5fc2hpZnRSZXBvcnRRdWV1ZShyZXBvcnRJdGVtKTtcblxuICAgICAgICByZXBvcnRJdGVtLnBlbmRpbmdUZXN0UnVuRG9uZVByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIF9wcmVwYXJlUmVwb3J0VGVzdEFjdGlvbkV2ZW50QXJncyAoeyBjb21tYW5kLCBkdXJhdGlvbiwgcmVzdWx0LCB0ZXN0UnVuLCBlcnIgfSkge1xuICAgICAgICBjb25zdCBhcmdzID0ge307XG5cbiAgICAgICAgaWYgKGVycilcbiAgICAgICAgICAgIGFyZ3MuZXJyID0gZXJyO1xuXG4gICAgICAgIGlmICh0eXBlb2YgZHVyYXRpb24gPT09ICdudW1iZXInKVxuICAgICAgICAgICAgYXJncy5kdXJhdGlvbiA9IGR1cmF0aW9uO1xuXG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKGFyZ3MsIHtcbiAgICAgICAgICAgIHRlc3RSdW5JZDogdGVzdFJ1bi5pZCxcbiAgICAgICAgICAgIHRlc3Q6ICAgICAge1xuICAgICAgICAgICAgICAgIGlkOiAgICB0ZXN0UnVuLnRlc3QuaWQsXG4gICAgICAgICAgICAgICAgbmFtZTogIHRlc3RSdW4udGVzdC5uYW1lLFxuICAgICAgICAgICAgICAgIHBoYXNlOiB0ZXN0UnVuLnBoYXNlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZpeHR1cmU6IHtcbiAgICAgICAgICAgICAgICBuYW1lOiB0ZXN0UnVuLnRlc3QuZml4dHVyZS5uYW1lLFxuICAgICAgICAgICAgICAgIGlkOiAgIHRlc3RSdW4udGVzdC5maXh0dXJlLmlkXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29tbWFuZDogZm9ybWF0Q29tbWFuZChjb21tYW5kLCByZXN1bHQpLFxuICAgICAgICAgICAgYnJvd3NlcjogdGVzdFJ1bi5jb250cm9sbGVyLmJyb3dzZXIsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIF9hc3NpZ25UYXNrRXZlbnRIYW5kbGVycyAoKSB7XG4gICAgICAgIGNvbnN0IHRhc2sgPSB0aGlzLnRhc2s7XG5cbiAgICAgICAgdGFzay5vbmNlKCdzdGFydCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0VGltZSAgPSBuZXcgRGF0ZSgpO1xuICAgICAgICAgICAgY29uc3QgdXNlckFnZW50cyA9IHRhc2suYnJvd3NlckNvbm5lY3Rpb25Hcm91cHMubWFwKGdyb3VwID0+IGdyb3VwWzBdLnVzZXJBZ2VudCk7XG4gICAgICAgICAgICBjb25zdCBmaXJzdCAgICAgID0gdGhpcy5yZXBvcnRRdWV1ZVswXTtcbiAgICAgICAgICAgIGNvbnN0IHRhc2tQcm9wZXJ0aWVzID0ge1xuICAgICAgICAgICAgICAgIGNvbmZpZ3VyYXRpb246IHRhc2sub3B0c1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4ucmVwb3J0VGFza1N0YXJ0KHN0YXJ0VGltZSwgdXNlckFnZW50cywgdGhpcy50ZXN0Q291bnQsIHRhc2sudGVzdFN0cnVjdHVyZSwgdGFza1Byb3BlcnRpZXMpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4ucmVwb3J0Rml4dHVyZVN0YXJ0KGZpcnN0LmZpeHR1cmUubmFtZSwgZmlyc3QuZml4dHVyZS5wYXRoLCBmaXJzdC5maXh0dXJlLm1ldGEpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0YXNrLm9uKCd0ZXN0LXJ1bi1zdGFydCcsIGFzeW5jIHRlc3RSdW4gPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVwb3J0SXRlbSA9IHRoaXMuX2dldFJlcG9ydEl0ZW1Gb3JUZXN0UnVuKHRlc3RSdW4pO1xuXG4gICAgICAgICAgICByZXBvcnRJdGVtLnRlc3RSdW5JZHMucHVzaCh0ZXN0UnVuLmlkKTtcblxuICAgICAgICAgICAgaWYgKCFyZXBvcnRJdGVtLnN0YXJ0VGltZSlcbiAgICAgICAgICAgICAgICByZXBvcnRJdGVtLnN0YXJ0VGltZSA9IG5ldyBEYXRlKCk7XG5cbiAgICAgICAgICAgIHJlcG9ydEl0ZW0ucGVuZGluZ1N0YXJ0cy0tO1xuXG4gICAgICAgICAgICBpZiAoIXJlcG9ydEl0ZW0ucGVuZGluZ1N0YXJ0cykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnBsdWdpbi5yZXBvcnRUZXN0U3RhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGVzdFN0YXJ0SW5mbyA9IHsgdGVzdFJ1bklkczogcmVwb3J0SXRlbS50ZXN0UnVuSWRzIH07XG5cbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4ucmVwb3J0VGVzdFN0YXJ0KHJlcG9ydEl0ZW0udGVzdC5uYW1lLCByZXBvcnRJdGVtLnRlc3QubWV0YSwgdGVzdFN0YXJ0SW5mbyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVwb3J0SXRlbS5wZW5kaW5nVGVzdFJ1blN0YXJ0UHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXBvcnRJdGVtLnBlbmRpbmdUZXN0UnVuU3RhcnRQcm9taXNlO1xuICAgICAgICB9KTtcblxuICAgICAgICB0YXNrLm9uKCd0ZXN0LXJ1bi1kb25lJywgYXN5bmMgdGVzdFJ1biA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXBvcnRJdGVtICAgICAgICAgICAgICAgICAgICA9IHRoaXMuX2dldFJlcG9ydEl0ZW1Gb3JUZXN0UnVuKHRlc3RSdW4pO1xuICAgICAgICAgICAgY29uc3QgaXNUZXN0UnVuU3RvcHBlZFRhc2tFeGVjdXRpb24gPSAhIXRlc3RSdW4uZXJycy5sZW5ndGggJiYgdGhpcy5zdG9wT25GaXJzdEZhaWw7XG5cbiAgICAgICAgICAgIHJlcG9ydEl0ZW0ucGVuZGluZ1J1bnMgPSBpc1Rlc3RSdW5TdG9wcGVkVGFza0V4ZWN1dGlvbiA/IDAgOiByZXBvcnRJdGVtLnBlbmRpbmdSdW5zIC0gMTtcbiAgICAgICAgICAgIHJlcG9ydEl0ZW0udW5zdGFibGUgICAgPSByZXBvcnRJdGVtLnVuc3RhYmxlIHx8IHRlc3RSdW4udW5zdGFibGU7XG4gICAgICAgICAgICByZXBvcnRJdGVtLmVycnMgICAgICAgID0gcmVwb3J0SXRlbS5lcnJzLmNvbmNhdCh0ZXN0UnVuLmVycnMpO1xuICAgICAgICAgICAgcmVwb3J0SXRlbS53YXJuaW5ncyAgICA9IHRlc3RSdW4ud2FybmluZ0xvZyA/IHVuaW9uKHJlcG9ydEl0ZW0ud2FybmluZ3MsIHRlc3RSdW4ud2FybmluZ0xvZy5tZXNzYWdlcykgOiBbXTtcblxuICAgICAgICAgICAgaWYgKCFyZXBvcnRJdGVtLnBlbmRpbmdSdW5zKVxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuX3Jlc29sdmVSZXBvcnRJdGVtKHJlcG9ydEl0ZW0sIHRlc3RSdW4pO1xuXG4gICAgICAgICAgICBhd2FpdCByZXBvcnRJdGVtLnBlbmRpbmdUZXN0UnVuRG9uZVByb21pc2U7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRhc2sub24oJ3Rlc3QtYWN0aW9uLXN0YXJ0JywgYXN5bmMgKHsgYXBpQWN0aW9uTmFtZSwgLi4uYXJncyB9KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5wbHVnaW4ucmVwb3J0VGVzdEFjdGlvblN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgYXJncyA9IHRoaXMuX3ByZXBhcmVSZXBvcnRUZXN0QWN0aW9uRXZlbnRBcmdzKGFyZ3MpO1xuXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4ucmVwb3J0VGVzdEFjdGlvblN0YXJ0KGFwaUFjdGlvbk5hbWUsIGFyZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB0YXNrLm9uKCd0ZXN0LWFjdGlvbi1kb25lJywgYXN5bmMgKHsgYXBpQWN0aW9uTmFtZSwgLi4uYXJncyB9KSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5wbHVnaW4ucmVwb3J0VGVzdEFjdGlvbkRvbmUpIHtcbiAgICAgICAgICAgICAgICBhcmdzID0gdGhpcy5fcHJlcGFyZVJlcG9ydFRlc3RBY3Rpb25FdmVudEFyZ3MoYXJncyk7XG5cbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5yZXBvcnRUZXN0QWN0aW9uRG9uZShhcGlBY3Rpb25OYW1lLCBhcmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGFzay5vbmNlKCdkb25lJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZW5kVGltZSA9IG5ldyBEYXRlKCk7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHtcbiAgICAgICAgICAgICAgICBwYXNzZWRDb3VudDogIHRoaXMucGFzc2VkLFxuICAgICAgICAgICAgICAgIGZhaWxlZENvdW50OiAgdGhpcy5mYWlsZWQsXG4gICAgICAgICAgICAgICAgc2tpcHBlZENvdW50OiB0aGlzLnNraXBwZWRcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnJlcG9ydFRhc2tEb25lKGVuZFRpbWUsIHRoaXMucGFzc2VkLCB0YXNrLndhcm5pbmdMb2cubWVzc2FnZXMsIHJlc3VsdCk7XG5cbiAgICAgICAgICAgIHRoaXMucGVuZGluZ1Rhc2tEb25lUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFzeW5jIGRpc3Bvc2UgKCkge1xuICAgICAgICBpZiAodGhpcy5kaXNwb3NlZClcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcblxuICAgICAgICB0aGlzLmRpc3Bvc2VkID0gdHJ1ZTtcblxuICAgICAgICBpZiAoIXRoaXMub3V0U3RyZWFtIHx8IFJlcG9ydGVyLl9pc1NwZWNpYWxTdHJlYW0odGhpcy5vdXRTdHJlYW0pIHx8ICFpc1dyaXRhYmxlU3RyZWFtKHRoaXMub3V0U3RyZWFtKSlcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcblxuICAgICAgICBjb25zdCBzdHJlYW1GaW5pc2hlZFByb21pc2UgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICAgIHRoaXMub3V0U3RyZWFtLm9uY2UoJ2ZpbmlzaCcsIHJlc29sdmUpO1xuICAgICAgICAgICAgdGhpcy5vdXRTdHJlYW0ub25jZSgnZXJyb3InLCByZXNvbHZlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5vdXRTdHJlYW0uZW5kKCk7XG5cbiAgICAgICAgcmV0dXJuIHN0cmVhbUZpbmlzaGVkUHJvbWlzZTtcbiAgICB9XG59XG4iXX0=