@gnuechtel/nx-cucumber
v2.1.1
Published
Plugin to use Cucumber within Nx workspaces
Downloads
7,168
Readme
nx-cucumber
Plugin to use Cucumber within Nx workspaces
- Introduction
- What changed in 2.x
- Prerequisites
- Quick start
- Install Nx
- Install dependencies
- Generate Cucumber projects
- Execute Cucumber projects
- Reports
- Code coverage
- Example projects
- End-to-end tests of this project
- Continuous delivery pipeline
- Debugging and watching scenarios
- Filter Cucumber scenarios
- Special tags
- Profiles
- Logging
- Contribution
- Troubleshooting
- Migration from 1.x
Introduction
This is nx-cucumber, a plugin for Nx which integrates Cucumber to create the best possible connection between these two essential tools for quality software. The plugin provides generators and inferred tasks for Cucumber for JavaScript within Nx workspaces, with optional Playwright support.
What changed in 2.x
Version 2.x is a deliberate breaking release that simplifies the plugin architecture:
- Inferred tasks replace explicit executors. The
@gnuechtel/nx-cucumber:cucumber-apiexecutor has been removed. Projects are discovered viacucumber.jsconfig files and targets are inferred automatically using Nx Project Crystal. - Framework-native execution. Tests run via
npx cucumber-jsdirectly instead of an in-process Cucumber API. This unlocks full Cucumber CLI capabilities without plugin-specific wrappers. - Less configuration. Generated projects include a
cucumber.jsconfig file and a minimalproject.json. All Cucumber and Playwright options are configured through standard Cucumber and Playwright mechanisms. - Nx >=22 only. The 2.x line requires Nx 22 or later.
- Adapter-oriented architecture. The plugin uses an adapter contract to support multiple executable-spec frameworks. See docs/adapters/contract.md for details.
- Faster execution. Removing the executor bootstrap, in-process Cucumber API, plugin-managed dev server lifecycle, and report post-processing from the execution path results in faster test runs.
- Reporting is formatter-first. Generated projects now rely on Cucumber-native formatters (
html,json,message,junit) plus a dedicated run-metadata formatter artifact. No HTML mutation layer is used. - Legacy HTML post-processing removed. The previously exported
createBeautifulHtmlReporthelper andcucumber-html-reporterintegration are no longer part of 2.x. - All cucumber-js config formats. Plugin discovery, generation, and migration support every cucumber-js configuration file format (
cucumber.js,.cjs,.mjs,.ts,.mts,.cts,.json,.yaml,.yml). See Config file formats.
Prerequisites
The only prerequisite for this software is Node.js. In our continuous delivery pipeline, we test against the latest Node.js LTS version. Other versions are expected to work, but there is no guarantee. Since this is an Nx plugin for Cucumber, these tools are required too. To provide the best experience for browser automation, the Playwright library is supported out-of-the-box, but is completely optional and must be enabled explicitly. The plugin major version tracks the current Nx major version: nx-cucumber 2.x targets Nx 22, 3.x will target Nx 23, and so on. Only the current Nx major version is supported. CI coverage focuses on latest and next Nx versions with the latest Cucumber and Playwright dependencies.
Quick start
To immediately use this plugin with a new example React application use the following commands:
# option 1: create a new app inside an existing nx workspace
npm i -D @nx/react
npx nx g @nx/react:application gnu-app --bundler=vite --style=css --e2eTestRunner=none --routing
# option 2: create a new nx workspace with a 'gnu-app' and change to its directory
npx create-nx-workspace gnu-repo --preset=react-monorepo --e2eTestRunner=none --appName=gnu-app --bundler=vite --style=css --nxCloud=skip
cd gnu-repo
# install cucumber and playwright-test
npm i -D @cucumber/cucumber @playwright/test
# install this plugin
npm i -D @gnuechtel/nx-cucumber
# register the plugin in nx.json (enables inferred tasks)
# add "@gnuechtel/nx-cucumber" to the "plugins" array in nx.json
# inspect available Nx project ids (quick-start app id is @gnu-repo/gnu-app)
npx nx show projects
# create a cucumber project for the quick-start app project id
npx nx g @gnuechtel/nx-cucumber:project --project="@gnu-repo/gnu-app" --test-runner=playwright
# run cucumber scenarios with the generated e2e project id
npx nx e2e "@gnu-repo/gnu-app-e2e"Install Nx
There are two feasible options to install Nx:
- either via
npx create-nx-workspace@latestto setup a fresh Nx repo or - via
npx nx@latest initto convert an existing Node.js project into an Nx workspace.
It is never recommended to install all those Nx dependencies manually. It would just cause too much unnecessary work.
Install dependencies
To use this plugin and Cucumber, at least the following two dependencies must be installed in the consuming Nx workspace:
- @gnuechtel/nx-cucumber (of course)
- @cucumber/cucumber (Cucumber for JavaScript)
If we want to use the Playwright test runner, we should also install one of the following dependencies:
- playwright (Playwright library) or
- @playwright/test (Playwright Test framework)
We recommend using @playwright/test, which also includes the playwright dependency and provides very useful expect extensions.
No additional reporting dependency is required for the default outputs.
Generate Cucumber projects
Choosing the --project value
--project must be an existing Nx project id, not the workspace folder name.
Use npx nx show projects to list valid project ids in your workspace. For Nx 22 monorepo presets (including this quick-start), app project ids are scoped by default (for example @gnu-repo/gnu-app).
Some existing/legacy workspaces can still use unscoped ids, so always copy the exact id from npx nx show projects.
If the id is scoped, quote it in shell commands:
npx nx g @gnuechtel/nx-cucumber:project --project="@smoke-test/smoke-test"If --project does not exist, generation fails fast with an explicit error.
When --name is unscoped and the tested project id is scoped, the generated e2e project id inherits the same scope.
Basic project generator usage
After the installation of the dependencies, we can create a project with Cucumber, for any kind of node application:
# Prerequisite: create an application and identify its Nx project id via "npx nx show projects"
# default core test runner (generates an e2e app 'my-project-e2e')
npx nx g @gnuechtel/nx-cucumber:project --project="<app-project-id>"
# playwright test runner (also generates an e2e app 'my-project-e2e')
npx nx g @gnuechtel/nx-cucumber:project --project="<app-project-id>" --test-runner=playwright
# playwright test runner with custom e2e project name (generates an app 'my-project-foo-e2e')
npx nx g @gnuechtel/nx-cucumber:project --project="<app-project-id>" --name my-project-foo-e2e --test-runner=playwrightThe generator creates:
- A
cucumber.jsconfig file with paths, formatters, and TypeScript support - A minimal
project.jsonwith lint target and implicit dependencies - Feature files, step definitions, and TypeScript configuration
The e2e target behavior depends on the selected test runner:
- Core runner: no explicit
e2etarget is generated. Thee2etask is inferred by the plugin fromcucumber.js. - Playwright runner: explicit command targets are generated:
e2e-prepareinstalls Playwright Chromium (Linux uses--with-deps) and is configured withcache: false.e2eruns a generatedrun-e2e.jslifecycle script that manages the full dev server lifecycle (clear port, start server, wait for readiness, run Cucumber, stop server) using only Node.js built-ins.e2e-cirunse2e-prepareand thene2e.
Additional project generator options
All possible project generator options may be passed as command-line parameters and are stored in the related schema file. They can also be displayed on the command-line with the following command: npx nx g @gnuechtel/nx-cucumber:project --help.
Execute Cucumber projects
Inferred tasks
In 2.x, no executor configuration is needed. For core projects, the e2e target is inferred automatically when the plugin detects a cucumber.js config file in a project directory:
npx nx e2e my-project-e2eFor Playwright projects generated by this plugin, explicit command targets are created:
e2e-prepare: browser setupe2e: test execution with managed web-server lifecyclee2e-ci:e2e-prepare+e2e
Plugin registration
To enable inferred tasks, register the plugin in nx.json:
{
"plugins": ["@gnuechtel/nx-cucumber"]
}Target names can be customized:
{
"plugins": [
{
"plugin": "@gnuechtel/nx-cucumber",
"options": {
"e2eTargetName": "integration"
}
}
]
}Cucumber configuration
The generator scaffolds a cucumber-js configuration file for each project. It is a standard cucumber-js config, so any advanced Cucumber option can be set there.
Default configuration
By default the generator creates a cucumber.js. Because the code formats are evaluated when loaded, options can be computed at runtime — for example, deriving the tag filter from an environment variable:
const tagsFilter =
process.env['CI_STAGE'] !== 'qa'
? 'and not @qa-stage-only'
: 'and (@qa-stage or @qa-stage-only)';
module.exports = {
default: {
tags: `not @ignore ${tagsFilter}`,
},
};Config file formats
Nx-cucumber supports every cucumber-js configuration file format for inferred-task discovery, generator output, and migration output. Select one with the generator's configFormat option (default js):
| configFormat | Config file | Style |
| -------------- | --------------- | -------- |
| js (default) | cucumber.js | CommonJS |
| cjs | cucumber.cjs | CommonJS |
| mjs | cucumber.mjs | ESM |
| ts | cucumber.ts | ESM / TS |
| mts | cucumber.mts | ESM / TS |
| cts | cucumber.cts | ESM / TS |
| json | cucumber.json | JSON |
| yaml | cucumber.yaml | YAML |
| yml | cucumber.yml | YAML |
The code formats (js, cjs, mjs, ts, mts, cts) are evaluated as modules, so they can contain logic like the default configuration above. The data formats (json, yaml, yml) are static and hold plain values only.
The same configuration expressed in the remaining formats:
ES module — cucumber.mjs
const tagsFilter =
process.env['CI_STAGE'] !== 'qa'
? 'and not @qa-stage-only'
: 'and (@qa-stage or @qa-stage-only)';
export default {
default: {
tags: `not @ignore ${tagsFilter}`,
},
};TypeScript — cucumber.ts, cucumber.mts, cucumber.cts
import type { IConfiguration } from '@cucumber/cucumber';
const tagsFilter =
process.env['CI_STAGE'] !== 'qa'
? 'and not @qa-stage-only'
: 'and (@qa-stage or @qa-stage-only)';
const config: { default: Partial<IConfiguration> } = {
default: {
tags: `not @ignore ${tagsFilter}`,
},
};
export default config;JSON — cucumber.json
JSON is static and cannot run the environment check above, so the tags are set directly:
{
"default": {
"tags": "not @ignore"
}
}YAML — cucumber.yaml, cucumber.yml
default:
tags: 'not @ignore'World parameters
Playwright-related options that were previously set in project.json executor options are now configured via worldParameters in cucumber.js:
module.exports = {
default: {
// ... paths, require, etc.
worldParameters: {
headed: false,
browser: 'chromium',
disableVideoFiles: true,
disableVideoAttachments: true,
disableScreenshotFiles: false,
disableScreenshotAttachments: false,
disableJavaScript: false,
disableCoverage: false,
},
},
};Enable videos
By default, video files and attachments are disabled. To enable them, set the world parameters in cucumber.js:
module.exports = {
default: {
// ... paths, require, etc.
worldParameters: {
disableVideoFiles: false,
disableVideoAttachments: false,
},
},
};Change screenshot options
By default, screenshots are attached to every Playwright scenario. Screenshot files are created only on error. To change this:
module.exports = {
default: {
// ... paths, require, etc.
worldParameters: {
enableSuccessfulScreenshotFiles: true, // also create files for passing scenarios
// disableScreenshotFiles: true, // disable screenshot files entirely
// disableScreenshotAttachments: true, // disable screenshot attachments in reports
},
},
};Custom Cucumber world
For the Playwright and the core test runner, an additional custom world may be created to extend the default behavior. To achieve this, we add the --custom-world parameter to the project generator.
Playwright world
A custom Playwright world must be derived from the PlaywrightWorld class of nx-cucumber since a lot of default behavior for the Playwright test runner is implemented there. To enable a custom Playwright world, it is also required to register that world via setWorldConstructor. The project generator will create this required code for us.
An example Playwright world, which extends the built-in clean-up method looks like this:
import { IWorldOptions } from '@cucumber/cucumber';
import { PlaywrightWorld } from '@gnuechtel/nx-cucumber';
export class CustomPlaywrightWorld extends PlaywrightWorld {
constructor(options: IWorldOptions) {
super(options);
}
override async cleanUp(): Promise<void> {
console.log('Some additional clean-up code in the custom playwright world');
await super.cleanUp();
}
}Core world
A custom core world is written from scratch and should be derived from the default World provided by Cucumber. An example core world, which adds a get-item and set-item method looks like this:
import { IWorldOptions, World } from '@cucumber/cucumber';
export class CustomWorld extends World {
constructor(options: IWorldOptions) {
super(options);
}
public setItem<T>(key: string, value: T): void {
this._items[key] = value;
}
public getItem<T>(key: string, defaultValue?: T): T {
return (this._items[key] as T) ?? (defaultValue as T);
}
private _items: Record<string, unknown> = {};
}Reports
Built-in formatter outputs
Generated projects configure Cucumber-native formatter outputs by default:
- HTML:
dist/e2e/<project-root>/reports/html/cucumber-test-report-builtin.html - JSON:
dist/e2e/<project-root>/reports/cucumber-json/cucumber-test-report.json - NDJSON messages:
dist/e2e/<project-root>/reports/cucumber-messages/cucumber-messages.ndjson - XML (JUnit):
dist/e2e/<project-root>/reports/test-results/cucumber-test-report.xml
Run metadata report
Generated projects also include an additional metadata artifact:
- Metadata JSON:
dist/e2e/<project-root>/reports/metadata/cucumber-run-metadata.json
This file is written by @gnuechtel/nx-cucumber/src/core/cucumber-run-metadata-formatter.js and is intentionally separate from Cucumber's standard JSON/NDJSON schema. It contains run context (for example Cucumber meta info, run timestamps, selected world parameters, and environment hints like browser/baseUrl/mode).
Custom formatter configuration
The plugin does not lock formatter choices. You can freely add, remove, or replace formatters in your cucumber.js file. The generated metadata formatter receives values via formatOptions.nxCucumberRunMetadata.worldParameters, while normal runtime behavior still uses worldParameters.
Code coverage
Code coverage is supported for the Playwright test runner through the PlaywrightWorld hooks, which collect Istanbul coverage automatically. To enable code coverage for a Playwright project:
- Install the Vite Istanbul plugin:
npm i -D vite-plugin-istanbul - Configure the plugin in the application's
vite.config.ts - The
PlaywrightWorldhooks will automatically collect and report coverage
All example projects demonstrate code coverage configuration.
Example projects
Main examples
This repository contains example projects that can be used directly to see nx-cucumber in action.
| | example react application and cucumber project | example Node.js app and cucumber project |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| Execute cucumber project | npx nx e2e example-react-app-e2e | npx nx e2e example-node-app-e2e |
| Source cucumber project | apps/example/react-app-e2e | apps/example/node-app-e2e |
More examples
If we have executed our nx-cucumber end-to-end tests, we got a lot of more example projects and their Cucumber output for free.
End-to-end tests of this project
We support Cucumber with this plugin, and it would be a shame if we used anything other than Cucumber for our own end to end tests. So, we just do it!
Generation coverage includes validation for unknown --project ids and execution against real Nx project ids detected in the test workspace.
To run our own end-to-end tests we simply execute them by:
npm run e2e:nx-cucumberContinuous delivery pipeline
Our continuous delivery pipeline runs builds and tests for Linux, macOS and Windows on the latest Node.js LTS version.
The end-to-end tests in the continuous delivery pipeline run on combinations of:
- latest and next Nx version
- the latest Cucumber version
- the latest and next Playwright version
Linux runs the full test suite. macOS and Windows run @core tagged scenarios for faster feedback.
Debugging and watching scenarios
During the development of Cucumber scenarios, it can be useful to use debugging and watching. Debugging means, that we can go to the Cucumber scenarios step by step. Watching means, that scenarios will be executed automatically after file changes.
Debugging
Debugging is available for the Playwright test runner only.
It enables the Playwright inspector with paused execution in a headed browser.
Set the PWDEBUG environment variable:
PWDEBUG=1 npx nx e2e my-project-e2eWatching
There is no dedicated watch mode in @gnuechtel/nx-cucumber.
If you want automatic re-runs on file changes, you can use Nx workspace watching as an optional outer loop:
npx nx watch --projects=my-project-e2e -- npx nx e2e my-project-e2eThis command belongs to Nx workspace tooling, not to a plugin-specific watch implementation.
Filter Cucumber scenarios
While development of Cucumber scenarios, we often want to execute only selected scenarios. We can achieve this by using the filter capabilities of Cucumber in the cucumber.js config or via CLI arguments.
Filter by tags
Add a tag to a scenario and filter:
@focus
Scenario: a user wants to get project information
Given any user has found our project home page
When the user requests project information
Then some advices will be shownnpx nx e2e my-project-e2e -- --tags "@focus"Filter by name
We can filter scenarios by name with regular expressions:
# execute all scenarios where the name contains 'payment'
npx nx e2e my-project-e2e -- --name "payment"
# execute all scenarios where the name does not contain 'mobile' nor something like 'top secret'
npx nx e2e my-project-e2e -- --name '^((?!mobile|top.?secret).)*$'Special tags
Cucumber tags can be used for scenario filtering and to control technical behavior. Nx-cucumber provides some technical built-in tags which are described here.
Tags @javascript and @noscript
In cucumber.js we can set worldParameters.disableJavaScript to true. With that setting, we would disable javascript for all Cucumber scenarios with the Playwright test runner. However, we can enable javascript again for selected scenarios by using the @javascript tag:
@javascript
Scenario: hidden easter egg
Given a user has found an easter egg on the website
When the user spins the wheel of fortune
Then a random color will be displayedOn the other hand, the default configuration is enabled javascript. But maybe we want to ensure that some scenario is working without javascript. Then we could use the @noscript tag:
@noscript
Scenario: homepage is displayed without javascript
When any user finds our project home page
Then a welcome message will be shownTag @headed
By default, all Cucumber scenarios with Playwright run in a headless browser. Some actions like copy-and-paste do not work headless. In such cases, we can add the @headed tag to scenarios to use a headed browser.
@headed
Scenario: Copy search data
Given the user has searched for content
When the users copies the search
Then the search data is stored in the clipboardProfiles
Nx-cucumber supports Cucumber profiles in the cucumber.js config:
module.exports = {
default: {
// ... default configuration
},
homepage: { name: ['a user visits the home page'] },
'project-info': { name: ['a user wants to get project information'] },
};Run profiles from the command-line:
npx nx e2e my-project-e2e -- --profile homepageLogging
Logging messages are produced by the debug library. The project generator creates a .env file which contains the default logging configuration. By changing the .env file in the generated Cucumber project, the verbosity of the log output may be decreased or increased.
Contribution
Currently, this project is written and maintained by a single person. Development is active with focus on 2.x improvements. Contributing is welcome, especially bug fixes and compatibility updates. Please open an issue if you want to join.
Troubleshooting
A tag is not found
A common mistake, is to forget the @ before any tag. This would be wrong: ~~npx nx e2e example-react-app-e2e -- --tags "mytag"~~.
The correct usage is: npx nx e2e example-react-app-e2e -- --tags "@mytag".
Some Cucumber product feature does not work with nx-cucumber
Since 2.x uses framework-native execution via npx cucumber-js, all Cucumber CLI features are available directly. Configure them in the cucumber.js file.
If a feature is missing, please open an issue with a minimal reproducible setup.
Garbled terminal output with verbose Playwright logs (pw:api)
If log lines look overwritten or scattered (for example on macOS, Linux, or Windows terminals), there are usually two independent redraw layers:
- Cucumber formatter output:
progress-baris a real-time updating bar (redraws terminal line).progressis step-by-step progress output without a live bar redraw.
- Nx task output lifecycle:
- dynamic/TUI modes may also rewrite terminal output while tasks run.
staticprints append-only output.
References:
- Cucumber formatters (
progressvsprogress-bar): https://github.com/cucumber/cucumber-js/blob/main/docs/formatters.md - Nx
outputStylemodes: https://nx.dev/reference/core-api/nx/documents/show#outputstyle
nx-cucumber templates currently use progress-bar. If redraw artifacts are distracting with verbose pw:api logs, switch to progress (or keep only summary) in your local cucumber.js.
If you still want fully append-only Nx logs, run:
npx nx e2e "<project-id>" --outputStyle=staticor set this in a workspace-root .env:
NX_DEFAULT_OUTPUT_STYLE=staticNote: nx-cucumber intentionally does not generate or modify a workspace-root .env, because that would change logging behavior globally for unrelated projects in the same workspace.
Workspace sync after generating projects
On Nx 20+, running e2e immediately after generating a new nx-cucumber project (core or Playwright) may fail with:
The workspace is out of sync
[@nx/js:typescript-sync]: Some TypeScript configuration files are missing project references...This is standard Nx behaviour and is not Windows-specific. It can happen on macOS, Linux, and Windows when sync generators detect pending workspace updates.
For deterministic smoke-test runs, execute:
npx nx syncand then rerun your npx nx e2e "<project-id>" command.
To avoid this manual step in interactive environments, configure nx.json:
{
"sync": { "applyChanges": true }
}With this setting Nx automatically applies sync changes before running tasks in interactive terminals.
In non-interactive local runs (no TTY), Nx cannot prompt; if sync changes are needed, task execution stops with a workspace-out-of-sync error.
In CI on Nx 22, task-time sync prompting is skipped, so add an explicit preflight:
npx nx sync:checkIf it reports changes are required, run npx nx sync and commit the resulting files.
npx nx reset is a recovery step for stale daemon/project-graph state (for example Cannot find project "..." right after generation, or a newly generated project missing from npx nx show projects even after npx nx sync). It is not the primary sync fix.
TS_NODE_PROJECT and formatter file extensions
Generated cucumber.js files set process.env.TS_NODE_PROJECT explicitly. Keep this setting so ts-node/register resolves the correct tsconfig.json in monorepos.
If you add custom formatters, prefer .js (or precompiled output) for formatter modules referenced in format. Cucumber loads formatter modules via dynamic import, and pointing directly to a .ts formatter can fail with ERR_UNKNOWN_FILE_EXTENSION before TypeScript transpilation hooks are applied.
Windows Playwright teardown noise
On Windows, after all scenarios finish, the following message may appear in the output:
ERROR: The process "XXXX" not found.This is harmless. The generated run-e2e.js lifecycle script attempts to stop the dev server after testing. If the server has already exited on its own, taskkill reports this message. It does not indicate a test failure.
Migration from 1.x
Prerequisites
- Upgrade to Nx
>=22 - Install
@gnuechtel/nx-cucumber@2
Version compatibility and upgrade order
@gnuechtel/nx-cucumber 1.x does not have one single Nx compatibility range (taken from published npm peerDependencies):
| nx-cucumber 1.x | Nx peer compatibility |
| --------------- | ------------------------- |
| 1.0.0 | ^16 \|\| ^17 |
| 1.0.1 | ^16 \|\| ^17 \|\| ^18 |
| 1.0.2 | 16 - 19 |
| 1.1.0 | >=19 <23 |
| 1.2.0 - 1.4.1 | >=20 <23 \|\| ^22.0.0-0 |
Recommended upgrade order for projects moving from 1.x to 2.x:
- If your project is on
1.0.0,1.0.1, or1.0.2, first install and run with a compatible Nx (for example Nx 17) to avoid peer-resolution conflicts. - Remove the legacy plugin package from
package.json:npm remove @gnuechtel/nx-cucumber - Upgrade Nx to 22:
npx [email protected] migrate 22.6.4npm installnpx nx migrate --run-migrations - Install
@gnuechtel/nx-cucumber@2. - Run the plugin migration (
nx migrate @gnuechtel/nx-cucumber@2+nx migrate --run-migrations).
For 1.1.0+, Nx 22 is already within the supported peer range. The temporary Nx-17 compatibility step is not required there.
Automated migration via nx migrate
You can run the legacy executor migration as part of the standard Nx migration flow:
npx nx migrate @gnuechtel/nx-cucumber@2
npx nx migrate --run-migrationsWhat this migration does:
- Detects projects using
@gnuechtel/nx-cucumber:cucumber-api. - Adds
@gnuechtel/nx-cucumbertonx.jsonplugins (if missing). - Removes legacy executor targets (
e2e-cucumber, and legacye2ewrappers pointing toe2e-cucumber). - Removes legacy
e2e-watchtargets that use the old--watch-messagerun-command flow. - Creates a
cucumber.jsfile when missing, based on detected legacy options. - Writes a migration report to
tmp/nx-cucumber-migration-report.json.
Dry-run mode:
- Set
NX_CUCUMBER_MIGRATION_DRY_RUN=truebefore running migrations to print planned changes without modifying files.
CI migration tests
The repository includes an automated migration matrix test (@migration scenarios) for all stable 1.x versions (1.0.0 to 1.4.1).
- For
1.0.0 - 1.0.2, the test uses a compatible Nx 17 workspace first, removes the legacy plugin package, upgrades Nx to 22, then runs the 2.x migration. - For
1.1.0+, the test runs directly on Nx 22.
npm install failures from legacy generator internals are not treated as acceptable in these migration tests.
Step 1: Register the plugin
Add the plugin to nx.json:
{
"plugins": ["@gnuechtel/nx-cucumber"]
}Step 2: Create cucumber.js config
For each e2e project, create a cucumber.js file. For Playwright projects:
const outputDir = 'dist/e2e/apps/my-project-e2e';
module.exports = {
default: {
paths: ['apps/my-project-e2e/features/**/*.feature'],
requireModule: ['ts-node/register'],
require: [
'apps/my-project-e2e/src/**/*.ts',
'node_modules/@gnuechtel/nx-cucumber/src/playwright/playwright-world-default.js',
'node_modules/@gnuechtel/nx-cucumber/src/playwright/playwright-hooks.js',
],
tags: 'not @ignore',
format: [
'summary',
'progress-bar',
`json:${outputDir}/reports/cucumber-json/cucumber-test-report.json`,
`message:${outputDir}/reports/cucumber-messages/cucumber-messages.ndjson`,
`html:${outputDir}/reports/html/cucumber-test-report-builtin.html`,
`junit:${outputDir}/reports/test-results/cucumber-test-report.xml`,
],
publishQuiet: true,
},
};For core (non-Playwright) projects, omit the Playwright require entries.
Step 3: Simplify project.json
Remove the executor-based e2e and e2e-cucumber targets from project.json. Also remove old e2e-watch run-commands. The plugin infers the e2e target automatically from the cucumber.js file. Keep only non-inferred targets like lint.
Step 4: Move executor options to cucumber.js
| 1.x executor option | 2.x equivalent |
| ------------------------------ | ----------------------------------------------------- |
| testRunner | Which require entries are in cucumber.js |
| featuresDirectory | paths in cucumber.js |
| tags | tags in cucumber.js |
| cucumberTimeout | timeout in cucumber.js |
| baseUrl, headed, browser | worldParameters in cucumber.js |
| disableVideoFiles, etc. | worldParameters in cucumber.js |
| devServerTarget | Use Nx task dependencies (dependsOn) |
| reportOptions | format entries in cucumber.js |
| instrumentTestRunner | External coverage tooling (nyc, vite-plugin-istanbul) |
Step 5: Verify
npx nx e2e my-project-e2eThe inferred target runs npx cucumber-js with the configuration from cucumber.js.
Rollback strategy
- Revert the migration commit in git if validation fails.
- Remove
@gnuechtel/nx-cucumberfromnx.jsonplugins if rollback to 1.x is required. - Restore previous
project.jsonexecutor targets andcucumber.jsfrom version control.
Known limitations
- Existing
cucumber.jsfiles are not overwritten automatically. - Framework-native watch mode is not generated automatically. If you still need watch, add your own adapter-native watch command after migration.
- Highly customized run-command wrappers may require manual cleanup after migration.
