testcafe
Version:
Automated browser testing for the modern web development stack.
136 lines • 21 kB
JavaScript
"use strict";
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 test_run_tracker_1 = __importDefault(require("../api/test-run-tracker"));
const builder_symbol_1 = __importDefault(require("./builder-symbol"));
const replicator_1 = require("./replicator");
const observation_1 = require("../test-run/commands/observation");
const compile_client_function_1 = __importDefault(require("../compiler/compile-client-function"));
const runtime_1 = require("../errors/runtime");
const type_assertions_1 = require("../errors/runtime/type-assertions");
const types_1 = require("../errors/types");
const get_callsite_1 = require("../errors/get-callsite");
const re_executable_promise_1 = __importDefault(require("../utils/re-executable-promise"));
const marker_symbol_1 = __importDefault(require("../test-run/marker-symbol"));
const DEFAULT_EXECUTION_CALLSITE_NAME = '__$$clientFunction$$';
class ClientFunctionBuilder {
constructor(fn, options, callsiteNames = {}) {
this.callsiteNames = {
instantiation: callsiteNames.instantiation,
execution: callsiteNames.execution || DEFAULT_EXECUTION_CALLSITE_NAME
};
if (lodash_1.isNil(options))
options = {};
this._validateOptions(options);
this.fn = fn;
this.options = options;
this.compiledFnCode = this._getCompiledFnCode();
if (!this.compiledFnCode)
throw this._createInvalidFnTypeError();
this.replicator = replicator_1.createReplicator(this._getReplicatorTransforms());
}
_decorateFunction(clientFn) {
clientFn[builder_symbol_1.default] = this;
clientFn.with = options => {
return this._getClientFnWithOverriddenOptions(options);
};
}
_getClientFnWithOverriddenOptions(options) {
if (typeof options === 'object')
options = lodash_1.assign({}, this.options, options);
const builder = new this.constructor(this.fn, options, {
instantiation: 'with',
execution: this.callsiteNames.execution
});
return builder.getFunction();
}
getBoundTestRun() {
// NOTE: `boundTestRun` can be either TestController or TestRun instance.
if (this.options.boundTestRun)
return this.options.boundTestRun.testRun || this.options.boundTestRun;
return null;
}
_getTestRun() {
return this.getBoundTestRun() || test_run_tracker_1.default.resolveContextTestRun();
}
getFunction() {
const builder = this;
const clientFn = function __$$clientFunction$$() {
const testRun = builder._getTestRun();
const callsite = get_callsite_1.getCallsiteForMethod(builder.callsiteNames.execution);
const args = [];
// OPTIMIZATION: don't leak `arguments` object.
for (let i = 0; i < arguments.length; i++)
args.push(arguments[i]);
return builder._executeCommand(args, testRun, callsite);
};
this._decorateFunction(clientFn);
return clientFn;
}
getCommand(args) {
const encodedArgs = this.replicator.encode(args);
const encodedDependencies = this.replicator.encode(this.getFunctionDependencies());
return this._createTestRunCommand(encodedArgs, encodedDependencies);
}
// Overridable methods
getFunctionDependencies() {
return this.options.dependencies || {};
}
_createTestRunCommand(encodedArgs, encodedDependencies) {
return new observation_1.ExecuteClientFunctionCommand({
instantiationCallsiteName: this.callsiteNames.instantiation,
fnCode: this.compiledFnCode,
args: encodedArgs,
dependencies: encodedDependencies
}, this._getTestRun());
}
_getCompiledFnCode() {
if (typeof this.fn === 'function')
return compile_client_function_1.default(this.fn.toString(), this.options.dependencies, this.callsiteNames.instantiation, this.callsiteNames.instantiation);
return null;
}
_createInvalidFnTypeError() {
return new runtime_1.ClientFunctionAPIError(this.callsiteNames.instantiation, this.callsiteNames.instantiation, types_1.RUNTIME_ERRORS.clientFunctionCodeIsNotAFunction, typeof this.fn);
}
_executeCommand(args, testRun, callsite) {
// NOTE: should be kept outside of lazy promise to preserve
// correct callsite in case of replicator error.
const command = this.getCommand(args);
return re_executable_promise_1.default.fromFn(async () => {
if (!testRun) {
const err = new runtime_1.ClientFunctionAPIError(this.callsiteNames.execution, this.callsiteNames.instantiation, types_1.RUNTIME_ERRORS.clientFunctionCannotResolveTestRun);
// NOTE: force callsite here, because more likely it will
// be impossible to resolve it by method name from a lazy promise.
err.callsite = callsite;
throw err;
}
const result = await testRun.executeCommand(command, callsite);
return this._processResult(result, args);
});
}
_processResult(result) {
return this.replicator.decode(result);
}
_validateOptions(options) {
type_assertions_1.assertType(type_assertions_1.is.nonNullObject, this.callsiteNames.instantiation, '"options" argument', options);
if (!lodash_1.isNil(options.boundTestRun)) {
// NOTE: `boundTestRun` can be either TestController or TestRun instance.
const boundTestRun = options.boundTestRun.testRun || options.boundTestRun;
if (!boundTestRun[marker_symbol_1.default])
throw new runtime_1.APIError(this.callsiteNames.instantiation, types_1.RUNTIME_ERRORS.invalidClientFunctionTestRunBinding);
}
if (!lodash_1.isNil(options.dependencies))
type_assertions_1.assertType(type_assertions_1.is.nonNullObject, this.callsiteNames.instantiation, '"dependencies" option', options.dependencies);
}
_getReplicatorTransforms() {
return [
new replicator_1.FunctionTransform(this.callsiteNames)
];
}
}
exports.default = ClientFunctionBuilder;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LWZ1bmN0aW9uLWJ1aWxkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2xpZW50LWZ1bmN0aW9ucy9jbGllbnQtZnVuY3Rpb24tYnVpbGRlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG1DQUE0RDtBQUM1RCwrRUFBcUQ7QUFDckQsc0VBQXFEO0FBQ3JELDZDQUFtRTtBQUNuRSxrRUFBZ0Y7QUFDaEYsa0dBQXdFO0FBQ3hFLCtDQUFxRTtBQUNyRSx1RUFBbUU7QUFDbkUsMkNBQWlEO0FBQ2pELHlEQUE4RDtBQUM5RCwyRkFBaUU7QUFDakUsOEVBQXNEO0FBRXRELE1BQU0sK0JBQStCLEdBQUcsc0JBQXNCLENBQUM7QUFFL0QsTUFBcUIscUJBQXFCO0lBQ3RDLFlBQWEsRUFBRSxFQUFFLE9BQU8sRUFBRSxhQUFhLEdBQUcsRUFBRTtRQUN4QyxJQUFJLENBQUMsYUFBYSxHQUFHO1lBQ2pCLGFBQWEsRUFBRSxhQUFhLENBQUMsYUFBYTtZQUMxQyxTQUFTLEVBQU0sYUFBYSxDQUFDLFNBQVMsSUFBSSwrQkFBK0I7U0FDNUUsQ0FBQztRQUVGLElBQUksY0FBaUIsQ0FBQyxPQUFPLENBQUM7WUFDMUIsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUVqQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFFL0IsSUFBSSxDQUFDLEVBQUUsR0FBZSxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLE9BQU8sR0FBVSxPQUFPLENBQUM7UUFDOUIsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUVoRCxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWM7WUFDcEIsTUFBTSxJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQztRQUUzQyxJQUFJLENBQUMsVUFBVSxHQUFHLDZCQUFnQixDQUFDLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLENBQUM7SUFDeEUsQ0FB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ZmluZWQsIGFzc2lnbiB9IGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgdGVzdFJ1blRyYWNrZXIgZnJvbSAnLi4vYXBpL3Rlc3QtcnVuLXRyYWNrZXInO1xuaW1wb3J0IGZ1bmN0aW9uQnVpbGRlclN5bWJvbCBmcm9tICcuL2J1aWxkZXItc3ltYm9sJztcbmltcG9ydCB7IGNyZWF0ZVJlcGxpY2F0b3IsIEZ1bmN0aW9uVHJhbnNmb3JtIH0gZnJvbSAnLi9yZXBsaWNhdG9yJztcbmltcG9ydCB7IEV4ZWN1dGVDbGllbnRGdW5jdGlvbkNvbW1hbmQgfSBmcm9tICcuLi90ZXN0LXJ1bi9jb21tYW5kcy9vYnNlcnZhdGlvbic7XG5pbXBvcnQgY29tcGlsZUNsaWVudEZ1bmN0aW9uIGZyb20gJy4uL2NvbXBpbGVyL2NvbXBpbGUtY2xpZW50LWZ1bmN0aW9uJztcbmltcG9ydCB7IEFQSUVycm9yLCBDbGllbnRGdW5jdGlvbkFQSUVycm9yIH0gZnJvbSAnLi4vZXJyb3JzL3J1bnRpbWUnO1xuaW1wb3J0IHsgYXNzZXJ0VHlwZSwgaXMgfSBmcm9tICcuLi9lcnJvcnMvcnVudGltZS90eXBlLWFzc2VydGlvbnMnO1xuaW1wb3J0IHsgUlVOVElNRV9FUlJPUlMgfSBmcm9tICcuLi9lcnJvcnMvdHlwZXMnO1xuaW1wb3J0IHsgZ2V0Q2FsbHNpdGVGb3JNZXRob2QgfSBmcm9tICcuLi9lcnJvcnMvZ2V0LWNhbGxzaXRlJztcbmltcG9ydCBSZUV4ZWN1dGFibGVQcm9taXNlIGZyb20gJy4uL3V0aWxzL3JlLWV4ZWN1dGFibGUtcHJvbWlzZSc7XG5pbXBvcnQgdGVzdFJ1bk1hcmtlciBmcm9tICcuLi90ZXN0LXJ1bi9tYXJrZXItc3ltYm9sJztcblxuY29uc3QgREVGQVVMVF9FWEVDVVRJT05fQ0FMTFNJVEVfTkFNRSA9ICdfXyQkY2xpZW50RnVuY3Rpb24kJCc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENsaWVudEZ1bmN0aW9uQnVpbGRlciB7XG4gICAgY29uc3RydWN0b3IgKGZuLCBvcHRpb25zLCBjYWxsc2l0ZU5hbWVzID0ge30pIHtcbiAgICAgICAgdGhpcy5jYWxsc2l0ZU5hbWVzID0ge1xuICAgICAgICAgICAgaW5zdGFudGlhdGlvbjogY2FsbHNpdGVOYW1lcy5pbnN0YW50aWF0aW9uLFxuICAgICAgICAgICAgZXhlY3V0aW9uOiAgICAgY2FsbHNpdGVOYW1lcy5leGVjdXRpb24gfHwgREVGQVVMVF9FWEVDVVRJT05fQ0FMTFNJVEVfTkFNRVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChvcHRpb25zKSlcbiAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcblxuICAgICAgICB0aGlzLl92YWxpZGF0ZU9wdGlvbnMob3B0aW9ucyk7XG5cbiAgICAgICAgdGhpcy5mbiAgICAgICAgICAgICA9IGZuO1xuICAgICAgICB0aGlzLm9wdGlvbnMgICAgICAgID0gb3B0aW9ucztcbiAgICAgICAgdGhpcy5jb21waWxlZEZuQ29kZSA9IHRoaXMuX2dldENvbXBpbGVkRm5Db2RlKCk7XG5cbiAgICAgICAgaWYgKCF0aGlzLmNvbXBpbGVkRm5Db2RlKVxuICAgICAgICAgICAgdGhyb3cgdGhpcy5fY3JlYXRlSW52YWxpZEZuVHlwZUVycm9yKCk7XG5cbiAgICAgICAgdGhpcy5yZXBsaWNhdG9yID0gY3JlYXRlUmVwbGljYXRvcih0aGlzLl9nZXRSZXBsaWNhdG9yVHJhbnNmb3JtcygpKTtcbiAgICB9XG5cbiAgICBfZGVjb3JhdGVGdW5jdGlvbiAoY2xpZW50Rm4pIHtcbiAgICAgICAgY2xpZW50Rm5bZnVuY3Rpb25CdWlsZGVyU3ltYm9sXSA9IHRoaXM7XG5cbiAgICAgICAgY2xpZW50Rm4ud2l0aCA9IG9wdGlvbnMgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2dldENsaWVudEZuV2l0aE92ZXJyaWRkZW5PcHRpb25zKG9wdGlvbnMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIF9nZXRDbGllbnRGbldpdGhPdmVycmlkZGVuT3B0aW9ucyAob3B0aW9ucykge1xuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICdvYmplY3QnKVxuICAgICAgICAgICAgb3B0aW9ucyA9IGFzc2lnbih7fSwgdGhpcy5vcHRpb25zLCBvcHRpb25zKTtcblxuICAgICAgICBjb25zdCBidWlsZGVyID0gbmV3IHRoaXMuY29uc3RydWN0b3IodGhpcy5mbiwgb3B0aW9ucywge1xuICAgICAgICAgICAgaW5zdGFudGlhdGlvbjogJ3dpdGgnLFxuICAgICAgICAgICAgZXhlY3V0aW9uOiAgICAgdGhpcy5jYWxsc2l0ZU5hbWVzLmV4ZWN1dGlvblxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gYnVpbGRlci5nZXRGdW5jdGlvbigpO1xuICAgIH1cblxuICAgIGdldEJvdW5kVGVzdFJ1biAoKSB7XG4gICAgICAgIC8vIE5PVEU6IGBib3VuZFRlc3RSdW5gIGNhbiBiZSBlaXRoZXIgVGVzdENvbnRyb2xsZXIgb3IgVGVzdFJ1biBpbnN0YW5jZS5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5ib3VuZFRlc3RSdW4pXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zLmJvdW5kVGVzdFJ1bi50ZXN0UnVuIHx8IHRoaXMub3B0aW9ucy5ib3VuZFRlc3RSdW47XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgX2dldFRlc3RSdW4gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRCb3VuZFRlc3RSdW4oKSB8fCB0ZXN0UnVuVHJhY2tlci5yZXNvbHZlQ29udGV4dFRlc3RSdW4oKTtcbiAgICB9XG5cbiAgICBnZXRGdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGJ1aWxkZXIgPSB0aGlzO1xuXG4gICAgICAgIGNvbnN0IGNsaWVudEZuID0gZnVuY3Rpb24gX18kJGNsaWVudEZ1bmN0aW9uJCQgKCkge1xuICAgICAgICAgICAgY29uc3QgdGVzdFJ1biAgPSBidWlsZGVyLl9nZXRUZXN0UnVuKCk7XG4gICAgICAgICAgICBjb25zdCBjYWxsc2l0ZSA9IGdldENhbGxzaXRlRm9yTWV0aG9kKGJ1aWxkZXIuY2FsbHNpdGVOYW1lcy5leGVjdXRpb24pO1xuICAgICAgICAgICAgY29uc3QgYXJncyAgICAgPSBbXTtcblxuICAgICAgICAgICAgLy8gT1BUSU1JWkFUSU9OOiBkb24ndCBsZWFrIGBhcmd1bWVudHNgIG9iamVjdC5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxuICAgICAgICAgICAgICAgIGFyZ3MucHVzaChhcmd1bWVudHNbaV0pO1xuXG4gICAgICAgICAgICByZXR1cm4gYnVpbGRlci5fZXhlY3V0ZUNvbW1hbmQoYXJncywgdGVzdFJ1biwgY2FsbHNpdGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMuX2RlY29yYXRlRnVuY3Rpb24oY2xpZW50Rm4pO1xuXG4gICAgICAgIHJldHVybiBjbGllbnRGbjtcbiAgICB9XG5cbiAgICBnZXRDb21tYW5kIChhcmdzKSB7XG4gICAgICAgIGNvbnN0IGVuY29kZWRBcmdzICAgICAgICAgPSB0aGlzLnJlcGxpY2F0b3IuZW5jb2RlKGFyZ3MpO1xuICAgICAgICBjb25zdCBlbmNvZGVkRGVwZW5kZW5jaWVzID0gdGhpcy5yZXBsaWNhdG9yLmVuY29kZSh0aGlzLmdldEZ1bmN0aW9uRGVwZW5kZW5jaWVzKCkpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLl9jcmVhdGVUZXN0UnVuQ29tbWFuZChlbmNvZGVkQXJncywgZW5jb2RlZERlcGVuZGVuY2llcyk7XG4gICAgfVxuXG5cbiAgICAvLyBPdmVycmlkYWJsZSBtZXRob2RzXG4gICAgZ2V0RnVuY3Rpb25EZXBlbmRlbmNpZXMgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zLmRlcGVuZGVuY2llcyB8fCB7fTtcbiAgICB9XG5cbiAgICBfY3JlYXRlVGVzdFJ1bkNvbW1hbmQgKGVuY29kZWRBcmdzLCBlbmNvZGVkRGVwZW5kZW5jaWVzKSB7XG4gICAgICAgIHJldHVybiBuZXcgRXhlY3V0ZUNsaWVudEZ1bmN0aW9uQ29tbWFuZCh7XG4gICAgICAgICAgICBpbnN0YW50aWF0aW9uQ2FsbHNpdGVOYW1lOiB0aGlzLmNhbGxzaXRlTmFtZXMuaW5zdGFudGlhdGlvbixcbiAgICAgICAgICAgIGZuQ29kZTogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcGlsZWRGbkNvZGUsXG4gICAgICAgICAgICBhcmdzOiAgICAgICAgICAgICAgICAgICAgICBlbmNvZGVkQXJncyxcbiAgICAgICAgICAgIGRlcGVuZGVuY2llczogICAgICAgICAgICAgIGVuY29kZWREZXBlbmRlbmNpZXNcbiAgICAgICAgfSwgdGhpcy5fZ2V0VGVzdFJ1bigpKTtcbiAgICB9XG5cbiAgICBfZ2V0Q29tcGlsZWRGbkNvZGUgKCkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuZm4gPT09ICdmdW5jdGlvbicpXG4gICAgICAgICAgICByZXR1cm4gY29tcGlsZUNsaWVudEZ1bmN0aW9uKHRoaXMuZm4udG9TdHJpbmcoKSwgdGhpcy5vcHRpb25zLmRlcGVuZGVuY2llcywgdGhpcy5jYWxsc2l0ZU5hbWVzLmluc3RhbnRpYXRpb24sIHRoaXMuY2FsbHNpdGVOYW1lcy5pbnN0YW50aWF0aW9uKTtcblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBfY3JlYXRlSW52YWxpZEZuVHlwZUVycm9yICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDbGllbnRGdW5jdGlvbkFQSUVycm9yKHRoaXMuY2FsbHNpdGVOYW1lcy5pbnN0YW50aWF0aW9uLCB0aGlzLmNhbGxzaXRlTmFtZXMuaW5zdGFudGlhdGlvbiwgUlVOVElNRV9FUlJPUlMuY2xpZW50RnVuY3Rpb25Db2RlSXNOb3RBRnVuY3Rpb24sIHR5cGVvZiB0aGlzLmZuKTtcbiAgICB9XG5cbiAgICBfZXhlY3V0ZUNvbW1hbmQgKGFyZ3MsIHRlc3RSdW4sIGNhbGxzaXRlKSB7XG4gICAgICAgIC8vIE5PVEU6IHNob3VsZCBiZSBrZXB0IG91dHNpZGUgb2YgbGF6eSBwcm9taXNlIHRvIHByZXNlcnZlXG4gICAgICAgIC8vIGNvcnJlY3QgY2FsbHNpdGUgaW4gY2FzZSBvZiByZXBsaWNhdG9yIGVycm9yLlxuICAgICAgICBjb25zdCBjb21tYW5kID0gdGhpcy5nZXRDb21tYW5kKGFyZ3MpO1xuXG4gICAgICAgIHJldHVybiBSZUV4ZWN1dGFibGVQcm9taXNlLmZyb21Gbihhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRlc3RSdW4pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBlcnIgPSBuZXcgQ2xpZW50RnVuY3Rpb25BUElFcnJvcih0aGlzLmNhbGxzaXRlTmFtZXMuZXhlY3V0aW9uLCB0aGlzLmNhbGxzaXRlTmFtZXMuaW5zdGFudGlhdGlvbiwgUlVOVElNRV9FUlJPUlMuY2xpZW50RnVuY3Rpb25DYW5ub3RSZXNvbHZlVGVzdFJ1bik7XG5cbiAgICAgICAgICAgICAgICAvLyBOT1RFOiBmb3JjZSBjYWxsc2l0ZSBoZXJlLCBiZWNhdXNlIG1vcmUgbGlrZWx5IGl0IHdpbGxcbiAgICAgICAgICAgICAgICAvLyBiZSBpbXBvc3NpYmxlIHRvIHJlc29sdmUgaXQgYnkgbWV0aG9kIG5hbWUgZnJvbSBhIGxhenkgcHJvbWlzZS5cbiAgICAgICAgICAgICAgICBlcnIuY2FsbHNpdGUgPSBjYWxsc2l0ZTtcblxuICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGVzdFJ1bi5leGVjdXRlQ29tbWFuZChjb21tYW5kLCBjYWxsc2l0ZSk7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9wcm9jZXNzUmVzdWx0KHJlc3VsdCwgYXJncyk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIF9wcm9jZXNzUmVzdWx0IChyZXN1bHQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVwbGljYXRvci5kZWNvZGUocmVzdWx0KTtcbiAgICB9XG5cbiAgICBfdmFsaWRhdGVPcHRpb25zIChvcHRpb25zKSB7XG4gICAgICAgIGFzc2VydFR5cGUoaXMubm9uTnVsbE9iamVjdCwgdGhpcy5jYWxsc2l0ZU5hbWVzLmluc3RhbnRpYXRpb24sICdcIm9wdGlvbnNcIiBhcmd1bWVudCcsIG9wdGlvbnMpO1xuXG4gICAgICAgIGlmICghaXNOdWxsT3JVbmRlZmluZWQob3B0aW9ucy5ib3VuZFRlc3RSdW4pKSB7XG4gICAgICAgICAgICAvLyBOT1RFOiBgYm91bmRUZXN0UnVuYCBjYW4gYmUgZWl0aGVyIFRlc3RDb250cm9sbGVyIG9yIFRlc3RSdW4gaW5zdGFuY2UuXG4gICAgICAgICAgICBjb25zdCBib3VuZFRlc3RSdW4gPSBvcHRpb25zLmJvdW5kVGVzdFJ1bi50ZXN0UnVuIHx8IG9wdGlvbnMuYm91bmRUZXN0UnVuO1xuXG4gICAgICAgICAgICBpZiAoIWJvdW5kVGVzdFJ1blt0ZXN0UnVuTWFya2VyXSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQVBJRXJyb3IodGhpcy5jYWxsc2l0ZU5hbWVzLmluc3RhbnRpYXRpb24sIFJVTlRJTUVfRVJST1JTLmludmFsaWRDbGllbnRGdW5jdGlvblRlc3RSdW5CaW5kaW5nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNOdWxsT3JVbmRlZmluZWQob3B0aW9ucy5kZXBlbmRlbmNpZXMpKVxuICAgICAgICAgICAgYXNzZXJ0VHlwZShpcy5ub25OdWxsT2JqZWN0LCB0aGlzLmNhbGxzaXRlTmFtZXMuaW5zdGFudGlhdGlvbiwgJ1wiZGVwZW5kZW5jaWVzXCIgb3B0aW9uJywgb3B0aW9ucy5kZXBlbmRlbmNpZXMpO1xuICAgIH1cblxuICAgIF9nZXRSZXBsaWNhdG9yVHJhbnNmb3JtcyAoKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBuZXcgRnVuY3Rpb25UcmFuc2Zvcm0odGhpcy5jYWxsc2l0ZU5hbWVzKVxuICAgICAgICBdO1xuICAgIH1cbn1cbiJdfQ==