testcafe
Version:
Automated browser testing for the modern web development stack.
163 lines (160 loc) • 27 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 dedent_1 = __importDefault(require("dedent"));
const client_function_builder_1 = __importDefault(require("../client-function-builder"));
const replicator_1 = require("../replicator");
const runtime_1 = require("../../errors/runtime");
const builder_symbol_1 = __importDefault(require("../builder-symbol"));
const types_1 = require("../../errors/types");
const type_assertions_1 = require("../../errors/runtime/type-assertions");
const observation_1 = require("../../test-run/commands/observation");
const define_lazy_property_1 = __importDefault(require("../../utils/define-lazy-property"));
const add_api_1 = require("./add-api");
const create_snapshot_methods_1 = __importDefault(require("./create-snapshot-methods"));
const prepare_api_args_1 = __importDefault(require("./prepare-api-args"));
class SelectorBuilder extends client_function_builder_1.default {
constructor(fn, options, callsiteNames) {
const apiFn = options && options.apiFn;
const apiFnID = options && options.apiFnID;
const builderFromSelector = fn && fn[builder_symbol_1.default];
const builderFromPromiseOrSnapshot = fn && fn.selector && fn.selector[builder_symbol_1.default];
let builder = builderFromSelector || builderFromPromiseOrSnapshot;
builder = builder instanceof SelectorBuilder ? builder : null;
if (builder) {
fn = builder.fn;
if (options === void 0 || typeof options === 'object')
options = lodash_1.merge({}, builder.options, options, { sourceSelectorBuilder: builder });
}
super(fn, options, callsiteNames);
if (!this.options.apiFnChain) {
const fnType = typeof this.fn;
let item = fnType === 'string' ? `'${this.fn}'` : `[${fnType}]`;
item = `Selector(${item})`;
this.options.apiFn = item;
this.options.apiFnChain = [item];
}
if (apiFn)
this.options.apiFnChain.push(apiFn);
this.options.apiFnID = typeof apiFnID === 'number' ? apiFnID : this.options.apiFnChain.length - 1;
}
_getCompiledFnCode() {
// OPTIMIZATION: if selector was produced from another selector and
// it has same dependencies as source selector, then we can
// avoid recompilation and just re-use already compiled code.
const hasSameDependenciesAsSourceSelector = this.options.sourceSelectorBuilder &&
this.options.sourceSelectorBuilder.options.dependencies ===
this.options.dependencies;
if (hasSameDependenciesAsSourceSelector)
return this.options.sourceSelectorBuilder.compiledFnCode;
const code = typeof this.fn === 'string' ?
`(function(){return document.querySelectorAll(${JSON.stringify(this.fn)});});` :
super._getCompiledFnCode();
if (code) {
return dedent_1.default(`(function(){
var __f$=${code};
return function(){
var args = __dependencies$.boundArgs || arguments;
var selectorFilter = window['%testCafeSelectorFilter%'];
var nodes = __f$.apply(this, args);
nodes = selectorFilter.cast(nodes);
if (!nodes.length && !selectorFilter.error)
selectorFilter.error = __dependencies$.apiInfo.apiFnID;
return selectorFilter.filter(nodes, __dependencies$.filterOptions, __dependencies$.apiInfo);
};
})();`);
}
return null;
}
_createInvalidFnTypeError() {
return new runtime_1.ClientFunctionAPIError(this.callsiteNames.instantiation, this.callsiteNames.instantiation, types_1.RUNTIME_ERRORS.selectorInitializedWithWrongType, typeof this.fn);
}
_executeCommand(args, testRun, callsite) {
const resultPromise = super._executeCommand(args, testRun, callsite);
this._addBoundArgsSelectorGetter(resultPromise, args);
// OPTIMIZATION: use buffer function as selector not to trigger lazy property ahead of time
add_api_1.addAPI(resultPromise, () => resultPromise.selector, SelectorBuilder, this.options.customDOMProperties, this.options.customMethods);
return resultPromise;
}
_getSourceSelectorBuilderApiFnID() {
let selectorAncestor = this;
while (selectorAncestor.options.sourceSelectorBuilder)
selectorAncestor = selectorAncestor.options.sourceSelectorBuilder;
return selectorAncestor.options.apiFnID;
}
getFunctionDependencies() {
const dependencies = super.getFunctionDependencies();
const { filterVisible, filterHidden, counterMode, collectionMode, index, customDOMProperties, customMethods, apiFnChain, boundArgs } = this.options;
return lodash_1.merge({}, dependencies, {
filterOptions: {
filterVisible,
filterHidden,
counterMode,
collectionMode,
index: lodash_1.isNil(index) ? null : index
},
apiInfo: {
apiFnChain,
apiFnID: this._getSourceSelectorBuilderApiFnID()
},
boundArgs,
customDOMProperties,
customMethods
});
}
_createTestRunCommand(encodedArgs, encodedDependencies) {
return new observation_1.ExecuteSelectorCommand({
instantiationCallsiteName: this.callsiteNames.instantiation,
fnCode: this.compiledFnCode,
args: encodedArgs,
dependencies: encodedDependencies,
needError: this.options.needError,
apiFnChain: this.options.apiFnChain,
visibilityCheck: !!this.options.visibilityCheck,
timeout: this.options.timeout
});
}
_validateOptions(options) {
super._validateOptions(options);
if (!lodash_1.isNil(options.visibilityCheck))
type_assertions_1.assertType(type_assertions_1.is.boolean, this.callsiteNames.instantiation, '"visibilityCheck" option', options.visibilityCheck);
if (!lodash_1.isNil(options.timeout))
type_assertions_1.assertType(type_assertions_1.is.nonNegativeNumber, this.callsiteNames.instantiation, '"timeout" option', options.timeout);
}
_getReplicatorTransforms() {
const transforms = super._getReplicatorTransforms();
transforms.push(new replicator_1.SelectorNodeTransform());
return transforms;
}
_addBoundArgsSelectorGetter(obj, selectorArgs) {
define_lazy_property_1.default(obj, 'selector', () => {
const builder = new SelectorBuilder(this.getFunction(), { boundArgs: selectorArgs });
return builder.getFunction();
});
}
_decorateFunction(selectorFn) {
super._decorateFunction(selectorFn);
add_api_1.addAPI(selectorFn, () => selectorFn, SelectorBuilder, this.options.customDOMProperties, this.options.customMethods);
}
_getClientFnWithOverriddenOptions(options) {
const apiFn = prepare_api_args_1.default('with', options);
const previousSelectorID = this.options.apiFnChain.length - 1;
return super._getClientFnWithOverriddenOptions(Object.assign(options, { apiFn, apiFnID: previousSelectorID }));
}
_processResult(result, selectorArgs) {
const snapshot = super._processResult(result, selectorArgs);
if (snapshot && !this.options.counterMode) {
this._addBoundArgsSelectorGetter(snapshot, selectorArgs);
create_snapshot_methods_1.default(snapshot);
if (this.options.customMethods)
add_api_1.addCustomMethods(snapshot, () => snapshot.selector, SelectorBuilder, this.options.customMethods);
}
return snapshot;
}
}
exports.default = SelectorBuilder;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0b3ItYnVpbGRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jbGllbnQtZnVuY3Rpb25zL3NlbGVjdG9ycy9zZWxlY3Rvci1idWlsZGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsbUNBQTJEO0FBQzNELG9EQUE0QjtBQUM1Qix5RkFBK0Q7QUFDL0QsOENBQXNEO0FBQ3RELGtEQUE4RDtBQUM5RCx1RUFBc0Q7QUFDdEQsOENBQW9EO0FBQ3BELDBFQUFzRTtBQUN0RSxxRUFBNkU7QUFDN0UsNEZBQWtFO0FBQ2xFLHVDQUFxRDtBQUNyRCx3RkFBOEQ7QUFDOUQsMEVBQWtEO0FBRWxELE1BQXFCLGVBQWdCLFNBQVEsaUNBQXFCO0lBQzlELFlBQWEsRUFBRSxFQUFFLE9BQU8sRUFBRSxhQUFhO1FBQ25DLE1BQU0sS0FBSyxHQUEwQixPQUFPLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQztRQUM5RCxNQUFNLE9BQU8sR0FBd0IsT0FBTyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUM7UUFDaEUsTUFBTSxtQkFBbUIsR0FBWSxFQUFFLElBQUksRUFBRSxDQUFDLHdCQUFxQixDQUFDLENBQUM7UUFDckUsTUFBTSw0QkFBNEIsR0FBRyxFQUFFLElBQUksRUFBRSxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUMsUUFBUSxDQUFDLHdCQUFxQixDQUFDLENBQUM7UUFDN0YsSUFBSSxPQUFPLEdBQTBCLG1CQUFtQixJQUFJLDRCQUE0QixDQUFDO1FBRXpGLE9BQU8sR0FBRyxPQUFPLFlBQVksZUFBZSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUU5RCxJQUFJLE9BQU8sRUFBRTtZQUNULEVBQUUsR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBRWhCLElBQUksT0FBTyxLQUFLLEtBQUssQ0FBQyxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVE7Z0JBQ2pELE9BQU8sR0FBRyxj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O1FBRUQsT0FBTyxRQUFRLENBQUM7SUFDcEIsQ0FBQztDQUNKO0FBbE1ELGtDQWtNQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlzTmlsIGFzIGlzTnVsbE9yVW5kZWZpbmVkLCBtZXJnZSB9IGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgZGVkZW50IGZyb20gJ2RlZGVudCc7XG5pbXBvcnQgQ2xpZW50RnVuY3Rpb25CdWlsZGVyIGZyb20gJy4uL2NsaWVudC1mdW5jdGlvbi1idWlsZGVyJztcbmltcG9ydCB7IFNlbGVjdG9yTm9kZVRyYW5zZm9ybSB9IGZyb20gJy4uL3JlcGxpY2F0b3InO1xuaW1wb3J0IHsgQ2xpZW50RnVuY3Rpb25BUElFcnJvciB9IGZyb20gJy4uLy4uL2Vycm9ycy9ydW50aW1lJztcbmltcG9ydCBmdW5jdGlvbkJ1aWxkZXJTeW1ib2wgZnJvbSAnLi4vYnVpbGRlci1zeW1ib2wnO1xuaW1wb3J0IHsgUlVOVElNRV9FUlJPUlMgfSBmcm9tICcuLi8uLi9lcnJvcnMvdHlwZXMnO1xuaW1wb3J0IHsgYXNzZXJ0VHlwZSwgaXMgfSBmcm9tICcuLi8uLi9lcnJvcnMvcnVudGltZS90eXBlLWFzc2VydGlvbnMnO1xuaW1wb3J0IHsgRXhlY3V0ZVNlbGVjdG9yQ29tbWFuZCB9IGZyb20gJy4uLy4uL3Rlc3QtcnVuL2NvbW1hbmRzL29ic2VydmF0aW9uJztcbmltcG9ydCBkZWZpbmVMYXp5UHJvcGVydHkgZnJvbSAnLi4vLi4vdXRpbHMvZGVmaW5lLWxhenktcHJvcGVydHknO1xuaW1wb3J0IHsgYWRkQVBJLCBhZGRDdXN0b21NZXRob2RzIH0gZnJvbSAnLi9hZGQtYXBpJztcbmltcG9ydCBjcmVhdGVTbmFwc2hvdE1ldGhvZHMgZnJvbSAnLi9jcmVhdGUtc25hcHNob3QtbWV0aG9kcyc7XG5pbXBvcnQgcHJlcGFyZUFwaUZuQXJncyBmcm9tICcuL3ByZXBhcmUtYXBpLWFyZ3MnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTZWxlY3RvckJ1aWxkZXIgZXh0ZW5kcyBDbGllbnRGdW5jdGlvbkJ1aWxkZXIge1xuICAgIGNvbnN0cnVjdG9yIChmbiwgb3B0aW9ucywgY2FsbHNpdGVOYW1lcykge1xuICAgICAgICBjb25zdCBhcGlGbiAgICAgICAgICAgICAgICAgICAgICAgID0gb3B0aW9ucyAmJiBvcHRpb25zLmFwaUZuO1xuICAgICAgICBjb25zdCBhcGlGbklEICAgICAgICAgICAgICAgICAgICAgID0gb3B0aW9ucyAmJiBvcHRpb25zLmFwaUZuSUQ7XG4gICAgICAgIGNvbnN0IGJ1aWxkZXJGcm9tU2VsZWN0b3IgICAgICAgICAgPSBmbiAmJiBmbltmdW5jdGlvbkJ1aWxkZXJTeW1ib2xdO1xuICAgICAgICBjb25zdCBidWlsZGVyRnJvbVByb21pc2VPclNuYXBzaG90ID0gZm4gJiYgZm4uc2VsZWN0b3IgJiYgZm4uc2VsZWN0b3JbZnVuY3Rpb25CdWlsZGVyU3ltYm9sXTtcbiAgICAgICAgbGV0IGJ1aWxkZXIgICAgICAgICAgICAgICAgICAgICAgICA9IGJ1aWxkZXJGcm9tU2VsZWN0b3IgfHwgYnVpbGRlckZyb21Qcm9taXNlT3JTbmFwc2hvdDtcblxuICAgICAgICBidWlsZGVyID0gYnVpbGRlciBpbnN0YW5jZW9mIFNlbGVjdG9yQnVpbGRlciA/IGJ1aWxkZXIgOiBudWxsO1xuXG4gICAgICAgIGlmIChidWlsZGVyKSB7XG4gICAgICAgICAgICBmbiA9IGJ1aWxkZXIuZm47XG5cbiAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkIDAgfHwgdHlwZW9mIG9wdGlvbnMgPT09ICdvYmplY3QnKVxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBtZXJnZSh7fSwgYnVpbGRlci5vcHRpb25zLCBvcHRpb25zLCB7IHNvdXJjZVNlbGVjdG9yQnVpbGRlcjogYnVpbGRlciB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN1cGVyKGZuLCBvcHRpb25zLCBjYWxsc2l0ZU5hbWVzKTtcblxuICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5hcGlGbkNoYWluKSB7XG4gICAgICAgICAgICBjb25zdCBmblR5cGUgPSB0eXBlb2YgdGhpcy5mbjtcbiAgICAgICAgICAgIGxldCBpdGVtICAgICA9IGZuVHlwZSA9PT0gJ3N0cmluZycgPyBgJyR7dGhpcy5mbn0nYCA6IGBbJHtmblR5cGV9XWA7XG5cbiAgICAgICAgICAgIGl0ZW0gICAgICAgICAgICAgICAgICAgID0gYFNlbGVjdG9yKCR7aXRlbX0pYDtcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucy5hcGlGbiAgICAgID0gaXRlbTtcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucy5hcGlGbkNoYWluID0gW2l0ZW1dO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFwaUZuKVxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLmFwaUZuQ2hhaW4ucHVzaChhcGlGbik7XG5cbiAgICAgICAgdGhpcy5vcHRpb25zLmFwaUZuSUQgPSB0eXBlb2YgYXBpRm5JRCA9PT0gJ251bWJlcicgPyBhcGlGbklEIDogdGhpcy5vcHRpb25zLmFwaUZuQ2hhaW4ubGVuZ3RoIC0gMTtcbiAgICB9XG5cbiAgICBfZ2V0Q29tcGlsZWRGbkNvZGUgKCkge1xuICAgICAgICAvLyBPUFRJTUlaQVRJT046IGlmIHNlbGVjdG9yIHdhcyBwcm9kdWNlZCBmcm9tIGFub3RoZXIgc2VsZWN0b3IgYW5kXG4gICAgICAgIC8vIGl0IGhhcyBzYW1lIGRlcGVuZGVuY2llcyBhcyBzb3VyY2Ugc2VsZWN0b3IsIHRoZW4gd2UgY2FuXG4gICAgICAgIC8vIGF2b2lkIHJlY29tcGlsYXRpb24gYW5kIGp1c3QgcmUtdXNlIGFscmVhZHkgY29tcGlsZWQgY29kZS5cbiAgICAgICAgY29uc3QgaGFzU2FtZURlcGVuZGVuY2llc0FzU291cmNlU2VsZWN0b3IgPSB0aGlzLm9wdGlvbnMuc291cmNlU2VsZWN0b3JCdWlsZGVyICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLnNvdXJjZVNlbGVjdG9yQnVpbGRlci5vcHRpb25zLmRlcGVuZGVuY2llcyA9PT1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMuZGVwZW5kZW5jaWVzO1xuXG4gICAgICAgIGlmIChoYXNTYW1lRGVwZW5kZW5jaWVzQXNTb3VyY2VTZWxlY3RvcilcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9wdGlvbnMuc291cmNlU2VsZWN0b3JCdWlsZGVyLmNvbXBpbGVkRm5Db2RlO1xuXG4gICAgICAgIGNvbnN0IGNvZGUgPSB0eXBlb2YgdGhpcy5mbiA9PT0gJ3N0cmluZycgP1xuICAgICAgICAgICAgYChmdW5jdGlvbigpe3JldHVybiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCR7SlNPTi5zdHJpbmdpZnkodGhpcy5mbil9KTt9KTtgIDpcbiAgICAgICAgICAgIHN1cGVyLl9nZXRDb21waWxlZEZuQ29kZSgpO1xuXG4gICAgICAgIGlmIChjb2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gZGVkZW50KFxuICAgICAgICAgICAgICAgIGAoZnVuY3Rpb24oKXtcbiAgICAgICAgICAgICAgICAgICAgdmFyIF9fZiQ9JHtjb2RlfTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXJncyAgICAgICAgICAgPSBfX2RlcGVuZGVuY2llcyQuYm91bmRBcmdzIHx8IGFyZ3VtZW50cztcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzZWxlY3RvckZpbHRlciA9IHdpbmRvd1snJXRlc3RDYWZlU2VsZWN0b3JGaWx0ZXIlJ107XG4gICAgICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IF9fZiQuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlcyAgICAgPSBzZWxlY3RvckZpbHRlci5jYXN0KG5vZGVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFub2Rlcy5sZW5ndGggJiYgIXNlbGVjdG9yRmlsdGVyLmVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdG9yRmlsdGVyLmVycm9yID0gX19kZXBlbmRlbmNpZXMkLmFwaUluZm8uYXBpRm5JRDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNlbGVjdG9yRmlsdGVyLmZpbHRlcihub2RlcywgX19kZXBlbmRlbmNpZXMkLmZpbHRlck9wdGlvbnMsIF9fZGVwZW5kZW5jaWVzJC5hcGlJbmZvKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgfSkoKTtgXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgX2NyZWF0ZUludmFsaWRGblR5cGVFcnJvciAoKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ2xpZW50RnVuY3Rpb25BUElFcnJvcih0aGlzLmNhbGxzaXRlTmFtZXMuaW5zdGFudGlhdGlvbiwgdGhpcy5jYWxsc2l0ZU5hbWVzLmluc3RhbnRpYXRpb24sIFJVTlRJTUVfRVJST1JTLnNlbGVjdG9ySW5pdGlhbGl6ZWRXaXRoV3JvbmdUeXBlLCB0eXBlb2YgdGhpcy5mbik7XG4gICAgfVxuXG4gICAgX2V4ZWN1dGVDb21tYW5kIChhcmdzLCB0ZXN0UnVuLCBjYWxsc2l0ZSkge1xuICAgICAgICBjb25zdCByZXN1bHRQcm9taXNlID0gc3VwZXIuX2V4ZWN1dGVDb21tYW5kKGFyZ3MsIHRlc3RSdW4sIGNhbGxzaXRlKTtcblxuICAgICAgICB0aGlzLl9hZGRCb3VuZEFyZ3NTZWxlY3RvckdldHRlcihyZXN1bHRQcm9taXNlLCBhcmdzKTtcblxuICAgICAgICAvLyBPUFRJTUlaQVRJT046IHVzZSBidWZmZXIgZnVuY3Rpb24gYXMgc2VsZWN0b3Igbm90IHRvIHRyaWdnZXIgbGF6eSBwcm9wZXJ0eSBhaGVhZCBvZiB0aW1lXG4gICAgICAgIGFkZEFQSShyZXN1bHRQcm9taXNlLCAoKSA9PiByZXN1bHRQcm9taXNlLnNlbGVjdG9yLCBTZWxlY3RvckJ1aWxkZXIsIHRoaXMub3B0aW9ucy5jdXN0b21ET01Qcm9wZXJ0aWVzLCB0aGlzLm9wdGlvbnMuY3VzdG9tTWV0aG9kcyk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdFByb21pc2U7XG4gICAgfVxuXG4gICAgX2dldFNvdXJjZVNlbGVjdG9yQnVpbGRlckFwaUZuSUQgKCkge1xuICAgICAgICBsZXQgc2VsZWN0b3JBbmNlc3RvciA9IHRoaXM7XG5cbiAgICAgICAgd2hpbGUgKHNlbGVjdG9yQW5jZXN0b3Iub3B0aW9ucy5zb3VyY2VTZWxlY3RvckJ1aWxkZXIpXG4gICAgICAgICAgICBzZWxlY3RvckFuY2VzdG9yID0gc2VsZWN0b3JBbmNlc3Rvci5vcHRpb25zLnNvdXJjZVNlbGVjdG9yQnVpbGRlcjtcblxuICAgICAgICByZXR1cm4gc2VsZWN0b3JBbmNlc3Rvci5vcHRpb25zLmFwaUZuSUQ7XG4gICAgfVxuXG4gICAgZ2V0RnVuY3Rpb25EZXBlbmRlbmNpZXMgKCkge1xuICAgICAgICBjb25zdCBkZXBlbmRlbmNpZXMgPSBzdXBlci5nZXRGdW5jdGlvbkRlcGVuZGVuY2llcygpO1xuXG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgIGZpbHRlclZpc2libGUsXG4gICAgICAgICAgICBmaWx0ZXJIaWRkZW4sXG4gICAgICAgICAgICBjb3VudGVyTW9kZSxcbiAgICAgICAgICAgIGNvbGxlY3Rpb25Nb2RlLFxuICAgICAgICAgICAgaW5kZXgsXG4gICAgICAgICAgICBjdXN0b21ET01Qcm9wZXJ0aWVzLFxuICAgICAgICAgICAgY3VzdG9tTWV0aG9kcyxcbiAgICAgICAgICAgIGFwaUZuQ2hhaW4sXG4gICAgICAgICAgICBib3VuZEFyZ3NcbiAgICAgICAgfSA9IHRoaXMub3B0aW9ucztcblxuICAgICAgICByZXR1cm4gbWVyZ2Uoe30sIGRlcGVuZGVuY2llcywge1xuICAgICAgICAgICAgZmlsdGVyT3B0aW9uczoge1xuICAgICAgICAgICAgICAgIGZpbHRlclZpc2libGUsXG4gICAgICAgICAgICAgICAgZmlsdGVySGlkZGVuLFxuICAgICAgICAgICAgICAgIGNvdW50ZXJNb2RlLFxuICAgICAgICAgICAgICAgIGNvbGxlY3Rpb25Nb2RlLFxuICAgICAgICAgICAgICAgIGluZGV4OiBpc051bGxPclVuZGVmaW5lZChpbmRleCkgPyBudWxsIDogaW5kZXhcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhcGlJbmZvOiB7XG4gICAgICAgICAgICAgICAgYXBpRm5DaGFpbixcbiAgICAgICAgICAgICAgICBhcGlGbklEOiB0aGlzLl9nZXRTb3VyY2VTZWxlY3RvckJ1aWxkZXJBcGlGbklEKClcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBib3VuZEFyZ3MsXG4gICAgICAgICAgICBjdXN0b21ET01Qcm9wZXJ0aWVzLFxuICAgICAgICAgICAgY3VzdG9tTWV0aG9kc1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBfY3JlYXRlVGVzdFJ1bkNvbW1hbmQgKGVuY29kZWRBcmdzLCBlbmNvZGVkRGVwZW5kZW5jaWVzKSB7XG4gICAgICAgIHJldHVybiBuZXcgRXhlY3V0ZVNlbGVjdG9yQ29tbWFuZCh7XG4gICAgICAgICAgICBpbnN0YW50aWF0aW9uQ2FsbHNpdGVOYW1lOiB0aGlzLmNhbGxzaXRlTmFtZXMuaW5zdGFudGlhdGlvbixcbiAgICAgICAgICAgIGZuQ29kZTogICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcGlsZWRGbkNvZGUsXG4gICAgICAgICAgICBhcmdzOiAgICAgICAgICAgICAgICAgICAgICBlbmNvZGVkQXJncyxcbiAgICAgICAgICAgIGRlcGVuZGVuY2llczogICAgICAgICAgICAgIGVuY29kZWREZXBlbmRlbmNpZXMsXG4gICAgICAgICAgICBuZWVkRXJyb3I6ICAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMubmVlZEVycm9yLFxuICAgICAgICAgICAgYXBpRm5DaGFpbjogICAgICAgICAgICAgICAgdGhpcy5vcHRpb25zLmFwaUZuQ2hhaW4sXG4gICAgICAgICAgICB2aXNpYmlsaXR5Q2hlY2s6ICAgICAgICAgICAhIXRoaXMub3B0aW9ucy52aXNpYmlsaXR5Q2hlY2ssXG4gICAgICAgICAgICB0aW1lb3V0OiAgICAgICAgICAgICAgICAgICB0aGlzLm9wdGlvbnMudGltZW91dFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBfdmFsaWRhdGVPcHRpb25zIChvcHRpb25zKSB7XG4gICAgICAgIHN1cGVyLl92YWxpZGF0ZU9wdGlvbnMob3B0aW9ucyk7XG5cbiAgICAgICAgaWYgKCFpc051bGxPclVuZGVmaW5lZChvcHRpb25zLnZpc2liaWxpdHlDaGVjaykpXG4gICAgICAgICAgICBhc3NlcnRUeXBlKGlzLmJvb2xlYW4sIHRoaXMuY2FsbHNpdGVOYW1lcy5pbnN0YW50aWF0aW9uLCAnXCJ2aXNpYmlsaXR5Q2hlY2tcIiBvcHRpb24nLCBvcHRpb25zLnZpc2liaWxpdHlDaGVjayk7XG5cbiAgICAgICAgaWYgKCFpc051bGxPclVuZGVmaW5lZChvcHRpb25zLnRpbWVvdXQpKVxuICAgICAgICAgICAgYXNzZXJ0VHlwZShpcy5ub25OZWdhdGl2ZU51bWJlciwgdGhpcy5jYWxsc2l0ZU5hbWVzLmluc3RhbnRpYXRpb24sICdcInRpbWVvdXRcIiBvcHRpb24nLCBvcHRpb25zLnRpbWVvdXQpO1xuICAgIH1cblxuICAgIF9nZXRSZXBsaWNhdG9yVHJhbnNmb3JtcyAoKSB7XG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybXMgPSBzdXBlci5fZ2V0UmVwbGljYXRvclRyYW5zZm9ybXMoKTtcblxuICAgICAgICB0cmFuc2Zvcm1zLnB1c2gobmV3IFNlbGVjdG9yTm9kZVRyYW5zZm9ybSgpKTtcblxuICAgICAgICByZXR1cm4gdHJhbnNmb3JtcztcbiAgICB9XG5cbiAgICBfYWRkQm91bmRBcmdzU2VsZWN0b3JHZXR0ZXIgKG9iaiwgc2VsZWN0b3JBcmdzKSB7XG4gICAgICAgIGRlZmluZUxhenlQcm9wZXJ0eShvYmosICdzZWxlY3RvcicsICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgU2VsZWN0b3JCdWlsZGVyKHRoaXMuZ2V0RnVuY3Rpb24oKSwgeyBib3VuZEFyZ3M6IHNlbGVjdG9yQXJncyB9KTtcblxuICAgICAgICAgICAgcmV0dXJuIGJ1aWxkZXIuZ2V0RnVuY3Rpb24oKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgX2RlY29yYXRlRnVuY3Rpb24gKHNlbGVjdG9yRm4pIHtcbiAgICAgICAgc3VwZXIuX2RlY29yYXRlRnVuY3Rpb24oc2VsZWN0b3JGbik7XG5cbiAgICAgICAgYWRkQVBJKHNlbGVjdG9yRm4sICgpID0+IHNlbGVjdG9yRm4sIFNlbGVjdG9yQnVpbGRlciwgdGhpcy5vcHRpb25zLmN1c3RvbURPTVByb3BlcnRpZXMsIHRoaXMub3B0aW9ucy5jdXN0b21NZXRob2RzKTtcbiAgICB9XG5cbiAgICBfZ2V0Q2xpZW50Rm5XaXRoT3ZlcnJpZGRlbk9wdGlvbnMgKG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgYXBpRm4gICAgICAgICAgICAgID0gcHJlcGFyZUFwaUZuQXJncygnd2l0aCcsIG9wdGlvbnMpO1xuICAgICAgICBjb25zdCBwcmV2aW91c1NlbGVjdG9ySUQgPSB0aGlzLm9wdGlvbnMuYXBpRm5DaGFpbi5sZW5ndGggLSAxO1xuXG4gICAgICAgIHJldHVybiBzdXBlci5fZ2V0Q2xpZW50Rm5XaXRoT3ZlcnJpZGRlbk9wdGlvbnMoT2JqZWN0LmFzc2lnbihvcHRpb25zLCB7IGFwaUZuLCBhcGlGbklEOiBwcmV2aW91c1NlbGVjdG9ySUQgfSkpO1xuICAgIH1cblxuICAgIF9wcm9jZXNzUmVzdWx0IChyZXN1bHQsIHNlbGVjdG9yQXJncykge1xuICAgICAgICBjb25zdCBzbmFwc2hvdCA9IHN1cGVyLl9wcm9jZXNzUmVzdWx0KHJlc3VsdCwgc2VsZWN0b3JBcmdzKTtcblxuICAgICAgICBpZiAoc25hcHNob3QgJiYgIXRoaXMub3B0aW9ucy5jb3VudGVyTW9kZSkge1xuICAgICAgICAgICAgdGhpcy5fYWRkQm91bmRBcmdzU2VsZWN0b3JHZXR0ZXIoc25hcHNob3QsIHNlbGVjdG9yQXJncyk7XG4gICAgICAgICAgICBjcmVhdGVTbmFwc2hvdE1ldGhvZHMoc25hcHNob3QpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5vcHRpb25zLmN1c3RvbU1ldGhvZHMpXG4gICAgICAgICAgICAgICAgYWRkQ3VzdG9tTWV0aG9kcyhzbmFwc2hvdCwgKCkgPT4gc25hcHNob3Quc2VsZWN0b3IsIFNlbGVjdG9yQnVpbGRlciwgdGhpcy5vcHRpb25zLmN1c3RvbU1ldGhvZHMpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHNuYXBzaG90O1xuICAgIH1cbn1cblxuIl19