@synap-ac/node-dot-extra-reporter
Version:
Custom dot reporter for the node test runner
209 lines • 28 kB
JavaScript
import { Transform } from "node:stream";
import chalk from "chalk";
import test from "node:test";
var EventType;
(function (EventType) {
EventType["ENQUEUE"] = "test:enqueue";
EventType["DEQUEUE"] = "test:dequeue";
EventType["START"] = "test:start";
EventType["PASS"] = "test:pass";
EventType["FAIL"] = "test:fail";
EventType["PLAN"] = "test:plan";
EventType["WATCH_DRAINED"] = "test:watch:drained";
EventType["STDOUT"] = "test:stdout";
EventType["STDERR"] = "test:stderr";
})(EventType || (EventType = {}));
class DotExtraReporter extends Transform {
passedTests;
skippedTests;
todoTests;
totalDuration;
failedTests;
testSuite;
currentSuite;
currentSuiteLineage = [];
nesting = 0;
constructor(options = {}) {
super({ ...options, writableObjectMode: true });
this.passedTests = 0;
this.skippedTests = [];
this.todoTests = [];
this.totalDuration = 0;
this.failedTests = [];
this.testSuite = {};
}
handleTestStart(test) {
// Add new child
const newItem = {
file: test.file,
name: test.name,
nesting: test.nesting,
children: {},
};
// If nesting > current nesting then
// We've moved into a nested suite so:
// - Add the current suite to the lineage
// - Add new item as a child of the current suite
if (test.nesting === 0) {
// First entry
this.currentSuite = newItem;
this.testSuite[`${test.file}:${test.name}`] = newItem;
}
else if (test.nesting > this.nesting) {
this.currentSuiteLineage.push(this.currentSuite);
this.currentSuite.children[test.name] = newItem;
this.currentSuite = newItem;
}
else {
// Not deeper so add to current parent, and set new item to current
const parent = this.currentSuiteLineage.pop();
parent.children[test.name] = newItem;
this.currentSuiteLineage.push(parent);
this.currentSuite = newItem;
}
this.nesting = test.nesting;
}
handleTestResult(test, eventType) {
// Update test result details
this.currentSuite.passed = eventType === EventType.PASS;
if (test.details) {
this.currentSuite.details = test.details;
}
if (test.skip) {
process.stdout.write(chalk.yellow("*"));
this.currentSuite.skip = test.skip;
}
else if (test.todo) {
process.stdout.write(chalk.blue("-"));
this.currentSuite.todo = test.todo;
}
else if (this.currentSuite.passed) {
process.stdout.write(chalk.green("."));
}
else {
process.stdout.write(chalk.red("F"));
}
this.nesting = test.nesting;
}
handleTestEnd(test) {
// Suite finished, step up to parent
this.currentSuite = this.currentSuiteLineage.pop();
this.nesting = test.nesting;
}
_transform(event, _encoding, callback) {
try {
const test = event.data;
switch (event.type) {
case EventType.START:
this.handleTestStart(test);
break;
case EventType.PASS:
case EventType.FAIL:
if (test.name !== test.file) {
this.handleTestResult(test, event.type);
}
break;
case EventType.PLAN:
this.handleTestEnd(test);
break;
case EventType.STDOUT:
process.stdout.write(event.data.message ?? "");
break;
case EventType.STDERR:
process.stderr.write(event.data.message ?? "");
break;
default:
break;
}
callback();
}
catch (error) {
console.log(error);
callback(error);
}
}
processOutcomes() {
Object.entries(this.testSuite).forEach(([file, suite]) => {
this.buildStats(suite);
// File suite doesn't have a duration so collate from all top level suites.
Object.values(suite.children ?? {}).forEach((child) => {
this.totalDuration += child.details?.duration_ms || 0;
});
});
}
buildStats(suite, prefix) {
const isSuite = (obj) => obj.details?.type === "suite";
if (isSuite(suite)) {
// Iterate over each child
Object.values(suite.children).forEach((child) => this.buildStats(child, prefix ? `${prefix} > ${suite.name}` : suite.name));
}
if (prefix) {
suite.name = `${prefix} > ${suite.name}`;
}
if (suite.skip) {
this.skippedTests.push(suite);
}
else if (suite.todo) {
this.todoTests.push(suite);
}
else if (!isSuite(suite)) {
if (suite.passed === false) {
this.failedTests.push(suite);
}
else {
this.passedTests++;
}
}
}
_flush() {
this.processOutcomes();
if (this.skippedTests.length > 0) {
console.log("\n\nSkipped:");
this.skippedTests.forEach((test, i) => {
console.log(`\n${i + 1}) ${test.name}`);
if (typeof test.skip === "string") {
console.log(chalk.yellow(`\tSkipped: ${test.skip}`));
}
else {
console.log(chalk.yellow(`\t${"Skipped: No reason"}`));
}
});
}
if (this.todoTests.length > 0) {
console.log("\n\nTodo:");
this.todoTests.forEach((test, i) => {
console.log(`\n${i + 1}) ${test.name}`);
if (typeof test.todo === "string") {
console.log(chalk.blue(`\tTODO: ${test.todo}`));
}
else {
console.log(chalk.blue(`\t${"TODO: No reason"}`));
}
});
}
if (this.failedTests.length > 0) {
console.log(chalk.red("\n✖") + " Failing tests:");
this.failedTests.forEach((test, i) => {
console.log(chalk.red(`\n${i + 1}) ${test.name} (${test.details.duration_ms}ms)`));
console.log(test.details.error?.cause);
});
}
console.log(`\n\nℹ Tests ${this.passedTests +
this.failedTests.length +
this.skippedTests.length +
this.todoTests.length}`);
console.log(`ℹ Passed ${chalk.green(this.passedTests)}`);
console.log(`ℹ Failed ${chalk.red(this.failedTests.length)}`);
console.log(`ℹ Skipped ${chalk.yellow(this.skippedTests.length)}`);
console.log(`ℹ Todo ${chalk.blue(this.todoTests.length)}`);
console.log(`ℹ Duration ${this.totalDuration.toFixed(2)}ms`);
this.passedTests = 0;
this.skippedTests = [];
this.todoTests = [];
this.totalDuration = 0;
this.failedTests = [];
this.testSuite = {};
}
}
export default DotExtraReporter;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG90LWV4dHJhLXJlcG9ydGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2RvdC1leHRyYS1yZXBvcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUEwQixNQUFNLGFBQWEsQ0FBQztBQUNoRSxPQUFPLEtBQUssTUFBTSxPQUFPLENBQUM7QUFDMUIsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBbUM3QixJQUFLLFNBVUo7QUFWRCxXQUFLLFNBQVM7SUFDWixxQ0FBd0IsQ0FBQTtJQUN4QixxQ0FBd0IsQ0FBQTtJQUN4QixpQ0FBb0IsQ0FBQTtJQUNwQiwrQkFBa0IsQ0FBQTtJQUNsQiwrQkFBa0IsQ0FBQTtJQUNsQiwrQkFBa0IsQ0FBQTtJQUNsQixpREFBb0MsQ0FBQTtJQUNwQyxtQ0FBc0IsQ0FBQTtJQUN0QixtQ0FBc0IsQ0FBQTtBQUN4QixDQUFDLEVBVkksU0FBUyxLQUFULFNBQVMsUUFVYjtBQU9ELE1BQU0sZ0JBQWlCLFNBQVEsU0FBUztJQUM5QixXQUFXLENBQVM7SUFFcEIsWUFBWSxDQUFTO0lBRXJCLFNBQVMsQ0FBUztJQUVsQixhQUFhLENBQVM7SUFFdEIsV0FBVyxDQUFTO0lBRXBCLFNBQVMsQ0FBWTtJQUVyQixZQUFZLENBQW9CO0lBRWhDLG1CQUFtQixHQUFZLEVBQUUsQ0FBQztJQUVsQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO0lBRXBCLFlBQVksT0FBTyxHQUFHLEVBQUU7UUFDdEIsS0FBSyxDQUFDLEVBQUUsR0FBRyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQztRQUNyQixJQUFJLENBQUMsWUFBWSxHQUFHLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztRQUNwQixJQUFJLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBQztRQUN2QixJQUFJ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QUFDO1FBQy9ELE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFN0QsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFDckIsSUFBSSxDQUFDLFlBQVksR0FBRyxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxDQUFDLENBQUM7UUFDdkIsSUFBSSxDQUFDLFdBQVcsR0FBRyxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUM7SUFDdEIsQ0FBQztDQUNGO0FBRUQsZUFBZSxnQkFBZ0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRyYW5zZm9ybSwgdHlwZSBUcmFuc2Zvcm1DYWxsYmFjayB9IGZyb20gXCJub2RlOnN0cmVhbVwiO1xuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiO1xuaW1wb3J0IHRlc3QgZnJvbSBcIm5vZGU6dGVzdFwiO1xuXG4vLyBVc2VmdWwgZG9jdW1lbnRhdGlvbiBoZXJlOiBodHRwczovL25vZGVqcy5vcmcvYXBpL3Rlc3QuaHRtbCNjbGFzcy10ZXN0c3N0cmVhbVxuXG4vLyBNYXAgb2YgZmlsZSBuYW1lIHRvXG50eXBlIFRlc3RTdWl0ZSA9IFJlY29yZDxzdHJpbmcsIFN1aXRlPjtcblxudHlwZSBTdWl0ZSA9IHtcbiAgZmlsZTogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIG5lc3Rpbmc6IG51bWJlcjtcbiAgY2hpbGRyZW4/OiBSZWNvcmQ8c3RyaW5nLCBUZXN0IHwgU3VpdGU+O1xuICBwYXNzZWQ/OiBib29sZWFuO1xuICBkZXRhaWxzPzogeyBkdXJhdGlvbl9tczogbnVtYmVyOyB0eXBlPzogXCJzdWl0ZVwiOyBlcnJvcj86IHsgY2F1c2U/OiBFcnJvciB9IH07XG4gIHNraXA/OiBib29sZWFuIHwgc3RyaW5nO1xuICB0b2RvPzogYm9vbGVhbiB8IHN0cmluZztcbn07XG5cbnR5cGUgVGVzdCA9IHtcbiAgZmlsZTogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIG5lc3Rpbmc6IG51bWJlcjtcbiAgbWVzc2FnZT86IHN0cmluZztcbiAgZGV0YWlsczoge1xuICAgIGR1cmF0aW9uX21zOiBudW1iZXI7XG4gICAgdHlwZT86IFwic3VpdGVcIjtcbiAgICBlcnJvcj86IHtcbiAgICAgIGNhdXNlOiBFcnJvcjtcbiAgICB9O1xuICB9O1xuICBza2lwPzogYm9vbGVhbiB8IHN0cmluZztcbiAgdG9kbz86IGJvb2xlYW4gfCBzdHJpbmc7XG4gIHBhc3NlZD86IGJvb2xlYW47XG59O1xuXG5lbnVtIEV2ZW50VHlwZSB7XG4gIEVOUVVFVUUgPSBcInRlc3Q6ZW5xdWV1ZVwiLFxuICBERVFVRVVFID0gXCJ0ZXN0OmRlcXVldWVcIixcbiAgU1RBUlQgPSBcInRlc3Q6c3RhcnRcIixcbiAgUEFTUyA9IFwidGVzdDpwYXNzXCIsXG4gIEZBSUwgPSBcInRlc3Q6ZmFpbFwiLFxuICBQTEFOID0gXCJ0ZXN0OnBsYW5cIixcbiAgV0FUQ0hfRFJBSU5FRCA9IFwidGVzdDp3YXRjaDpkcmFpbmVkXCIsXG4gIFNURE9VVCA9IFwidGVzdDpzdGRvdXRcIixcbiAgU1RERVJSID0gXCJ0ZXN0OnN0ZGVyclwiLFxufVxuXG50eXBlIEV2ZW50ID0ge1xuICB0eXBlOiBFdmVudFR5cGU7XG4gIGRhdGE6IFRlc3Q7XG59O1xuXG5jbGFzcyBEb3RFeHRyYVJlcG9ydGVyIGV4dGVuZHMgVHJhbnNmb3JtIHtcbiAgcHJpdmF0ZSBwYXNzZWRUZXN0czogbnVtYmVyO1xuXG4gIHByaXZhdGUgc2tpcHBlZFRlc3RzOiBUZXN0W107XG5cbiAgcHJpdmF0ZSB0b2RvVGVzdHM6IFRlc3RbXTtcblxuICBwcml2YXRlIHRvdGFsRHVyYXRpb246IG51bWJlcjtcblxuICBwcml2YXRlIGZhaWxlZFRlc3RzOiBUZXN0W107XG5cbiAgcHJpdmF0ZSB0ZXN0U3VpdGU6IFRlc3RTdWl0ZTtcblxuICBwcml2YXRlIGN1cnJlbnRTdWl0ZTogU3VpdGUgfCB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSBjdXJyZW50U3VpdGVMaW5lYWdlOiBTdWl0ZVtdID0gW107XG5cbiAgcHJpdmF0ZSBuZXN0aW5nID0gMDtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zID0ge30pIHtcbiAgICBzdXBlcih7IC4uLm9wdGlvbnMsIHdyaXRhYmxlT2JqZWN0TW9kZTogdHJ1ZSB9KTtcbiAgICB0aGlzLnBhc3NlZFRlc3RzID0gMDtcbiAgICB0aGlzLnNraXBwZWRUZXN0cyA9IFtdO1xuICAgIHRoaXMudG9kb1Rlc3RzID0gW107XG4gICAgdGhpcy50b3RhbER1cmF0aW9uID0gMDtcbiAgICB0aGlzLmZhaWxlZFRlc3RzID0gW107XG4gICAgdGhpcy50ZXN0U3VpdGUgPSB7fTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlVGVzdFN0YXJ0KHRlc3Q6IFRlc3QpIHtcbiAgICAvLyBBZGQgbmV3IGNoaWxkXG4gICAgY29uc3QgbmV3SXRlbSA9IHtcbiAgICAgIGZpbGU6IHRlc3QuZmlsZSxcbiAgICAgIG5hbWU6IHRlc3QubmFtZSxcbiAgICAgIG5lc3Rpbmc6IHRlc3QubmVzdGluZyxcbiAgICAgIGNoaWxkcmVuOiB7fSxcbiAgICB9O1xuXG4gICAgLy8gSWYgbmVzdGluZyA+IGN1cnJlbnQgbmVzdGluZyB0aGVuXG4gICAgLy8gV2UndmUgbW92ZWQgaW50byBhIG5lc3RlZCBzdWl0ZSBzbzpcbiAgICAvLyAtIEFkZCB0aGUgY3VycmVudCBzdWl0ZSB0byB0aGUgbGluZWFnZVxuICAgIC8vIC0gQWRkIG5ldyBpdGVtIGFzIGEgY2hpbGQgb2YgdGhlIGN1cnJlbnQgc3VpdGVcbiAgICBpZiAodGVzdC5uZXN0aW5nID09PSAwKSB7XG4gICAgICAvLyBGaXJzdCBlbnRyeVxuICAgICAgdGhpcy5jdXJyZW50U3VpdGUgPSBuZXdJdGVtO1xuICAgICAgdGhpcy50ZXN0U3VpdGVbYCR7dGVzdC5maWxlfToke3Rlc3QubmFtZX1gXSA9IG5ld0l0ZW07XG4gICAgfSBlbHNlIGlmICh0ZXN0Lm5lc3RpbmcgPiB0aGlzLm5lc3RpbmcpIHtcbiAgICAgIHRoaXMuY3VycmVudFN1aXRlTGluZWFnZS5wdXNoKHRoaXMuY3VycmVudFN1aXRlISk7XG4gICAgICB0aGlzLmN1cnJlbnRTdWl0ZSEuY2hpbGRyZW4hW3Rlc3QubmFtZV0gPSBuZXdJdGVtO1xuXG4gICAgICB0aGlzLmN1cnJlbnRTdWl0ZSA9IG5ld0l0ZW07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIE5vdCBkZWVwZXIgc28gYWRkIHRvIGN1cnJlbnQgcGFyZW50LCBhbmQgc2V0IG5ldyBpdGVtIHRvIGN1cnJlbnRcbiAgICAgIGNvbnN0IHBhcmVudCA9IHRoaXMuY3VycmVudFN1aXRlTGluZWFnZS5wb3AoKTtcbiAgICAgIHBhcmVudCEuY2hpbGRyZW4hW3Rlc3QubmFtZV0gPSBuZXdJdGVtO1xuICAgICAgdGhpcy5jdXJyZW50U3VpdGVMaW5lYWdlLnB1c2gocGFyZW50ISk7XG4gICAgICB0aGlzLmN1cnJlbnRTdWl0ZSA9IG5ld0l0ZW07XG4gICAgfVxuICAgIHRoaXMubmVzdGluZyA9IHRlc3QubmVzdGluZztcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlVGVzdFJlc3VsdCh0ZXN0OiBUZXN0LCBldmVudFR5cGU6IEV2ZW50VHlwZSkge1xuICAgIC8vIFVwZGF0ZSB0ZXN0IHJlc3VsdCBkZXRhaWxzXG4gICAgdGhpcy5jdXJyZW50U3VpdGUhLnBhc3NlZCA9IGV2ZW50VHlwZSA9PT0gRXZlbnRUeXBlLlBBU1M7XG5cbiAgICBpZiAodGVzdC5kZXRhaWxzKSB7XG4gICAgICB0aGlzLmN1cnJlbnRTdWl0ZSEuZGV0YWlscyA9IHRlc3QuZGV0YWlscztcbiAgICB9XG4gICAgaWYgKHRlc3Quc2tpcCkge1xuICAgICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoY2hhbGsueWVsbG93KFwiKlwiKSk7XG4gICAgICB0aGlzLmN1cnJlbnRTdWl0ZSEuc2tpcCA9IHRlc3Quc2tpcDtcbiAgICB9IGVsc2UgaWYgKHRlc3QudG9kbykge1xuICAgICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoY2hhbGsuYmx1ZShcIi1cIikpO1xuICAgICAgdGhpcy5jdXJyZW50U3VpdGUhLnRvZG8gPSB0ZXN0LnRvZG87XG4gICAgfSBlbHNlIGlmICh0aGlzLmN1cnJlbnRTdWl0ZSEucGFzc2VkKSB7XG4gICAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShjaGFsay5ncmVlbihcIi5cIikpO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShjaGFsay5yZWQoXCJGXCIpKTtcbiAgICB9XG4gICAgdGhpcy5uZXN0aW5nID0gdGVzdC5uZXN0aW5nO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVUZXN0RW5kKHRlc3Q6IFRlc3QpIHtcbiAgICAvLyBTdWl0ZSBmaW5pc2hlZCwgc3RlcCB1cCB0byBwYXJlbnRcbiAgICB0aGlzLmN1cnJlbnRTdWl0ZSA9IHRoaXMuY3VycmVudFN1aXRlTGluZWFnZS5wb3AoKTtcbiAgICB0aGlzLm5lc3RpbmcgPSB0ZXN0Lm5lc3Rpbmc7XG4gIH1cblxuICBwdWJsaWMgb3ZlcnJpZGUgX3RyYW5zZm9ybShcbiAgICBldmVudDogRXZlbnQsXG4gICAgX2VuY29kaW5nOiBCdWZmZXJFbmNvZGluZyxcbiAgICBjYWxsYmFjazogVHJhbnNmb3JtQ2FsbGJhY2tcbiAgKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRlc3QgPSBldmVudC5kYXRhIGFzIFRlc3Q7XG5cbiAgICAgIHN3aXRjaCAoZXZlbnQudHlwZSkge1xuICAgICAgICBjYXNlIEV2ZW50VHlwZS5TVEFSVDpcbiAgICAgICAgICB0aGlzLmhhbmRsZVRlc3RTdGFydCh0ZXN0KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBFdmVudFR5cGUuUEFTUzpcbiAgICAgICAgY2FzZSBFdmVudFR5cGUuRkFJTDpcbiAgICAgICAgICBpZiAodGVzdC5uYW1lICE9PSB0ZXN0LmZpbGUpIHtcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlVGVzdFJlc3VsdCh0ZXN0LCBldmVudC50eXBlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgRXZlbnRUeXBlLlBMQU46XG4gICAgICAgICAgdGhpcy5oYW5kbGVUZXN0RW5kKHRlc3QpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEV2ZW50VHlwZS5TVERPVVQ6XG4gICAgICAgICAgcHJvY2Vzcy5zdGRvdXQud3JpdGUoZXZlbnQuZGF0YS5tZXNzYWdlID8/IFwiXCIpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEV2ZW50VHlwZS5TVERFUlI6XG4gICAgICAgICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoZXZlbnQuZGF0YS5tZXNzYWdlID8/IFwiXCIpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBjYWxsYmFjaygpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmxvZyhlcnJvcik7XG4gICAgICBjYWxsYmFjayhlcnJvciBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHByb2Nlc3NPdXRjb21lcygpIHtcbiAgICBPYmplY3QuZW50cmllcyh0aGlzLnRlc3RTdWl0ZSkuZm9yRWFjaCgoW2ZpbGUsIHN1aXRlXSkgPT4ge1xuICAgICAgdGhpcy5idWlsZFN0YXRzKHN1aXRlKTtcbiAgICAgIC8vIEZpbGUgc3VpdGUgZG9lc24ndCBoYXZlIGEgZHVyYXRpb24gc28gY29sbGF0ZSBmcm9tIGFsbCB0b3AgbGV2ZWwgc3VpdGVzLlxuICAgICAgT2JqZWN0LnZhbHVlcyhzdWl0ZS5jaGlsZHJlbiA/PyB7fSkuZm9yRWFjaCgoY2hpbGQpID0+IHtcbiAgICAgICAgdGhpcy50b3RhbER1cmF0aW9uICs9IGNoaWxkLmRldGFpbHM/LmR1cmF0aW9uX21zIHx8IDA7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRTdGF0cyhzdWl0ZTogU3VpdGUgfCBUZXN0LCBwcmVmaXg/OiBzdHJpbmcpIHtcbiAgICBjb25zdCBpc1N1aXRlID0gKG9iajogU3VpdGUgfCBUZXN0KTogb2JqIGlzIFN1aXRlID0+XG4gICAgICBvYmouZGV0YWlscz8udHlwZSA9PT0gXCJzdWl0ZVwiO1xuXG4gICAgaWYgKGlzU3VpdGUoc3VpdGUpKSB7XG4gICAgICAvLyBJdGVyYXRlIG92ZXIgZWFjaCBjaGlsZFxuICAgICAgT2JqZWN0LnZhbHVlcyhzdWl0ZS5jaGlsZHJlbiEpLmZvckVhY2goKGNoaWxkKSA9PlxuICAgICAgICB0aGlzLmJ1aWxkU3RhdHMoXG4gICAgICAgICAgY2hpbGQsXG4gICAgICAgICAgcHJlZml4ID8gYCR7cHJlZml4fSA+ICR7c3VpdGUubmFtZX1gIDogc3VpdGUubmFtZVxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChwcmVmaXgpIHtcbiAgICAgIHN1aXRlLm5hbWUgPSBgJHtwcmVmaXh9ID4gJHtzdWl0ZS5uYW1lfWA7XG4gICAgfVxuICAgIGlmIChzdWl0ZS5za2lwKSB7XG4gICAgICB0aGlzLnNraXBwZWRUZXN0cy5wdXNoKHN1aXRlIGFzIFRlc3QpO1xuICAgIH0gZWxzZSBpZiAoc3VpdGUudG9kbykge1xuICAgICAgdGhpcy50b2RvVGVzdHMucHVzaChzdWl0ZSBhcyBUZXN0KTtcbiAgICB9IGVsc2UgaWYgKCFpc1N1aXRlKHN1aXRlKSkge1xuICAgICAgaWYgKHN1aXRlLnBhc3NlZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy5mYWlsZWRUZXN0cy5wdXNoKHN1aXRlIGFzIFRlc3QpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5wYXNzZWRUZXN0cysrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBvdmVycmlkZSBfZmx1c2goKSB7XG4gICAgdGhpcy5wcm9jZXNzT3V0Y29tZXMoKTtcblxuICAgIGlmICh0aGlzLnNraXBwZWRUZXN0cy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zb2xlLmxvZyhcIlxcblxcblNraXBwZWQ6XCIpO1xuICAgICAgdGhpcy5za2lwcGVkVGVzdHMuZm9yRWFjaCgodGVzdCwgaSkgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZyhgXFxuJHtpICsgMX0pICR7dGVzdC5uYW1lfWApO1xuICAgICAgICBpZiAodHlwZW9mIHRlc3Quc2tpcCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLnllbGxvdyhgXFx0U2tpcHBlZDogJHt0ZXN0LnNraXB9YCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLnllbGxvdyhgXFx0JHtcIlNraXBwZWQ6IE5vIHJlYXNvblwifWApKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudG9kb1Rlc3RzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnNvbGUubG9nKFwiXFxuXFxuVG9kbzpcIik7XG4gICAgICB0aGlzLnRvZG9UZXN0cy5mb3JFYWNoKCh0ZXN0LCBpKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBcXG4ke2kgKyAxfSkgJHt0ZXN0Lm5hbWV9YCk7XG4gICAgICAgIGlmICh0eXBlb2YgdGVzdC50b2RvID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coY2hhbGsuYmx1ZShgXFx0VE9ETzogJHt0ZXN0LnRvZG99YCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmJsdWUoYFxcdCR7XCJUT0RPOiBObyByZWFzb25cIn1gKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmZhaWxlZFRlc3RzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnNvbGUubG9nKGNoYWxrLnJlZChcIlxcbuKcllwiKSArIFwiIEZhaWxpbmcgdGVzdHM6XCIpO1xuICAgICAgdGhpcy5mYWlsZWRUZXN0cy5mb3JFYWNoKCh0ZXN0LCBpKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGNoYWxrLnJlZChgXFxuJHtpICsgMX0pICR7dGVzdC5uYW1lfSAoJHt0ZXN0LmRldGFpbHMuZHVyYXRpb25fbXN9bXMpYClcbiAgICAgICAgKTtcbiAgICAgICAgY29uc29sZS5sb2codGVzdC5kZXRhaWxzLmVycm9yPy5jYXVzZSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGBcXG5cXG7ihLkgVGVzdHMgICAgJHtcbiAgICAgICAgdGhpcy5wYXNzZWRUZXN0cyArXG4gICAgICAgIHRoaXMuZmFpbGVkVGVzdHMubGVuZ3RoICtcbiAgICAgICAgdGhpcy5za2lwcGVkVGVzdHMubGVuZ3RoICtcbiAgICAgICAgdGhpcy50b2RvVGVzdHMubGVuZ3RoXG4gICAgICB9YFxuICAgICk7XG4gICAgY29uc29sZS5sb2coYOKEuSBQYXNzZWQgICAke2NoYWxrLmdyZWVuKHRoaXMucGFzc2VkVGVzdHMpfWApO1xuICAgIGNvbnNvbGUubG9nKGDihLkgRmFpbGVkICAgJHtjaGFsay5yZWQodGhpcy5mYWlsZWRUZXN0cy5sZW5ndGgpfWApO1xuICAgIGNvbnNvbGUubG9nKGDihLkgU2tpcHBlZCAgJHtjaGFsay55ZWxsb3codGhpcy5za2lwcGVkVGVzdHMubGVuZ3RoKX1gKTtcbiAgICBjb25zb2xlLmxvZyhg4oS5IFRvZG8gICAgICR7Y2hhbGsuYmx1ZSh0aGlzLnRvZG9UZXN0cy5sZW5ndGgpfWApO1xuICAgIGNvbnNvbGUubG9nKGDihLkgRHVyYXRpb24gJHt0aGlzLnRvdGFsRHVyYXRpb24udG9GaXhlZCgyKX1tc2ApO1xuXG4gICAgdGhpcy5wYXNzZWRUZXN0cyA9IDA7XG4gICAgdGhpcy5za2lwcGVkVGVzdHMgPSBbXTtcbiAgICB0aGlzLnRvZG9UZXN0cyA9IFtdO1xuICAgIHRoaXMudG90YWxEdXJhdGlvbiA9IDA7XG4gICAgdGhpcy5mYWlsZWRUZXN0cyA9IFtdO1xuICAgIHRoaXMudGVzdFN1aXRlID0ge307XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgRG90RXh0cmFSZXBvcnRlcjtcbiJdfQ==