@browserstack/testcafe
Version:
Automated browser testing for the modern web development stack.
414 lines • 70.1 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable */
const path_1 = require("path");
const debug_1 = __importDefault(require("debug"));
const promisify_event_1 = __importDefault(require("promisify-event"));
const map_reverse_1 = __importDefault(require("map-reverse"));
const events_1 = require("events");
const lodash_1 = require("lodash");
const bootstrapper_1 = __importDefault(require("./bootstrapper"));
const reporter_1 = __importDefault(require("../reporter"));
const task_1 = __importDefault(require("./task"));
const debug_logger_1 = __importDefault(require("../notifications/debug-logger"));
const runtime_1 = require("../errors/runtime");
const types_1 = require("../errors/types");
const type_assertions_1 = require("../errors/runtime/type-assertions");
const utils_1 = require("../errors/test-run/utils");
const detect_ffmpeg_1 = __importDefault(require("../utils/detect-ffmpeg"));
const check_file_path_1 = __importDefault(require("../utils/check-file-path"));
const handle_errors_1 = require("../utils/handle-errors");
const option_names_1 = __importDefault(require("../configuration/option-names"));
const flag_list_1 = __importDefault(require("../utils/flag-list"));
const prepare_reporters_1 = __importDefault(require("../utils/prepare-reporters"));
const load_1 = __importDefault(require("../custom-client-scripts/load"));
const utils_2 = require("../custom-client-scripts/utils");
const string_1 = require("../utils/string");
const reporter_stream_controller_1 = __importDefault(require("./reporter-stream-controller"));
const DEBUG_LOGGER = debug_1.default('testcafe:runner');
class Runner extends events_1.EventEmitter {
constructor(proxy, browserConnectionGateway, configuration, compilerService) {
super();
this.proxy = proxy;
this.bootstrapper = this._createBootstrapper(browserConnectionGateway, compilerService);
this.pendingTaskPromises = [];
this.configuration = configuration;
this.isCli = false;
this.apiMethodWasCalled = new flag_list_1.default([
option_names_1.default.src,
option_names_1.default.browsers,
option_names_1.default.reporter,
option_names_1.default.clientScripts
]);
}
_createBootstrapper(browserConnectionGateway, compilerService) {
return new bootstrapper_1.default(browserConnectionGateway, compilerService);
}
_disposeBrowserSet(browserSet) {
return browserSet.dispose().catch(e => DEBUG_LOGGER(e));
}
_disposeReporters(reporters) {
return Promise.all(reporters.map(reporter => reporter.dispose().catch(e => DEBUG_LOGGER(e))));
}
_disposeTestedApp(testedApp) {
return testedApp ? testedApp.kill().catch(e => DEBUG_LOGGER(e)) : Promise.resolve();
}
async _disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp) {
task.abort();
task.unRegisterClientScriptRouting();
task.clearListeners();
await this._disposeAssets(browserSet, reporters, testedApp);
}
_disposeAssets(browserSet, reporters, testedApp) {
return Promise.all([
this._disposeBrowserSet(browserSet),
this._disposeReporters(reporters),
this._disposeTestedApp(testedApp)
]);
}
_prepareArrayParameter(array) {
array = lodash_1.flattenDeep(array);
if (this.isCli)
return array.length === 0 ? void 0 : array;
return array;
}
_createCancelablePromise(taskPromise) {
const promise = taskPromise.then(({ completionPromise }) => completionPromise);
const removeFromPending = () => lodash_1.pull(this.pendingTaskPromises, promise);
promise
.then(removeFromPending)
.catch(removeFromPending);
promise.cancel = () => taskPromise
.then(({ cancelTask }) => cancelTask())
.then(removeFromPending);
this.pendingTaskPromises.push(promise);
return promise;
}
// Run task
_getFailedTestCount(task, reporter) {
let failedTestCount = reporter.testCount - reporter.passed;
if (task.opts.stopOnFirstFail && !!failedTestCount)
failedTestCount = 1;
return failedTestCount;
}
async _getTaskResult(task, browserSet, reporters, testedApp) {
if (!task.opts.live) {
task.on('browser-job-done', job => {
job.browserConnections.forEach(bc => browserSet.releaseConnection(bc));
});
}
const browserSetErrorPromise = promisify_event_1.default(browserSet, 'error');
const streamController = new reporter_stream_controller_1.default(task, reporters);
const taskDonePromise = task.once('done')
.then(() => browserSetErrorPromise.cancel())
.then(() => {
return Promise.all(reporters.map(reporter => reporter.pendingTaskDonePromise));
});
const promises = [
taskDonePromise,
browserSetErrorPromise
];
if (testedApp)
promises.push(testedApp.errorPromise);
try {
await Promise.race(promises);
}
catch (err) {
await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp);
throw err;
}
await this._disposeAssets(browserSet, reporters, testedApp);
if (streamController.multipleStreamError)
throw streamController.multipleStreamError;
return this._getFailedTestCount(task, reporters[0]);
}
_createTask(tests, browserConnectionGroups, proxy, opts) {
return new task_1.default(tests, browserConnectionGroups, proxy, opts);
}
_runTask(reporterPlugins, browserSet, tests, testedApp) {
const task = this._createTask(tests, browserSet.browserConnectionGroups, this.proxy, this.configuration.getOptions());
const reporters = reporterPlugins.map(reporter => new reporter_1.default(reporter.plugin, task, reporter.outStream, reporter.name));
const completionPromise = this._getTaskResult(task, browserSet, reporters, testedApp);
let completed = false;
task.on('start', handle_errors_1.startHandlingTestErrors);
if (!this.configuration.getOption(option_names_1.default.skipUncaughtErrors)) {
task.on('test-run-start', handle_errors_1.addRunningTest);
task.on('test-run-done', handle_errors_1.removeRunningTest);
}
task.on('done', handle_errors_1.stopHandlingTestErrors);
const onTaskCompleted = () => {
task.unRegisterClientScriptRouting();
completed = true;
};
completionPromise
.then(onTaskCompleted)
.catch(onTaskCompleted);
const cancelTask = async () => {
if (!completed)
await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp);
};
return { completionPromise, cancelTask };
}
_registerAssets(assets) {
assets.forEach(asset => this.proxy.GET(asset.path, asset.info));
}
_validateDebugLogger() {
const debugLogger = this.configuration.getOption(option_names_1.default.debugLogger);
const debugLoggerDefinedCorrectly = debugLogger === null || !!debugLogger &&
['showBreakpoint', 'hideBreakpoint'].every(method => method in debugLogger && lodash_1.isFunction(debugLogger[method]));
if (!debugLoggerDefinedCorrectly) {
this.configuration.mergeOptions({
[option_names_1.default.debugLogger]: debug_logger_1.default
});
}
}
_validateSpeedOption() {
const speed = this.configuration.getOption(option_names_1.default.speed);
if (speed === void 0)
return;
if (typeof speed !== 'number' || isNaN(speed) || speed < 0.01 || speed > 1)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidSpeedValue);
}
_validateConcurrencyOption() {
const concurrency = this.configuration.getOption(option_names_1.default.concurrency);
if (concurrency === void 0)
return;
if (typeof concurrency !== 'number' || isNaN(concurrency) || concurrency < 1)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidConcurrencyFactor);
}
_validateProxyBypassOption() {
let proxyBypass = this.configuration.getOption(option_names_1.default.proxyBypass);
if (proxyBypass === void 0)
return;
type_assertions_1.assertType([type_assertions_1.is.string, type_assertions_1.is.array], null, '"proxyBypass" argument', proxyBypass);
if (typeof proxyBypass === 'string')
proxyBypass = [proxyBypass];
proxyBypass = proxyBypass.reduce((arr, rules) => {
type_assertions_1.assertType(type_assertions_1.is.string, null, '"proxyBypass" argument', rules);
return arr.concat(rules.split(','));
}, []);
this.configuration.mergeOptions({ proxyBypass });
}
_getScreenshotOptions() {
let { path, pathPattern } = this.configuration.getOption(option_names_1.default.screenshots) || {};
if (!path)
path = this.configuration.getOption(option_names_1.default.screenshotPath);
if (!pathPattern)
pathPattern = this.configuration.getOption(option_names_1.default.screenshotPathPattern);
return { path, pathPattern };
}
_validateScreenshotOptions() {
const { path, pathPattern } = this._getScreenshotOptions();
const disableScreenshots = this.configuration.getOption(option_names_1.default.disableScreenshots) || !path;
this.configuration.mergeOptions({ [option_names_1.default.disableScreenshots]: disableScreenshots });
if (disableScreenshots)
return;
if (path) {
this._validateScreenshotPath(path, 'screenshots base directory path');
this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { path: path_1.resolve(path) } });
}
if (pathPattern) {
this._validateScreenshotPath(pathPattern, 'screenshots path pattern');
this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { pathPattern } });
}
}
async _validateVideoOptions() {
const videoPath = this.configuration.getOption(option_names_1.default.videoPath);
const videoEncodingOptions = this.configuration.getOption(option_names_1.default.videoEncodingOptions);
let videoOptions = this.configuration.getOption(option_names_1.default.videoOptions);
if (!videoPath) {
if (videoOptions || videoEncodingOptions)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotSetVideoOptionsWithoutBaseVideoPathSpecified);
return;
}
this.configuration.mergeOptions({ [option_names_1.default.videoPath]: path_1.resolve(videoPath) });
if (!videoOptions) {
videoOptions = {};
this.configuration.mergeOptions({ [option_names_1.default.videoOptions]: videoOptions });
}
if (videoOptions.ffmpegPath)
videoOptions.ffmpegPath = path_1.resolve(videoOptions.ffmpegPath);
else
videoOptions.ffmpegPath = await detect_ffmpeg_1.default();
if (!videoOptions.ffmpegPath)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotFindFFMPEG);
}
async _validateRunOptions() {
this._validateDebugLogger();
this._validateScreenshotOptions();
await this._validateVideoOptions();
this._validateSpeedOption();
this._validateConcurrencyOption();
this._validateProxyBypassOption();
}
_validateTestForAllowMultipleWindowsOption(tests) {
if (tests.some(test => test.isLegacy))
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotUseAllowMultipleWindowsOptionForLegacyTests);
}
_validateBrowsersForAllowMultipleWindowsOption(browserSet) {
const browserConnections = browserSet.browserConnectionGroups.map(browserConnectionGroup => browserConnectionGroup[0]);
const unsupportedBrowserConnections = browserConnections.filter(browserConnection => !browserConnection.activeWindowId);
if (!unsupportedBrowserConnections.length)
return;
const unsupportedBrowserAliases = unsupportedBrowserConnections.map(browserConnection => browserConnection.browserInfo.alias);
const browserAliases = string_1.getConcatenatedValuesString(unsupportedBrowserAliases);
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotUseAllowMultipleWindowsOptionForSomeBrowsers, browserAliases);
}
_validateAllowMultipleWindowsOption(tests, browserSet) {
const allowMultipleWindows = this.configuration.getOption(option_names_1.default.allowMultipleWindows);
if (!allowMultipleWindows)
return;
this._validateTestForAllowMultipleWindowsOption(tests);
this._validateBrowsersForAllowMultipleWindowsOption(browserSet);
}
_createRunnableConfiguration() {
return this.bootstrapper
.createRunnableConfiguration()
.then(runnableConfiguration => {
this.emit('done-bootstrapping');
return runnableConfiguration;
});
}
_validateScreenshotPath(screenshotPath, pathType) {
const forbiddenCharsList = check_file_path_1.default(screenshotPath);
if (forbiddenCharsList.length)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.forbiddenCharatersInScreenshotPath, screenshotPath, pathType, utils_1.renderForbiddenCharsList(forbiddenCharsList));
}
_setBootstrapperOptions() {
this.configuration.prepare();
this.configuration.notifyAboutOverriddenOptions();
this.bootstrapper.sources = this.configuration.getOption(option_names_1.default.src) || this.bootstrapper.sources;
this.bootstrapper.browsers = this.configuration.getOption(option_names_1.default.browsers) || this.bootstrapper.browsers;
this.bootstrapper.concurrency = this.configuration.getOption(option_names_1.default.concurrency);
this.bootstrapper.appCommand = this.configuration.getOption(option_names_1.default.appCommand) || this.bootstrapper.appCommand;
this.bootstrapper.appInitDelay = this.configuration.getOption(option_names_1.default.appInitDelay);
this.bootstrapper.filter = this.configuration.getOption(option_names_1.default.filter) || this.bootstrapper.filter;
this.bootstrapper.reporters = this.configuration.getOption(option_names_1.default.reporter) || this.bootstrapper.reporters;
this.bootstrapper.tsConfigPath = this.configuration.getOption(option_names_1.default.tsConfigPath);
this.bootstrapper.clientScripts = this.configuration.getOption(option_names_1.default.clientScripts) || this.bootstrapper.clientScripts;
this.bootstrapper.allowMultipleWindows = this.configuration.getOption(option_names_1.default.allowMultipleWindows);
this.bootstrapper.testScheduling = (this.configuration.getOption(option_names_1.default.testScheduling) || 'false').toString().toLowerCase() === 'true';
}
enableTestScheduling(testScheduling) {
this.configuration.mergeOptions({ testScheduling });
return this;
}
// API
embeddingOptions(opts) {
const { assets, TestRunCtor } = opts;
this._registerAssets(assets);
this.configuration.mergeOptions({ TestRunCtor });
return this;
}
src(...sources) {
if (this.apiMethodWasCalled.src)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.src);
sources = this._prepareArrayParameter(sources);
this.configuration.mergeOptions({ [option_names_1.default.src]: sources });
this.apiMethodWasCalled.src = true;
return this;
}
browsers(...browsers) {
if (this.apiMethodWasCalled.browsers)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.browsers);
browsers = this._prepareArrayParameter(browsers);
this.configuration.mergeOptions({ browsers });
this.apiMethodWasCalled.browsers = true;
return this;
}
concurrency(concurrency) {
this.configuration.mergeOptions({ concurrency });
return this;
}
reporter(name, output) {
if (this.apiMethodWasCalled.reporter)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.reporter);
let reporters = prepare_reporters_1.default(name, output);
reporters = this._prepareArrayParameter(reporters);
this.configuration.mergeOptions({ [option_names_1.default.reporter]: reporters });
this.apiMethodWasCalled.reporter = true;
return this;
}
filter(filter) {
this.configuration.mergeOptions({ filter });
return this;
}
useProxy(proxy, proxyBypass) {
this.configuration.mergeOptions({ proxy, proxyBypass });
return this;
}
screenshots(...options) {
let fullPage;
let [path, takeOnFails, pathPattern] = options;
if (options.length === 1 && options[0] && typeof options[0] === 'object')
({ path, takeOnFails, pathPattern, fullPage } = options[0]);
this.configuration.mergeOptions({ screenshots: { path, takeOnFails, pathPattern, fullPage } });
return this;
}
video(path, options, encodingOptions) {
this.configuration.mergeOptions({
[option_names_1.default.videoPath]: path,
[option_names_1.default.videoOptions]: options,
[option_names_1.default.videoEncodingOptions]: encodingOptions
});
return this;
}
startApp(command, initDelay) {
this.configuration.mergeOptions({
[option_names_1.default.appCommand]: command,
[option_names_1.default.appInitDelay]: initDelay
});
return this;
}
tsConfigPath(path) {
this.configuration.mergeOptions({
[option_names_1.default.tsConfigPath]: path
});
return this;
}
clientScripts(...scripts) {
if (this.apiMethodWasCalled.clientScripts)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.clientScripts);
scripts = this._prepareArrayParameter(scripts);
this.configuration.mergeOptions({ [option_names_1.default.clientScripts]: scripts });
this.apiMethodWasCalled.clientScripts = true;
return this;
}
async _prepareClientScripts(tests, clientScripts) {
return Promise.all(tests.map(async (test) => {
if (test.isLegacy)
return;
let loadedTestClientScripts = await load_1.default(test.clientScripts, path_1.dirname(test.testFile.filename));
loadedTestClientScripts = clientScripts.concat(loadedTestClientScripts);
test.clientScripts = utils_2.setUniqueUrls(loadedTestClientScripts);
}));
}
run(options = {}) {
this.apiMethodWasCalled.reset();
this.configuration.mergeOptions(options);
this._setBootstrapperOptions();
const runTaskPromise = Promise.resolve()
.then(() => this._validateRunOptions())
.then(() => this._createRunnableConfiguration())
.then(async ({ reporterPlugins, browserSet, tests, testedApp, commonClientScripts }) => {
await this._prepareClientScripts(tests, commonClientScripts);
this._validateAllowMultipleWindowsOption(tests, browserSet);
return this._runTask(reporterPlugins, browserSet, tests, testedApp);
});
return this._createCancelablePromise(runTaskPromise);
}
async stop() {
// NOTE: When taskPromise is cancelled, it is removed from
// the pendingTaskPromises array, which leads to shifting indexes
// towards the beginning. So, we must copy the array in order to iterate it,
// or we can perform iteration from the end to the beginning.
const cancellationPromises = map_reverse_1.default(this.pendingTaskPromises, taskPromise => taskPromise.cancel());
await Promise.all(cancellationPromises);
}
}
exports.default = Runner;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVubmVyL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsb0JBQW9CO0FBQ3BCLCtCQUF1RDtBQUN2RCxrREFBMEI7QUFDMUIsc0VBQTZDO0FBQzdDLDhEQUFxQztBQUNyQyxtQ0FBc0M7QUFDdEMsbUNBQTRFO0FBQzVFLGtFQUEwQztBQUMxQywyREFBbUM7QUFDbkMsa0RBQTBCO0FBQzFCLGlGQUErRDtBQUMvRCwrQ0FBaUQ7QUFDakQsMkNBQWlEO0FBQ2pELHVFQUFtRTtBQUNuRSxvREFBb0U7QUFDcEUsMkVBQWtEO0FBQ2xELCtFQUFxRDtBQUNyRCwwREFBNEg7QUFDNUgsaUZBQXlEO0FBQ3pELG1FQUEwQztBQUMxQyxtRkFBMEQ7QUFDMUQseUVBQThEO0FBQzlELDBEQUErRDtBQUMvRCw0Q0FBOEQ7QUFDOUQsOEZBQW9FO0FBRXBFLE1BQU0sWUFBWSxHQUFHLGVBQUssQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBRTlDLE1BQXFCLE1BQU8sU0FBUSxxQkFBWTtJQUM1QyxZQUFhLEtBQUssRUFBRSx3QkFBd0IsRUFBRSxhQUFhLEVBQUUsZUFBZTtRQUN4RSxLQUFLLEVBQUUsQ0FBQztRQUVSLElBQUksQ0FBQyxLQUFLLEdBQWlCLEtBQUssQ0FBQztRQUNqQyxJQUFJLENBQUMsWUFBWSxHQUFVLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyx3QkFBd0IsRUFBRSxlQUFlLENBQUMsQ0FBQztRQUMvRixJQUFJLENBQUMsbUJBQW1CLEdBQUcsRUFBRSxDQUFDO1FBQzlCLElBQUksQ0FBQyxhQUFhLEdBQVMsYUFBYSxDQUFDO1FBQ3pDLElBQUksQ0FBQyxLQUFLLEdBQWlCLEtBQUssQ0FBQztRQUVqQyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxtQkFBUSxDQUFDO1lBQ25DLHNCQUFZLENBQUMsR0FBRztZQUNoQixzQkFBWSxDQUFDLFFBQVE7WUFDckIs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Q0FBQyxDQUFDO1FBQ3hFLENBQUMsQ0FBQyxDQUFDO1FBRVAsT0FBTyxJQUFJLENBQUMsd0JBQXdCLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJO1FBQ04sMERBQTBEO1FBQzFELGlFQUFpRTtRQUNqRSw0RUFBNEU7UUFDNUUsNkRBQTZEO1FBQzdELE1BQU0sb0JBQW9CLEdBQUcscUJBQVUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUV2RyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsQ0FBQztJQUM1QyxDQUFDO0NBQ0o7QUE1Z0JELHlCQTRnQkMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSAqL1xuaW1wb3J0IHsgcmVzb2x2ZSBhcyByZXNvbHZlUGF0aCwgZGlybmFtZSB9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IGRlYnVnIGZyb20gJ2RlYnVnJztcbmltcG9ydCBwcm9taXNpZnlFdmVudCBmcm9tICdwcm9taXNpZnktZXZlbnQnO1xuaW1wb3J0IG1hcFJldmVyc2UgZnJvbSAnbWFwLXJldmVyc2UnO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnZXZlbnRzJztcbmltcG9ydCB7IGZsYXR0ZW5EZWVwIGFzIGZsYXR0ZW4sIHB1bGwgYXMgcmVtb3ZlLCBpc0Z1bmN0aW9uIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBCb290c3RyYXBwZXIgZnJvbSAnLi9ib290c3RyYXBwZXInO1xuaW1wb3J0IFJlcG9ydGVyIGZyb20gJy4uL3JlcG9ydGVyJztcbmltcG9ydCBUYXNrIGZyb20gJy4vdGFzayc7XG5pbXBvcnQgZGVmYXVsdERlYnVnTG9nZ2VyIGZyb20gJy4uL25vdGlmaWNhdGlvbnMvZGVidWctbG9nZ2VyJztcbmltcG9ydCB7IEdlbmVyYWxFcnJvciB9IGZyb20gJy4uL2Vycm9ycy9ydW50aW1lJztcbmltcG9ydCB7IFJVTlRJTUVfRVJST1JTIH0gZnJvbSAnLi4vZXJyb3JzL3R5cGVzJztcbmltcG9ydCB7IGFzc2VydFR5cGUsIGlzIH0gZnJvbSAnLi4vZXJyb3JzL3J1bnRpbWUvdHlwZS1hc3NlcnRpb25zJztcbmltcG9ydCB7IHJlbmRlckZvcmJpZGRlbkNoYXJzTGlzdCB9IGZyb20gJy4uL2Vycm9ycy90ZXN0LXJ1bi91dGlscyc7XG5pbXBvcnQgZGV0ZWN0RkZNUEVHIGZyb20gJy4uL3V0aWxzL2RldGVjdC1mZm1wZWcnO1xuaW1wb3J0IGNoZWNrRmlsZVBhdGggZnJvbSAnLi4vdXRpbHMvY2hlY2stZmlsZS1wYXRoJztcbmltcG9ydCB7IGFkZFJ1bm5pbmdUZXN0LCByZW1vdmVSdW5uaW5nVGVzdCwgc3RhcnRIYW5kbGluZ1Rlc3RFcnJvcnMsIHN0b3BIYW5kbGluZ1Rlc3RFcnJvcnMgfSBmcm9tICcuLi91dGlscy9oYW5kbGUtZXJyb3JzJztcbmltcG9ydCBPUFRJT05fTkFNRVMgZnJvbSAnLi4vY29uZmlndXJhdGlvbi9vcHRpb24tbmFtZXMnO1xuaW1wb3J0IEZsYWdMaXN0IGZyb20gJy4uL3V0aWxzL2ZsYWctbGlzdCc7XG5pbXBvcnQgcHJlcGFyZVJlcG9ydGVycyBmcm9tICcuLi91dGlscy9wcmVwYXJlLXJlcG9ydGVycyc7XG5pbXBvcnQgbG9hZENsaWVudFNjcmlwdHMgZnJvbSAnLi4vY3VzdG9tLWNsaWVudC1zY3JpcHRzL2xvYWQnO1xuaW1wb3J0IHsgc2V0VW5pcXVlVXJscyB9IGZyb20gJy4uL2N1c3RvbS1jbGllbnQtc2NyaXB0cy91dGlscyc7XG5pbXBvcnQgeyBnZXRDb25jYXRlbmF0ZWRWYWx1ZXNTdHJpbmcgfSBmcm9tICcuLi91dGlscy9zdHJpbmcnO1xuaW1wb3J0IFJlcG9ydGVyU3RyZWFtQ29udHJvbGxlciBmcm9tICcuL3JlcG9ydGVyLXN0cmVhbS1jb250cm9sbGVyJztcblxuY29uc3QgREVCVUdfTE9HR0VSID0gZGVidWcoJ3Rlc3RjYWZlOnJ1bm5lcicpO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSdW5uZXIgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuICAgIGNvbnN0cnVjdG9yIChwcm94eSwgYnJvd3NlckNvbm5lY3Rpb25HYXRld2F5LCBjb25maWd1cmF0aW9uLCBjb21waWxlclNlcnZpY2UpIHtcbiAgICAgICAgc3VwZXIoKTtcblxuICAgICAgICB0aGlzLnByb3h5ICAgICAgICAgICAgICAgPSBwcm94eTtcbiAgICAgICAgdGhpcy5ib290c3RyYXBwZXIgICAgICAgID0gdGhpcy5fY3JlYXRlQm9vdHN0cmFwcGVyKGJyb3dzZXJDb25uZWN0aW9uR2F0ZXdheSwgY29tcGlsZXJTZXJ2aWNlKTtcbiAgICAgICAgdGhpcy5wZW5kaW5nVGFza1Byb21pc2VzID0gW107XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbiAgICAgICA9IGNvbmZpZ3VyYXRpb247XG4gICAgICAgIHRoaXMuaXNDbGkgICAgICAgICAgICAgICA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMuYXBpTWV0aG9kV2FzQ2FsbGVkID0gbmV3IEZsYWdMaXN0KFtcbiAgICAgICAgICAgIE9QVElPTl9OQU1FUy5zcmMsXG4gICAgICAgICAgICBPUFRJT05fTkFNRVMuYnJvd3NlcnMsXG4gICAgICAgICAgICBPUFRJT05fTkFNRVMucmVwb3J0ZXIsXG4gICAgICAgICAgICBPUFRJT05fTkFNRVMuY2xpZW50U2NyaXB0c1xuICAgICAgICBdKTtcbiAgICB9XG5cbiAgICBfY3JlYXRlQm9vdHN0cmFwcGVyIChicm93c2VyQ29ubmVjdGlvbkdhdGV3YXksIGNvbXBpbGVyU2VydmljZSkge1xuICAgICAgICByZXR1cm4gbmV3IEJvb3RzdHJhcHBlcihicm93c2VyQ29ubmVjdGlvbkdhdGV3YXksIGNvbXBpbGVyU2VydmljZSk7XG4gICAgfVxuXG4gICAgX2Rpc3Bvc2VCcm93c2VyU2V0IChicm93c2VyU2V0KSB7XG4gICAgICAgIHJldHVybiBicm93c2VyU2V0LmRpc3Bvc2UoKS5jYXRjaChlID0+IERFQlVHX0xPR0dFUihlKSk7XG4gICAgfVxuXG4gICAgX2Rpc3Bvc2VSZXBvcnRlcnMgKHJlcG9ydGVycykge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocmVwb3J0ZXJzLm1hcChyZXBvcnRlciA9PiByZXBvcnRlci5kaXNwb3NlKCkuY2F0Y2goZSA9PiBERUJVR19MT0dHRVIoZSkpKSk7XG4gICAgfVxuXG4gICAgX2Rpc3Bvc2VUZXN0ZWRBcHAgKHRlc3RlZEFwcCkge1xuICAgICAgICByZXR1cm4gdGVzdGVkQXBwID8gdGVzdGVkQXBwLmtpbGwoKS5jYXRjaChlID0+IERFQlVHX0xPR0dFUihlKSkgOiBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBhc3luYyBfZGlzcG9zZVRhc2tBbmRSZWxhdGVkQXNzZXRzICh0YXNrLCBicm93c2VyU2V0LCByZXBvcnRlcnMsIHRlc3RlZEFwcCkge1xuICAgICAgICB0YXNrLmFib3J0KCk7XG4gICAgICAgIHRhc2sudW5SZWdpc3RlckNsaWVudFNjcmlwdFJvdXRpbmcoKTtcbiAgICAgICAgdGFzay5jbGVhckxpc3RlbmVycygpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuX2Rpc3Bvc2VBc3NldHMoYnJvd3NlclNldCwgcmVwb3J0ZXJzLCB0ZXN0ZWRBcHApO1xuICAgIH1cblxuICAgIF9kaXNwb3NlQXNzZXRzIChicm93c2VyU2V0LCByZXBvcnRlcnMsIHRlc3RlZEFwcCkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoW1xuICAgICAgICAgICAgdGhpcy5fZGlzcG9zZUJyb3dzZXJTZXQoYnJvd3NlclNldCksXG4gICAgICAgICAgICB0aGlzLl9kaXNwb3NlUmVwb3J0ZXJzKHJlcG9ydGVycyksXG4gICAgICAgICAgICB0aGlzLl9kaXNwb3NlVGVzdGVkQXBwKHRlc3RlZEFwcClcbiAgICAgICAgXSk7XG4gICAgfVxuXG4gICAgX3ByZXBhcmVBcnJheVBhcmFtZXRlciAoYXJyYXkpIHtcbiAgICAgICAgYXJyYXkgPSBmbGF0dGVuKGFycmF5KTtcblxuICAgICAgICBpZiAodGhpcy5pc0NsaSlcbiAgICAgICAgICAgIHJldHVybiBhcnJheS5sZW5ndGggPT09IDAgPyB2b2lkIDAgOiBhcnJheTtcblxuICAgICAgICByZXR1cm4gYXJyYXk7XG4gICAgfVxuXG4gICAgX2NyZWF0ZUNhbmNlbGFibGVQcm9taXNlICh0YXNrUHJvbWlzZSkge1xuICAgICAgICBjb25zdCBwcm9taXNlICAgICAgICAgICA9IHRhc2tQcm9taXNlLnRoZW4oKHsgY29tcGxldGlvblByb21pc2UgfSkgPT4gY29tcGxldGlvblByb21pc2UpO1xuICAgICAgICBjb25zdCByZW1vdmVGcm9tUGVuZGluZyA9ICgpID0+IHJlbW92ZSh0aGlzLnBlbmRpbmdUYXNrUHJvbWlzZXMsIHByb21pc2UpO1xuXG4gICAgICAgIHByb21pc2VcbiAgICAgICAgICAgIC50aGVuKHJlbW92ZUZyb21QZW5kaW5nKVxuICAgICAgICAgICAgLmNhdGNoKHJlbW92ZUZyb21QZW5kaW5nKTtcblxuICAgICAgICBwcm9taXNlLmNhbmNlbCA9ICgpID0+IHRhc2tQcm9taXNlXG4gICAgICAgICAgICAudGhlbigoeyBjYW5jZWxUYXNrIH0pID0+IGNhbmNlbFRhc2soKSlcbiAgICAgICAgICAgIC50aGVuKHJlbW92ZUZyb21QZW5kaW5nKTtcblxuICAgICAgICB0aGlzLnBlbmRpbmdUYXNrUHJvbWlzZXMucHVzaChwcm9taXNlKTtcblxuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9XG5cbiAgICAvLyBSdW4gdGFza1xuICAgIF9nZXRGYWlsZWRUZXN0Q291bnQgKHRhc2ssIHJlcG9ydGVyKSB7XG4gICAgICAgIGxldCBmYWlsZWRUZXN0Q291bnQgPSByZXBvcnRlci50ZXN0Q291bnQgLSByZXBvcnRlci5wYXNzZWQ7XG5cbiAgICAgICAgaWYgKHRhc2sub3B0cy5zdG9wT25GaXJzdEZhaWwgJiYgISFmYWlsZWRUZXN0Q291bnQpXG4gICAgICAgICAgICBmYWlsZWRUZXN0Q291bnQgPSAxO1xuXG4gICAgICAgIHJldHVybiBmYWlsZWRUZXN0Q291bnQ7XG4gICAgfVxuXG4gICAgYXN5bmMgX2dldFRhc2tSZXN1bHQgKHRhc2ssIGJyb3dzZXJTZXQsIHJlcG9ydGVycywgdGVzdGVkQXBwKSB7XG4gICAgICAgIGlmICghdGFzay5vcHRzLmxpdmUpIHtcbiAgICAgICAgICAgIHRhc2sub24oJ2Jyb3dzZXItam9iLWRvbmUnLCBqb2IgPT4ge1xuICAgICAgICAgICAgICAgIGpvYi5icm93c2VyQ29ubmVjdGlvbnMuZm9yRWFjaChiYyA9PiBicm93c2VyU2V0LnJlbGVhc2VDb25uZWN0aW9uKGJjKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGJyb3dzZXJTZXRFcnJvclByb21pc2UgPSBwcm9taXNpZnlFdmVudChicm93c2VyU2V0LCAnZXJyb3InKTtcbiAgICAgICAgY29uc3Qgc3RyZWFtQ29udHJvbGxlciAgICAgICA9IG5ldyBSZXBvcnRlclN0cmVhbUNvbnRyb2xsZXIodGFzaywgcmVwb3J0ZXJzKTtcblxuICAgICAgICBjb25zdCB0YXNrRG9uZVByb21pc2UgPSB0YXNrLm9uY2UoJ2RvbmUnKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4gYnJvd3NlclNldEVycm9yUHJvbWlzZS5jYW5jZWwoKSlcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocmVwb3J0ZXJzLm1hcChyZXBvcnRlciA9PiByZXBvcnRlci5wZW5kaW5nVGFza0RvbmVQcm9taXNlKSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtcbiAgICAgICAgICAgIHRhc2tEb25lUHJvbWlzZSxcbiAgICAgICAgICAgIGJyb3dzZXJTZXRFcnJvclByb21pc2VcbiAgICAgICAgXTtcblxuICAgICAgICBpZiAodGVzdGVkQXBwKVxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0ZXN0ZWRBcHAuZXJyb3JQcm9taXNlKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5yYWNlKHByb21pc2VzKTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9kaXNwb3NlVGFza0FuZFJlbGF0ZWRBc3NldHModGFzaywgYnJvd3NlclNldCwgcmVwb3J0ZXJzLCB0ZXN0ZWRBcHApO1xuXG4gICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgIH1cblxuICAgICAgICBh