UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

136 lines 21 kB
"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==