UNPKG

32.2 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const lodash_1 = require("lodash");
7const is_stream_1 = require("is-stream");
8const plugin_host_1 = __importDefault(require("./plugin-host"));
9const command_report_item_1 = require("./command-report-item");
10const error_list_1 = __importDefault(require("../errors/error-list"));
11class Reporter {
12 constructor(plugin, task, outStream) {
13 this.plugin = new plugin_host_1.default(plugin, outStream);
14 this.task = task;
15 this.disposed = false;
16 this.passed = 0;
17 this.failed = 0;
18 this.skipped = 0;
19 this.testCount = task.tests.filter(test => !test.skip).length;
20 this.reportQueue = Reporter._createReportQueue(task);
21 this.stopOnFirstFail = task.opts.stopOnFirstFail;
22 this.outStream = outStream;
23 this.pendingTaskDonePromise = Reporter._createPendingPromise();
24 this._assignTaskEventHandlers();
25 }
26 static _isSpecialStream(stream) {
27 return stream.isTTY || stream === process.stdout || stream === process.stderr;
28 }
29 static _createPendingPromise() {
30 let resolver = null;
31 const promise = new Promise(resolve => {
32 resolver = resolve;
33 });
34 promise.resolve = resolver;
35 return promise;
36 }
37 static _createReportItem(test, runsPerTest) {
38 return {
39 fixture: test.fixture,
40 test: test,
41 screenshotPath: null,
42 screenshots: [],
43 quarantine: null,
44 errs: [],
45 warnings: [],
46 unstable: false,
47 startTime: null,
48 testRunInfo: null,
49 pendingRuns: runsPerTest,
50 pendingStarts: runsPerTest,
51 pendingTestRunDonePromise: Reporter._createPendingPromise(),
52 pendingTestRunStartPromise: Reporter._createPendingPromise()
53 };
54 }
55 static _createReportQueue(task) {
56 const runsPerTest = task.browserConnectionGroups.length;
57 return task.tests.map(test => Reporter._createReportItem(test, runsPerTest));
58 }
59 static _createTestRunInfo(reportItem) {
60 return {
61 errs: lodash_1.sortBy(reportItem.errs, ['userAgent', 'code']),
62 warnings: reportItem.warnings,
63 durationMs: new Date() - reportItem.startTime,
64 unstable: reportItem.unstable,
65 screenshotPath: reportItem.screenshotPath,
66 screenshots: reportItem.screenshots,
67 quarantine: reportItem.quarantine,
68 skipped: reportItem.test.skip
69 };
70 }
71 _getReportItemForTestRun(testRun) {
72 return lodash_1.find(this.reportQueue, i => i.test === testRun.test);
73 }
74 async _shiftReportQueue(reportItem) {
75 let currentFixture = null;
76 let nextReportItem = null;
77 while (this.reportQueue.length && this.reportQueue[0].testRunInfo) {
78 reportItem = this.reportQueue.shift();
79 currentFixture = reportItem.fixture;
80 await this.plugin.reportTestDone(reportItem.test.name, reportItem.testRunInfo, reportItem.test.meta);
81 // NOTE: here we assume that tests are sorted by fixture.
82 // Therefore, if the next report item has a different
83 // fixture, we can report this fixture start.
84 nextReportItem = this.reportQueue[0];
85 if (nextReportItem && nextReportItem.fixture !== currentFixture)
86 await this.plugin.reportFixtureStart(nextReportItem.fixture.name, nextReportItem.fixture.path, nextReportItem.fixture.meta);
87 }
88 }
89 async _resolveReportItem(reportItem, testRun) {
90 if (this.task.screenshots.hasCapturedFor(testRun.test)) {
91 reportItem.screenshotPath = this.task.screenshots.getPathFor(testRun.test);
92 reportItem.screenshots = this.task.screenshots.getScreenshotsInfo(testRun.test);
93 }
94 if (testRun.quarantine) {
95 reportItem.quarantine = testRun.quarantine.attempts.reduce((result, errors, index) => {
96 const passed = !errors.length;
97 const quarantineAttempt = index + 1;
98 result[quarantineAttempt] = { passed };
99 return result;
100 }, {});
101 }
102 if (!reportItem.testRunInfo) {
103 reportItem.testRunInfo = Reporter._createTestRunInfo(reportItem);
104 if (reportItem.test.skip)
105 this.skipped++;
106 else if (reportItem.errs.length)
107 this.failed++;
108 else
109 this.passed++;
110 }
111 await this._shiftReportQueue(reportItem);
112 reportItem.pendingTestRunDonePromise.resolve();
113 }
114 _prepareReportTestActionEventArgs({ command, testRun, errors }) {
115 const args = {};
116 if (errors) {
117 errors = errors instanceof error_list_1.default ? errors.items : [errors];
118 args.errors = errors;
119 }
120 return Object.assign(args, {
121 test: {
122 name: testRun.test.name,
123 phase: testRun.phase
124 },
125 command: new command_report_item_1.CommandReportItem(command),
126 browser: testRun.controller.browser,
127 });
128 }
129 _assignTaskEventHandlers() {
130 const task = this.task;
131 task.once('start', async () => {
132 const startTime = new Date();
133 const userAgents = task.browserConnectionGroups.map(group => group[0].userAgent);
134 const first = this.reportQueue[0];
135 await this.plugin.reportTaskStart(startTime, userAgents, this.testCount);
136 await this.plugin.reportFixtureStart(first.fixture.name, first.fixture.path, first.fixture.meta);
137 });
138 task.on('test-run-start', async (testRun) => {
139 const reportItem = this._getReportItemForTestRun(testRun);
140 if (!reportItem.startTime)
141 reportItem.startTime = new Date();
142 reportItem.pendingStarts--;
143 if (!reportItem.pendingStarts) {
144 if (this.plugin.reportTestStart)
145 await this.plugin.reportTestStart(reportItem.test.name, reportItem.test.meta);
146 reportItem.pendingTestRunStartPromise.resolve();
147 }
148 return reportItem.pendingTestRunStartPromise;
149 });
150 task.on('test-run-done', async (testRun) => {
151 const reportItem = this._getReportItemForTestRun(testRun);
152 const isTestRunStoppedTaskExecution = !!testRun.errs.length && this.stopOnFirstFail;
153 reportItem.pendingRuns = isTestRunStoppedTaskExecution ? 0 : reportItem.pendingRuns - 1;
154 reportItem.unstable = reportItem.unstable || testRun.unstable;
155 reportItem.errs = reportItem.errs.concat(testRun.errs);
156 reportItem.warnings = testRun.warningLog ? lodash_1.union(reportItem.warnings, testRun.warningLog.messages) : [];
157 if (!reportItem.pendingRuns)
158 await this._resolveReportItem(reportItem, testRun);
159 await reportItem.pendingTestRunDonePromise;
160 });
161 task.on('test-action-start', async ({ apiActionName, command, testRun }) => {
162 if (this.plugin.reportTestActionStart) {
163 const args = this._prepareReportTestActionEventArgs({ command, testRun });
164 await this.plugin.reportTestActionStart(apiActionName, args);
165 }
166 });
167 task.on('test-action-done', async ({ apiActionName, command, testRun, errors }) => {
168 if (this.plugin.reportTestActionDone) {
169 const args = this._prepareReportTestActionEventArgs({ command, testRun, errors });
170 await this.plugin.reportTestActionDone(apiActionName, args);
171 }
172 });
173 task.once('done', async () => {
174 const endTime = new Date();
175 const result = {
176 passedCount: this.passed,
177 failedCount: this.failed,
178 skippedCount: this.skipped
179 };
180 await this.plugin.reportTaskDone(endTime, this.passed, task.warningLog.messages, result);
181 this.pendingTaskDonePromise.resolve();
182 });
183 }
184 async dispose() {
185 if (this.disposed)
186 return Promise.resolve();
187 this.disposed = true;
188 if (!this.outStream || Reporter._isSpecialStream(this.outStream) || !is_stream_1.writable(this.outStream))
189 return Promise.resolve();
190 const streamFinishedPromise = new Promise(resolve => {
191 this.outStream.once('finish', resolve);
192 this.outStream.once('error', resolve);
193 });
194 this.outStream.end();
195 return streamFinishedPromise;
196 }
197}
198exports.default = Reporter;
199module.exports = exports.default;
200//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwb3J0ZXIvaW5kZXguanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxtQ0FBNkM7QUFDN0MseUNBQXlEO0FBQ3pELGdFQUErQztBQUMvQywrREFBMEQ7QUFDMUQsc0VBQXFEO0FBRXJELE1BQXFCLFFBQVE7SUFDekIsWUFBYSxNQUFNLEVBQUUsSUFBSSxFQUFFLFNBQVM7UUFDaEMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLHFCQUFrQixDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQztRQUN4RCxJQUFJLENBQUMsSUFBSSxHQUFLLElBQUksQ0FBQztRQUVuQixJQUFJLENBQUMsUUFBUSxHQUFVLEtBQUssQ0FBQztRQUM3QixJQUFJLENBQUMsTUFBTSxHQUFZLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsTUFBTSxHQUFZLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsT0FBTyxHQUFXLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsU0FBUyxHQUFTLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDO1FBQ3BFLElBQUksQ0FBQyxXQUFXLEdBQU8sUUFBUSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3pELElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUM7UUFDakQsSUFBSSxDQUFDLFNBQVMsR0FBUyxTQUFTLENBQUM7UUFFakMsSUFBSSxDQUFDLHNCQUFzQixHQUFHLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBRS9ELElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO0lBQ3BDLENBQUM7SUFFRCxNQUFNLENBQUMsZ0JBQWdCLENBQUUsTUFBTTtRQUMzQixPQUFPLE1BQU0s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TzthQUM3QixDQUFDO1lBRUYsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUV6RixJQUFJLENBQUMsc0JBQXNCLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDMUMsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsS0FBSyxDQUFDLE9BQU87UUFDVCxJQUFJLElBQUksQ0FBQyxRQUFRO1lBQ2IsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFN0IsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7UUFFckIsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksUUFBUSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLG9CQUFnQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7WUFDakcsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFN0IsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNoRCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDdkMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzFDLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUVyQixPQUFPLHFCQUFxQixDQUFDO0lBQ2pDLENBQUM7Q0FDSjtBQW5QRCwyQkFtUEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBmaW5kLCBzb3J0QnksIHVuaW9uIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IHdyaXRhYmxlIGFzIGlzV3JpdGFibGVTdHJlYW0gfSBmcm9tICdpcy1zdHJlYW0nO1xuaW1wb3J0IFJlcG9ydGVyUGx1Z2luSG9zdCBmcm9tICcuL3BsdWdpbi1ob3N0JztcbmltcG9ydCB7IENvbW1hbmRSZXBvcnRJdGVtIH0gZnJvbSAnLi9jb21tYW5kLXJlcG9ydC1pdGVtJztcbmltcG9ydCBUZXN0Q2FmZUVycm9yTGlzdCBmcm9tICcuLi9lcnJvcnMvZXJyb3ItbGlzdCc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlcG9ydGVyIHtcbiAgICBjb25zdHJ1Y3RvciAocGx1Z2luLCB0YXNrLCBvdXRTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5wbHVnaW4gPSBuZXcgUmVwb3J0ZXJQbHVnaW5Ib3N0KHBsdWdpbiwgb3V0U3RyZWFtKTtcbiAgICAgICAgdGhpcy50YXNrICAgPSB0YXNrO1xuXG4gICAgICAgIHRoaXMuZGlzcG9zZWQgICAgICAgID0gZmFsc2U7XG4gICAgICAgIHRoaXMucGFzc2VkICAgICAgICAgID0gMDtcbiAgICAgICAgdGhpcy5mYWlsZWQgICAgICAgICAgPSAwO1xuICAgICAgICB0aGlzLnNraXBwZWQgICAgICAgICA9IDA7XG4gICAgICAgIHRoaXMudGVzdENvdW50ICAgICAgID0gdGFzay50ZXN0cy5maWx0ZXIodGVzdCA9PiAhdGVzdC5za2lwKS5sZW5ndGg7XG4gICAgICAgIHRoaXMucmVwb3J0UXVldWUgICAgID0gUmVwb3J0ZXIuX2NyZWF0ZVJlcG9ydFF1ZXVlKHRhc2spO1xuICAgICAgICB0aGlzLnN0b3BPbkZpcnN0RmFpbCA9IHRhc2sub3B0cy5zdG9wT25GaXJzdEZhaWw7XG4gICAgICAgIHRoaXMub3V0U3RyZWFtICAgICAgID0gb3V0U3RyZWFtO1xuXG4gICAgICAgIHRoaXMucGVuZGluZ1Rhc2tEb25lUHJvbWlzZSA9IFJlcG9ydGVyLl9jcmVhdGVQZW5kaW5nUHJvbWlzZSgpO1xuXG4gICAgICAgIHRoaXMuX2Fzc2lnblRhc2tFdmVudEhhbmRsZXJzKCk7XG4gICAgfVxuXG4gICAgc3RhdGljIF9pc1NwZWNpYWxTdHJlYW0gKHN0cmVhbSkge1xuICAgICAgICByZXR1cm4gc3RyZWFtLmlzVFRZIHx8IHN0cmVhbSA9PT0gcHJvY2Vzcy5zdGRvdXQgfHwgc3RyZWFtID09PSBwcm9jZXNzLnN0ZGVycjtcbiAgICB9XG5cbiAgICBzdGF0aWMgX2NyZWF0ZVBlbmRpbmdQcm9taXNlICgpIHtcbiAgICAgICAgbGV0IHJlc29sdmVyID0gbnVsbDtcblxuICAgICAgICBjb25zdCBwcm9taXNlID0gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlciA9IHJlc29sdmU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHByb21pc2UucmVzb2x2ZSA9IHJlc29sdmVyO1xuXG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIHN0YXRpYyBfY3JlYXRlUmVwb3J0SXRlbSAodGVzdCwgcnVuc1BlclRlc3QpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGZpeHR1cmU6ICAgICAgICAgICAgICAgICAgICB0ZXN0LmZpeHR1cmUsXG4gICAgICAgICAgICB0ZXN0OiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCxcbiAgICAgICAgICAgIHNjcmVlbnNob3RQYXRoOiAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgc2NyZWVuc2hvdHM6ICAgICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgcXVhcmFudGluZTogICAgICAgICAgICAgICAgIG51bGwsXG4gICAgICAgICAgICBlcnJzOiAgICAgICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICB3YXJuaW5nczogICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICB1bnN0YWJsZTogICAgICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICBzdGFydFRpbWU6ICAgICAgICAgICAgICAgICAgbnVsbCxcbiAgICAgICAgICAgIHRlc3RSdW5JbmZvOiAgICAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgcGVuZGluZ1J1bnM6ICAgICAgICAgICAgICAgIHJ1bnNQZXJUZXN0LFxuICAgICAgICAgICAgcGVuZGluZ1N0YXJ0czogICAgICAgICAgICAgIHJ1bnNQZXJUZXN0LFxuICAgICAgICAgICAgcGVuZGluZ1Rlc3RSdW5Eb25lUHJvbWlzZTogIFJlcG9ydGVyLl9jcmVhdGVQZW5kaW5nUHJvbWlzZSgpLFxuICAgICAgICAgICAgcGVuZGluZ1Rlc3RSdW5TdGFydFByb21pc2U6IFJlcG9ydGVyLl9jcmVhdGVQZW5kaW5nUHJvbWlzZSgpXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgc3RhdGljIF9jcmVhdGVSZXBvcnRRdWV1ZSAodGFzaykge1xuICAgICAgICBjb25zdCBydW5zUGVyVGVzdCA9IHRhc2suYnJvd3NlckNvbm5lY3Rpb25Hcm91cHMubGVuZ3RoO1xuXG4gICAgICAgIHJldHVybiB0YXNrLnRlc3RzLm1hcCh0ZXN0ID0+IFJlcG9ydGVyLl9jcmVhdGVSZXBvcnRJdGVtKHRlc3QsIHJ1bnNQZXJUZXN0KSk7XG4gICAgfVxuXG4gICAgc3RhdGljIF9jcmVhdGVUZXN0UnVuSW5mbyAocmVwb3J0SXRlbSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZXJyczogICAgICAgICAgIHNvcnRCeShyZXBvcnRJdGVtLmVycnMsIFsndXNlckFnZW50JywgJ2NvZGUnXSksXG4gICAgICAgICAgICB3YXJuaW5nczogICAgICAgcmVwb3J0SXRlbS53YXJuaW5ncyxcbiAgICAgICAgICAgIGR1cmF0aW9uTXM6ICAgICBuZXcgRGF0ZSgpIC0gcmVwb3J0SXRlbS5zdGFydFRpbWUsXG4gICAgICAgICAgICB1bnN0YWJsZTogICAgICAgcmVwb3J0SXRlbS51bnN0YWJsZSxcbiAgICAgICAgICAgIHNjcmVlbnNob3RQYXRoOiByZXBvcnRJdGVtLnNjcmVlbnNob3RQYXRoLFxuICAgICAgICAgICAgc2NyZWVuc2hvdHM6ICAgIHJlcG9ydEl0ZW0uc2NyZWVuc2hvdHMsXG4gICAgICAgICAgICBxdWFyYW50aW5lOiAgICAgcmVwb3J0SXRlbS5xdWFyYW50aW5lLFxuICAgICAgICAgICAgc2tpcHBlZDogICAgICAgIHJlcG9ydEl0ZW0udGVzdC5za2lwXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgX2dldFJlcG9ydEl0ZW1Gb3JUZXN0UnVuICh0ZXN0UnVuKSB7XG4gICAgICAgIHJldHVybiBmaW5kKHRoaXMucmVwb3J0UXVldWUsIGkgPT4gaS50ZXN0ID09PSB0ZXN0UnVuLnRlc3QpO1xuICAgIH1cblxuICAgIGFzeW5jIF9zaGlmdFJlcG9ydFF1ZXVlIChyZXBvcnRJdGVtKSB7XG4gICAgICAgIGxldCBjdXJyZW50Rml4dHVyZSA9IG51bGw7XG4gICAgICAgIGxldCBuZXh0UmVwb3J0SXRlbSA9IG51bGw7XG5cbiAgICAgICAgd2hpbGUgKHRoaXMucmVwb3J0UXVldWUubGVuZ3RoICYmIHRoaXMucmVwb3J0UXVldWVbMF0udGVzdFJ1bkluZm8pIHtcbiAgICAgICAgICAgIHJlcG9ydEl0ZW0gICAgID0gdGhpcy5yZXBvcnRRdWV1ZS5zaGlmdCgpO1xuICAgICAgICAgICAgY3VycmVudEZpeHR1cmUgPSByZXBvcnRJdGVtLmZpeHR1cmU7XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMucGx1Z2luLnJlcG9ydFRlc3REb25lKHJlcG9ydEl0ZW0udGVzdC5uYW1lLCByZXBvcnRJdGVtLnRlc3RSdW5JbmZvLCByZXBvcnRJdGVtLnRlc3QubWV0YSk7XG5cbiAgICAgICAgICAgIC8vIE5PVEU6IGhlcmUgd2UgYXNzdW1lIHRoYXQgdGVzdHMgYXJlIHNvcnRlZCBieSBmaXh0dXJlLlxuICAgICAgICAgICAgLy8gVGhlcmVmb3JlLCBpZiB0aGUgbmV4dCByZXBvcnQgaXRlbSBoYXMgYSBkaWZmZXJlbnRcbiAgICAgICAgICAgIC8vIGZpeHR1cmUsIHdlIGNhbiByZXBvcnQgdGhpcyBmaXh0dXJlIHN0YXJ0LlxuICAgICAgICAgICAgbmV4dFJlcG9ydEl0ZW0gPSB0aGlzLnJlcG9ydFF1ZXVlWzBdO1xuXG4gICAgICAgICAgICBpZiAobmV4dFJlcG9ydEl0ZW0gJiYgbmV4dFJlcG9ydEl0ZW0uZml4dHVyZSAhPT0gY3VycmVudEZpeHR1cmUpXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4ucmVwb3J0Rml4dHVyZVN0YXJ0KG5leHRSZXBvcnRJdGVtLmZpeHR1cmUubmFtZSwgbmV4dFJlcG9ydEl0ZW0uZml4dHVyZS5wYXRoLCBuZXh0UmVwb3J0SXRlbS5maXh0dXJlLm1ldGEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgX3Jlc29sdmVSZXBvcnRJdGVtIChyZXBvcnRJdGVtLCB0ZXN0UnVuKSB7XG4gICAgICAgIGlmICh0aGlzLnRhc2suc2NyZWVuc2hvdHMuaGFzQ2FwdHVyZWRGb3IodGVzdFJ1bi50ZXN0KSkge1xuICAgICAgICAgICAgcmVwb3J0SXRlbS5zY3JlZW5zaG90UGF0aCA9IHRoaXMudGFzay5zY3JlZW5zaG90cy5nZXRQYXRoRm9yKHRlc3RSdW4udGVzdCk7XG4gICAgICAgICAgICByZXBvcnRJdGVtLnNjcmVlbnNob3RzICAgID0gdGhpcy50YXNrLnNjcmVlbnNob3RzLmdldFNjcmVlbnNob3RzSW5mbyh0ZXN0UnVuLnRlc3QpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRlc3RSdW4ucXVhcmFudGluZSkge1xuICAgICAgICAgICAgcmVwb3J0SXRlbS5xdWFyYW50aW5lID0gdGVzdFJ1bi5xdWFyYW50aW5lLmF0dGVtcHRzLnJlZHVjZSgocmVzdWx0LCBlcnJvcnMsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFzc2VkICAgICAgICAgICAgPSAhZXJyb3JzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBjb25zdCBxdWFyYW50aW5lQXR0ZW1wdCA9IGluZGV4ICsgMTtcblxuICAgICAgICAgICAgICAgIHJlc3VsdFtxdWFyYW50aW5lQXR0ZW1wdF0gPSB7IHBhc3NlZCB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sIHt9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghcmVwb3J0SXRlbS50ZXN0UnVuSW5mbykge1xuICAgICAgICAgICAgcmVwb3J0SXRlbS50ZXN0UnVuSW5mbyA9IFJlcG9ydGVyLl9jcmVhdGVUZXN0UnVuSW5mbyhyZXBvcnRJdGVtKTtcblxuICAgICAgICAgICAgaWYgKHJlcG9ydEl0ZW0udGVzdC5za2lwKVxuICAgICAgICAgICAgICAgIHRoaXMuc2tpcHBlZCsrO1xuICAgICAgICAgICAgZWxzZSBpZiAocmVwb3J0SXRlbS5lcnJzLmxlbmd0aClcbiAgICAgICAgICAgICAgICB0aGlzLmZhaWxlZCsrO1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIHRoaXMucGFzc2VkKys7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLl9zaGlmdFJlcG9ydFF1ZXVlKHJlcG9ydEl0ZW0pO1xuXG4gICAgICAgIHJlcG9ydEl0ZW0ucGVuZGluZ1Rlc3RSdW5Eb25lUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfVxuXG4gICAgX3ByZXBhcmVSZXBvcnRUZXN0QWN0aW9uRXZlbnRBcmdzICh7IGNvbW1hbmQsIHRlc3RSdW4sIGVycm9ycyB9KSB7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSB7fTtcblxuICAgICAgICBpZiAoZXJyb3JzKSB7XG4gICAgICAgICAgICBlcnJvcnMgPSBlcnJvcnMgaW5zdGFuY2VvZiBUZXN0Q2FmZUVycm9yTGlzdCA/IGVycm9ycy5pdGVtcyA6IFtlcnJvcnNdO1xuXG4gICAgICAgICAgICBhcmdzLmVycm9ycyA9IGVycm9ycztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKGFyZ3MsIHtcbiAgICAgICAgICAgIHRlc3Q6IHtcbiAgICAgICAgICAgICAgICBuYW1lOiAgdGVzdFJ1bi50ZXN0Lm5hbWUsXG4gICAgICAgICAgICAgICAgcGhhc2U6IHRlc3RSdW4ucGhhc2VcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjb21tYW5kOiBuZXcgQ29tbWFuZFJlcG9ydEl0ZW0oY29tbWFuZCksXG4gICAgICAgICAgICBicm93c2VyOiB0ZXN0UnVuLmNvbnRyb2xsZXIuYnJvd3NlcixcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgX2Fzc2lnblRhc2tFdmVudEhhbmRsZXJzICgpIHtcbiAgICAgICAgY29uc3QgdGFzayA9IHRoaXMudGFzaztcblxuICAgICAgICB0YXNrLm9uY2UoJ3N0YXJ0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc3RhcnRUaW1lICA9IG5ldyBEYXRlKCk7XG4gICAgICAgICAgICBjb25zdCB1c2VyQWdlbnRzID0gdGFzay5icm93c2VyQ29ubmVjdGlvbkdyb3Vwcy5tYXAoZ3JvdXAgPT4gZ3JvdXBbMF0udXNlckFnZW50KTtcbiAgICAgICAgICAgIGNvbnN0IGZpcnN0ICAgICAgPSB0aGlzLnJlcG9ydFF1ZXVlWzBdO1xuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5yZXBvcnRUYXNrU3RhcnQoc3RhcnRUaW1lLCB1c2VyQWdlbnRzLCB0aGlzLnRlc3RDb3VudCk7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5yZXBvcnRGaXh0dXJlU3RhcnQoZmlyc3QuZml4dHVyZS5uYW1lLCBmaXJzdC5maXh0dXJlLnBhdGgsIGZpcnN0LmZpeHR1cmUubWV0YSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRhc2sub24oJ3Rlc3QtcnVuLXN0YXJ0JywgYXN5bmMgdGVzdFJ1biA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXBvcnRJdGVtID0gdGhpcy5fZ2V0UmVwb3J0SXRlbUZvclRlc3RSdW4odGVzdFJ1bik7XG5cbiAgICAgICAgICAgIGlmICghcmVwb3J0SXRlbS5zdGFydFRpbWUpXG4gICAgICAgICAgICAgICAgcmVwb3J0SXRlbS5zdGFydFRpbWUgPSBuZXcgRGF0ZSgpO1xuXG4gICAgICAgICAgICByZXBvcnRJdGVtLnBlbmRpbmdTdGFydHMtLTtcblxuICAgICAgICAgICAgaWYgKCFyZXBvcnRJdGVtLnBlbmRpbmdTdGFydHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5wbHVnaW4ucmVwb3J0VGVzdFN0YXJ0KVxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5yZXBvcnRUZXN0U3RhcnQocmVwb3J0SXRlbS50ZXN0Lm5hbWUsIHJlcG9ydEl0ZW0udGVzdC5tZXRhKTtcblxuICAgICAgICAgICAgICAgIHJlcG9ydEl0ZW0ucGVuZGluZ1Rlc3RSdW5TdGFydFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmVwb3J0SXRlbS5wZW5kaW5nVGVzdFJ1blN0YXJ0UHJvbWlzZTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGFzay5vbigndGVzdC1ydW4tZG9uZScsIGFzeW5jIHRlc3RSdW4gPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVwb3J0SXRlbSAgICAgICAgICAgICAgICAgICAgPSB0aGlzLl9nZXRSZXBvcnRJdGVtRm9yVGVzdFJ1bih0ZXN0UnVuKTtcbiAgICAgICAgICAgIGNvbnN0IGlzVGVzdFJ1blN0b3BwZWRUYXNrRXhlY3V0aW9uID0gISF0ZXN0UnVuLmVycnMubGVuZ3RoICYmIHRoaXMuc3RvcE9uRmlyc3RGYWlsO1xuXG4gICAgICAgICAgICByZXBvcnRJdGVtLnBlbmRpbmdSdW5zID0gaXNUZXN0UnVuU3RvcHBlZFRhc2tFeGVjdXRpb24gPyAwIDogcmVwb3J0SXRlbS5wZW5kaW5nUnVucyAtIDE7XG4gICAgICAgICAgICByZXBvcnRJdGVtLnVuc3RhYmxlICAgID0gcmVwb3J0SXRlbS51bnN0YWJsZSB8fCB0ZXN0UnVuLnVuc3RhYmxlO1xuICAgICAgICAgICAgcmVwb3J0SXRlbS5lcnJzICAgICAgICA9IHJlcG9ydEl0ZW0uZXJycy5jb25jYXQodGVzdFJ1bi5lcnJzKTtcbiAgICAgICAgICAgIHJlcG9ydEl0ZW0ud2FybmluZ3MgICAgPSB0ZXN0UnVuLndhcm5pbmdMb2cgPyB1bmlvbihyZXBvcnRJdGVtLndhcm5pbmdzLCB0ZXN0UnVuLndhcm5pbmdMb2cubWVzc2FnZXMpIDogW107XG5cbiAgICAgICAgICAgIGlmICghcmVwb3J0SXRlbS5wZW5kaW5nUnVucylcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9yZXNvbHZlUmVwb3J0SXRlbShyZXBvcnRJdGVtLCB0ZXN0UnVuKTtcblxuICAgICAgICAgICAgYXdhaXQgcmVwb3J0SXRlbS5wZW5kaW5nVGVzdFJ1bkRvbmVQcm9taXNlO1xuICAgICAgICB9KTtcblxuICAgICAgICB0YXNrLm9uKCd0ZXN0LWFjdGlvbi1zdGFydCcsIGFzeW5jICh7IGFwaUFjdGlvbk5hbWUsIGNvbW1hbmQsIHRlc3RSdW4gfSkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGx1Z2luLnJlcG9ydFRlc3RBY3Rpb25TdGFydCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSB0aGlzLl9wcmVwYXJlUmVwb3J0VGVzdEFjdGlvbkV2ZW50QXJncyh7IGNvbW1hbmQsIHRlc3RSdW4gfSk7XG5cbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5yZXBvcnRUZXN0QWN0aW9uU3RhcnQoYXBpQWN0aW9uTmFtZSwgYXJncyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRhc2sub24oJ3Rlc3QtYWN0aW9uLWRvbmUnLCBhc3luYyAoeyBhcGlBY3Rpb25OYW1lLCBjb21tYW5kLCB0ZXN0UnVuLCBlcnJvcnMgfSkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMucGx1Z2luLnJlcG9ydFRlc3RBY3Rpb25Eb25lKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYXJncyA9IHRoaXMuX3ByZXBhcmVSZXBvcnRUZXN0QWN0aW9uRXZlbnRBcmdzKHsgY29tbWFuZCwgdGVzdFJ1biwgZXJyb3JzIH0pO1xuXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5wbHVnaW4ucmVwb3J0VGVzdEFjdGlvbkRvbmUoYXBpQWN0aW9uTmFtZSwgYXJncyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRhc2sub25jZSgnZG9uZScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGVuZFRpbWUgPSBuZXcgRGF0ZSgpO1xuXG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSB7XG4gICAgICAgICAgICAgICAgcGFzc2VkQ291bnQ6ICB0aGlzLnBhc3NlZCxcbiAgICAgICAgICAgICAgICBmYWlsZWRDb3VudDogIHRoaXMuZmFpbGVkLFxuICAgICAgICAgICAgICAgIHNraXBwZWRDb3VudDogdGhpcy5za2lwcGVkXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBsdWdpbi5yZXBvcnRUYXNrRG9uZShlbmRUaW1lLCB0aGlzLnBhc3NlZCwgdGFzay53YXJuaW5nTG9nLm1lc3NhZ2VzLCByZXN1bHQpO1xuXG4gICAgICAgICAgICB0aGlzLnBlbmRpbmdUYXNrRG9uZVByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYyBkaXNwb3NlICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZGlzcG9zZWQpXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbiAgICAgICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG5cbiAgICAgICAgaWYgKCF0aGlzLm91dFN0cmVhbSB8fCBSZXBvcnRlci5faXNTcGVjaWFsU3RyZWFtKHRoaXMub3V0U3RyZWFtKSB8fCAhaXNXcml0YWJsZVN0cmVhbSh0aGlzLm91dFN0cmVhbSkpXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG5cbiAgICAgICAgY29uc3Qgc3RyZWFtRmluaXNoZWRQcm9taXNlID0gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgICB0aGlzLm91dFN0cmVhbS5vbmNlKCdmaW5pc2gnLCByZXNvbHZlKTtcbiAgICAgICAgICAgIHRoaXMub3V0U3RyZWFtLm9uY2UoJ2Vycm9yJywgcmVzb2x2ZSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMub3V0U3RyZWFtLmVuZCgpO1xuXG4gICAgICAgIHJldHVybiBzdHJlYW1GaW5pc2hlZFByb21pc2U7XG4gICAgfVxufVxuIl19
\No newline at end of file