creevey
Version:
creevey is a tool for automated visual testing, that tightly integrated with storybook
247 lines (205 loc) • 22.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _path = _interopRequireDefault(require("path"));
var _fs = require("fs");
var _util = require("util");
var _events = require("events");
var _types = require("../../types");
var _pool = _interopRequireDefault(require("./pool"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const copyFileAsync = (0, _util.promisify)(_fs.copyFile);
const mkdirAsync = (0, _util.promisify)(_fs.mkdir);
class Runner extends _events.EventEmitter {
get isRunning() {
return Object.values(this.pools).some(pool => pool.isRunning);
}
constructor(config, tests) {
super();
this.tests = tests;
_defineProperty(this, "screenDir", void 0);
_defineProperty(this, "reportDir", void 0);
_defineProperty(this, "browsers", void 0);
_defineProperty(this, "pools", {});
_defineProperty(this, "handlePoolMessage", message => {
const {
id,
status,
result
} = message;
const test = this.tests[id];
if (!test) return;
test.status = status;
if (!result) {
this.sendUpdate({
tests: {
[id]: {
path: test.path,
status
}
}
});
return;
}
if (!test.results) {
test.results = [];
}
test.results.push(result);
this.sendUpdate({
tests: {
[id]: {
path: test.path,
status,
results: [result]
}
}
});
});
_defineProperty(this, "handlePoolStop", () => {
if (!this.isRunning) {
this.sendUpdate({
isRunning: false
});
this.emit('stop');
}
});
this.screenDir = config.screenDir;
this.reportDir = config.reportDir;
this.browsers = Object.keys(config.browsers);
this.browsers.map(browser => this.pools[browser] = new _pool.default(config, browser)).map(pool => pool.on('test', this.handlePoolMessage));
}
async init() {
await Promise.all(Object.values(this.pools).map(pool => pool.init()));
}
updateTests(testsDiff) {
const tests = {};
const removedTests = [];
Object.entries(testsDiff).forEach(([id, newTest]) => {
const oldTest = this.tests[id];
if (newTest) {
if (oldTest) {
this.tests[id] = { ...newTest,
status: 'unknown',
retries: oldTest.retries,
results: oldTest.results,
approved: oldTest.approved
};
} else this.tests[id] = newTest; // eslint-disable-next-line @typescript-eslint/no-unused-vars
const {
story,
fn,
...restTest
} = newTest;
tests[id] = { ...restTest,
status: 'unknown'
};
} else {
if (oldTest) removedTests.push(oldTest.path);
delete this.tests[id];
}
});
this.sendUpdate({
tests,
removedTests
});
}
start(ids) {
if (this.isRunning) return;
const testsToStart = ids.map(id => this.tests[id]).filter(_types.isDefined).filter(test => !test.skip);
if (testsToStart.length == 0) return;
this.sendUpdate({
isRunning: true,
tests: testsToStart.reduce((update, {
id
}) => {
var _this$tests$id;
return { ...update,
[id]: {
path: (_this$tests$id = this.tests[id]) === null || _this$tests$id === void 0 ? void 0 : _this$tests$id.path,
status: 'pending'
}
};
}, {})
});
const testsByBrowser = testsToStart.reduce((tests, test) => {
const {
id,
path
} = test;
const [browser, ...restPath] = path;
test.status = 'pending';
return { ...tests,
[browser]: [...(tests[browser] || []), {
id,
path: restPath
}]
};
}, {});
this.browsers.forEach(browser => {
const pool = this.pools[browser];
const tests = testsByBrowser[browser];
if (tests && tests.length > 0 && pool.start(tests)) {
pool.once('stop', this.handlePoolStop);
}
});
}
stop() {
if (!this.isRunning) return;
this.browsers.forEach(browser => this.pools[browser].stop());
}
get status() {
const tests = {};
Object.values(this.tests).filter(_types.isDefined) // eslint-disable-next-line @typescript-eslint/no-unused-vars
.forEach(({
story,
fn,
...test
}) => tests[test.id] = test);
return {
isRunning: this.isRunning,
tests
};
}
async approve({
id,
retry,
image
}) {
const test = this.tests[id];
if (!test || !test.results) return;
const result = test.results[retry];
if (!result || !result.images) return;
const images = result.images[image];
if (!images) return;
if (!test.approved) {
test.approved = {};
}
const [browser, ...restPath] = test.path;
const testPath = _path.default.join(...restPath.reverse(), image == browser ? '' : browser);
const srcImagePath = _path.default.join(this.reportDir, testPath, images.actual);
const dstImagePath = _path.default.join(this.screenDir, testPath, `${image}.png`);
await mkdirAsync(_path.default.join(this.screenDir, testPath), {
recursive: true
});
await copyFileAsync(srcImagePath, dstImagePath);
test.approved[image] = retry;
this.sendUpdate({
tests: {
[id]: {
path: test.path,
approved: {
[image]: retry
}
}
}
});
}
sendUpdate(data) {
this.emit('update', data);
}
}
exports.default = Runner;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZXJ2ZXIvbWFzdGVyL3J1bm5lci50cyJdLCJuYW1lcyI6WyJjb3B5RmlsZUFzeW5jIiwiY29weUZpbGUiLCJta2RpckFzeW5jIiwibWtkaXIiLCJSdW5uZXIiLCJFdmVudEVtaXR0ZXIiLCJpc1J1bm5pbmciLCJPYmplY3QiLCJ2YWx1ZXMiLCJwb29scyIsInNvbWUiLCJwb29sIiwiY29uc3RydWN0b3IiLCJjb25maWciLCJ0ZXN0cyIsIm1lc3NhZ2UiLCJpZCIsInN0YXR1cyIsInJlc3VsdCIsInRlc3QiLCJzZW5kVXBkYXRlIiwicGF0aCIsInJlc3VsdHMiLCJwdXNoIiwiZW1pdCIsInNjcmVlbkRpciIsInJlcG9ydERpciIsImJyb3dzZXJzIiwia2V5cyIsIm1hcCIsImJyb3dzZXIiLCJQb29sIiwib24iLCJoYW5kbGVQb29sTWVzc2FnZSIsImluaXQiLCJQcm9taXNlIiwiYWxsIiwidXBkYXRlVGVzdHMiLCJ0ZXN0c0RpZmYiLCJyZW1vdmVkVGVzdHMiLCJlbnRyaWVzIiwiZm9yRWFjaCIsIm5ld1Rlc3QiLCJvbGRUZXN0IiwicmV0cmllcyIsImFwcHJvdmVkIiwic3RvcnkiLCJmbiIsInJlc3RUZXN0Iiwic3RhcnQiLCJpZHMiLCJ0ZXN0c1RvU3RhcnQiLCJmaWx0ZXIiLCJpc0RlZmluZWQiLCJza2lwIiwibGVuZ3RoIiwicmVkdWNlIiwidXBkYXRlIiwidGVzdHNCeUJyb3dzZXIiLCJyZXN0UGF0aCIsIm9uY2UiLCJoYW5kbGVQb29sU3RvcCIsInN0b3AiLCJhcHByb3ZlIiwicmV0cnkiLCJpbWFnZSIsImltYWdlcyIsInRlc3RQYXRoIiwiam9pbiIsInJldmVyc2UiLCJzcmNJbWFnZVBhdGgiLCJhY3R1YWwiLCJkc3RJbWFnZVBhdGgiLCJyZWN1cnNpdmUiLCJkYXRhIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBVUE7Ozs7OztBQUVBLE1BQU1BLGFBQWEsR0FBRyxxQkFB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QyxTQUFmLEVBQTBCMEMsUUFBMUIsQ0FBRCxFQUFzQztBQUFFTSxNQUFBQSxTQUFTLEVBQUU7QUFBYixLQUF0QyxDQUFoQjtBQUNBLFVBQU16RSxhQUFhLENBQUNzRSxZQUFELEVBQWVFLFlBQWYsQ0FBbkI7QUFDQXJELElBQUFBLElBQUksQ0FBQzBCLFFBQUwsQ0FBY29CLEtBQWQsSUFBdUJELEtBQXZCO0FBQ0EsU0FBSzVDLFVBQUwsQ0FBZ0I7QUFBRU4sTUFBQUEsS0FBSyxFQUFFO0FBQUUsU0FBQ0UsRUFBRCxHQUFNO0FBQUVLLFVBQUFBLElBQUksRUFBRUYsSUFBSSxDQUFDRSxJQUFiO0FBQW1Cd0IsVUFBQUEsUUFBUSxFQUFFO0FBQUUsYUFBQ29CLEtBQUQsR0FBU0Q7QUFBWDtBQUE3QjtBQUFSO0FBQVQsS0FBaEI7QUFDRDs7QUFFTzVDLEVBQUFBLFVBQVIsQ0FBbUJzRCxJQUFuQixFQUE4QztBQUM1QyxTQUFLbEQsSUFBTCxDQUFVLFFBQVYsRUFBb0JrRCxJQUFwQjtBQUNEOztBQXpKOEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IGNvcHlGaWxlLCBta2RpciB9IGZyb20gJ2ZzJztcbmltcG9ydCB7IHByb21pc2lmeSB9IGZyb20gJ3V0aWwnO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnZXZlbnRzJztcbmltcG9ydCB7XG4gIENvbmZpZyxcbiAgQ3JlZXZleVN0YXR1cyxcbiAgVGVzdFJlc3VsdCxcbiAgQXBwcm92ZVBheWxvYWQsXG4gIGlzRGVmaW5lZCxcbiAgQ3JlZXZleVVwZGF0ZSxcbiAgVGVzdFN0YXR1cyxcbiAgU2VydmVyVGVzdCxcbn0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IFBvb2wgZnJvbSAnLi9wb29sJztcblxuY29uc3QgY29weUZpbGVBc3luYyA9IHByb21pc2lmeShjb3B5RmlsZSk7XG5jb25zdCBta2RpckFzeW5jID0gcHJvbWlzaWZ5KG1rZGlyKTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUnVubmVyIGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcbiAgcHJpdmF0ZSBzY3JlZW5EaXI6IHN0cmluZztcbiAgcHJpdmF0ZSByZXBvcnREaXI6IHN0cmluZztcbiAgcHJpdmF0ZSBicm93c2Vyczogc3RyaW5nW107XG4gIHByaXZhdGUgcG9vbHM6IHsgW2Jyb3dzZXI6IHN0cmluZ106IFBvb2wgfSA9IHt9O1xuICBwdWJsaWMgZ2V0IGlzUnVubmluZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLnBvb2xzKS5zb21lKChwb29sKSA9PiBwb29sLmlzUnVubmluZyk7XG4gIH1cbiAgY29uc3RydWN0b3IoY29uZmlnOiBDb25maWcsIHByaXZhdGUgdGVzdHM6IFBhcnRpYWw8eyBbaWQ6IHN0cmluZ106IFNlcnZlclRlc3QgfT4pIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5zY3JlZW5EaXIgPSBjb25maWcuc2NyZWVuRGlyO1xuICAgIHRoaXMucmVwb3J0RGlyID0gY29uZmlnLnJlcG9ydERpcjtcbiAgICB0aGlzLmJyb3dzZXJzID0gT2JqZWN0LmtleXMoY29uZmlnLmJyb3dzZXJzKTtcbiAgICB0aGlzLmJyb3dzZXJzXG4gICAgICAubWFwKChicm93c2VyKSA9PiAodGhpcy5wb29sc1ticm93c2VyXSA9IG5ldyBQb29sKGNvbmZpZywgYnJvd3NlcikpKVxuICAgICAgLm1hcCgocG9vbCkgPT4gcG9vbC5vbigndGVzdCcsIHRoaXMuaGFuZGxlUG9vbE1lc3NhZ2UpKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlUG9vbE1lc3NhZ2UgPSAobWVzc2FnZTogeyBpZDogc3RyaW5nOyBzdGF0dXM6IFRlc3RTdGF0dXM7IHJlc3VsdD86IFRlc3RSZXN1bHQgfSk6IHZvaWQgPT4ge1xuICAgIGNvbnN0IHsgaWQsIHN0YXR1cywgcmVzdWx0IH0gPSBtZXNzYWdlO1xuICAgIGNvbnN0IHRlc3QgPSB0aGlzLnRlc3RzW2lkXTtcbiAgICBpZiAoIXRlc3QpIHJldHVybjtcbiAgICB0ZXN0LnN0YXR1cyA9IHN0YXR1cztcbiAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgdGhpcy5zZW5kVXBkYXRlKHsgdGVzdHM6IHsgW2lkXTogeyBwYXRoOiB0ZXN0LnBhdGgsIHN0YXR1cyB9IH0gfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghdGVzdC5yZXN1bHRzKSB7XG4gICAgICB0ZXN0LnJlc3VsdHMgPSBbXTtcbiAgICB9XG4gICAgdGVzdC5yZXN1bHRzLnB1c2gocmVzdWx0KTtcbiAgICB0aGlzLnNlbmRVcGRhdGUoeyB0ZXN0czogeyBbaWRdOiB7IHBhdGg6IHRlc3QucGF0aCwgc3RhdHVzLCByZXN1bHRzOiBbcmVzdWx0XSB9IH0gfSk7XG4gIH07XG5cbiAgcHJpdmF0ZSBoYW5kbGVQb29sU3RvcCA9ICgpOiB2b2lkID0+IHtcbiAgICBpZiAoIXRoaXMuaXNSdW5uaW5nKSB7XG4gICAgICB0aGlzLnNlbmRVcGRhdGUoeyBpc1J1bm5pbmc6IGZhbHNlIH0pO1xuICAgICAgdGhpcy5lbWl0KCdzdG9wJyk7XG4gICAgfVxuICB9O1xuXG4gIHB1YmxpYyBhc3luYyBpbml0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKE9iamVjdC52YWx1ZXModGhpcy5wb29scykubWFwKChwb29sKSA9PiBwb29sLmluaXQoKSkpO1xuICB9XG5cbiAgcHVibGljIHVwZGF0ZVRlc3RzKHRlc3RzRGlmZjogUGFydGlhbDx7IFtpZDogc3RyaW5nXTogU2VydmVyVGVzdCB9Pik6IHZvaWQge1xuICAgIGNvbnN0IHRlc3RzOiBDcmVldmV5U3RhdHVzWyd0ZXN0cyddID0ge307XG4gICAgY29uc3QgcmVtb3ZlZFRlc3RzOiBzdHJpbmdbXVtdID0gW107XG4gICAgT2JqZWN0LmVudHJpZXModGVzdHNEaWZmKS5mb3JFYWNoKChbaWQsIG5ld1Rlc3RdKSA9PiB7XG4gICAgICBjb25zdCBvbGRUZXN0ID0gdGhpcy50ZXN0c1tpZF07XG4gICAgICBpZiAobmV3VGVzdCkge1xuICAgICAgICBpZiAob2xkVGVzdCkge1xuICAgICAgICAgIHRoaXMudGVzdHNbaWRdID0ge1xuICAgICAgICAgICAgLi4ubmV3VGVzdCxcbiAgICAgICAgICAgIHN0YXR1czogJ3Vua25vd24nLFxuICAgICAgICAgICAgcmV0cmllczogb2xkVGVzdC5yZXRyaWVzLFxuICAgICAgICAgICAgcmVzdWx0czogb2xkVGVzdC5yZXN1bHRzLFxuICAgICAgICAgICAgYXBwcm92ZWQ6IG9sZFRlc3QuYXBwcm92ZWQsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHRoaXMudGVzdHNbaWRdID0gbmV3VGVzdDtcblxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgICAgIGNvbnN0IHsgc3RvcnksIGZuLCAuLi5yZXN0VGVzdCB9ID0gbmV3VGVzdDtcbiAgICAgICAgdGVzdHNbaWRdID0geyAuLi5yZXN0VGVzdCwgc3RhdHVzOiAndW5rbm93bicgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChvbGRUZXN0KSByZW1vdmVkVGVzdHMucHVzaChvbGRUZXN0LnBhdGgpO1xuICAgICAgICBkZWxldGUgdGhpcy50ZXN0c1tpZF07XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5zZW5kVXBkYXRlKHsgdGVzdHMsIHJlbW92ZWRUZXN0cyB9KTtcbiAgfVxuXG4gIHB1YmxpYyBzdGFydChpZHM6IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgaW50ZXJmYWNlIFRlc3RzQnlCcm93c2VyIHtcbiAgICAgIFticm93c2VyOiBzdHJpbmddOiB7IGlkOiBzdHJpbmc7IHBhdGg6IHN0cmluZ1tdIH1bXTtcbiAgICB9XG4gICAgaWYgKHRoaXMuaXNSdW5uaW5nKSByZXR1cm47XG5cbiAgICBjb25zdCB0ZXN0c1RvU3RhcnQgPSBpZHNcbiAgICAgIC5tYXAoKGlkKSA9PiB0aGlzLnRlc3RzW2lkXSlcbiAgICAgIC5maWx0ZXIoaXNEZWZpbmVkKVxuICAgICAgLmZpbHRlcigodGVzdCkgPT4gIXRlc3Quc2tpcCk7XG5cbiAgICBpZiAodGVzdHNUb1N0YXJ0Lmxlbmd0aCA9PSAwKSByZXR1cm47XG5cbiAgICB0aGlzLnNlbmRVcGRhdGUoe1xuICAgICAgaXNSdW5uaW5nOiB0cnVlLFxuICAgICAgdGVzdHM6IHRlc3RzVG9TdGFydC5yZWR1Y2UoXG4gICAgICAgICh1cGRhdGUsIHsgaWQgfSkgPT4gKHsgLi4udXBkYXRlLCBbaWRdOiB7IHBhdGg6IHRoaXMudGVzdHNbaWRdPy5wYXRoLCBzdGF0dXM6ICdwZW5kaW5nJyB9IH0pLFxuICAgICAgICB7fSxcbiAgICAgICksXG4gICAgfSk7XG5cbiAgICBjb25zdCB0ZXN0c0J5QnJvd3NlcjogUGFydGlhbDxUZXN0c0J5QnJvd3Nlcj4gPSB0ZXN0c1RvU3RhcnQucmVkdWNlKCh0ZXN0czogVGVzdHNCeUJyb3dzZXIsIHRlc3QpID0+IHtcbiAgICAgIGNvbnN0IHsgaWQsIHBhdGggfSA9IHRlc3Q7XG4gICAgICBjb25zdCBbYnJvd3NlciwgLi4ucmVzdFBhdGhdID0gcGF0aDtcbiAgICAgIHRlc3Quc3RhdHVzID0gJ3BlbmRpbmcnO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4udGVzdHMsXG4gICAgICAgIFticm93c2VyXTogWy4uLih0ZXN0c1ticm93c2VyXSB8fCBbXSksIHsgaWQsIHBhdGg6IHJlc3RQYXRoIH1dLFxuICAgICAgfTtcbiAgICB9LCB7fSk7XG5cbiAgICB0aGlzLmJyb3dzZXJzLmZvckVhY2goKGJyb3dzZXIpID0+IHtcbiAgICAgIGNvbnN0IHBvb2wgPSB0aGlzLnBvb2xzW2Jyb3dzZXJdO1xuICAgICAgY29uc3QgdGVzdHMgPSB0ZXN0c0J5QnJvd3Nlclticm93c2VyXTtcblxuICAgICAgaWYgKHRlc3RzICYmIHRlc3RzLmxlbmd0aCA+IDAgJiYgcG9vbC5zdGFydCh0ZXN0cykpIHtcbiAgICAgICAgcG9vbC5vbmNlKCdzdG9wJywgdGhpcy5oYW5kbGVQb29sU3RvcCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgc3RvcCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNSdW5uaW5nKSByZXR1cm47XG4gICAgdGhpcy5icm93c2Vycy5mb3JFYWNoKChicm93c2VyKSA9PiB0aGlzLnBvb2xzW2Jyb3dzZXJdLnN0b3AoKSk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHN0YXR1cygpOiBDcmVldmV5U3RhdHVzIHtcbiAgICBjb25zdCB0ZXN0czogQ3JlZXZleVN0YXR1c1sndGVzdHMnXSA9IHt9O1xuICAgIE9iamVjdC52YWx1ZXModGhpcy50ZXN0cylcbiAgICAgIC5maWx0ZXIoaXNEZWZpbmVkKVxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgICAgLmZvckVhY2goKHsgc3RvcnksIGZuLCAuLi50ZXN0IH0pID0+ICh0ZXN0c1t0ZXN0LmlkXSA9IHRlc3QpKTtcbiAgICByZXR1cm4ge1xuICAgICAgaXNSdW5uaW5nOiB0aGlzLmlzUnVubmluZyxcbiAgICAgIHRlc3RzLFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgYXBwcm92ZSh7IGlkLCByZXRyeSwgaW1hZ2UgfTogQXBwcm92ZVBheWxvYWQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB0ZXN0ID0gdGhpcy50ZXN0c1tpZF07XG4gICAgaWYgKCF0ZXN0IHx8ICF0ZXN0LnJlc3VsdHMpIHJldHVybjtcbiAgICBjb25zdCByZXN1bHQgPSB0ZXN0LnJlc3VsdHNbcmV0cnldO1xuICAgIGlmICghcmVzdWx0IHx8ICFyZXN1bHQuaW1hZ2VzKSByZXR1cm47XG4gICAgY29uc3QgaW1hZ2VzID0gcmVzdWx0LmltYWdlc1tpbWFnZV07XG4gICAgaWYgKCFpbWFnZXMpIHJldHVybjtcbiAgICBpZiAoIXRlc3QuYXBwcm92ZWQpIHtcbiAgICAgIHRlc3QuYXBwcm92ZWQgPSB7fTtcbiAgICB9XG4gICAgY29uc3QgW2Jyb3dzZXIsIC4uLnJlc3RQYXRoXSA9IHRlc3QucGF0aDtcbiAgICBjb25zdCB0ZXN0UGF0aCA9IHBhdGguam9pbiguLi5yZXN0UGF0aC5yZXZlcnNlKCksIGltYWdlID09IGJyb3dzZXIgPyAnJyA6IGJyb3dzZXIpO1xuICAgIGNvbnN0IHNyY0ltYWdlUGF0aCA9IHBhdGguam9pbih0aGlzLnJlcG9ydERpciwgdGVzdFBhdGgsIGltYWdlcy5hY3R1YWwpO1xuICAgIGNvbnN0IGRzdEltYWdlUGF0aCA9IHBhdGguam9pbih0aGlzLnNjcmVlbkRpciwgdGVzdFBhdGgsIGAke2ltYWdlfS5wbmdgKTtcbiAgICBhd2FpdCBta2RpckFzeW5jKHBhdGguam9pbih0aGlzLnNjcmVlbkRpciwgdGVzdFBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICBhd2FpdCBjb3B5RmlsZUFzeW5jKHNyY0ltYWdlUGF0aCwgZHN0SW1hZ2VQYXRoKTtcbiAgICB0ZXN0LmFwcHJvdmVkW2ltYWdlXSA9IHJldHJ5O1xuICAgIHRoaXMuc2VuZFVwZGF0ZSh7IHRlc3RzOiB7IFtpZF06IHsgcGF0aDogdGVzdC5wYXRoLCBhcHByb3ZlZDogeyBbaW1hZ2VdOiByZXRyeSB9IH0gfSB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2VuZFVwZGF0ZShkYXRhOiBDcmVldmV5VXBkYXRlKTogdm9pZCB7XG4gICAgdGhpcy5lbWl0KCd1cGRhdGUnLCBkYXRhKTtcbiAgfVxufVxuIl19