UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

155 lines 24 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 execute_client_function_1 = require("../test-run/commands/execute-client-function"); 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 templates_1 = __importDefault(require("../errors/test-run/templates")); const dedent_1 = __importDefault(require("dedent")); 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 ((0, 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 = (0, replicator_1.createReplicator)(this._getReplicatorTransforms()); } _renderError(error) { // The rendered template is shown in the Watch panel of browser dev tools or IDE. // Viewport size is unlimited there. const viewportWidth = Number.MIN_SAFE_INTEGER; const renderedMessage = templates_1.default[error.code](error, viewportWidth); return (0, dedent_1.default)(renderedMessage); } _decorateFunction(clientFn) { clientFn[builder_symbol_1.default] = this; clientFn.with = options => { return this._getClientFnWithOverriddenOptions(options); }; } _getClientFnWithOverriddenOptions(options) { if (typeof options === 'object') options = (0, 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(); } _getObservedCallsites() { var _a; return ((_a = this._getTestRun()) === null || _a === void 0 ? void 0 : _a.observedCallsites) || null; } getFunction() { const builder = this; const clientFn = function __$$clientFunction$$() { const testRun = builder._getTestRun(); const callsite = (0, 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 execute_client_function_1.ExecuteClientFunctionCommand({ instantiationCallsiteName: this.callsiteNames.instantiation, fnCode: this.compiledFnCode, args: encodedArgs, dependencies: encodedDependencies, }, this._getTestRun()); } _getCompiledFnCode() { if (typeof this.fn === 'function') return (0, 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) { // HACK: in some cases related to navigation from ClientFunction or removing target iframe for the ClientFunction // we get an invalid result from the replicator on the client side. // I didn't find a stable reproduction scenario. // So, I just added a hack for this case. if (result === null) result = [result]; return this.replicator.decode(result); } _validateOptions(options) { (0, type_assertions_1.assertType)(type_assertions_1.is.nonNullObject, this.callsiteNames.instantiation, 'The "options" argument', options); if (!(0, 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 (!(0, lodash_1.isNil)(options.dependencies)) (0, type_assertions_1.assertType)(type_assertions_1.is.nonNullObject, this.callsiteNames.instantiation, 'The "dependencies" option', options.dependencies); } _getReplicatorTransforms() { return [ new replicator_1.FunctionTransform(this.callsiteNames), ]; } } exports.default = ClientFunctionBuilder; module.exports = exports.default; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LWZ1bmN0aW9uLWJ1aWxkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2xpZW50LWZ1bmN0aW9ucy9jbGllbnQtZnVuY3Rpb24tYnVpbGRlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG1DQUE0RDtBQUM1RCwrRUFBcUQ7QUFDckQsc0VBQXFEO0FBQ3JELDZDQUFtRTtBQUNuRSwwRkFBNEY7QUFDNUYsa0dBQXdFO0FBQ3hFLCtDQUFxRTtBQUNyRSx1RUFBbUU7QUFDbkUsMkNBQWlEO0FBQ2pELHlEQUE4RDtBQUM5RCwyRkFBaUU7QUFDakUsOEVBQXNEO0FBQ3RELDZFQUFxRDtBQUNyRCxvREFBNEI7QUFFNUIsTUFBTSwrQkFBK0IsR0FBRyxzQkFBc0IsQ0FBQztBQUUvRCxNQUFxQixxQkFBcUI7SUFDdEMsWUFBYSxFQUFFLEVBQUUsT0FBTyxFQUFFLGFBQWEsR0FBRyxFQUFFO1FBQ3hDLElBQUksQ0FBQyxhQUFhLEdBQUc7WUFDakIsYUFBYSxFQUFFLGFBQWEsQ0FBQyxhQUFhO1lBQzFDLFNBQVMsRUFBTSxhQUFhLENBQUMsU0FBUyxJQUFJLCtCQUErQjtTQUM1RSxDQUFDO1FBRUYsSUFBSSxJQUFBLGNBQWlCLEVBQUMsT0FBTyxDQUFDO1lBQzFCLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFFakIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRS9CLElBQUksQ0FBQyxFQUFFLEdBQWUsRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxPQUFPLEdBQVUsT0FBTyxDQUFDO1FBQzlCLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFFaEQsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjO1lBQ3BCLE1BQU0sSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUM7UUFFM0MsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFBLDZCQUFnQixFQUFDLElBQUks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LEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQztZQUUxRSxJQUFJLENBQUMsWUFBWSxDQUFDLHVCQUFhLENBQUM7Z0JBQzVCLE1BQU0sSUFBSSxrQkFBUSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsYUFBYSxFQUFFLHNCQUFjLENBQUMsbUNBQW1DLENBQUMsQ0FBQztTQUNoSDtRQUVELElBQUksQ0FBQyxJQUFBLGNBQWlCLEVBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQztZQUN4QyxJQUFBLDRCQUFVLEVBQUMsb0JBQUUsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxhQUFhLEVBQUUsMkJBQTJCLEVBQUUsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQzFILENBQUM7SUFFRCx3QkFBd0I7UUFDcEIsT0FBTztZQUNILElBQUksOEJBQWlCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQztTQUM1QyxDQUFDO0lBQ04sQ0FBQztDQUNKO0FBN0tELHdDQTZLQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlzTmlsIGFzIGlzTnVsbE9yVW5kZWZpbmVkLCBhc3NpZ24gfSBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHRlc3RSdW5UcmFja2VyIGZyb20gJy4uL2FwaS90ZXN0LXJ1bi10cmFja2VyJztcbmltcG9ydCBmdW5jdGlvbkJ1aWxkZXJTeW1ib2wgZnJvbSAnLi9idWlsZGVyLXN5bWJvbCc7XG5pbXBvcnQgeyBjcmVhdGVSZXBsaWNhdG9yLCBGdW5jdGlvblRyYW5zZm9ybSB9IGZyb20gJy4vcmVwbGljYXRvcic7XG5pbXBvcnQgeyBFeGVjdXRlQ2xpZW50RnVuY3Rpb25Db21tYW5kIH0gZnJvbSAnLi4vdGVzdC1ydW4vY29tbWFuZHMvZXhlY3V0ZS1jbGllbnQtZnVuY3Rpb24nO1xuaW1wb3J0IGNvbXBpbGVDbGllbnRGdW5jdGlvbiBmcm9tICcuLi9jb21waWxlci9jb21waWxlLWNsaWVudC1mdW5jdGlvbic7XG5pbXBvcnQgeyBBUElFcnJvciwgQ2xpZW50RnVuY3Rpb25BUElFcnJvciB9IGZyb20gJy4uL2Vycm9ycy9ydW50aW1lJztcbmltcG9ydCB7IGFzc2VydFR5cGUsIGlzIH0gZnJvbSAnLi4vZXJyb3JzL3J1bnRpbWUvdHlwZS1hc3NlcnRpb25zJztcbmltcG9ydCB7IFJVTlRJTUVfRVJST1JTIH0gZnJvbSAnLi4vZXJyb3JzL3R5cGVzJztcbmltcG9ydCB7IGdldENhbGxzaXRlRm9yTWV0aG9kIH0gZnJvbSAnLi4vZXJyb3JzL2dldC1jYWxsc2l0ZSc7XG5pbXBvcnQgUmVFeGVjdXRhYmxlUHJvbWlzZSBmcm9tICcuLi91dGlscy9yZS1leGVjdXRhYmxlLXByb21pc2UnO1xuaW1wb3J0IHRlc3RSdW5NYXJrZXIgZnJvbSAnLi4vdGVzdC1ydW4vbWFya2VyLXN5bWJvbCc7XG5pbXBvcnQgVEVNUExBVEVTIGZyb20gJy4uL2Vycm9ycy90ZXN0LXJ1bi90ZW1wbGF0ZXMnO1xuaW1wb3J0IGRlZGVudCBmcm9tICdkZWRlbnQnO1xuXG5jb25zdCBERUZBVUxUX0VYRUNVVElPTl9DQUxMU0lURV9OQU1FID0gJ19fJCRjbGllbnRGdW5jdGlvbiQkJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ2xpZW50RnVuY3Rpb25CdWlsZGVyIHtcbiAgICBjb25zdHJ1Y3RvciAoZm4sIG9wdGlvbnMsIGNhbGxzaXRlTmFtZXMgPSB7fSkge1xuICAgICAgICB0aGlzLmNhbGxzaXRlTmFtZXMgPSB7XG4gICAgICAgICAgICBpbnN0YW50aWF0aW9uOiBjYWxsc2l0ZU5hbWVzLmluc3RhbnRpYXRpb24sXG4gICAgICAgICAgICBleGVjdXRpb246ICAgICBjYWxsc2l0ZU5hbWVzLmV4ZWN1dGlvbiB8fCBERUZBVUxUX0VYRUNVVElPTl9DQUxMU0lURV9OQU1FLFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChvcHRpb25zKSlcbiAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcblxuICAgICAgICB0aGlzLl92YWxpZGF0ZU9wdGlvbnMob3B0aW9ucyk7XG5cbiAgICAgICAgdGhpcy5mbiAgICAgICAgICAgICA9IGZuO1xuICAgICAgICB0aGlzLm9wdGlvbnMgICAgICAgID0gb3B0aW9ucztcbiAgICAgICAgdGhpcy5jb21waWxlZEZuQ29kZSA9IHRoaXMuX2dldENvbXBpbGVkRm5Db2RlKCk7XG5cbiAgICAgICAgaWYgKCF0aGlzLmNvbXBpbGVkRm5Db2RlKVxuICAgICAgICAgICAgdGhyb3cgdGhpcy5fY3JlYXRlSW52YWxpZEZuVHlwZUVycm9yKCk7XG5cbiAgICAgICAgdGhpcy5yZXBsaWNhdG9yID0gY3JlYXRlUmVwbGljYXRvcih0aGlzLl9nZXRSZXBsaWNhdG9yVHJhbnNmb3JtcygpKTtcbiAgICB9XG5cbiAgICBfcmVuZGVyRXJyb3IgKGVycm9yKSB7XG4gICAgICAgIC8vIFRoZSByZW5kZXJlZCB0ZW1wbGF0ZSBpcyBzaG93biBpbiB0aGUgV2F0Y2ggcGFuZWwgb2YgYnJvd3NlciBkZXYgdG9vbHMgb3IgSURFLlxuICAgICAgICAvLyBWaWV3cG9ydCBzaXplIGlzIHVubGltaXRlZCB0aGVyZS5cbiAgICAgICAgY29uc3Qgdmlld3BvcnRXaWR0aCAgID0gTnVtYmVyLk1JTl9TQUZFX0lOVEVHRVI7XG4gICAgICAgIGNvbnN0IHJlbmRlcmVkTWVzc2FnZSA9IFRFTVBMQVRFU1tlcnJvci5jb2RlXShlcnJvciwgdmlld3BvcnRXaWR0aCk7XG5cbiAgICAgICAgcmV0dXJuIGRlZGVudChyZW5kZXJlZE1lc3NhZ2UpO1xuICAgIH1cblxuICAgIF9kZWNvcmF0ZUZ1bmN0aW9uIChjbGllbnRGbikge1xuICAgICAgICBjbGllbnRGbltmdW5jdGlvbkJ1aWxkZXJTeW1ib2xdID0gdGhpcztcblxuICAgICAgICBjbGllbnRGbi53aXRoID0gb3B0aW9ucyA9PiB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fZ2V0Q2xpZW50Rm5XaXRoT3ZlcnJpZGRlbk9wdGlvbnMob3B0aW9ucyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgX2dldENsaWVudEZuV2l0aE92ZXJyaWRkZW5PcHRpb25zIChvcHRpb25zKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ29iamVjdCcpXG4gICAgICAgICAgICBvcHRpb25zID0gYXNzaWduKHt9LCB0aGlzLm9wdGlvbnMsIG9wdGlvbnMpO1xuXG4gICAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgdGhpcy5jb25zdHJ1Y3Rvcih0aGlzLmZuLCBvcHRpb25zLCB7XG4gICAgICAgICAgICBpbnN0YW50aWF0aW9uOiAnd2l0aCcsXG4gICAgICAgICAgICBleGVjdXRpb246ICAgICB0aGlzLmNhbGxzaXRlTmFtZXMuZXhlY3V0aW9uLFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gYnVpbGRlci5nZXRGdW5jdGlvbigpO1xuICAgIH1cblxuICAgIGdldEJvdW5kVGVzdFJ1biAoKSB7XG4gICAgICAgIC8vIE5PVEU6IGBib3VuZFRlc3RSdW5gIGNhbiBiZSBlaXRoZXIgVGVzdENvbnRyb2xsZXIgb3IgVGVzdFJ1biBpbnN0YW5jZS5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5ib3VuZFRlc3RSdW4pXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vcHRpb25zLmJvdW5kVGVzdFJ1bi50ZXN0UnVuIHx8IHRoaXMub3B0aW9ucy5ib3VuZFRlc3RSdW47XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgX2dldFRlc3RSdW4gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRCb3VuZFRlc3RSdW4oKSB8fCB0ZXN0UnVuVHJhY2tlci5yZXNvbHZlQ29udGV4dFRlc3RSdW4oKTtcbiAgICB9XG5cbiAgICBfZ2V0T2JzZXJ2ZWRDYWxsc2l0ZXMgKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2V0VGVzdFJ1bigpPy5vYnNlcnZlZENhbGxzaXRlcyB8fCBudWxsO1xuICAgIH1cblxuICAgIGdldEZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgYnVpbGRlciA9IHRoaXM7XG5cbiAgICAgICAgY29uc3QgY2xpZW50Rm4gPSBmdW5jdGlvbiBfXyQkY2xpZW50RnVuY3Rpb24kJCAoKSB7XG4gICAgICAgICAgICBjb25zdCB0ZXN0UnVuICA9IGJ1aWxkZXIuX2dldFRlc3RSdW4oKTtcbiAgICAgICAgICAgIGNvbnN0IGNhbGxzaXRlID0gZ2V0Q2FsbHNpdGVGb3JNZXRob2QoYnVpbGRlci5jYWxsc2l0ZU5hbWVzLmV4ZWN1dGlvbik7XG4gICAgICAgICAgICBjb25zdCBhcmdzICAgICA9IFtdO1xuXG4gICAgICAgICAgICAvLyBPUFRJTUlaQVRJT046IGRvbid0IGxlYWsgYGFyZ3VtZW50c2Agb2JqZWN0LlxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspXG4gICAgICAgICAgICAgICAgYXJncy5wdXNoKGFyZ3VtZW50c1tpXSk7XG5cbiAgICAgICAgICAgIHJldHVybiBidWlsZGVyLl9leGVjdXRlQ29tbWFuZChhcmdzLCB0ZXN0UnVuLCBjYWxsc2l0ZSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5fZGVjb3JhdGVGdW5jdGlvbihjbGllbnRGbik7XG5cbiAgICAgICAgcmV0dXJuIGNsaWVudEZuO1xuICAgIH1cblxuICAgIGdldENvbW1hbmQgKGFyZ3MgPSBbXSkge1xuICAgICAgICBjb25zdCBlbmNvZGVkQXJncyAgICAgICAgID0gdGhpcy5yZXBsaWNhdG9yLmVuY29kZShhcmdzKTtcbiAgICAgICAgY29uc3QgZW5jb2RlZERlcGVuZGVuY2llcyA9IHRoaXMucmVwbGljYXRvci5lbmNvZGUodGhpcy5nZXRGdW5jdGlvbkRlcGVuZGVuY2llcygpKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fY3JlYXRlVGVzdFJ1bkNvbW1hbmQoZW5jb2RlZEFyZ3MsIGVuY29kZWREZXBlbmRlbmNpZXMpO1xuICAgIH1cblxuXG4gICAgLy8gT3ZlcnJpZGFibGUgbWV0aG9kc1xuICAgIGdldEZ1bmN0aW9uRGVwZW5kZW5jaWVzICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3B0aW9ucy5kZXBlbmRlbmNpZXMgfHwge307XG4gICAgfVxuXG4gICAgX2NyZWF0ZVRlc3RSdW5Db21tYW5kIChlbmNvZGVkQXJncywgZW5jb2RlZERlcGVuZGVuY2llcykge1xuICAgICAgICByZXR1cm4gbmV3IEV4ZWN1dGVDbGllbnRGdW5jdGlvbkNvbW1hbmQoe1xuICAgICAgICAgICAgaW5zdGFudGlhdGlvbkNhbGxzaXRlTmFtZTogdGhpcy5jYWxsc2l0ZU5hbWVzLmluc3RhbnRpYXRpb24sXG4gICAgICAgICAgICBmbkNvZGU6ICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBpbGVkRm5Db2RlLFxuICAgICAgICAgICAgYXJnczogICAgICAgICAgICAgICAgICAgICAgZW5jb2RlZEFyZ3MsXG4gICAgICAgICAgICBkZXBlbmRlbmNpZXM6ICAgICAgICAgICAgICBlbmNvZGVkRGVwZW5kZW5jaWVzLFxuICAgICAgICB9LCB0aGlzLl9nZXRUZXN0UnVuKCkpO1xuICAgIH1cblxuICAgIF9nZXRDb21waWxlZEZuQ29kZSAoKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5mbiA9PT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgICAgIHJldHVybiBjb21waWxlQ2xpZW50RnVuY3Rpb24odGhpcy5mbi50b1N0cmluZygpLCB0aGlzLm9wdGlvbnMuZGVwZW5kZW5jaWVzLCB0aGlzLmNhbGxzaXRlTmFtZXMuaW5zdGFudGlhdGlvbiwgdGhpcy5jYWxsc2l0ZU5hbWVzLmluc3RhbnRpYXRpb24pO1xuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIF9jcmVhdGVJbnZhbGlkRm5UeXBlRXJyb3IgKCkge1xuICAgICAgICByZXR1cm4gbmV3IENsaWVudEZ1bmN0aW9uQVBJRXJyb3IodGhpcy5jYWxsc2l0ZU5hbWVzLmluc3RhbnRpYXRpb24sIHRoaXMuY2FsbHNpdGVOYW1lcy5pbnN0YW50aWF0aW9uLCBSVU5USU1FX0VSUk9SUy5jbGllbnRGdW5jdGlvbkNvZGVJc05vdEFGdW5jdGlvbiwgdHlwZW9mIHRoaXMuZm4pO1xuICAgIH1cblxuICAgIF9leGVjdXRlQ29tbWFuZCAoYXJncywgdGVzdFJ1biwgY2FsbHNpdGUpIHtcbiAgICAgICAgLy8gTk9URTogc2hvdWxkIGJlIGtlcHQgb3V0c2lkZSBvZiBsYXp5IHByb21pc2UgdG8gcHJlc2VydmVcbiAgICAgICAgLy8gY29ycmVjdCBjYWxsc2l0ZSBpbiBjYXNlIG9mIHJlcGxpY2F0b3IgZXJyb3IuXG4gICAgICAgIGNvbnN0IGNvbW1hbmQgPSB0aGlzLmdldENvbW1hbmQoYXJncyk7XG5cbiAgICAgICAgcmV0dXJuIFJlRXhlY3V0YWJsZVByb21pc2UuZnJvbUZuKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGlmICghdGVzdFJ1bikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGVyciA9IG5ldyBDbGllbnRGdW5jdGlvbkFQSUVycm9yKHRoaXMuY2FsbHNpdGVOYW1lcy5leGVjdXRpb24sIHRoaXMuY2FsbHNpdGVOYW1lcy5pbnN0YW50aWF0aW9uLCBSVU5USU1FX0VSUk9SUy5jbGllbnRGdW5jdGlvbkNhbm5vdFJlc29sdmVUZXN0UnVuKTtcblxuICAgICAgICAgICAgICAgIC8vIE5PVEU6IGZvcmNlIGNhbGxzaXRlIGhlcmUsIGJlY2F1c2UgbW9yZSBsaWtlbHkgaXQgd2lsbFxuICAgICAgICAgICAgICAgIC8vIGJlIGltcG9zc2libGUgdG8gcmVzb2x2ZSBpdCBieSBtZXRob2QgbmFtZSBmcm9tIGEgbGF6eSBwcm9taXNlLlxuICAgICAgICAgICAgICAgIGVyci5jYWxsc2l0ZSA9IGNhbGxzaXRlO1xuXG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0ZXN0UnVuLmV4ZWN1dGVDb21tYW5kKGNvbW1hbmQsIGNhbGxzaXRlKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3Byb2Nlc3NSZXN1bHQocmVzdWx0LCBhcmdzKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgX3Byb2Nlc3NSZXN1bHQgKHJlc3VsdCkge1xuICAgICAgICAvLyBIQUNLOiBpbiBzb21lIGNhc2VzIHJlbGF0ZWQgdG8gbmF2aWdhdGlvbiBmcm9tIENsaWVudEZ1bmN0aW9uIG9yIHJlbW92aW5nIHRhcmdldCBpZnJhbWUgZm9yIHRoZSBDbGllbnRGdW5jdGlvblxuICAgICAgICAvLyB3ZSBnZXQgYW4gaW52YWxpZCByZXN1bHQgZnJvbSB0aGUgcmVwbGljYXRvciBvbiB0aGUgY2xpZW50IHNpZGUuXG4gICAgICAgIC8vIEkgZGlkbid0IGZpbmQgYSBzdGFibGUgcmVwcm9kdWN0aW9uIHNjZW5hcmlvLlxuICAgICAgICAvLyBTbywgSSBqdXN0IGFkZGVkIGEgaGFjayBmb3IgdGhpcyBjYXNlLlxuICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsKVxuICAgICAgICAgICAgcmVzdWx0ID0gW3Jlc3VsdF07XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucmVwbGljYXRvci5kZWNvZGUocmVzdWx0KTtcbiAgICB9XG5cbiAgICBfdmFsaWRhdGVPcHRpb25zIChvcHRpb25zKSB7XG4gICAgICAgIGFzc2VydFR5cGUoaXMubm9uTnVsbE9iamVjdCwgdGhpcy5jYWxsc2l0ZU5hbWVzLmluc3RhbnRpYXRpb24sICdUaGUgXCJvcHRpb25zXCIgYXJndW1lbnQnLCBvcHRpb25zKTtcblxuICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKG9wdGlvbnMuYm91bmRUZXN0UnVuKSkge1xuICAgICAgICAgICAgLy8gTk9URTogYGJvdW5kVGVzdFJ1bmAgY2FuIGJlIGVpdGhlciBUZXN0Q29udHJvbGxlciBvciBUZXN0UnVuIGluc3RhbmNlLlxuICAgICAgICAgICAgY29uc3QgYm91bmRUZXN0UnVuID0gb3B0aW9ucy5ib3VuZFRlc3RSdW4udGVzdFJ1biB8fCBvcHRpb25zLmJvdW5kVGVzdFJ1bjtcblxuICAgICAgICAgICAgaWYgKCFib3VuZFRlc3RSdW5bdGVzdFJ1bk1hcmtlcl0pXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEFQSUVycm9yKHRoaXMuY2FsbHNpdGVOYW1lcy5pbnN0YW50aWF0aW9uLCBSVU5USU1FX0VSUk9SUy5pbnZhbGlkQ2xpZW50RnVuY3Rpb25UZXN0UnVuQmluZGluZyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKG9wdGlvbnMuZGVwZW5kZW5jaWVzKSlcbiAgICAgICAgICAgIGFzc2VydFR5cGUoaXMubm9uTnVsbE9iamVjdCwgdGhpcy5jYWxsc2l0ZU5hbWVzLmluc3RhbnRpYXRpb24sICdUaGUgXCJkZXBlbmRlbmNpZXNcIiBvcHRpb24nLCBvcHRpb25zLmRlcGVuZGVuY2llcyk7XG4gICAgfVxuXG4gICAgX2dldFJlcGxpY2F0b3JUcmFuc2Zvcm1zICgpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIG5ldyBGdW5jdGlvblRyYW5zZm9ybSh0aGlzLmNhbGxzaXRlTmFtZXMpLFxuICAgICAgICBdO1xuICAgIH1cbn1cbiJdfQ==