From ab6fdefe5d76799206f6a197ad8c4e4d1d499d0c Mon Sep 17 00:00:00 2001 From: Ravi Sawlani Date: Wed, 12 Jan 2022 15:17:35 +0530 Subject: [PATCH] Add more supporting CucumberJS cli options (#2978) --- examples/cucumber-js/README.md | 19 +++++ lib/runner/test-runners/cucumber.js | 40 +++++++--- .../cucumber-integration/testCliArgs.js | 75 +++++++++++++++++++ 3 files changed, 122 insertions(+), 12 deletions(-) create mode 100644 test/src/runner/cucumber-integration/testCliArgs.js diff --git a/examples/cucumber-js/README.md b/examples/cucumber-js/README.md index 27ec1a3bb5..b952068ddc 100644 --- a/examples/cucumber-js/README.md +++ b/examples/cucumber-js/README.md @@ -33,6 +33,25 @@ $ npm i @cucumber/cucumber --save-dev } ``` +## CLI Options +| option | description | +|------------------------|------------------------------| +| --dry-run | Do all the aggregation work of looking at your feature files, loading your support code etc but without actually executing the tests. [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/dry_run.md) +| --name | Specify a scenario by its name matching a regular expression. [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/cli.md#running-specific-features) +| --tags | Use tags to run specific scenario or features. [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/cli.md#tags) +| --require | Use `--require ` to explicitly require support files before executing the features. [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/cli.md#requiring-support-files) +| --format | Use `--format ` to specify the format of the output. [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/cli.md#formats) +| --format-options | Many formatters, including the built-in ones, support some configurability via options. You can provide this data as a JSON literal via the --format-options CLI option. [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/formatters.md#options) +| --fail-fast | Abort the run on first failure (default: false). [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/cli.md#--fail-fast) +| --retries | Use `--retries ` to have Cucumber attempt it multiple times until either it passes or the maximum number of attempts is reached. [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/retry.md#retry) +| --retry-tag-filter | Use `--retry-tag-filter` to retry failed scenarios based on tags. [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/retry.md#targeting-scenarios) +| --require-module | [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/cli.md#transpilation) +| --no-strict | By default, cucumber runner works in strict mode, meaning it will fail if there are pending steps. +| --parallel | Use `--parallel ` to run your scenarios in parallel. [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/parallel.md#parallel) +| --profile | As of now only `cucumber.js` is considered while picking up profiles. [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/profiles.md) +| --world-parameters | Provide this data as a JSON literal via the `--world-parameters`. [read more](https://github.com/cucumber/cucumber-js/blob/main/docs/support_files/world.md#world-parameters) + + ## Running Cucumber spec files/step definition files can be provided in `src_folders` in Nightwatch config or as a CLI argument. diff --git a/lib/runner/test-runners/cucumber.js b/lib/runner/test-runners/cucumber.js index 98d7340cd7..247e9dc294 100644 --- a/lib/runner/test-runners/cucumber.js +++ b/lib/runner/test-runners/cucumber.js @@ -90,17 +90,9 @@ class CucumberSuite extends TestSuite { const initialRequires = [ '--require', cucumberSetupFile ]; - - let extraRequires = this.argv.require; - if (extraRequires) { - if (isString(extraRequires)) { - extraRequires = [extraRequires]; - } - extraRequires.forEach((filePath) => { - initialRequires.push('--require', filePath); - }); - } - + initialRequires.push(...this.buildArgvArray('require')); + initialRequires.push(...this.buildArgvArray('require-module')); + const profiles = this.buildArgvArray('profile'); const specs = this.allModulePaths.reduce((prev, spec) => { prev.push('--require', spec); @@ -115,6 +107,7 @@ class CucumberSuite extends TestSuite { const {feature_path} = options; const parallelArgs = this.usingCucumberWorkers ? ['--parallel', this.usingCucumberWorkers]: []; const tagsOption = this.argv.tags ? ['--tags', this.argv.tags] : []; + const retryTagsOption = this.argv['retry-tag-filter'] ? ['--retry-tag-filter', this.argv['retry-tag-filter']] : []; const extraParams = ['--world-parameters', JSON.stringify(this.argv)]; let formatArg = this.argv.format || []; if (!Array.isArray(formatArg)) { @@ -127,11 +120,34 @@ class CucumberSuite extends TestSuite { }, []); const formatOptions = this.argv['format-options'] ? ['--format-options', this.argv['format-options']] : []; + const dryRun = this.argv['dry-run'] ? ['--dry-run'] : []; + const failFast = this.argv['fail-fast'] ? ['--fail-fast'] : []; + const retryOption = this.argv['retries'] ? ['--retry', Number(this.argv['retries'])] : []; + const noStrict = this.argv['no-strict'] ? ['--no-strict'] : []; + const featureNameFilter = this.argv['name'] ? ['--name', this.argv['name']] : []; return [ process.execPath, require.resolve('@cucumber/cucumber') - ].concat(feature_path, parallelArgs, specs, tagsOption, formatArg, formatOptions, extraParams); + ].concat(feature_path, parallelArgs, specs, tagsOption, formatArg, formatOptions, extraParams, dryRun, failFast, retryOption, profiles, noStrict, featureNameFilter, retryTagsOption); + } + + + buildArgvArray(argName) { + let argvArray = []; + let argValues = this.argv[argName]; + + if (!argValues) { + return argvArray; + } + if (isString(argValues)) { + argValues = [argValues]; + } + argValues.forEach((arg)=>{ + argvArray.push(`--${argName}`, arg); + }); + + return argvArray; } onTestSuiteFinished(result) { diff --git a/test/src/runner/cucumber-integration/testCliArgs.js b/test/src/runner/cucumber-integration/testCliArgs.js new file mode 100644 index 0000000000..338994b58f --- /dev/null +++ b/test/src/runner/cucumber-integration/testCliArgs.js @@ -0,0 +1,75 @@ +const assert = require('assert'); +const path = require('path'); +const mockery = require('mockery'); +const common = require('../../../common.js'); +const CucumberRunner = common.require('runner/test-runners/cucumber.js'); + + + + +describe('Cucumber cli arguements', function(){ + let cliArgs; + + this.beforeAll(function(){ + mockery.enable(); + mockery.registerMock('@cucumber/cucumber/lib/cli/index', + { + default: class CucumberCli { + constructor({ + argv, cwd, stdout + }){ + cliArgs =argv; + } + } + + }); + }); + + this.afterAll(function(){ + mockery.deregisterAll(); + mockery.disable(); + }); + + it('Cucumber cli args --require-modules', function(){ + const runner = new CucumberRunner({test_runner: { + type: 'cucumber', + options: {} + }}, {'require-module': ['coffeescript/register', 'ts-node/register']}); + runner.createTestSuite({modules: [path.join(__dirname, '../../../cucumbertests/testSample.js')], modulePath: [path.join(__dirname, '../../../cucumbertests/testSample.js')]}); + assert.ok(cliArgs.includes('--require-module')); + let index = cliArgs.indexOf('--require-module')+1; + assert.strictEqual(cliArgs[index], 'coffeescript/register'); + index = cliArgs.indexOf('--require-module', index)+1; + assert.strictEqual(cliArgs[index], 'ts-node/register'); + }); + + it('Cucumber cli args', function(){ + const runner = new CucumberRunner({test_runner: { + type: 'cucumber', + options: {} + }}, {'no-strict': true, retries: 2, profile: 'local', 'fail-fast': true, parallel: 3, name: 'sample', 'retry-tag-filter': '@nightwatch'}, {}); + runner.createTestSuite({modules: [path.join(__dirname, '../../../cucumbertests/testSample.js')], modulePath: [path.join(__dirname, '../../../cucumbertests/testSample.js')]}); + assert.ok(cliArgs.includes('--name')); + assert.strictEqual(cliArgs[cliArgs.indexOf('--name')+1], 'sample'); + assert.ok(cliArgs.includes('--fail-fast')); + assert.ok(cliArgs.includes('--retry')); + assert.strictEqual(cliArgs[cliArgs.indexOf('--retry')+1], 2); + assert.ok(cliArgs.includes('--retry-tag-filter')); + assert.strictEqual(cliArgs[cliArgs.indexOf('--retry-tag-filter')+1], '@nightwatch'); + assert.ok(cliArgs.includes('--profile')); + assert.strictEqual(cliArgs[cliArgs.indexOf('--profile')+1], 'local'); + assert.ok(cliArgs.includes('--no-strict')); + assert.ok(cliArgs.includes('--parallel')); + assert.strictEqual(cliArgs[cliArgs.indexOf('--parallel')+1], 3); + }); + + it('Cucumber cli arg --dry-run', function(){ + const runner = new CucumberRunner({test_runner: { + type: 'cucumber', + options: {} + }}, {'dry-run': true}, {}); + runner.createTestSuite({modules: [path.join(__dirname, '../../../cucumbertests/testSample.js')], modulePath: [path.join(__dirname, '../../../cucumbertests/testSample.js')]}); + assert.ok(cliArgs.includes('--dry-run')); + }); + +});