testcafe
Version:
Automated browser testing for the modern web development stack.
173 lines • 28.2 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chalk_1 = __importDefault(require("chalk"));
const indent_string_1 = __importDefault(require("indent-string"));
const callsite_1 = __importDefault(require("callsite"));
const lodash_1 = require("lodash");
const moment_loader_1 = __importDefault(require("../utils/moment-loader"));
const string_1 = require("../utils/string");
const get_viewport_width_1 = __importDefault(require("../utils/get-viewport-width"));
const colors_1 = require("../utils/diff/colors");
const symbols_1 = __importDefault(require("../reporter/symbols"));
const plugin_methods_1 = __importDefault(require("./plugin-methods"));
// NOTE: we should not expose internal state to
// the plugin, to avoid accidental rewrites.
// Therefore we use symbols to store them.
const stream = Symbol();
const wordWrapEnabled = Symbol();
const indent = Symbol();
const errorDecorator = Symbol();
class ReporterPluginHost {
constructor(plugin, outStream, name, pluginHooks) {
this.name = name;
this.streamController = null;
this[stream] = outStream || process.stdout;
this[wordWrapEnabled] = false;
this[indent] = 0;
const useColors = this[stream] === process.stdout && chalk_1.default.enabled && !plugin.noColors;
this.chalk = new chalk_1.default.constructor({ enabled: useColors });
this.moment = moment_loader_1.default;
this.viewportWidth = (0, get_viewport_width_1.default)(this[stream]);
this.symbols = Object.assign({}, symbols_1.default);
(0, lodash_1.assignIn)(this, plugin);
this._hooks = pluginHooks;
this[errorDecorator] = this.createErrorDecorator();
}
// Error decorator
createErrorDecorator() {
return {
'span user-agent': (str) => this.chalk.grey(str),
'span subtitle': (str) => `- ${this.chalk.bold.red(str)} -`,
'div message': (str) => this.chalk.bold.red(str),
'div screenshot-info': lodash_1.identity,
'a screenshot-path': (str) => this.chalk.grey.underline(str),
'code': lodash_1.identity,
'span syntax-string': (str) => this.chalk.green(str),
'span syntax-punctuator': (str) => this.chalk.grey(str),
'span syntax-keyword': (str) => this.chalk.cyan(str),
'span syntax-number': (str) => this.chalk.magenta(str),
'span syntax-regex': (str) => this.chalk.magenta(str),
'span syntax-comment': (str) => this.chalk.grey.bold(str),
'span syntax-invalid': (str) => this.chalk.inverse(str),
[`span ${colors_1.DIFF_COLORS.DIFF_NOT_MODIFIED}`]: (str) => this.chalk.gray(str),
[`span ${colors_1.DIFF_COLORS.DIFF_ADDED}`]: (str) => this.chalk.green(str),
[`span ${colors_1.DIFF_COLORS.DIFF_REMOVED}`]: (str) => this.chalk.red(str),
'div code-frame': lodash_1.identity,
'div code-line': (str) => str + '\n',
'div code-line-last': lodash_1.identity,
'div code-line-num': (str) => ` ${str} |`,
'div code-line-num-base': (str) => this.chalk.bgRed(` > ${str} `) + '|',
'div code-line-src': lodash_1.identity,
'div stack': (str) => '\n\n' + str,
'div stack-line': (str) => str + '\n',
'div stack-line-last': lodash_1.identity,
'div stack-line-name': (str) => ` at ${this.chalk.bold(str)}`,
'div stack-line-location': (str) => ` (${this.chalk.grey.underline(str)})`,
'strong': (str) => this.chalk.bold(str),
'a': (str) => `"${this.chalk.underline(str)}"`,
};
}
// String helpers
indentString(str, indentVal) {
return (0, indent_string_1.default)(str, ' ', indentVal);
}
wordWrap(str, indentVal, width) {
return (0, string_1.wordWrap)(str, indentVal, width);
}
escapeHtml(str) {
return (0, lodash_1.escape)(str);
}
formatError(err, prefix = '') {
const prefixLengthWithoutColors = (0, string_1.removeTTYColors)(prefix).length;
const maxMsgLength = this.viewportWidth - this[indent] - prefixLengthWithoutColors;
let msg = err.formatMessage(this[errorDecorator], maxMsgLength);
if (this[wordWrapEnabled])
msg = this.wordWrap(msg, prefixLengthWithoutColors, maxMsgLength);
else
msg = this.indentString(msg, prefixLengthWithoutColors);
return prefix + msg.substr(prefixLengthWithoutColors);
}
// Writing helpers
newline() {
this._writeToUniqueStream('\n');
return this;
}
write(text, data) {
var _a;
if (this[wordWrapEnabled])
text = this.wordWrap(text, this[indent], this.viewportWidth);
else
text = this.indentString(text, this[indent]);
if ((_a = this._hooks) === null || _a === void 0 ? void 0 : _a.onBeforeWrite) {
const writeInfo = this._createBeforeWriteInfo(text, data);
this._hooks.onBeforeWrite(writeInfo);
this._writeToUniqueStream(writeInfo.formattedText);
}
else
this._writeToUniqueStream(text);
return this;
}
useWordWrap(use) {
this[wordWrapEnabled] = use;
return this;
}
setIndent(val) {
this[indent] = val;
return this;
}
_createBeforeWriteInfo(formattedText, data = {}) {
const initiator = data.initiator || this._getWriteInitiatorEvent();
return {
formatOptions: {
indent: this[indent],
useWordWrap: this[wordWrapEnabled],
},
formattedText,
initiator,
data,
};
}
_getWriteInitiatorEvent() {
const pluginMethods = Object.keys(plugin_methods_1.default);
const funcNames = (0, callsite_1.default)().map(site => site.getFunctionName());
const initiator = funcNames.find(funcName => pluginMethods.some(methodName => methodName === funcName));
return initiator || '';
}
_writeToUniqueStream(text) {
if (!this.streamController || this.streamController.ensureUniqueStream(this[stream], this))
this[stream].write(text);
}
// Abstract methods implemented in plugin
async reportTaskStart( /* startTime, userAgents, testCount, testStructure, taskProperties */) {
throw new Error('Not implemented');
}
async reportFixtureStart( /* name, path */) {
throw new Error('Not implemented');
}
// NOTE: It's an optional method
// async reportTestStart (/* name, testMeta */) {
// throw new Error('Not implemented');
// }
async reportTestDone( /* name, testRunInfo */) {
throw new Error('Not implemented');
}
async reportTaskDone( /* endTime, passed, warnings */) {
throw new Error('Not implemented');
}
// NOTE: It's an optional method
async init( /* testcafeVersion */) {
// Optional
}
// NOTE: It's an optional method
async reportWarnings( /* warnings */) {
}
// NOTE: It's an optional method
async reportData( /* testRun, ...data */) {
}
}
exports.default = ReporterPluginHost;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWhvc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwb3J0ZXIvcGx1Z2luLWhvc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxrREFBcUM7QUFDckMsa0VBQXlDO0FBQ3pDLHdEQUFnQztBQUVoQyxtQ0FJZ0I7QUFFaEIsMkVBQTRDO0FBQzVDLDRDQUE0RDtBQUM1RCxxRkFBMkQ7QUFDM0QsaURBQW1EO0FBS25ELGtFQUFtRDtBQUduRCxzRUFBb0Q7QUFFcEQsK0NBQStDO0FBQy9DLDRDQUE0QztBQUM1QywwQ0FBMEM7QUFDMUMsTUFBTSxNQUFNLEdBQVksTUFBTSxFQUFFLENBQUM7QUFDakMsTUFBTSxlQUFlLEdBQUcsTUFBTSxFQUFFLENBQUM7QUFDakMsTUFBTSxNQUFNLEdBQVksTUFBTSxFQUFFLENBQUM7QUFDakMsTUFBTSxjQUFjLEdBQUksTUFBTSxFQUFFLENBQUM7QUFFakMsTUFBcUIsa0JBQWtCO0lBYW5DLFlBQW9CLE1BQVcsRUFBRSxTQUFvQixFQUFFLElBQWEsRUFBRSxXQUFpQztRQUNuRyxJQUFJLENBQUMsSUFBSSxHQUFlLElBQUksQ0FBQztRQUM3QixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO1FBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBWSxTQUFTLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQztRQUNwRCxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsS0FBSyxDQUFDO1FBQzlCLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBWSxDQUFDLENBQUM7UUFFMUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLE9BQU8sQ0FBQyxNQUFNLElBQUksZUFBSyxDQUFDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7UUFFdkYsSUFBSSxDQUFDLEtBQUssR0FBVyxJQUFJLGVBQUssQ0FBQyxXQUFXLENBQUMsRUFBRSxPQUFPLEVB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LEtBQUssQ0FBQyxJQUFJLEVBQUUscUJBQXFCO1FBQ3BDLFdBQVc7SUFDZixDQUFDO0lBRUQsZ0NBQWdDO0lBQ3pCLEtBQUssQ0FBQyxjQUFjLEVBQUUsY0FBYztJQUMzQyxDQUFDO0lBRUQsZ0NBQWdDO0lBQ3pCLEtBQUssQ0FBQyxVQUFVLEVBQUUsc0JBQXNCO0lBQy9DLENBQUM7Q0FDSjtBQTVNRCxxQ0E0TUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY2hhbGssIHsgQ2hhbGsgfSBmcm9tICdjaGFsayc7XG5pbXBvcnQgaW5kZW50U3RyaW5nIGZyb20gJ2luZGVudC1zdHJpbmcnO1xuaW1wb3J0IGNhbGxzaXRlIGZyb20gJ2NhbGxzaXRlJztcblxuaW1wb3J0IHtcbiAgICBpZGVudGl0eSxcbiAgICBlc2NhcGUgYXMgZXNjYXBlSHRtbCxcbiAgICBhc3NpZ25Jbixcbn0gZnJvbSAnbG9kYXNoJztcblxuaW1wb3J0IG1vbWVudCBmcm9tICcuLi91dGlscy9tb21lbnQtbG9hZGVyJztcbmltcG9ydCB7IHdvcmRXcmFwLCByZW1vdmVUVFlDb2xvcnMgfSBmcm9tICcuLi91dGlscy9zdHJpbmcnO1xuaW1wb3J0IGdldFZpZXdwb3J0V2lkdGggZnJvbSAnLi4vdXRpbHMvZ2V0LXZpZXdwb3J0LXdpZHRoJztcbmltcG9ydCB7IERJRkZfQ09MT1JTIH0gZnJvbSAnLi4vdXRpbHMvZGlmZi9jb2xvcnMnO1xuaW1wb3J0IHsgTW9tZW50IH0gZnJvbSAnbW9tZW50JztcbmltcG9ydCBSZXBvcnRlclN0cmVhbUNvbnRyb2xsZXIgZnJvbSAnLi4vcnVubmVyL3JlcG9ydGVyLXN0cmVhbS1jb250cm9sbGVyJztcbmltcG9ydCB7IFdyaXRhYmxlIH0gZnJvbSAnc3RyZWFtJztcbmltcG9ydCBUZXN0UnVuRXJyb3JGb3JtYXR0YWJsZUFkYXB0ZXIgZnJvbSAnLi4vZXJyb3JzL3Rlc3QtcnVuL2Zvcm1hdHRhYmxlLWFkYXB0ZXInO1xuaW1wb3J0IFJFUE9SVEVSX1NZTUJPTFMgZnJvbSAnLi4vcmVwb3J0ZXIvc3ltYm9scyc7XG5pbXBvcnQgeyBSZXBvcnRlclN5bWJvbHMgfSBmcm9tICcuL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgUmVwb3J0ZXJQbHVnaW5Ib29rcywgV3JpdGVJbmZvIH0gZnJvbSAnLi9pbmRleCc7XG5pbXBvcnQgUmVwb3J0ZXJQbHVnaW5NZXRob2QgZnJvbSAnLi9wbHVnaW4tbWV0aG9kcyc7XG5cbi8vIE5PVEU6IHdlIHNob3VsZCBub3QgZXhwb3NlIGludGVybmFsIHN0YXRlIHRvXG4vLyB0aGUgcGx1Z2luLCB0byBhdm9pZCBhY2NpZGVudGFsIHJld3JpdGVzLlxuLy8gVGhlcmVmb3JlIHdlIHVzZSBzeW1ib2xzIHRvIHN0b3JlIHRoZW0uXG5jb25zdCBzdHJlYW0gICAgICAgICAgPSBTeW1ib2woKTtcbmNvbnN0IHdvcmRXcmFwRW5hYmxlZCA9IFN5bWJvbCgpO1xuY29uc3QgaW5kZW50ICAgICAgICAgID0gU3ltYm9sKCk7XG5jb25zdCBlcnJvckRlY29yYXRvciAgPSBTeW1ib2woKTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmVwb3J0ZXJQbHVnaW5Ib3N0IHtcbiAgICBwdWJsaWMgbmFtZT86IHN0cmluZztcbiAgICBwdWJsaWMgc3RyZWFtQ29udHJvbGxlcjogUmVwb3J0ZXJTdHJlYW1Db250cm9sbGVyIHwgbnVsbDtcbiAgICBwdWJsaWMgY2hhbGs6IENoYWxrO1xuICAgIHB1YmxpYyBtb21lbnQ6IE1vbWVudDtcbiAgICBwdWJsaWMgdmlld3BvcnRXaWR0aDogbnVtYmVyO1xuICAgIHB1YmxpYyBzeW1ib2xzOiBSZXBvcnRlclN5bWJvbHM7XG4gICAgcHJpdmF0ZSBbc3RyZWFtXTogV3JpdGFibGU7XG4gICAgcHJpdmF0ZSBbd29yZFdyYXBFbmFibGVkXTogYm9vbGVhbjtcbiAgICBwcml2YXRlIFtpbmRlbnRdOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBbZXJyb3JEZWNvcmF0b3JdOiBSZWNvcmQ8c3RyaW5nLCBGdW5jdGlvbj47XG4gICAgcHJpdmF0ZSBfaG9va3M6IFJlcG9ydGVyUGx1Z2luSG9va3MgfCB1bmRlZmluZWQ7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IgKHBsdWdpbjogYW55LCBvdXRTdHJlYW0/OiBXcml0YWJsZSwgbmFtZT86IHN0cmluZywgcGx1Z2luSG9va3M/OiBSZXBvcnRlclBsdWdpbkhvb2tzKSB7XG4gICAgICAgIHRoaXMubmFtZSAgICAgICAgICAgICA9IG5hbWU7XG4gICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlciA9IG51bGw7XG4gICAgICAgIHRoaXNbc3RyZWFtXSAgICAgICAgICA9IG91dFN0cmVhbSB8fCBwcm9jZXNzLnN0ZG91dDtcbiAgICAgICAgdGhpc1t3b3JkV3JhcEVuYWJsZWRdID0gZmFsc2U7XG4gICAgICAgIHRoaXNbaW5kZW50XSAgICAgICAgICA9IDA7XG5cbiAgICAgICAgY29uc3QgdXNlQ29sb3JzID0gdGhpc1tzdHJlYW1dID09PSBwcm9jZXNzLnN0ZG91dCAmJiBjaGFsay5lbmFibGVkICYmICFwbHVnaW4ubm9Db2xvcnM7XG5cbiAgICAgICAgdGhpcy5jaGFsayAgICAgICAgID0gbmV3IGNoYWxrLmNvbnN0cnVjdG9yKHsgZW5hYmxlZDogdXNlQ29sb3JzIH0pO1xuICAgICAgICB0aGlzLm1vbWVudCAgICAgICAgPSBtb21lbnQ7XG4gICAgICAgIHRoaXMudmlld3BvcnRXaWR0aCA9IGdldFZpZXdwb3J0V2lkdGgodGhpc1tzdHJlYW1dKTtcbiAgICAgICAgdGhpcy5zeW1ib2xzICAgICAgID0gT2JqZWN0LmFzc2lnbih7fSwgUkVQT1JURVJfU1lNQk9MUyk7XG5cbiAgICAgICAgYXNzaWduSW4odGhpcywgcGx1Z2luKTtcblxuICAgICAgICB0aGlzLl9ob29rcyA9IHBsdWdpbkhvb2tzO1xuXG4gICAgICAgIHRoaXNbZXJyb3JEZWNvcmF0b3JdID0gdGhpcy5jcmVhdGVFcnJvckRlY29yYXRvcigpO1xuICAgIH1cblxuICAgIC8vIEVycm9yIGRlY29yYXRvclxuICAgIHB1YmxpYyBjcmVhdGVFcnJvckRlY29yYXRvciAoKTogUmVjb3JkPHN0cmluZywgRnVuY3Rpb24+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICdzcGFuIHVzZXItYWdlbnQnOiAoc3RyOiBzdHJpbmcpID0+IHRoaXMuY2hhbGsuZ3JleShzdHIpLFxuXG4gICAgICAgICAgICAnc3BhbiBzdWJ0aXRsZSc6IChzdHI6IHN0cmluZykgPT4gYC0gJHt0aGlzLmNoYWxrLmJvbGQucmVkKHN0cil9IC1gLFxuICAgICAgICAgICAgJ2RpdiBtZXNzYWdlJzogICAoc3RyOiBzdHJpbmcpID0+IHRoaXMuY2hhbGsuYm9sZC5yZWQoc3RyKSxcblxuICAgICAgICAgICAgJ2RpdiBzY3JlZW5zaG90LWluZm8nOiBpZGVudGl0eSxcbiAgICAgICAgICAgICdhIHNjcmVlbnNob3QtcGF0aCc6ICAgKHN0cjogc3RyaW5nKSA9PiB0aGlzLmNoYWxrLmdyZXkudW5kZXJsaW5lKHN0ciksXG5cbiAgICAgICAgICAgICdjb2RlJzogaWRlbnRpdHksXG5cbiAgICAgICAgICAgICdzcGFuIHN5bnRheC1zdHJpbmcnOiAgICAgKHN0cjogc3RyaW5nKSA9PiB0aGlzLmNoYWxrLmdyZWVuKHN0ciksXG4gICAgICAgICAgICAnc3BhbiBzeW50YXgtcHVuY3R1YXRvcic6IChzdHI6IHN0cmluZykgPT4gdGhpcy5jaGFsay5ncmV5KHN0ciksXG4gICAgICAgICAgICAnc3BhbiBzeW50YXgta2V5d29yZCc6ICAgIChzdHI6IHN0cmluZykgPT4gdGhpcy5jaGFsay5jeWFuKHN0ciksXG4gICAgICAgICAgICAnc3BhbiBzeW50YXgtbnVtYmVyJzogICAgIChzdHI6IHN0cmluZykgPT4gdGhpcy5jaGFsay5tYWdlbnRhKHN0ciksXG4gICAgICAgICAgICAnc3BhbiBzeW50YXgtcmVnZXgnOiAgICAgIChzdHI6IHN0cmluZykgPT4gdGhpcy5jaGFsay5tYWdlbnRhKHN0ciksXG4gICAgICAgICAgICAnc3BhbiBzeW50YXgtY29tbWVudCc6ICAgIChzdHI6IHN0cmluZykgPT4gdGhpcy5jaGFsay5ncmV5LmJvbGQoc3RyKSxcbiAgICAgICAgICAgICdzcGFuIHN5bnRheC1pbnZhbGlkJzogICAgKHN0cjogc3RyaW5nKSA9PiB0aGlzLmNoYWxrLmludmVyc2Uoc3RyKSxcblxuICAgICAgICAgICAgW2BzcGFuICR7RElGRl9DT0xPUlMuRElGRl9OT1RfTU9ESUZJRUR9YF06IChzdHI6IHN0cmluZykgPT4gdGhpcy5jaGFsay5ncmF5KHN0ciksXG4gICAgICAgICAgICBbYHNwYW4gJHtESUZGX0NPTE9SUy5ESUZGX0FEREVEfWBdOiAgICAgICAgKHN0cjogc3RyaW5nKSA9PiB0aGlzLmNoYWxrLmdyZWVuKHN0ciksXG4gICAgICAgICAgICBbYHNwYW4gJHtESUZGX0NPTE9SUy5ESUZGX1JFTU9WRUR9YF06ICAgICAgKHN0cjogc3RyaW5nKSA9PiB0aGlzLmNoYWxrLnJlZChzdHIpLFxuXG4gICAgICAgICAgICAnZGl2IGNvZGUtZnJhbWUnOiAgICAgICAgIGlkZW50aXR5LFxuICAgICAgICAgICAgJ2RpdiBjb2RlLWxpbmUnOiAgICAgICAgICAoc3RyOiBzdHJpbmcpID0+IHN0ciArICdcXG4nLFxuICAgICAgICAgICAgJ2RpdiBjb2RlLWxpbmUtbGFzdCc6ICAgICBpZGVudGl0eSxcbiAgICAgICAgICAgICdkaXYgY29kZS1saW5lLW51bSc6ICAgICAgKHN0cjogc3RyaW5nKSA9PiBgICAgJHtzdHJ9IHxgLFxuICAgICAgICAgICAgJ2RpdiBjb2RlLWxpbmUtbnVtLWJhc2UnOiAoc3RyOiBzdHJpbmcpID0+IHRoaXMuY2hhbGsuYmdSZWQoYCA+ICR7c3RyfSBgKSArICd8JyxcbiAgICAgICAgICAgICdkaXYgY29kZS1saW5lLXNyYyc6ICAgICAgaWRlbnRpdHksXG5cbiAgICAgICAgICAgICdkaXYgc3RhY2snOiAgICAgICAgICAgICAgIChzdHI6IHN0cmluZykgPT4gJ1xcblxcbicgKyBzdHIsXG4gICAgICAgICAgICAnZGl2IHN0YWNrLWxpbmUnOiAgICAgICAgICAoc3RyOiBzdHJpbmcpID0+IHN0ciArICdcXG4nLFxuICAgICAgICAgICAgJ2RpdiBzdGFjay1saW5lLWxhc3QnOiAgICAgaWRlbnRpdHksXG4gICAgICAgICAgICAnZGl2IHN0YWNrLWxpbmUtbmFtZSc6ICAgICAoc3RyOiBzdHJpbmcpID0+IGAgICBhdCAke3RoaXMuY2hhbGsuYm9sZChzdHIpfWAsXG4gICAgICAgICAgICAnZGl2IHN0YWNrLWxpbmUtbG9jYXRpb24nOiAoc3RyOiBzdHJpbmcpID0+IGAgKCR7dGhpcy5jaGFsay5ncmV5LnVuZGVybGluZShzdHIpfSlgLFxuXG4gICAgICAgICAgICAnc3Ryb25nJzogKHN0cjogc3RyaW5nKSA9PiB0aGlzLmNoYWxrLmJvbGQoc3RyKSxcbiAgICAgICAgICAgICdhJzogICAgICAoc3RyOiBzdHJpbmcpID0+IGBcIiR7dGhpcy5jaGFsay51bmRlcmxpbmUoc3RyKX1cImAsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gU3RyaW5nIGhlbHBlcnNcbiAgICBwdWJsaWMgaW5kZW50U3RyaW5nIChzdHI6IHN0cmluZywgaW5kZW50VmFsOiBudW1iZXIpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gaW5kZW50U3RyaW5nKHN0ciwgJyAnLCBpbmRlbnRWYWwpO1xuICAgIH1cblxuICAgIHB1YmxpYyB3b3JkV3JhcCAoc3RyOiBzdHJpbmcsIGluZGVudFZhbDogbnVtYmVyLCB3aWR0aDogbnVtYmVyKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHdvcmRXcmFwKHN0ciwgaW5kZW50VmFsLCB3aWR0aCk7XG4gICAgfVxuXG4gICAgcHVibGljIGVzY2FwZUh0bWwgKHN0cjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGVzY2FwZUh0bWwoc3RyKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZm9ybWF0RXJyb3IgKGVycjogVGVzdFJ1bkVycm9yRm9ybWF0dGFibGVBZGFwdGVyLCBwcmVmaXggPSAnJyk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHByZWZpeExlbmd0aFdpdGhvdXRDb2xvcnMgPSByZW1vdmVUVFlDb2xvcnMocHJlZml4KS5sZW5ndGg7XG4gICAgICAgIGNvbnN0IG1heE1zZ0xlbmd0aCAgICAgICAgICAgICAgPSB0aGlzLnZpZXdwb3J0V2lkdGggLSB0aGlzW2luZGVudF0gLSBwcmVmaXhMZW5ndGhXaXRob3V0Q29sb3JzO1xuXG4gICAgICAgIGxldCBtc2cgPSBlcnIuZm9ybWF0TWVzc2FnZSh0aGlzW2Vycm9yRGVjb3JhdG9yXSwgbWF4TXNnTGVuZ3RoKTtcblxuICAgICAgICBpZiAodGhpc1t3b3JkV3JhcEVuYWJsZWRdKVxuICAgICAgICAgICAgbXNnID0gdGhpcy53b3JkV3JhcChtc2csIHByZWZpeExlbmd0aFdpdGhvdXRDb2xvcnMsIG1heE1zZ0xlbmd0aCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIG1zZyA9IHRoaXMuaW5kZW50U3RyaW5nKG1zZywgcHJlZml4TGVuZ3RoV2l0aG91dENvbG9ycyk7XG5cbiAgICAgICAgcmV0dXJuIHByZWZpeCArIG1zZy5zdWJzdHIocHJlZml4TGVuZ3RoV2l0aG91dENvbG9ycyk7XG4gICAgfVxuXG5cbiAgICAvLyBXcml0aW5nIGhlbHBlcnNcbiAgICBwdWJsaWMgbmV3bGluZSAoKTogUmVwb3J0ZXJQbHVnaW5Ib3N0IHtcbiAgICAgICAgdGhpcy5fd3JpdGVUb1VuaXF1ZVN0cmVhbSgnXFxuJyk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgcHVibGljIHdyaXRlICh0ZXh0OiBzdHJpbmcsIGRhdGE/OiBhbnkpOiBSZXBvcnRlclBsdWdpbkhvc3Qge1xuICAgICAgICBpZiAodGhpc1t3b3JkV3JhcEVuYWJsZWRdKVxuICAgICAgICAgICAgdGV4dCA9IHRoaXMud29yZFdyYXAodGV4dCwgdGhpc1tpbmRlbnRdLCB0aGlzLnZpZXdwb3J0V2lkdGgpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICB0ZXh0ID0gdGhpcy5pbmRlbnRTdHJpbmcodGV4dCwgdGhpc1tpbmRlbnRdKTtcblxuICAgICAgICBpZiAodGhpcy5faG9va3M/Lm9uQmVmb3JlV3JpdGUpIHtcbiAgICAgICAgICAgIGNvbnN0IHdyaXRlSW5mbyA9IHRoaXMuX2NyZWF0ZUJlZm9yZVdyaXRlSW5mbyh0ZXh0LCBkYXRhKTtcblxuICAgICAgICAgICAgdGhpcy5faG9va3Mub25CZWZvcmVXcml0ZSh3cml0ZUluZm8pO1xuICAgICAgICAgICAgdGhpcy5fd3JpdGVUb1VuaXF1ZVN0cmVhbSh3cml0ZUluZm8uZm9ybWF0dGVkVGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhpcy5fd3JpdGVUb1VuaXF1ZVN0cmVhbSh0ZXh0KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBwdWJsaWMgdXNlV29yZFdyYXAgKHVzZTogYm9vbGVhbik6IFJlcG9ydGVyUGx1Z2luSG9zdCB7XG4gICAgICAgIHRoaXNbd29yZFdyYXBFbmFibGVkXSA9IHVzZTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0SW5kZW50ICh2YWw6IG51bWJlcik6IFJlcG9ydGVyUGx1Z2luSG9zdCB7XG4gICAgICAgIHRoaXNbaW5kZW50XSA9IHZhbDtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBwcml2YXRlIF9jcmVhdGVCZWZvcmVXcml0ZUluZm8gKGZvcm1hdHRlZFRleHQ6IHN0cmluZywgZGF0YTogYW55ID0ge30pOiBXcml0ZUluZm8ge1xuICAgICAgICBjb25zdCBpbml0aWF0b3IgPSBkYXRhLmluaXRpYXRvciB8fCB0aGlzLl9nZXRXcml0ZUluaXRpYXRvckV2ZW50KCk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGZvcm1hdE9wdGlvbnM6IHtcbiAgICAgICAgICAgICAgICBpbmRlbnQ6ICAgICAgdGhpc1tpbmRlbnRdLFxuICAgICAgICAgICAgICAgIHVzZVdvcmRXcmFwOiB0aGlzW3dvcmRXcmFwRW5hYmxlZF0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZm9ybWF0dGVkVGV4dCxcbiAgICAgICAgICAgIGluaXRpYXRvcixcbiAgICAgICAgICAgIGRhdGEsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZ2V0V3JpdGVJbml0aWF0b3JFdmVudCAoKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgcGx1Z2luTWV0aG9kcyA9IE9iamVjdC5rZXlzKFJlcG9ydGVyUGx1Z2luTWV0aG9kKTtcbiAgICAgICAgY29uc3QgZnVuY05hbWVzID0gY2FsbHNpdGUoKS5tYXAoc2l0ZSA9PiBzaXRlLmdldEZ1bmN0aW9uTmFtZSgpKTtcbiAgICAgICAgY29uc3QgaW5pdGlhdG9yID0gZnVuY05hbWVzLmZpbmQoZnVuY05hbWUgPT4gcGx1Z2luTWV0aG9kcy5zb21lKG1ldGhvZE5hbWUgPT4gbWV0aG9kTmFtZSA9PT0gZnVuY05hbWUpKTtcblxuICAgICAgICByZXR1cm4gaW5pdGlhdG9yIHx8ICcnO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3dyaXRlVG9VbmlxdWVTdHJlYW0gKHRleHQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICBpZiAoIXRoaXMuc3RyZWFtQ29udHJvbGxlciB8fCB0aGlzLnN0cmVhbUNvbnRyb2xsZXIuZW5zdXJlVW5pcXVlU3RyZWFtKHRoaXNbc3RyZWFtXSwgdGhpcykpXG4gICAgICAgICAgICB0aGlzW3N0cmVhbV0ud3JpdGUodGV4dCk7XG4gICAgfVxuXG5cbiAgICAvLyBBYnN0cmFjdCBtZXRob2RzIGltcGxlbWVudGVkIGluIHBsdWdpblxuICAgIHB1YmxpYyBhc3luYyByZXBvcnRUYXNrU3RhcnQgKC8qIHN0YXJ0VGltZSwgdXNlckFnZW50cywgdGVzdENvdW50LCB0ZXN0U3RydWN0dXJlLCB0YXNrUHJvcGVydGllcyAqLyk6IFByb21pc2U8bmV2ZXI+IHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgaW1wbGVtZW50ZWQnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgcmVwb3J0Rml4dHVyZVN0YXJ0ICgvKiBuYW1lLCBwYXRoICovKTogUHJvbWlzZTxuZXZlcj4ge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBpbXBsZW1lbnRlZCcpO1xuICAgIH1cblxuICAgIC8vIE5PVEU6IEl0J3MgYW4gb3B0aW9uYWwgbWV0aG9kXG4gICAgLy8gYXN5bmMgcmVwb3J0VGVzdFN0YXJ0ICgvKiBuYW1lLCB0ZXN0TWV0YSAqLykge1xuICAgIC8vICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBpbXBsZW1lbnRlZCcpO1xuICAgIC8vIH1cblxuICAgIHB1YmxpYyBhc3luYyByZXBvcnRUZXN0RG9uZSAoLyogbmFtZSwgdGVzdFJ1bkluZm8gKi8pOiBQcm9taXNlPG5ldmVyPiB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm90IGltcGxlbWVudGVkJyk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHJlcG9ydFRhc2tEb25lICgvKiBlbmRUaW1lLCBwYXNzZWQsIHdhcm5pbmdzICovKTogUHJvbWlzZTxuZXZlcj4ge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vdCBpbXBsZW1lbnRlZCcpO1xuICAgIH1cblxuICAgIC8vIE5PVEU6IEl0J3MgYW4gb3B0aW9uYWwgbWV0aG9kXG4gICAgcHVibGljIGFzeW5jIGluaXQgKC8qIHRlc3RjYWZlVmVyc2lvbiAqLyk6IFByb21pc2U8dm9pZD4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuICAgICAgICAvLyBPcHRpb25hbFxuICAgIH1cblxuICAgIC8vIE5PVEU6IEl0J3MgYW4gb3B0aW9uYWwgbWV0aG9kXG4gICAgcHVibGljIGFzeW5jIHJlcG9ydFdhcm5pbmdzICgvKiB3YXJuaW5ncyAqLyk6IFByb21pc2U8dm9pZD4geyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuICAgIH1cblxuICAgIC8vIE5PVEU6IEl0J3MgYW4gb3B0aW9uYWwgbWV0aG9kXG4gICAgcHVibGljIGFzeW5jIHJlcG9ydERhdGEgKC8qIHRlc3RSdW4sIC4uLmRhdGEgKi8pOiBQcm9taXNlPHZvaWQ+IHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbiAgICB9XG59XG4iXX0=