Innovenergy_trunk/frontend/node_modules/testcafe/lib/runner/index.js

622 lines
106 KiB
JavaScript
Raw Permalink Normal View History

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = require("path");
const debug_1 = __importDefault(require("debug"));
const promisify_event_1 = __importDefault(require("promisify-event"));
const events_1 = require("events");
const config_storage_1 = __importDefault(require("../dashboard/config-storage"));
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 reporter_stream_controller_1 = __importDefault(require("./reporter-stream-controller"));
const customizable_compilers_1 = __importDefault(require("../configuration/customizable-compilers"));
const string_1 = require("../utils/string");
const is_localhost_1 = __importDefault(require("../utils/is-localhost"));
const warning_log_1 = __importDefault(require("../notifications/warning-log"));
const authentication_helper_1 = __importDefault(require("../cli/authentication-helper"));
const testcafe_browser_tools_1 = require("testcafe-browser-tools");
const is_ci_1 = __importDefault(require("is-ci"));
const remote_1 = __importDefault(require("../browser/provider/built-in/remote"));
const connection_1 = __importDefault(require("../browser/connection"));
const os_family_1 = __importDefault(require("os-family"));
const detect_display_1 = __importDefault(require("../utils/detect-display"));
const quarantine_1 = require("../utils/get-options/quarantine");
const log_entry_1 = __importDefault(require("../utils/log-entry"));
const message_bus_1 = __importDefault(require("../utils/message-bus"));
const get_env_options_1 = __importDefault(require("../dashboard/get-env-options"));
const skip_js_errors_1 = require("../utils/get-options/skip-js-errors");
const DEBUG_LOGGER = (0, debug_1.default)('testcafe:runner');
const DASHBOARD_REPORTER_NAME = 'dashboard';
class Runner extends events_1.EventEmitter {
constructor({ proxy, browserConnectionGateway, configuration, compilerService }) {
super();
this._messageBus = new message_bus_1.default();
this.proxy = proxy;
this.bootstrapper = this._createBootstrapper(browserConnectionGateway, compilerService, this._messageBus, configuration);
this.pendingTaskPromises = [];
this.configuration = configuration;
this.isCli = configuration._options && configuration._options.isCli;
this.warningLog = new warning_log_1.default(null, warning_log_1.default.createAddWarningCallback(this._messageBus));
this.compilerService = compilerService;
this._options = {};
this._hasTaskErrors = 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, messageBus, configuration) {
return new bootstrapper_1.default({ browserConnectionGateway, compilerService, messageBus, configuration });
}
_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, runnableConfigurationId) {
task.abort();
task.unRegisterClientScriptRouting();
task.clearListeners();
this._messageBus.abort();
await this._finalizeCompilerServiceState(task, runnableConfigurationId);
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 = (0, 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 = () => (0, 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;
}
async _finalizeCompilerServiceState(task, runnableConfigurationId) {
var _a;
if (!this.compilerService)
return;
await ((_a = this.compilerService) === null || _a === void 0 ? void 0 : _a.removeUnitsFromState({ runnableConfigurationId }));
// NOTE: In some cases (browser restart, stop task on first fail, etc.),
// the fixture contexts may not be deleted.
// We remove all fixture context at the end of test execution to clean forgotten contexts.
const fixtureIds = (0, lodash_1.uniq)(task.tests.map(test => test.fixture.id));
await this.compilerService.removeFixtureCtxsFromState({ fixtureIds });
}
// Run task
_getFailedTestCount(task, reporter) {
let failedTestCount = reporter.taskInfo.testCount - reporter.taskInfo.passed;
if (task.opts.stopOnFirstFail && !!failedTestCount)
failedTestCount = 1;
return failedTestCount;
}
async _getTaskResult(task, browserSet, reporters, testedApp, runnableConfigurationId) {
if (!task.opts.live) {
task.on('browser-job-done', async (job) => {
await Promise.all(job.browserConnections.map(async (bc) => {
await browserSet.releaseConnection(bc);
}));
});
}
this._messageBus.clearListeners('error');
const browserSetErrorPromise = (0, promisify_event_1.default)(browserSet, 'error');
const taskErrorPromise = (0, promisify_event_1.default)(task, 'error');
const messageBusErrorPromise = (0, promisify_event_1.default)(this._messageBus, 'error');
const streamController = new reporter_stream_controller_1.default(this._messageBus, reporters);
const taskDonePromise = this._messageBus.once('done')
.then(() => browserSetErrorPromise.cancel())
.then(() => {
return Promise.all(reporters.map(reporter => reporter.taskInfo.pendingTaskDonePromise));
});
const promises = [
taskDonePromise,
browserSetErrorPromise,
taskErrorPromise,
messageBusErrorPromise,
];
if (testedApp)
promises.push(testedApp.errorPromise);
try {
await Promise.race(promises);
}
catch (err) {
await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp, runnableConfigurationId);
throw err;
}
await this._disposeAssets(browserSet, reporters, testedApp);
await this._finalizeCompilerServiceState(task, runnableConfigurationId);
if (streamController.multipleStreamError)
throw streamController.multipleStreamError;
return this._getFailedTestCount(task, reporters[0]);
}
_createTask(tests, browserConnectionGroups, proxy, opts, warningLog) {
return new task_1.default({
tests,
browserConnectionGroups,
proxy,
opts,
runnerWarningLog: warningLog,
compilerService: this.compilerService,
messageBus: this._messageBus,
});
}
_runTask({ reporters, browserSet, tests, testedApp, options, runnableConfigurationId }) {
const task = this._createTask(tests, browserSet.browserConnectionGroups, this.proxy, options, this.warningLog);
const completionPromise = this._getTaskResult(task, browserSet, reporters, testedApp, runnableConfigurationId);
let completed = false;
this._messageBus.on('start', handle_errors_1.startHandlingTestErrors);
if (!this.configuration.getOption(option_names_1.default.skipUncaughtErrors)) {
this._messageBus.on('test-run-start', handle_errors_1.addRunningTest);
this._messageBus.on('test-run-done', ({ errs }) => {
if (errs.length)
this._hasTaskErrors = true;
(0, handle_errors_1.removeRunningTest)();
});
}
this._messageBus.on('done', handle_errors_1.stopHandlingTestErrors);
task.on('error', 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, runnableConfigurationId);
};
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 && (0, 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);
if (concurrency > 1 && this.bootstrapper.browsers.some(browser => {
return browser instanceof connection_1.default
? browser.browserInfo.browserOption.cdpPort
: browser.browserOption.cdpPort;
}))
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotSetConcurrencyWithCDPPort);
}
_validateSkipJsErrorsOption() {
const skipJsErrorsOptions = this.configuration.getOption(option_names_1.default.skipJsErrors);
if (!skipJsErrorsOptions)
return;
(0, skip_js_errors_1.validateSkipJsErrorsOptionValue)(skipJsErrorsOptions, runtime_1.GeneralError);
}
_validateCustomActionsOption() {
const customActions = this.configuration.getOption(option_names_1.default.customActions);
if (!customActions)
return;
if (typeof customActions !== 'object')
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidCustomActionsOptionType);
for (const name in customActions) {
if (typeof customActions[name] !== 'function')
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.invalidCustomActionType, name, typeof customActions[name]);
}
}
async _validateBrowsers() {
const browsers = this.configuration.getOption(option_names_1.default.browsers);
if (!browsers || Array.isArray(browsers) && !browsers.length)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.browserNotSet);
if (os_family_1.default.mac)
await this._checkRequiredPermissions(browsers);
if (os_family_1.default.linux && !(0, detect_display_1.default)())
await this._checkThatTestsCanRunWithoutDisplay(browsers);
}
_validateRequestTimeoutOption(optionName) {
const requestTimeout = this.configuration.getOption(optionName);
if (requestTimeout === void 0)
return;
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumber, null, `"${optionName}" option`, requestTimeout);
}
_validateProxyBypassOption() {
let proxyBypass = this.configuration.getOption(option_names_1.default.proxyBypass);
if (proxyBypass === void 0)
return;
(0, type_assertions_1.assertType)([type_assertions_1.is.string, type_assertions_1.is.array], null, 'The "proxyBypass" argument', proxyBypass);
if (typeof proxyBypass === 'string')
proxyBypass = [proxyBypass];
proxyBypass = proxyBypass.reduce((arr, rules) => {
(0, type_assertions_1.assertType)(type_assertions_1.is.string, null, 'The "proxyBypass" argument', rules);
return arr.concat(rules.split(','));
}, []);
this.configuration.mergeOptions({ proxyBypass });
}
_getScreenshotOptions() {
let { path, pathPattern, takeOnFails } = 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);
if (!takeOnFails)
takeOnFails = false;
return { path, pathPattern, takeOnFails };
}
_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: (0, 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]: (0, path_1.resolve)(videoPath) });
if (!videoOptions) {
videoOptions = {};
this.configuration.mergeOptions({ [option_names_1.default.videoOptions]: videoOptions });
}
if (videoOptions.ffmpegPath)
videoOptions.ffmpegPath = (0, path_1.resolve)(videoOptions.ffmpegPath);
else
videoOptions.ffmpegPath = await (0, detect_ffmpeg_1.default)();
if (!videoOptions.ffmpegPath)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotFindFFMPEG);
}
_validateCompilerOptions() {
const compilerOptions = this.configuration.getOption(option_names_1.default.compilerOptions);
if (!compilerOptions)
return;
const specifiedCompilers = Object.keys(compilerOptions);
const customizedCompilers = Object.keys(customizable_compilers_1.default);
const wrongCompilers = specifiedCompilers.filter(compiler => !customizedCompilers.includes(compiler));
if (!wrongCompilers.length)
return;
const compilerListStr = (0, string_1.getConcatenatedValuesString)(wrongCompilers, void 0, "'");
const pluralSuffix = (0, string_1.getPluralSuffix)(wrongCompilers);
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotCustomizeSpecifiedCompilers, compilerListStr, pluralSuffix);
}
_validateRetryTestPagesOption() {
const retryTestPagesOption = this.configuration.getOption(option_names_1.default.retryTestPages);
if (!retryTestPagesOption)
return;
const ssl = this.configuration.getOption(option_names_1.default.ssl);
if (ssl)
return;
const hostname = this.configuration.getOption(option_names_1.default.hostname);
if ((0, is_localhost_1.default)(hostname))
return;
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotEnableRetryTestPagesOption);
}
_validateQuarantineOptions() {
const quarantineMode = this.configuration.getOption(option_names_1.default.quarantineMode);
if (typeof quarantineMode === 'object')
(0, quarantine_1.validateQuarantineOptions)(quarantineMode);
}
async _validateRunOptions() {
this._validateDebugLogger();
this._validateScreenshotOptions();
await this._validateVideoOptions();
this._validateSpeedOption();
this._validateProxyBypassOption();
this._validateCompilerOptions();
this._validateRetryTestPagesOption();
this._validateRequestTimeoutOption(option_names_1.default.pageRequestTimeout);
this._validateRequestTimeoutOption(option_names_1.default.ajaxRequestTimeout);
this._validateQuarantineOptions();
this._validateConcurrencyOption();
this._validateSkipJsErrorsOption();
this._validateCustomActionsOption();
await this._validateBrowsers();
}
_createRunnableConfiguration() {
return this.bootstrapper
.createRunnableConfiguration()
.then(runnableConfiguration => {
this.emit('done-bootstrapping');
return runnableConfiguration;
});
}
_validateScreenshotPath(screenshotPath, pathType) {
const forbiddenCharsList = (0, check_file_path_1.default)(screenshotPath);
if (forbiddenCharsList.length)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.forbiddenCharatersInScreenshotPath, screenshotPath, pathType, (0, utils_1.renderForbiddenCharsList)(forbiddenCharsList));
}
_setBootstrapperOptions() {
this.configuration.prepare();
this.configuration.notifyAboutOverriddenOptions(this.warningLog);
this.configuration.notifyAboutDeprecatedOptions(this.warningLog);
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.disableMultipleWindows = this.configuration.getOption(option_names_1.default.disableMultipleWindows);
this.bootstrapper.proxyless = this.configuration.getOption(option_names_1.default.experimentalProxyless);
this.bootstrapper.compilerOptions = this.configuration.getOption(option_names_1.default.compilerOptions);
this.bootstrapper.browserInitTimeout = this.configuration.getOption(option_names_1.default.browserInitTimeout);
this.bootstrapper.hooks = this.configuration.getOption(option_names_1.default.hooks);
this.bootstrapper.configuration = this.configuration;
}
async _addDashboardReporterIfNeeded() {
const dashboardOptions = await this._getDashboardOptions();
let reporterOptions = this.configuration.getOption(option_names_1.default.reporter);
// NOTE: we should send reports when sendReport is undefined
// TODO: make this option binary instead of tri-state
if (!dashboardOptions.token || dashboardOptions.sendReport === false)
return;
if (!reporterOptions)
reporterOptions = [];
const dashboardReporter = reporterOptions.find(reporter => reporter.name === DASHBOARD_REPORTER_NAME);
if (!dashboardReporter)
reporterOptions.push({ name: DASHBOARD_REPORTER_NAME, options: dashboardOptions });
else
dashboardReporter.options = dashboardOptions;
this.configuration.mergeOptions({ [option_names_1.default.reporter]: reporterOptions });
}
_turnOnScreenshotsIfNeeded() {
const { takeOnFails } = this._getScreenshotOptions();
const reporterOptions = this.configuration.getOption(option_names_1.default.reporter);
if (!takeOnFails && reporterOptions && (0, lodash_1.castArray)(reporterOptions).some(reporter => reporter.name === DASHBOARD_REPORTER_NAME))
this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { takeOnFails: true, autoTakeOnFails: true } });
}
async _getDashboardOptions() {
const storageOptions = await this._loadDashboardOptionsFromStorage();
const configOptions = this.configuration.getOption(option_names_1.default.dashboard);
const envOptions = (0, get_env_options_1.default)();
return (0, lodash_1.merge)({}, storageOptions, configOptions, envOptions);
}
async _loadDashboardOptionsFromStorage() {
const storage = new config_storage_1.default();
await storage.load();
return storage.options;
}
async _prepareClientScripts(tests, clientScripts) {
return Promise.all(tests.map(async (test) => {
if (test.isLegacy)
return;
let loadedTestClientScripts = await (0, load_1.default)(test.clientScripts, (0, path_1.dirname)(test.testFile.filename));
loadedTestClientScripts = clientScripts.concat(loadedTestClientScripts);
test.clientScripts = (0, utils_2.setUniqueUrls)(loadedTestClientScripts);
}));
}
async _hasLocalBrowsers(browserInfo) {
for (const browser of browserInfo) {
if (browser instanceof connection_1.default)
continue;
if (await browser.provider.isLocalBrowser(void 0, browser.browserName))
return true;
}
return false;
}
async _checkRequiredPermissions(browserInfo) {
const hasLocalBrowsers = await this._hasLocalBrowsers(browserInfo);
const { error } = await (0, authentication_helper_1.default)(() => (0, testcafe_browser_tools_1.findWindow)(''), testcafe_browser_tools_1.errors.UnableToAccessScreenRecordingAPIError, {
interactive: hasLocalBrowsers && !is_ci_1.default,
});
if (!error)
return;
if (hasLocalBrowsers)
throw error;
remote_1.default.canDetectLocalBrowsers = false;
}
async _checkThatTestsCanRunWithoutDisplay(browserInfoSource) {
for (let browserInfo of browserInfoSource) {
if (browserInfo instanceof connection_1.default)
browserInfo = browserInfo.browserInfo;
const isLocalBrowser = await browserInfo.provider.isLocalBrowser(void 0, browserInfo.browserName);
const isHeadlessBrowser = await browserInfo.provider.isHeadlessBrowser(void 0, browserInfo.browserName);
if (isLocalBrowser && !isHeadlessBrowser) {
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.cannotRunLocalNonHeadlessBrowserWithoutDisplay, browserInfo.alias);
}
}
}
async _setConfigurationOptions() {
await this.configuration.asyncMergeOptions(this._options);
}
// API
embeddingOptions(opts) {
const { assets, TestRunCtor } = opts;
this._registerAssets(assets);
this._options.TestRunCtor = TestRunCtor;
return this;
}
src(...sources) {
if (this.apiMethodWasCalled.src)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.multipleAPIMethodCallForbidden, option_names_1.default.src);
this._options[option_names_1.default.src] = this._prepareArrayParameter(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);
this._options.browsers = this._prepareArrayParameter(browsers);
this.apiMethodWasCalled.browsers = true;
return this;
}
concurrency(concurrency) {
this._options.concurrency = 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);
this._options[option_names_1.default.reporter] = this._prepareArrayParameter((0, prepare_reporters_1.default)(name, output));
this.apiMethodWasCalled.reporter = true;
return this;
}
filter(filter) {
this._options.filter = filter;
return this;
}
useProxy(proxy, proxyBypass) {
this._options.proxy = proxy;
this._options.proxyBypass = proxyBypass;
return this;
}
screenshots(...options) {
let fullPage;
let thumbnails;
let [path, takeOnFails, pathPattern] = options;
if (options.length === 1 && options[0] && typeof options[0] === 'object')
({ path, takeOnFails, pathPattern, fullPage, thumbnails } = options[0]);
this._options.screenshots = { path, takeOnFails, pathPattern, fullPage, thumbnails };
return this;
}
video(path, options, encodingOptions) {
this._options[option_names_1.default.videoPath] = path;
this._options[option_names_1.default.videoOptions] = options;
this._options[option_names_1.default.videoEncodingOptions] = encodingOptions;
return this;
}
startApp(command, initDelay) {
this._options[option_names_1.default.appCommand] = command;
this._options[option_names_1.default.appInitDelay] = initDelay;
return this;
}
tsConfigPath(path) {
this._options[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);
this._options[option_names_1.default.clientScripts] = this._prepareArrayParameter(scripts);
this.apiMethodWasCalled.clientScripts = true;
return this;
}
compilerOptions(opts) {
this._options[option_names_1.default.compilerOptions] = opts;
return this;
}
run(options = {}) {
let reporters;
this.apiMethodWasCalled.reset();
this._messageBus.clearListeners();
const messageBusErrorPromise = (0, promisify_event_1.default)(this._messageBus, 'error');
this._options = Object.assign(this._options, options);
const runTaskPromise = Promise.resolve()
.then(() => this._setConfigurationOptions())
.then(async () => {
await this._addDashboardReporterIfNeeded();
await this._turnOnScreenshotsIfNeeded();
})
.then(() => reporter_1.default.getReporterPlugins(this.configuration.getOption(option_names_1.default.reporter)))
.then(reporterPlugins => {
reporters = reporterPlugins.map(reporter => new reporter_1.default(reporter.plugin, this._messageBus, reporter.outStream, reporter.name));
return Promise.all(reporters.map(reporter => reporter.init()));
})
.then(() => this._setBootstrapperOptions())
.then(() => {
(0, log_entry_1.default)(DEBUG_LOGGER, this.configuration);
return this._validateRunOptions();
})
.then(() => this._createRunnableConfiguration())
.then(async ({ browserSet, tests, testedApp, commonClientScripts, id }) => {
var _a, _b;
await this._prepareClientScripts(tests, commonClientScripts);
const dashboardReporter = (_a = reporters.find(r => r.plugin.name === 'dashboard')) === null || _a === void 0 ? void 0 : _a.plugin;
const dashboardUrl = (dashboardReporter === null || dashboardReporter === void 0 ? void 0 : dashboardReporter.getReportUrl) ? dashboardReporter.getReportUrl() : '';
const resultOptions = Object.assign(Object.assign({}, this.configuration.getOptions()), { dashboardUrl });
await ((_b = this.bootstrapper.compilerService) === null || _b === void 0 ? void 0 : _b.setOptions({ value: resultOptions }));
return this._runTask({
reporters,
browserSet,
tests,
testedApp,
options: resultOptions,
runnableConfigurationId: id,
});
});
const promises = [
runTaskPromise,
messageBusErrorPromise,
];
return this._createCancelablePromise(Promise.race(promises));
}
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 = this.pendingTaskPromises.reduceRight((result, taskPromise) => {
result.push(taskPromise.cancel());
return result;
}, []);
await Promise.all(cancellationPromises);
}
}
exports.default = Runner;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVubmVyL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0JBQXVEO0FBQ3ZELGtEQUEwQjtBQUMxQixzRUFBNkM7QUFDN0MsbUNBQXNDO0FBQ3RDLGlGQUFpRTtBQUVqRSxtQ0FPZ0I7QUFFaEIsa0VBQTBDO0FBQzFDLDJEQUFtQztBQUNuQyxrREFBMEI7QUFDMUIsaUZBQStEO0FBQy9ELCtDQUFpRDtBQUNqRCwyQ0FBaUQ7QUFDakQsdUVBQW1FO0FBQ25FLG9EQUFvRTtBQUNwRSwyRUFBa0Q7QUFDbEQsK0VBQXFEO0FBQ3JELDBEQUtnQztBQUVoQyxpRkFBeUQ7QUFDekQsbUVBQTBDO0FBQzFDLG1GQUEwRDtBQUMxRCx5RUFBOEQ7QUFDOUQsMERBQStEO0FBQy9ELDhGQUFvRTtBQUNwRSxxR0FBNEU7QUFDNUUsNENBQStFO0FBQy9FLHlFQUFnRDtBQUNoRCwrRUFBc0Q7QUFDdEQseUZBQWdFO0FBQ2hFLG1FQUE0RDtBQUM1RCxrREFBeUI7QUFDekIsaUZBQXdFO0FBQ3hFLHVFQUFzRDtBQUN0RCwwREFBMkI7QUFDM0IsNkVBQW9EO0FBQ3BELGdFQUE0RTtBQUM1RSxtRUFBMEM7QUFDMUMsdUVBQThDO0FBQzlDLG1GQUF5RDtBQUN6RCx3RUFBc0Y7QUFFdEYsTUFBTSxZQUFZLEdBQWMsSUFBQSxlQUFLLEVBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUN6RCxNQUFNLHVCQUF1QixHQUFHLFdBQVcsQ0FBQztBQUU1QyxNQUFxQixNQUFPLFNBQVEscUJBQVk7SUFDNUMsWUFBYSxFQUFFLEtBQUssRUFBRSx3QkFBd0IsRUFBRSxhQUFhLEVBQUUsZUFBZSxFQUFFO1FBQzVFLEtBQUssRUFBRSxDQUFDO1FBRVIsSUFBSSxDQUFDLFdBQVcsR0FBVyxJQUFJLHFCQUFVLEVBQUUsQ0FBQztRQUM1QyxJQUFJLENBQUMsS0FBSyxHQUFpQixLQUFLLENBQUM7UUFD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