UNPKG

testcafe

Version:

Automated browser testing for the modern web development stack.

607 lines 103 kB
"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 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 skip_js_errors_1 = require("../utils/get-options/skip-js-errors"); const DEBUG_LOGGER = (0, debug_1.default)('testcafe:runner'); class Runner extends events_1.EventEmitter { constructor({ proxy, browserConnectionGateway, configuration }) { super(); this._messageBus = new message_bus_1.default(); this.proxy = proxy; this.bootstrapper = this._createBootstrapper(browserConnectionGateway, 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._options = {}; this._hasTaskErrors = false; this._reporters = null; 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, messageBus, configuration) { return new bootstrapper_1.default({ browserConnectionGateway, 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) { task.abort(); task.clearListeners(); this._messageBus.abort(); 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; } // 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._messageBus.emit('unhandled-rejection'); await Promise.all(reporters.map(reporter => reporter.taskInfo.pendingTaskDonePromise)); await this._disposeTaskAndRelatedAssets(task, browserSet, reporters, testedApp, runnableConfigurationId); 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, warningLog) { return new task_1.default({ tests, browserConnectionGroups, proxy, opts, runnerWarningLog: warningLog, 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); this._messageBus.on('before-test-run-created-error', handle_errors_1.stopHandlingTestErrors); task.on('error', handle_errors_1.stopHandlingTestErrors); const onTaskCompleted = () => { 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, pathPatternOnFails } = 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 (!pathPatternOnFails) pathPatternOnFails = this.configuration.getOption(option_names_1.default.screenshotPathPatternOnFails); return { path, pathPattern, pathPatternOnFails }; } _validateScreenshotOptions() { const { path, pathPattern, pathPatternOnFails } = 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 } }); } if (pathPatternOnFails) { this._validateScreenshotPath(pathPatternOnFails, 'screenshots path pattern on fails'); this.configuration.mergeOptions({ [option_names_1.default.screenshots]: { pathPatternOnFails } }); } } 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.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; } _resetBeforeRun() { this.apiMethodWasCalled.reset(); this._messageBus.clearListeners(); } _prepareAndRunTask(options) { const messageBusErrorPromise = (0, promisify_event_1.default)(this._messageBus, 'error'); const taskOptionsPromise = this._getRunTaskOptions(options); const bindedTaskRunner = this._runTask.bind(this); const runTaskPromise = taskOptionsPromise.then(bindedTaskRunner); const promise = Promise.race([ runTaskPromise, messageBusErrorPromise, ]); return this._createCancelablePromise(promise); } async _prepareReporters() { var _a; const reporterPlugins = await reporter_1.default.getReporterPlugins(this.configuration.getOption(option_names_1.default.reporter)); const reporterHooks = (_a = this.configuration.getOption(option_names_1.default.hooks)) === null || _a === void 0 ? void 0 : _a.reporter; if (reporterHooks) this._assertReporterHooks(reporterHooks); this._reporters = reporterPlugins.map(reporter => { const reporterOptions = { plugin: reporter.plugin, messageBus: this._messageBus, outStream: reporter.outStream, name: reporter.name, reporterPluginHooks: this._resolvePluginHooks(reporter.name, reporterHooks), }; return new reporter_1.default(reporterOptions); }); await Promise.all(this._reporters.map(reporter => reporter.init())); } _resolvePluginHooks(name, reporterHooks) { if (!reporterHooks) return void 0; const resultHooks = {}; if (reporterHooks.onBeforeWrite && reporterHooks.onBeforeWrite[name]) resultHooks.onBeforeWrite = reporterHooks.onBeforeWrite[name]; return resultHooks; } _assertReporterHooks(hooks) { if (hooks === null || hooks === void 0 ? void 0 : hooks.onBeforeWrite) { (0, type_assertions_1.assertType)(type_assertions_1.is.nonNullObject, 'onBeforeWrite', 'The reporter.onBeforeWrite', hooks.onBeforeWrite); Object.entries(hooks === null || hooks === void 0 ? void 0 : hooks.onBeforeWrite).forEach(([reporterName, hook]) => { (0, type_assertions_1.assertType)(type_assertions_1.is.function, reporterName, `The reporter.onBeforeWrite.${reporterName}`, hook); }); } } async _prepareOptions(options) { this._options = Object.assign(this._options, options); await this._setConfigurationOptions(); await this._prepareReporters(); await this._setBootstrapperOptions(); (0, log_entry_1.default)(DEBUG_LOGGER, this.configuration); await this._validateRunOptions(); } async _getRunTaskOptions(options) { await this._prepareOptions(options); const { browserSet, tests, testedApp, commonClientScripts, id } = await this._createRunnableConfiguration(); await this._prepareClientScripts(tests, commonClientScripts); const resultOptions = Object.assign({}, this.configuration.getOptions()); return { browserSet, tests, testedApp, runnableConfigurationId: id, options: resultOptions, reporters: this._reporters, }; } 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 pathPatternOnFails; let [path, takeOnFails, pathPattern] = options; if (options.length === 1 && options[0] && typeof options[0] === 'object') ({ path, takeOnFails, pathPattern, pathPatternOnFails, fullPage, thumbnails } = options[0]); this._options.screenshots = { path, takeOnFails, pathPattern, pathPatternOnFails, 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 = {}) { this._resetBeforeRun(); return this._prepareAndRunTask(options); } 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVubmVyL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0JBQXVEO0FBQ3ZELGtEQUEwQjtBQUMxQixzRUFBNkM7QUFDN0MsbUNBQXNDO0FBRXRDLG1DQUlnQjtBQUVoQixrRUFBMEM7QUFDMUMsMkRBQW1DO0FBQ25DLGtEQUEwQjtBQUMxQixpRkFBK0Q7QUFDL0QsK0NBQWlEO0FBQ2pELDJDQUFpRDtBQUNqRCx1RUFBbUU7QUFDbkUsb0RBQW9FO0FBQ3BFLDJFQUFrRDtBQUNsRCwrRUFBcUQ7QUFDckQsMERBS2dDO0FBRWhDLGlGQUF5RDtBQUN6RCxtRUFBMEM7QUFDMUMsbUZBQTBEO0FBQzFELHlFQUE4RDtBQUM5RCwwREFBK0Q7QUFDL0QsOEZBQW9FO0FBQ3BFLHFHQUE0RTtBQUM1RSw0Q0FBK0U7QUFDL0UseUVBQWdEO0FBQ2hELCtFQUFzRDtBQUN0RCx5RkFBZ0U7QUFDaEUsbUVBQTREO0FBQzVELGtEQUF5QjtBQUN6QixpRkFBd0U7QUFDeEUsdUVBQXNEO0FBQ3RELDBEQUEyQjtBQUMzQiw2RUFBb0Q7QUFDcEQsZ0VBQTRFO0FBQzVFLG1FQUEwQztBQUMxQyx1RUFBOEM7QUFDOUMsd0VBQXNGO0FBRXRGLE1BQU0sWUFBWSxHQUFHLElBQUEsZUFBSyxFQUFDLGlCQUFpQixDQUFDLENBQUM7QUFFOUMsTUFBcUIsTUFBTyxTQUFRLHFCQUFZO0lBQzVDLFlBQWEsRUFBRSxLQUFLLEVBQUUsd0JBQXdCLEVBQUUsYUFBYSxFQUFFO1FBQzNELEtBQUssRUFBRSxDQUFDO1FBRVIsSUFBSSxDQUFDLFdBQVcsR0FBVyxJQUFJLHFCQUFVLEVBQUUsQ0FBQztRQUM1QyxJQUFJLENBQUMsS0FBSyxHQUFpQixLQUFLLENBQUM7UUFDakMsSUFBSSxDQUFDLFlBQVksR0FBVSxJQUFJLENBQUMsbUJBQW1CLENBQUMsd0JBQXdCLEVBQUUsSUFBSSxDQUFDLFdB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