Innovenergy_trunk/frontend/node_modules/testcafe/lib/cli/argument-parser/index.js

390 lines
72 KiB
JavaScript
Raw Normal View History

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
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 commander_1 = __importStar(require("commander"));
const dedent_1 = __importDefault(require("dedent"));
const runtime_1 = require("../../errors/runtime");
const types_1 = require("../../errors/types");
const type_assertions_1 = require("../../errors/runtime/type-assertions");
const get_viewport_width_1 = __importDefault(require("../../utils/get-viewport-width"));
const string_1 = require("../../utils/string");
const get_options_1 = require("../../utils/get-options");
const get_filter_fn_1 = __importDefault(require("../../utils/get-filter-fn"));
const screenshot_option_names_1 = __importDefault(require("../../configuration/screenshot-option-names"));
const run_option_names_1 = __importDefault(require("../../configuration/run-option-names"));
const quarantine_option_names_1 = __importDefault(require("../../configuration/quarantine-option-names"));
const node_arguments_filter_1 = require("../node-arguments-filter");
const get_testcafe_version_1 = __importDefault(require("../../utils/get-testcafe-version"));
const parse_utils_1 = require("./parse-utils");
const command_names_1 = __importDefault(require("./command-names"));
const skip_js_errors_option_names_1 = require("../../configuration/skip-js-errors-option-names");
const REMOTE_ALIAS_RE = /^remote(?::(\d*))?$/;
const DESCRIPTION = (0, dedent_1.default)(`
To select a browser, specify an alias ("ie", "chrome", etc.) or the path to the browser executable. You can select more than one browser.
Use the "all" alias to run tests against all available browsers.
Use the "remote" alias to run tests on remote devices, like smartphones or tablets. Specify the number of remote browsers after the semicolon ("remote:3").
If you use a browser provider plugin, specify both the name of the plugin and the name of the browser. Separate the two with a semicolon ("saucelabs:chrome@51").
To execute multiple test files, specify multiple file paths or glob patterns.
Full documentation: https://testcafe.io/documentation/402639/reference/command-line-interface
`);
class CLIArgumentParser {
constructor(cwd) {
this.cwd = cwd || process.cwd();
this.remoteCount = 0;
this.opts = {};
this.args = [];
this.isDashboardCommand = false;
this.testCafeCommand = this._addTestCafeCommand();
this._patchHelpOutput(this.testCafeCommand);
CLIArgumentParser._setupRootCommand();
}
static _setupRootCommand() {
// NOTE: We are forced to set the name of the root command to 'testcafe'
// to avoid the automatic command name calculation using the executed file path.
// It's necessary to correct command description for nested commands.
commander_1.default.name(command_names_1.default.TestCafe);
}
static _removeCommandIfExists(name) {
// NOTE: Bug in the 'commander' module.
// It's possible to add a few commands with the same name.
// Also, removing is a better than conditionally adding
// because it allows avoiding the parsed option duplicates.
const index = commander_1.default.commands.findIndex(cmd => cmd.name() === name);
if (index > -1)
commander_1.default.commands.splice(index, 1);
}
static _getDescription() {
// NOTE: add empty line to workaround commander-forced indentation on the first line.
return '\n' + (0, string_1.wordWrap)(DESCRIPTION, 2, (0, get_viewport_width_1.default)(process.stdout));
}
_addTestCafeCommand() {
CLIArgumentParser._removeCommandIfExists(command_names_1.default.TestCafe);
return commander_1.default
.command(command_names_1.default.TestCafe, { isDefault: true })
.version((0, get_testcafe_version_1.default)(), '-v, --version')
.usage('[options] <comma-separated-browser-list> <file-or-glob ...>')
.description(CLIArgumentParser._getDescription())
.allowUnknownOption()
.option('-b, --list-browsers [provider]', 'display the list of aliases for available browsers and browser providers')
.option('-r, --reporter <name[:outputFile][,...]>', 'specify reporters and report filenames')
.option('-s, --screenshots <option=value[,...]>', 'specify screenshot options')
.option('-S, --screenshots-on-fails', 'take a screenshot on test failure')
.option('-p, --screenshot-path-pattern <pattern>', 'specify the naming schema for screenshot filenames and paths: ${BROWSER}, ${BROWSER_VERSION}, ${OS}, etc.')
.option('-q, --quarantine-mode [option=value,...]', 'enable and configure quarantine mode')
.option('-d, --debug-mode', 'enable debug mode. When you run TestCafe in debug mode, it executes test steps one by one, and pauses the test after each step.')
.option('-e, --skip-js-errors [option=value,...]', 'ignore JavaScript errors that match the specified criteria')
.option('-u, --skip-uncaught-errors', 'ignore uncaught errors and unhandled promise rejections')
.option('-t, --test <name>', 'filter tests by name')
.option('-T, --test-grep <pattern>', 'filter tests by regular expression')
.option('-f, --fixture <name>', 'filter fixtures by name')
.option('-F, --fixture-grep <pattern>', 'filter fixtures by regular expression')
.option('-a, --app <command>', 'execute a shell command on startup to launch a web application or perform other preparatory tasks')
.option('-c, --concurrency <number>', 'run tests concurrently')
.option('-L, --live', 'enable live mode. Live mode restarts tests when you make changes to test files.')
.option('--test-meta <key=value[,key2=value2,...]>', 'filter tests by metadata')
.option('--fixture-meta <key=value[,key2=value2,...]>', 'filter fixtures by metadata')
.option('--debug-on-fail', 'pause tests on failure')
.option('--experimental-proxyless', 'enable proxyless mode: https://testcafe.io/documentation/404237/guides/experimental-capabilities/proxyless-mode')
.option('--app-init-delay <ms>', 'specify your application`s initialization time')
.option('--selector-timeout <ms>', 'specify the maximum Selector resolution time')
.option('--assertion-timeout <ms>', 'specify the maximum Assertion resolution time')
.option('--page-load-timeout <ms>', 'specify the maximum time between the window.load event and the DOMContentLoaded event (ms)')
.option('--page-request-timeout <ms>', 'specify the maximum page request resolution time')
.option('--ajax-request-timeout <ms>', 'specify the maximum AJAX request resolution time')
.option('--browser-init-timeout <ms>', 'specify the maximum browser startup time')
.option('--test-execution-timeout <ms>', 'specify the maximum test execution time')
.option('--run-execution-timeout <ms>', 'specify the maximum test run time')
.option('--speed <factor>', 'set test execution speed (0.01 ... 1)')
.option('--ports <port1,port2>', 'specify network ports to use during the test run. The second port is necessary to access cross-domain resources.')
.option('--hostname <name>', `specify your hostname. Necessary to run tests in remote browsers.`)
.option('--proxy <host>', 'specify the proxy server hostname or IP address')
.option('--proxy-bypass <rules>', 'specify URLs that bypass the proxy server')
.option('--ssl <options>', 'specify SSL options to run TestCafe over HTTPS')
.option('--video <path>', 'record videos of test runs')
.option('--video-options <option=value[,...]>', 'specify video recording options')
.option('--video-encoding-options <option=value[,...]>', 'specify video encoding options')
.option('--dev', 'log and diagnose TestCafe errors')
.option('--qr-code', 'output QR codes with URLs for remote browser connections')
.option('--sf, --stop-on-first-fail', 'stop the test run if any test fails')
.option('--config-file <path>', 'specify a custom path to the testcafe configuration file')
.option('--ts-config-path <path>', 'specify the path to a custom TypeScript configuration file')
.option('--cs, --client-scripts <paths>', 'inject client-side scripts into the page', parse_utils_1.parseList, [])
.option('--disable-page-caching', 'do not cache pages')
.option('--disable-page-reloads', 'do not reload pages between tests')
.option('--retry-test-pages', 'retry page requests in case of failure')
.option('--disable-screenshots', 'disable screenshots')
.option('--screenshots-full-page', 'enable full-page screenshots')
.option('--compiler-options <option=value[,...]>', 'specify test compilation settings')
.option('--disable-multiple-windows', 'disable the multi-window mode')
.option('--disable-http2', 'force the proxy to issue HTTP/1.1 requests')
.option('--cache', 'cache web assets between test runs')
.option('--base-url <url>', 'set the base url for the test run')
// NOTE: these options will be handled by chalk internally
.option('--color', 'force TestCafe to format CLI output with color')
.option('--no-color', 'disable text color formatting in the CLI')
// NOTE: Temporarily exclude experimental options from --help output
.addOption(new commander_1.Option('--experimental-debug', 'enable experimental the debug mode').hideHelp())
.addOption(new commander_1.Option('--experimental-esm', 'enable experimental the esm mode').hideHelp())
.addOption(new commander_1.Option('--disable-cross-domain', 'experimental').hideHelp())
.action((opts) => {
this.opts = opts;
});
}
_patchHelpOutput(defaultSubCommand) {
// NOTE: In the future versions of the 'commander' module
// need to investigate how to remove this hack.
commander_1.default.outputHelp = function () {
const storedParent = defaultSubCommand.parent;
defaultSubCommand.parent = null;
defaultSubCommand.outputHelp();
defaultSubCommand.parent = storedParent;
};
}
_checkAndCountRemotes(browser) {
const remoteMatch = browser.match(REMOTE_ALIAS_RE);
if (remoteMatch) {
this.remoteCount += parseInt(remoteMatch[1], 10) || 1;
return false;
}
return true;
}
async _parseFilteringOptions() {
if (this.opts.testGrep)
this.opts.testGrep = (0, get_options_1.getGrepOptions)('--test-grep', this.opts.testGrep);
if (this.opts.fixtureGrep)
this.opts.fixtureGrep = (0, get_options_1.getGrepOptions)('--fixture-grep', this.opts.fixtureGrep);
if (this.opts.testMeta)
this.opts.testMeta = await (0, get_options_1.getMetaOptions)('--test-meta', this.opts.testMeta);
if (this.opts.fixtureMeta)
this.opts.fixtureMeta = await (0, get_options_1.getMetaOptions)('--fixture-meta', this.opts.fixtureMeta);
this.opts.filter = (0, get_filter_fn_1.default)(this.opts);
}
_parseAppInitDelay() {
if (this.opts.appInitDelay) {
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The tested app initialization delay', this.opts.appInitDelay);
this.opts.appInitDelay = parseInt(this.opts.appInitDelay, 10);
}
}
_parseSelectorTimeout() {
if (this.opts.selectorTimeout) {
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The Selector timeout', this.opts.selectorTimeout);
this.opts.selectorTimeout = parseInt(this.opts.selectorTimeout, 10);
}
}
_parseAssertionTimeout() {
if (this.opts.assertionTimeout) {
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The assertion timeout', this.opts.assertionTimeout);
this.opts.assertionTimeout = parseInt(this.opts.assertionTimeout, 10);
}
}
_parsePageLoadTimeout() {
if (this.opts.pageLoadTimeout) {
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The page load timeout', this.opts.pageLoadTimeout);
this.opts.pageLoadTimeout = parseInt(this.opts.pageLoadTimeout, 10);
}
}
_parsePageRequestTimeout() {
if (!this.opts.pageRequestTimeout)
return;
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The page request timeout', this.opts.pageRequestTimeout);
this.opts.pageRequestTimeout = parseInt(this.opts.pageRequestTimeout, 10);
}
_parseAjaxRequestTimeout() {
if (!this.opts.ajaxRequestTimeout)
return;
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The AJAX request timeout', this.opts.ajaxRequestTimeout);
this.opts.ajaxRequestTimeout = parseInt(this.opts.ajaxRequestTimeout, 10);
}
_parseBrowserInitTimeout() {
if (!this.opts.browserInitTimeout)
return;
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The browser initialization timeout', this.opts.browserInitTimeout);
this.opts.browserInitTimeout = parseInt(this.opts.browserInitTimeout, 10);
}
_parseTestExecutionTimeout() {
if (this.opts.testExecutionTimeout) {
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The test execution timeout', this.opts.testExecutionTimeout);
this.opts.testExecutionTimeout = parseInt(this.opts.testExecutionTimeout, 10);
}
}
_parseRunExecutionTimeout() {
if (this.opts.runExecutionTimeout) {
(0, type_assertions_1.assertType)(type_assertions_1.is.nonNegativeNumberString, null, 'The run execution timeout', this.opts.runExecutionTimeout);
this.opts.runExecutionTimeout = parseInt(this.opts.runExecutionTimeout, 10);
}
}
_parseSpeed() {
if (this.opts.speed)
this.opts.speed = parseFloat(this.opts.speed);
}
_parseConcurrency() {
if (this.opts.concurrency)
this.opts.concurrency = parseInt(this.opts.concurrency, 10);
}
async _parseQuarantineOptions() {
if (this.opts.quarantineMode)
this.opts.quarantineMode = await (0, get_options_1.getQuarantineOptions)('--quarantine-mode', this.opts.quarantineMode);
}
async _parseSkipJsErrorsOptions() {
if (this.opts.skipJsErrors)
this.opts.skipJsErrors = await (0, get_options_1.getSkipJsErrorsOptions)('--skip-js-errors', this.opts.skipJsErrors);
}
_parsePorts() {
if (this.opts.ports) {
const parsedPorts = this.opts.ports /* eslint-disable-line no-extra-parens */
.split(',')
.map(parse_utils_1.parsePortNumber);
if (parsedPorts.length < 2)
throw new runtime_1.GeneralError(types_1.RUNTIME_ERRORS.portsOptionRequiresTwoNumbers);
this.opts.ports = parsedPorts;
}
}
_parseBrowsersFromArgs() {
const browsersArg = this.testCafeCommand.args[0] || '';
this.opts.browsers = (0, string_1.splitQuotedText)(browsersArg, ',')
.filter(browser => browser && this._checkAndCountRemotes(browser));
}
async _parseSslOptions() {
if (this.opts.ssl)
this.opts.ssl = await (0, get_options_1.getSSLOptions)(this.opts.ssl);
}
async _parseReporters() {
const reporters = this.opts.reporter ? this.opts.reporter.split(',') : []; /* eslint-disable-line no-extra-parens*/
this.opts.reporter = reporters.map((reporter) => {
const separatorIndex = reporter.indexOf(':');
if (separatorIndex < 0)
return { name: reporter };
const name = reporter.substring(0, separatorIndex);
const output = reporter.substring(separatorIndex + 1);
return { name, output };
});
}
_parseFileList() {
this.opts.src = this.testCafeCommand.args.slice(1);
}
async _parseScreenshotOptions() {
if (this.opts.screenshots)
this.opts.screenshots = await (0, get_options_1.getScreenshotOptions)(this.opts.screenshots);
else
this.opts.screenshots = {};
if (!(0, lodash_1.has)(this.opts.screenshots, screenshot_option_names_1.default.pathPattern) && this.opts.screenshotPathPattern)
this.opts.screenshots[screenshot_option_names_1.default.pathPattern] = this.opts.screenshotPathPattern;
if (!(0, lodash_1.has)(this.opts.screenshots, screenshot_option_names_1.default.takeOnFails) && this.opts.screenshotsOnFails)
this.opts.screenshots[screenshot_option_names_1.default.takeOnFails] = this.opts.screenshotsOnFails;
}
async _parseVideoOptions() {
if (this.opts.videoOptions)
this.opts.videoOptions = await (0, get_options_1.getVideoOptions)(this.opts.videoOptions);
if (this.opts.videoEncodingOptions)
this.opts.videoEncodingOptions = await (0, get_options_1.getVideoOptions)(this.opts.videoEncodingOptions);
}
async _parseCompilerOptions() {
if (!this.opts.compilerOptions)
return;
const parsedCompilerOptions = await (0, get_options_1.getCompilerOptions)(this.opts.compilerOptions);
const resultCompilerOptions = Object.create(null);
for (const [key, value] of Object.entries(parsedCompilerOptions))
(0, lodash_1.set)(resultCompilerOptions, key, value);
this.opts.compilerOptions = resultCompilerOptions;
}
async _parseDashboardOptions() {
if (this.opts.dashboardOptions)
this.opts.dashboardOptions = await (0, get_options_1.getDashboardOptions)(this.opts.dashboardOptions);
}
_parseListBrowsers() {
const listBrowserOption = this.opts.listBrowsers;
this.opts.listBrowsers = !!this.opts.listBrowsers;
if (!this.opts.listBrowsers)
return;
this.opts.providerName = typeof listBrowserOption === 'string' ? listBrowserOption : 'locally-installed';
}
static _prepareBooleanOrObjectOption(argv, optionNames, subOptionsNames) {
// NOTE: move options to the end of the array to correctly parse both Boolean and Object type arguments (GH-6231)
const optionIndex = argv.findIndex(el => optionNames.some(opt => el.startsWith(opt)));
if (optionIndex > -1) {
const isNotLastOption = optionIndex < argv.length - 1;
const shouldMoveOptionToEnd = isNotLastOption &&
!subOptionsNames.some(opt => argv[optionIndex + 1].startsWith(opt));
if (shouldMoveOptionToEnd)
argv.push(argv.splice(optionIndex, 1)[0]);
}
}
async parse(argv) {
CLIArgumentParser._prepareBooleanOrObjectOption(argv, ['-q', '--quarantine-mode'], Object.values(quarantine_option_names_1.default));
CLIArgumentParser._prepareBooleanOrObjectOption(argv, ['-e', '--skip-js-errors'], Object.values(skip_js_errors_option_names_1.SKIP_JS_ERRORS_OPTIONS_OBJECT_OPTION_NAMES));
const { args, v8Flags } = (0, node_arguments_filter_1.extractNodeProcessArguments)(argv);
commander_1.default.parse(args);
this.args = commander_1.default.args;
this.opts = Object.assign(this.opts, { v8Flags });
this._parseListBrowsers();
// NOTE: the '--list-browsers' option only lists browsers and immediately exits the app.
// Therefore, we don't need to process other arguments.
if (this.opts.listBrowsers)
return;
this._parseSelectorTimeout();
this._parseAssertionTimeout();
this._parsePageLoadTimeout();
this._parsePageRequestTimeout();
this._parseAjaxRequestTimeout();
this._parseBrowserInitTimeout();
this._parseTestExecutionTimeout();
this._parseRunExecutionTimeout();
this._parseAppInitDelay();
this._parseSpeed();
this._parsePorts();
this._parseBrowsersFromArgs();
this._parseConcurrency();
this._parseFileList();
await this._parseFilteringOptions();
await this._parseQuarantineOptions();
await this._parseSkipJsErrorsOptions();
await this._parseScreenshotOptions();
await this._parseVideoOptions();
await this._parseCompilerOptions();
await this._parseSslOptions();
await this._parseReporters();
await this._parseDashboardOptions();
}
getRunOptions() {
const result = Object.create(null);
run_option_names_1.default.forEach(optionName => {
if (optionName in this.opts)
// @ts-ignore a hack to add an index signature to interface
result[optionName] = this.opts[optionName];
});
return result;
}
}
exports.default = CLIArgumentParser;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY2xpL2FyZ3VtZW50LXBhcnNlci9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsbUNBQWtDO0FBRWxDLHVEQUdtQjtBQUVuQixvREFBNEI7QUFDNUIsa0RBQW9EO0FBQ3BELDhDQUFvRDtBQUNwRCwwRUFBc0U7QUFDdEUsd0ZBQThEO0FBQzlELCtDQUErRDtBQUMvRCx5REFVaUM7QUFFakMsOEVBQW9EO0FBQ3BELDBHQUFrRjtBQUNsRiw0RkFBb0U7QUFNcEUsMEdBQWtGO0FBQ2xGLG9FQUF1RTtBQUN2RSw0RkFBa0U7QUFDbEUsK0NBQTJEO0FBQzNELG9FQUE0QztBQUU1QyxpR0FBNkc7QUFFN0csTUFBTSxlQUFlLEdBQUcscUJBQXFCLENBQUM7QUFFOUMsTUFBTSxXQUFXLEdBQUcsSUFBQSxnQkFBTSxFQUFDOzs7Ozs7Ozs7OztDQVcxQixDQUFDLENBQUM7QUF5Q0gsTUFBcUIsaUJBQWlCO0lBU2xDLFlBQW9CLEdBQVk7UUFDNUIsSUFBSSxDQUFDLEdBQUcsR0FBVyxHQUFHLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3hDLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDO1FBQ3JCLElBQUksQ0FBQyxJQUFJLEdBQVUsRUFBRSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxJQUFJLEdBQVUsRUFBRSxDQUFDO1FBRXRCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxLQUFLLENBQUM7UUFDaEMsSUFBSSxDQUFDLGVBQWUsR0FBTSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUVyRCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQzVDLGlCQUFpQixDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDMUMsQ0FBQztJQUVPLE1BQU0sQ0FBQyxpQkFBaUI7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