@gnuechtel/nx-cucumber 24.1.0 → 24.2.0-17559059976
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -101
- package/package.json +3 -3
- package/src/generators/project/files/playwright-bdd/README.md.template +39 -2
- package/src/generators/project/files/playwright-bdd/playwright.config.mts.template +16 -3
- package/src/generators/project/files/playwright-bdd-api/features/health.feature.template +4 -0
- package/src/generators/project/files/playwright-bdd-api/src/fixtures.ts.template +3 -0
- package/src/generators/project/files/playwright-bdd-api/src/steps/health.steps.ts.template +8 -0
- package/src/generators/project/playwright-bdd.js +36 -4
- package/src/generators/project/playwright-bdd.js.map +1 -1
- package/src/generators/project/project.js +3 -0
- package/src/generators/project/project.js.map +1 -1
- package/src/generators/project/schema.d.ts +3 -0
- package/src/generators/project/schema.json +13 -0
package/README.md
CHANGED
|
@@ -7,8 +7,8 @@ Plugin to use Cucumber within Nx workspaces
|
|
|
7
7
|
- [Introduction](#introduction)
|
|
8
8
|
- [Release 24.1.0 and versioning](#release-2410-and-versioning)
|
|
9
9
|
- [Playwright-BDD and UI Mode](#playwright-bdd-and-ui-mode)
|
|
10
|
+
- [API-only Playwright-BDD tests](#api-only-playwright-bdd-tests)
|
|
10
11
|
- [Dependency security notice](#dependency-security-notice)
|
|
11
|
-
- [What changed in 2.x](#what-changed-in-2x)
|
|
12
12
|
- [Prerequisites](#prerequisites)
|
|
13
13
|
- [Quick start](#quick-start)
|
|
14
14
|
- [Install Nx](#install-nx)
|
|
@@ -36,7 +36,6 @@ Plugin to use Cucumber within Nx workspaces
|
|
|
36
36
|
- [Code coverage](#code-coverage)
|
|
37
37
|
- [Example projects](#example-projects)
|
|
38
38
|
- [Main examples](#main-examples)
|
|
39
|
-
- [More examples](#more-examples)
|
|
40
39
|
- [End-to-end tests of this project](#end-to-end-tests-of-this-project)
|
|
41
40
|
- [Continuous delivery pipeline](#continuous-delivery-pipeline)
|
|
42
41
|
- [Debugging and watching scenarios](#debugging-and-watching-scenarios)
|
|
@@ -68,7 +67,7 @@ own changes. For example, a plugin-only fix can be released as 23.0.1 while the
|
|
|
68
67
|
supported Nx baseline stays the same. The exact compatibility ranges are defined
|
|
69
68
|
in the package's dependencies and peer dependencies.
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
The Cucumber integration targets Nx 24, Cucumber 13 and Playwright 1.64+. Existing worlds, hooks and test metadata remain supported. Version 24.1.0 also adds Playwright-BDD generation and conversion through the normal Nx Playwright plugin. See the [24.1.0 release notes](../../docs/release-notes/24.1.0.md), including the reviewed upstream security exception, before upgrading.
|
|
72
71
|
|
|
73
72
|
## Playwright-BDD and UI Mode
|
|
74
73
|
|
|
@@ -103,6 +102,16 @@ Playwright Test installed. The converter deliberately leaves original projects
|
|
|
103
102
|
and dependency cleanup to us. Follow the
|
|
104
103
|
[cleanup and uninstall steps](https://gitlab.com/gnuechtel/open-source/-/blob/main/docs/playwright-bdd-migration.md#remove-nx-cucumber-after-migration).
|
|
105
104
|
|
|
105
|
+
## API-only Playwright-BDD tests
|
|
106
|
+
|
|
107
|
+
Version 24.2.0 adds API-only generation with Playwright's native request fixtures
|
|
108
|
+
and requires no browser installation. See the
|
|
109
|
+
[API guide](../../docs/playwright-bdd-api.md) for generation, backend startup,
|
|
110
|
+
authentication, reports and execution without our runtime packages.
|
|
111
|
+
Our [local API example](../../apps/example/api-app-bdd-e2e/README.md) demonstrates
|
|
112
|
+
health checks, authenticated requests and rejection without a token.
|
|
113
|
+
The [24.2.0 release notes](../../docs/release-notes/24.2.0.md) summarize the changes.
|
|
114
|
+
|
|
106
115
|
## Dependency security notice
|
|
107
116
|
|
|
108
117
|
**Known upstream dependency risk: accepted release exception.** As checked on October
|
|
@@ -135,20 +144,6 @@ findings and scan errors still block release. The dependency itself remains
|
|
|
135
144
|
affected until a repaired Nx patch is adopted. See
|
|
136
145
|
[the security explanation and verification](../../docs/dependency-security-fix.md).
|
|
137
146
|
|
|
138
|
-
## What changed in 2.x
|
|
139
|
-
|
|
140
|
-
Version 2.x is a deliberate breaking release that simplifies the plugin architecture:
|
|
141
|
-
|
|
142
|
-
- **Inferred tasks replace explicit executors.** The `@gnuechtel/nx-cucumber:cucumber-api` executor has been removed. Projects are discovered via `cucumber.js` config files and targets are inferred automatically using [Nx Project Crystal](https://nx.dev/concepts/inferred-tasks).
|
|
143
|
-
- **Framework-native execution.** Tests run via `npx cucumber-js` directly instead of an in-process Cucumber API. This unlocks full Cucumber CLI capabilities without plugin-specific wrappers.
|
|
144
|
-
- **Less configuration.** Generated projects include a `cucumber.js` config file and a minimal `project.json`. All Cucumber and Playwright options are configured through standard Cucumber and Playwright mechanisms.
|
|
145
|
-
- **Nx 22.** The 2.x line targets Nx `>=22 <23`.
|
|
146
|
-
- **Adapter-oriented architecture.** The plugin uses an adapter contract to support multiple executable-spec frameworks. See [docs/adapters/contract.md](https://gitlab.com/gnuechtel/open-source/-/blob/main/docs/adapters/contract.md) for details.
|
|
147
|
-
- **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.
|
|
148
|
-
- **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.
|
|
149
|
-
- **Legacy HTML post-processing removed.** The previously exported `createBeautifulHtmlReport` helper and `cucumber-html-reporter` integration are no longer part of 2.x.
|
|
150
|
-
- **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](#config-file-formats).
|
|
151
|
-
|
|
152
147
|
## Prerequisites
|
|
153
148
|
|
|
154
149
|
This plugin requires [Node.js](https://nodejs.org/), [Nx](https://nx.dev/) and [Cucumber](https://github.com/cucumber/cucumber-js). Version 24.1.0 targets Nx `>=24 <25` and Node.js 24; published 2.x packages remain the Nx-22 path. Plugin 23.x remains available for Nx 23. Browser automation uses the [Playwright library](https://playwright.dev/docs/library) when selected by the generator. Consult `package.json` for all dependency requirements and `.gitlab-ci.yml` for the pinned CI versions. Minor and patch versions follow this plugin's changes independently of Nx.
|
|
@@ -192,9 +187,6 @@ There are two feasible options to [install Nx](https://nx.dev/getting-started/in
|
|
|
192
187
|
- either via `npx create-nx-workspace@24.0.1` to setup a fresh Nx repo or
|
|
193
188
|
- via `npx nx@24.0.1 init` to convert an existing Node.js project into an Nx workspace.
|
|
194
189
|
|
|
195
|
-
It is never recommended to install all those Nx [dependencies](https://www.npmjs.com/org/nx) manually.
|
|
196
|
-
It would just cause too much unnecessary work.
|
|
197
|
-
|
|
198
190
|
Before installing this plugin, verify the installed Nx version with `npx nx --version`: it must be `>=24 <25`. The workspace CLI can download a template with a newer Nx version independently of its own version. In that case, start from a template pinned to Nx 24 or use an existing Nx-24 workspace; do not bypass the peer requirements.
|
|
199
191
|
|
|
200
192
|
## Install dependencies
|
|
@@ -272,7 +264,7 @@ All possible project generator options may be passed as command-line parameters
|
|
|
272
264
|
|
|
273
265
|
### Inferred tasks
|
|
274
266
|
|
|
275
|
-
|
|
267
|
+
For core projects, the `e2e` target is inferred automatically when the plugin detects a supported cucumber-js config file in a project directory:
|
|
276
268
|
|
|
277
269
|
```bash
|
|
278
270
|
npx nx e2e my-project-e2e
|
|
@@ -315,7 +307,7 @@ The generator scaffolds a cucumber-js configuration file for each project. It is
|
|
|
315
307
|
|
|
316
308
|
#### Default configuration
|
|
317
309
|
|
|
318
|
-
By default the generator creates a `cucumber.js`. Because the code formats are evaluated when loaded, options can be computed at runtime
|
|
310
|
+
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:
|
|
319
311
|
|
|
320
312
|
```javascript
|
|
321
313
|
const tagsFilter = process.env['CI_STAGE'] !== 'qa' ? 'and not @qa-stage-only' : 'and (@qa-stage or @qa-stage-only)';
|
|
@@ -345,54 +337,8 @@ Nx-cucumber supports every cucumber-js configuration file format for inferred-ta
|
|
|
345
337
|
|
|
346
338
|
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.
|
|
347
339
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
**ES module** — `cucumber.mjs`
|
|
351
|
-
|
|
352
|
-
```javascript
|
|
353
|
-
const tagsFilter = process.env['CI_STAGE'] !== 'qa' ? 'and not @qa-stage-only' : 'and (@qa-stage or @qa-stage-only)';
|
|
354
|
-
|
|
355
|
-
export default {
|
|
356
|
-
default: {
|
|
357
|
-
tags: `not @ignore ${tagsFilter}`,
|
|
358
|
-
},
|
|
359
|
-
};
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
**TypeScript** — `cucumber.ts`, `cucumber.mts`, `cucumber.cts`
|
|
363
|
-
|
|
364
|
-
```typescript
|
|
365
|
-
import type { IConfiguration } from '@cucumber/cucumber';
|
|
366
|
-
|
|
367
|
-
const tagsFilter = process.env['CI_STAGE'] !== 'qa' ? 'and not @qa-stage-only' : 'and (@qa-stage or @qa-stage-only)';
|
|
368
|
-
|
|
369
|
-
const config: { default: Partial<IConfiguration> } = {
|
|
370
|
-
default: {
|
|
371
|
-
tags: `not @ignore ${tagsFilter}`,
|
|
372
|
-
},
|
|
373
|
-
};
|
|
374
|
-
|
|
375
|
-
export default config;
|
|
376
|
-
```
|
|
377
|
-
|
|
378
|
-
**JSON** — `cucumber.json`
|
|
379
|
-
|
|
380
|
-
JSON is static and cannot run the environment check above, so the tags are set directly:
|
|
381
|
-
|
|
382
|
-
```json
|
|
383
|
-
{
|
|
384
|
-
"default": {
|
|
385
|
-
"tags": "not @ignore"
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
**YAML** — `cucumber.yaml`, `cucumber.yml`
|
|
391
|
-
|
|
392
|
-
```yaml
|
|
393
|
-
default:
|
|
394
|
-
tags: 'not @ignore'
|
|
395
|
-
```
|
|
340
|
+
ES modules use `export default`; CommonJS uses `module.exports`. JSON and YAML
|
|
341
|
+
contain the same profile/options structure without executable expressions.
|
|
396
342
|
|
|
397
343
|
### World parameters
|
|
398
344
|
|
|
@@ -434,7 +380,7 @@ module.exports = {
|
|
|
434
380
|
|
|
435
381
|
### Change screenshot options
|
|
436
382
|
|
|
437
|
-
By default, screenshots are attached
|
|
383
|
+
By default, screenshots are attached after each Playwright step. Screenshot _files_ are created for unsuccessful steps. To change this:
|
|
438
384
|
|
|
439
385
|
```javascript
|
|
440
386
|
module.exports = {
|
|
@@ -543,13 +489,10 @@ This repository contains [example projects](https://gitlab.com/gnuechtel/open-so
|
|
|
543
489
|
| **Execute cucumber project** | `npx nx e2e example-react-app-e2e` | `npx nx e2e example-node-app-e2e` |
|
|
544
490
|
| **Source cucumber project** | [apps/example/react-app-e2e](https://gitlab.com/gnuechtel/open-source/-/tree/main/apps/example/react-app-e2e) | [apps/example/node-app-e2e](https://gitlab.com/gnuechtel/open-source/-/tree/main/apps/example/node-app-e2e) |
|
|
545
491
|
|
|
546
|
-
### More examples
|
|
547
|
-
|
|
548
|
-
If we have executed our nx-cucumber [end-to-end tests](#end-to-end-tests-of-this-project), we got a lot of more example projects and their Cucumber output for free.
|
|
549
|
-
|
|
550
492
|
## End-to-end tests of this project
|
|
551
493
|
|
|
552
|
-
|
|
494
|
+
The [Cucumber scenarios](https://gitlab.com/gnuechtel/open-source/-/blob/main/apps/nx-cucumber-e2e/features/nx-cucumber.feature)
|
|
495
|
+
exercise generation, migration and installed-package behavior.
|
|
553
496
|
|
|
554
497
|
Generation coverage includes validation for unknown `--project` ids and execution against real Nx project ids detected in the test workspace.
|
|
555
498
|
|
|
@@ -578,9 +521,9 @@ are retained under `dist/e2e/apps/nx-cucumber-e2e/playwright-bdd`.
|
|
|
578
521
|
|
|
579
522
|
## Continuous delivery pipeline
|
|
580
523
|
|
|
581
|
-
Our [continuous delivery pipeline](https://gitlab.com/gnuechtel/open-source/-/pipelines/latest) runs builds and tests for Linux, macOS and Windows on
|
|
524
|
+
Our [continuous delivery pipeline](https://gitlab.com/gnuechtel/open-source/-/pipelines/latest) runs builds and tests for Linux, macOS and Windows on Node.js 24.
|
|
582
525
|
|
|
583
|
-
The end-to-end tests use pinned versions in [`.gitlab-ci.yml`](../../.gitlab-ci.yml)
|
|
526
|
+
The end-to-end tests use the pinned Nx/framework versions in [`.gitlab-ci.yml`](../../.gitlab-ci.yml). Current CI jobs exclude the historical `@migration` scenario. These checks validate the existing implementation; they do not establish compatibility with future upstream releases.
|
|
584
527
|
|
|
585
528
|
Linux runs the full test suite. macOS and Windows run `@core` tagged scenarios for faster feedback.
|
|
586
529
|
|
|
@@ -592,9 +535,9 @@ Watching means, that scenarios will be executed automatically after file changes
|
|
|
592
535
|
|
|
593
536
|
### Debugging
|
|
594
537
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
538
|
+
For cucumber-js browser projects, set `PWDEBUG` to pause execution in the
|
|
539
|
+
Playwright inspector with a headed browser. Playwright-BDD projects provide
|
|
540
|
+
[native UI/debug targets](../../docs/playwright-bdd-migration.md#ui-mode-regeneration-and-debugging).
|
|
598
541
|
|
|
599
542
|
```bash
|
|
600
543
|
PWDEBUG=1 npx nx e2e my-project-e2e
|
|
@@ -723,7 +666,7 @@ The correct usage is: `npx nx e2e example-react-app-e2e -- --tags "@mytag"`.
|
|
|
723
666
|
|
|
724
667
|
### Some Cucumber product feature does not work with nx-cucumber
|
|
725
668
|
|
|
726
|
-
|
|
669
|
+
Cucumber tasks run the native `cucumber-js` CLI. Configure Cucumber options and formatters in the project's Cucumber configuration.
|
|
727
670
|
|
|
728
671
|
If a feature is missing, please open an issue with a minimal reproducible setup.
|
|
729
672
|
|
|
@@ -802,23 +745,17 @@ If it reports changes are required, run `npx nx sync` and commit the resulting f
|
|
|
802
745
|
|
|
803
746
|
### `TS_NODE_PROJECT` and formatter file extensions
|
|
804
747
|
|
|
805
|
-
|
|
748
|
+
Inferred Cucumber tasks set `TS_NODE_PROJECT` to the project's `tsconfig.json`.
|
|
749
|
+
For generated Cucumber/Playwright projects, `run-e2e.js` sets it for the Cucumber
|
|
750
|
+
child process. New config templates do not set it as a module side effect.
|
|
751
|
+
When invoking `cucumber-js` directly, supply the same environment variable so
|
|
752
|
+
`ts-node/register` resolves the project's TypeScript configuration.
|
|
806
753
|
|
|
807
754
|
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.
|
|
808
755
|
|
|
809
|
-
### Windows Playwright teardown noise
|
|
810
|
-
|
|
811
|
-
On Windows, after all scenarios finish, the following message may appear in the output:
|
|
812
|
-
|
|
813
|
-
```
|
|
814
|
-
ERROR: The process "XXXX" not found.
|
|
815
|
-
```
|
|
816
|
-
|
|
817
|
-
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.
|
|
818
|
-
|
|
819
756
|
## Migration from 1.x
|
|
820
757
|
|
|
821
|
-
The following is the historical migration to **2.x on Nx 22**. Use that intermediate release before assessing the separate [Nx
|
|
758
|
+
The following is the historical migration to **2.x on Nx 22**. Use that intermediate release before assessing the separate [Nx 23 upgrade](../../docs/release-notes/23.0.0.md). The historical migration scenario is separate from current compatibility validation.
|
|
822
759
|
|
|
823
760
|
### Prerequisites
|
|
824
761
|
|
|
@@ -873,14 +810,12 @@ Dry-run mode:
|
|
|
873
810
|
|
|
874
811
|
- Set `NX_CUCUMBER_MIGRATION_DRY_RUN=true` before running migrations to print planned changes without modifying files.
|
|
875
812
|
|
|
876
|
-
###
|
|
877
|
-
|
|
878
|
-
The repository includes an automated migration matrix test (`@migration` scenarios) for all stable 1.x versions (`1.0.0` to `1.4.1`).
|
|
879
|
-
|
|
880
|
-
- 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.
|
|
881
|
-
- For `1.1.0+`, the test runs directly on Nx 22.
|
|
813
|
+
### Historical migration tests
|
|
882
814
|
|
|
883
|
-
|
|
815
|
+
The repository retains an `@migration` scenario for a configured legacy version,
|
|
816
|
+
but current CI jobs exclude it. It is not an active all-1.x compatibility matrix.
|
|
817
|
+
The migration helper handles the Nx 17 to 22 upgrade path for `1.0.0` through `1.0.2`;
|
|
818
|
+
`1.1.0+` can start on Nx 22.
|
|
884
819
|
|
|
885
820
|
### Step 1: Register the plugin
|
|
886
821
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gnuechtel/nx-cucumber",
|
|
3
|
-
"version": "24.
|
|
3
|
+
"version": "24.2.0-17559059976",
|
|
4
4
|
"description": "Plugin to use Cucumber within Nx workspaces",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"@nx/devkit": ">=24 <25",
|
|
13
13
|
"minimatch": "^10.0.0",
|
|
14
14
|
"tslib": "^2.8.1",
|
|
15
|
-
"@gnuechtel/shared-coverage": "24.
|
|
16
|
-
"@gnuechtel/shared-util": "24.
|
|
15
|
+
"@gnuechtel/shared-coverage": "24.2.0-17559059976",
|
|
16
|
+
"@gnuechtel/shared-util": "24.2.0-17559059976"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"@cucumber/cucumber": ">=13 <14",
|
|
@@ -6,10 +6,12 @@ the normal `@nx/playwright` plugin executes them. No nx-cucumber runtime is used
|
|
|
6
6
|
Run these commands from the Nx workspace root:
|
|
7
7
|
|
|
8
8
|
```sh
|
|
9
|
-
npx playwright install chromium
|
|
9
|
+
<% if (!isApi) { %>npx playwright install chromium
|
|
10
|
+
<% } %>
|
|
10
11
|
npx nx run "<%= name %>:<%= e2eTarget %>"
|
|
11
12
|
npx nx run "<%= name %>:<%= ciTarget %>"
|
|
12
|
-
npx nx run "<%= name %>:<%= e2eTarget %>-headed"
|
|
13
|
+
<% if (!isApi) { %>npx nx run "<%= name %>:<%= e2eTarget %>-headed"
|
|
14
|
+
<% } %>
|
|
13
15
|
npx nx run "<%= name %>:<%= e2eTarget %>-ui"
|
|
14
16
|
npx nx run "<%= name %>:<%= e2eTarget %>-debug"
|
|
15
17
|
```
|
|
@@ -30,6 +32,40 @@ npx bddgen --config <%= projectRoot %>/playwright.config.mts
|
|
|
30
32
|
npx playwright test --config <%= projectRoot %>/playwright.config.mts
|
|
31
33
|
```
|
|
32
34
|
|
|
35
|
+
<% if (isApi) { %>
|
|
36
|
+
This API-only project uses Playwright's native `request` fixture and needs no
|
|
37
|
+
browser installation. The example expects `GET /health` to return HTTP 200 and
|
|
38
|
+
JSON containing `{ "status": "ok" }`. Adapt the endpoint and assertions to our
|
|
39
|
+
backend contract; the generator does not change the backend.
|
|
40
|
+
|
|
41
|
+
`API_BASE_URL` overrides the default in `playwright.config.mts`. An optional
|
|
42
|
+
`API_TOKEN` sets the `Authorization: Bearer ...` header on requests. Supply values
|
|
43
|
+
through our shell or CI secret store; no `.env` loader is installed. Never commit
|
|
44
|
+
credentials. Change `extraHTTPHeaders` for a different authentication scheme.
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
API_BASE_URL=http://localhost:3000 npx nx run "<%= name %>:<%= ciTarget %>" --skip-nx-cache
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
<% if (apiServeCommandJson) { %>
|
|
51
|
+
Playwright starts the configured Nx target and waits for the base URL. Keep that
|
|
52
|
+
URL consistent with the target's host/port; no frontend port flags are added.
|
|
53
|
+
Existing servers are reused locally, while CI starts its own server. Readiness
|
|
54
|
+
uses Playwright's HTTP URL check; configure a public health URL if the root needs
|
|
55
|
+
authentication. Playwright owns server shutdown.
|
|
56
|
+
<% } else { %>
|
|
57
|
+
No server is started. Start our backend separately or point `API_BASE_URL` at an
|
|
58
|
+
already reachable API. The implicit project dependency does not start a server.
|
|
59
|
+
<% } %>
|
|
60
|
+
|
|
61
|
+
API execution targets are uncached because server data can change independently
|
|
62
|
+
of source files. BDD generation remains cached. HTML and JUnit reports go below
|
|
63
|
+
`dist/e2e/<%= projectRoot %>`. Traces are disabled by default because they can
|
|
64
|
+
capture request/response data and authentication. No screenshot/video hooks or
|
|
65
|
+
BrowserWorld are generated. UI Mode is optional and requires a desktop; normal
|
|
66
|
+
and CI execution need no browsers. This is new-project generation, not API-test
|
|
67
|
+
conversion. Features, configuration and steps belong to this project.
|
|
68
|
+
<% } else { %>
|
|
33
69
|
Features and steps belong to this project. `src/fixtures.ts` supplies a local
|
|
34
70
|
world so Cucumber-style `function (this: BrowserWorld)` definitions can remain.
|
|
35
71
|
Extend the local fixtures for application behavior. Cucumber hook argument
|
|
@@ -46,6 +82,7 @@ The original project is preserved. Missing steps must be implemented before
|
|
|
46
82
|
claiming the migration is complete. Review tags, timeouts, world parameters,
|
|
47
83
|
coverage and custom metadata; these are not automatically reproduced.
|
|
48
84
|
|
|
85
|
+
<% } %>
|
|
49
86
|
After switching CI and retiring old Cucumber projects, nx-cucumber can be
|
|
50
87
|
uninstalled if no other project needs it. Remove its unused `nx.json` plugin
|
|
51
88
|
registration first, preserve `@nx/playwright/plugin`, and verify a fresh run with
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineConfig
|
|
1
|
+
import { defineConfig<% if (!isApi) { %>, devices<% } %> } from '@playwright/test';
|
|
2
2
|
import { defineBddConfig } from 'playwright-bdd';
|
|
3
3
|
import { nxE2EPreset } from '@nx/playwright/preset';
|
|
4
4
|
import { join } from 'node:path';
|
|
@@ -25,22 +25,35 @@ export default defineConfig({
|
|
|
25
25
|
['junit', { outputFile: join(reports, 'reports/test-results/junit.xml') }],
|
|
26
26
|
],
|
|
27
27
|
use: {
|
|
28
|
+
<% if (isApi) { %>
|
|
29
|
+
baseURL: process.env['API_BASE_URL'] || <%- baseUrlJson %>,
|
|
30
|
+
extraHTTPHeaders: process.env['API_TOKEN']
|
|
31
|
+
? { Authorization: `Bearer ${process.env['API_TOKEN']}` }
|
|
32
|
+
: {},
|
|
33
|
+
// Request/response data and credentials can be captured in traces. Enable explicitly if needed.
|
|
34
|
+
trace: 'off',
|
|
35
|
+
<% } else { %>
|
|
28
36
|
baseURL: 'http://localhost:4200',
|
|
29
37
|
// The local AfterStep hook attaches screenshots with the world's mask options.
|
|
30
38
|
// Avoid an additional, automatically captured screenshot without those masks.
|
|
31
39
|
screenshot: 'off',
|
|
32
40
|
video: 'retain-on-failure',
|
|
33
41
|
trace: 'retain-on-failure',
|
|
42
|
+
<% } %>
|
|
34
43
|
},
|
|
44
|
+
<% if (!isApi || apiServeCommandJson) { %>
|
|
35
45
|
webServer: {
|
|
36
|
-
command: <%- serveCommandJson %>,
|
|
46
|
+
command: <%- isApi ? apiServeCommandJson : serveCommandJson %>,
|
|
37
47
|
cwd: workspaceRoot,
|
|
38
48
|
// Prevent inherited cucumber-js ts-node settings from configuring the app server.
|
|
39
49
|
env: { TS_NODE_PROJECT: '' },
|
|
40
|
-
url: 'http://localhost:4200'
|
|
50
|
+
url: <% if (isApi) { %>process.env['API_BASE_URL'] || <%- baseUrlJson %><% } else { %>'http://localhost:4200'<% } %>,
|
|
41
51
|
reuseExistingServer: !process.env['CI'],
|
|
42
52
|
timeout: 60_000,
|
|
43
53
|
gracefulShutdown: { signal: 'SIGTERM', timeout: 5_000 },
|
|
44
54
|
},
|
|
55
|
+
<% } %>
|
|
56
|
+
<% if (!isApi) { %>
|
|
45
57
|
projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }],
|
|
58
|
+
<% } %>
|
|
46
59
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { expect } from '@playwright/test';
|
|
2
|
+
import { Then } from '../fixtures';
|
|
3
|
+
|
|
4
|
+
Then('GET {string} returns a healthy response', async ({ request }, endpoint: string) => {
|
|
5
|
+
const response = await request.get(endpoint);
|
|
6
|
+
expect(response.status()).toBe(200);
|
|
7
|
+
expect(await response.json()).toMatchObject({ status: 'ok' });
|
|
8
|
+
});
|
|
@@ -7,6 +7,28 @@ const path = tslib_1.__importStar(require("node:path"));
|
|
|
7
7
|
const names_1 = require("./names");
|
|
8
8
|
async function playwrightBddProjectGenerator(tree, options) {
|
|
9
9
|
(0, devkit_1.readProjectConfiguration)(tree, options.project);
|
|
10
|
+
const isApi = options.testType === 'api';
|
|
11
|
+
if (!isApi && (options.baseUrl !== undefined || options.webServerTarget !== undefined)) {
|
|
12
|
+
throw new Error('baseUrl and webServerTarget require --test-type=api.');
|
|
13
|
+
}
|
|
14
|
+
const baseUrl = options.baseUrl ?? 'http://localhost:3000';
|
|
15
|
+
if (isApi) {
|
|
16
|
+
const url = new URL(baseUrl);
|
|
17
|
+
if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) {
|
|
18
|
+
throw new Error('baseUrl must be an HTTP(S) URL without credentials. Use API_TOKEN for authentication.');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
let serverProject;
|
|
22
|
+
if (options.webServerTarget !== undefined) {
|
|
23
|
+
const [project, target, configuration, ...rest] = options.webServerTarget.split(':');
|
|
24
|
+
if (!project || !target || configuration === '' || rest.length || !/^[\w@./:-]+$/.test(options.webServerTarget)) {
|
|
25
|
+
throw new Error('webServerTarget must be project:target[:configuration].');
|
|
26
|
+
}
|
|
27
|
+
// Devkit's Tree configuration omits plugin-inferred targets. Let Nx resolve the
|
|
28
|
+
// target/configuration at execution time, so inferred backend targets work too.
|
|
29
|
+
(0, devkit_1.readProjectConfiguration)(tree, project);
|
|
30
|
+
serverProject = project;
|
|
31
|
+
}
|
|
10
32
|
const name = (0, names_1.normalizeGeneratedProjectName)(options.project, options.name);
|
|
11
33
|
const layout = (0, devkit_1.getWorkspaceLayout)(tree);
|
|
12
34
|
const directory = (0, devkit_1.normalizePath)(options.directory || (0, names_1.defaultProjectDirectory)(name));
|
|
@@ -40,6 +62,7 @@ async function playwrightBddProjectGenerator(tree, options) {
|
|
|
40
62
|
{ externalDependencies: ['@playwright/test', 'playwright-bdd', '@nx/playwright'] },
|
|
41
63
|
{ env: 'CI' },
|
|
42
64
|
];
|
|
65
|
+
const testInputs = isApi ? [...inputs, { env: 'API_BASE_URL' }, { env: 'API_TOKEN' }] : inputs;
|
|
43
66
|
const config = `${root}/playwright.config.mts`;
|
|
44
67
|
const bddgen = `npx bddgen --config ${config}`;
|
|
45
68
|
const run = `npx playwright test --config ${config}`;
|
|
@@ -48,7 +71,7 @@ async function playwrightBddProjectGenerator(tree, options) {
|
|
|
48
71
|
root,
|
|
49
72
|
sourceRoot: `${root}/src`,
|
|
50
73
|
projectType: 'application',
|
|
51
|
-
implicitDependencies: [options.project],
|
|
74
|
+
implicitDependencies: [...new Set([options.project, ...(serverProject ? [serverProject] : [])])],
|
|
52
75
|
targets: {
|
|
53
76
|
bddgen: {
|
|
54
77
|
command: bddgen,
|
|
@@ -57,10 +80,10 @@ async function playwrightBddProjectGenerator(tree, options) {
|
|
|
57
80
|
outputs: [`{projectRoot}/.features-gen`],
|
|
58
81
|
},
|
|
59
82
|
// @nx/playwright/plugin infers the actual e2e task from the generated config.
|
|
60
|
-
[e2eTarget]: { dependsOn: ['bddgen'], inputs, outputs: [output] },
|
|
83
|
+
[e2eTarget]: { dependsOn: ['bddgen'], inputs: testInputs, outputs: [output], ...(isApi ? { cache: false } : {}) },
|
|
61
84
|
// A native command replaces an inferred atomized aggregator, including its Cloud-only metadata.
|
|
62
85
|
// Generated specs do not exist when Nx first discovers individual test files.
|
|
63
|
-
[ciTarget]: { command: run, dependsOn: ['bddgen'], cache:
|
|
86
|
+
[ciTarget]: { command: run, dependsOn: ['bddgen'], cache: !isApi, inputs: testInputs, outputs: [output] },
|
|
64
87
|
[`${e2eTarget}-ui`]: { command: `${run} --ui`, dependsOn: ['bddgen'], cache: false, continuous: true },
|
|
65
88
|
[`${e2eTarget}-headed`]: { command: `${run} --headed`, dependsOn: ['bddgen'], cache: false, outputs: [output] },
|
|
66
89
|
[`${e2eTarget}-debug`]: { command: `${run} --debug`, dependsOn: ['bddgen'], cache: false, continuous: true },
|
|
@@ -69,15 +92,24 @@ async function playwrightBddProjectGenerator(tree, options) {
|
|
|
69
92
|
});
|
|
70
93
|
(0, devkit_1.generateFiles)(tree, path.join(__dirname, 'files', 'playwright-bdd'), root, {
|
|
71
94
|
...options,
|
|
95
|
+
isApi,
|
|
96
|
+
baseUrlJson: JSON.stringify(baseUrl),
|
|
97
|
+
apiServeCommandJson: options.webServerTarget ? JSON.stringify(`npx nx run ${options.webServerTarget}`) : undefined,
|
|
72
98
|
name,
|
|
73
99
|
e2eTarget,
|
|
74
100
|
ciTarget,
|
|
75
101
|
projectRoot: root,
|
|
76
102
|
workspaceRootRelative,
|
|
77
|
-
serveCommandJson: JSON.stringify((0, names_1.buildServeCommand)(tree, options.project, `${options.project}:serve`, 'http://localhost:4200')),
|
|
103
|
+
serveCommandJson: JSON.stringify(isApi ? '' : (0, names_1.buildServeCommand)(tree, options.project, `${options.project}:serve`, 'http://localhost:4200')),
|
|
78
104
|
rootEslintConfig: ['eslint.config.mjs', 'eslint.config.js', 'eslint.config.cjs'].find((file) => tree.exists(file)) ??
|
|
79
105
|
'eslint.config.mjs',
|
|
80
106
|
});
|
|
107
|
+
if (isApi) {
|
|
108
|
+
for (const file of ['src/world.ts', 'src/steps/homepage.steps.ts', 'features/homepage.feature']) {
|
|
109
|
+
tree.delete(`${root}/${file}`);
|
|
110
|
+
}
|
|
111
|
+
(0, devkit_1.generateFiles)(tree, path.join(__dirname, 'files', 'playwright-bdd-api'), root, {});
|
|
112
|
+
}
|
|
81
113
|
(0, devkit_1.updateJson)(tree, 'nx.json', (json) => {
|
|
82
114
|
json.plugins ??= [];
|
|
83
115
|
if (!json.plugins.some((entry) => (typeof entry === 'string' ? entry : entry.plugin) === '@nx/playwright/plugin')) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright-bdd.js","sourceRoot":"","sources":["../../../../../../libs/nx-cucumber/src/generators/project/playwright-bdd.ts"],"names":[],"mappings":";;AAmBA,sEAsGC;;AAzHD,uCAcoB;AACpB,wDAAkC;AAClC,mCAAoG;AAG7F,KAAK,UAAU,6BAA6B,CAAC,IAAU,EAAE,OAAkC;IAChG,IAAA,iCAAwB,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,IAAA,qCAA6B,EAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,IAAA,2BAAkB,EAAC,IAAI,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,IAAA,sBAAa,EAAC,OAAO,CAAC,SAAS,IAAI,IAAA,+BAAuB,EAAC,IAAI,CAAC,CAAC,CAAC;IACpF,MAAM,IAAI,GACR,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB;QACxE,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,IAAI,SAAS,EAAE;QAClC,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,IAAI,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,8CAA8C,CAAC,CAAC;IACjH,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,mDAAmD,CAAC,CAAC;IAC3F,MAAM,qBAAqB,GAAG,IAAA,uBAAc,EAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,IAAA,iBAAQ,EAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAChD,kFAAkF;IAClF,MAAM,SAAS,GAAW,IAAA,qBAAY,EAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC;IACnF,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5G,MAAM,cAAc,GAAG,CAAC,IAAA,iBAAQ,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CACnE,CAAC,KAAkC,EAAE,EAAE,CACrC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,uBAAuB,CACjF,CAAC;IACF,MAAM,SAAS,GAAW,OAAO,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACrH,MAAM,cAAc,GAClB,OAAO,cAAc,KAAK,QAAQ;QAChC,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,YAAY,IAAI,QAAQ,CAAC;QACpD,CAAC,CAAC,cAAc;YACd,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,EAAE,CAAC;IACX,MAAM,QAAQ,GAAW,cAAc,IAAI,GAAG,SAAS,KAAK,CAAC;IAC7D,MAAM,MAAM,GAAG;QACb,SAAS;QACT,aAAa;QACb,gCAAgC;QAChC,EAAE,oBAAoB,EAAE,CAAC,kBAAkB,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,EAAE;QAClF,EAAE,GAAG,EAAE,IAAI,EAAE;KACd,CAAC;IACF,MAAM,MAAM,GAAG,GAAG,IAAI,wBAAwB,CAAC;IAC/C,MAAM,MAAM,GAAG,uBAAuB,MAAM,EAAE,CAAC;IAC/C,MAAM,GAAG,GAAG,gCAAgC,MAAM,EAAE,CAAC;IACrD,MAAM,MAAM,GAAG,4BAA4B,IAAI,EAAE,CAAC;IAClD,IAAA,gCAAuB,EAAC,IAAI,EAAE,IAAI,EAAE;QAClC,IAAI;QACJ,UAAU,EAAE,GAAG,IAAI,MAAM;QACzB,WAAW,EAAE,aAAa;QAC1B,oBAAoB,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;QACvC,OAAO,EAAE;YACP,MAAM,EAAE;gBACN,OAAO,EAAE,MAAM;gBACf,KAAK,EAAE,IAAI;gBACX,MAAM;gBACN,OAAO,EAAE,CAAC,6BAA6B,CAAC;aACzC;YACD,8EAA8E;YAC9E,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;YACjE,gGAAgG;YAChG,8EAA8E;YAC9E,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;YAC3F,CAAC,GAAG,SAAS,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE;YACtG,CAAC,GAAG,SAAS,SAAS,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,WAAW,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;YAC/G,CAAC,GAAG,SAAS,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,UAAU,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE;YAC5G,IAAI,EAAE,EAAE,OAAO,EAAE,cAAc,IAAI,aAAa,IAAI,oBAAoB,EAAE;SAC3E;KACF,CAAC,CAAC;IACH,IAAA,sBAAa,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,gBAAgB,CAAC,EAAE,IAAI,EAAE;QACzE,GAAG,OAAO;QACV,IAAI;QACJ,SAAS;QACT,QAAQ;QACR,WAAW,EAAE,IAAI;QACjB,qBAAqB;QACrB,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAC9B,IAAA,yBAAiB,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,QAAQ,EAAE,uBAAuB,CAAC,CAC9F;QACD,gBAAgB,EACd,CAAC,mBAAmB,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAChG,mBAAmB;KACtB,CAAC,CAAC;IACH,IAAA,mBAAU,EAAC,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;QACnC,IAAI,CAAC,OAAO,KAAK,EAAE,CAAC;QACpB,IACE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAChB,CAAC,KAAkC,EAAE,EAAE,CACrC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,uBAAuB,CACjF,EACD,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,uBAAuB,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3G,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAA,qCAA4B,EAC1C,IAAI,EACJ,EAAE,EACF;QACE,gBAAgB,EAAE,SAAS;QAC3B,kBAAkB,EAAE,QAAQ,CAAC,eAAe,EAAE,CAAC,kBAAkB,CAAC,IAAI,QAAQ;QAC9E,gBAAgB,EAAE,OAAO;KAC1B,CACF,CAAC;IACF,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IACxB,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;AACzD,CAAC","sourcesContent":["import {\n addDependenciesToPackageJson,\n addProjectConfiguration,\n formatFiles,\n generateFiles,\n getWorkspaceLayout,\n getProjects,\n normalizePath,\n offsetFromRoot,\n readJson,\n readJsonFile,\n readProjectConfiguration,\n Tree,\n updateJson,\n} from '@nx/devkit';\nimport * as path from 'node:path';\nimport { buildServeCommand, defaultProjectDirectory, normalizeGeneratedProjectName } from './names';\nimport { CucumberJsGeneratorSchema } from './schema';\n\nexport async function playwrightBddProjectGenerator(tree: Tree, options: CucumberJsGeneratorSchema) {\n readProjectConfiguration(tree, options.project);\n const name = normalizeGeneratedProjectName(options.project, options.name);\n const layout = getWorkspaceLayout(tree);\n const directory = normalizePath(options.directory || defaultProjectDirectory(name));\n const root =\n layout.appsDir && layout.appsDir !== '.' && !options.ignoreWorkspaceLayout\n ? `${layout.appsDir}/${directory}`\n : directory;\n if (path.isAbsolute(root) || root.split('/').includes('..'))\n throw new Error('Destination must be inside the workspace.');\n if (getProjects(tree).has(name)) throw new Error(`Project \"${name}\" already exists; choose a new project name.`);\n if (tree.exists(root) || tree.children(root).length > 0)\n throw new Error(`Destination \"${root}\" already exists; choose a new project directory.`);\n const workspaceRootRelative = offsetFromRoot(root).replace(/\\/$/, '');\n const manifest = readJson(tree, 'package.json');\n // Match the installed Nx runtime, rather than pinning consumers to our own patch.\n const nxVersion: string = readJsonFile(require.resolve('nx/package.json')).version;\n if (!nxVersion.startsWith('24.')) throw new Error('Playwright-BDD generation requires an Nx 24 workspace.');\n const existingPlugin = (readJson(tree, 'nx.json').plugins ?? []).find(\n (entry: string | { plugin: string }) =>\n (typeof entry === 'string' ? entry : entry.plugin) === '@nx/playwright/plugin',\n );\n const e2eTarget: string = typeof existingPlugin === 'object' ? (existingPlugin.options?.targetName ?? 'e2e') : 'e2e';\n const nativeCiTarget =\n typeof existingPlugin === 'object'\n ? (existingPlugin.options?.ciTargetName ?? 'e2e-ci')\n : existingPlugin\n ? 'e2e-ci'\n : '';\n const ciTarget: string = nativeCiTarget || `${e2eTarget}-ci`;\n const inputs = [\n 'default',\n '^production',\n '{workspaceRoot}/tsconfig*.json',\n { externalDependencies: ['@playwright/test', 'playwright-bdd', '@nx/playwright'] },\n { env: 'CI' },\n ];\n const config = `${root}/playwright.config.mts`;\n const bddgen = `npx bddgen --config ${config}`;\n const run = `npx playwright test --config ${config}`;\n const output = `{workspaceRoot}/dist/e2e/${root}`;\n addProjectConfiguration(tree, name, {\n root,\n sourceRoot: `${root}/src`,\n projectType: 'application',\n implicitDependencies: [options.project],\n targets: {\n bddgen: {\n command: bddgen,\n cache: true,\n inputs,\n outputs: [`{projectRoot}/.features-gen`],\n },\n // @nx/playwright/plugin infers the actual e2e task from the generated config.\n [e2eTarget]: { dependsOn: ['bddgen'], inputs, outputs: [output] },\n // A native command replaces an inferred atomized aggregator, including its Cloud-only metadata.\n // Generated specs do not exist when Nx first discovers individual test files.\n [ciTarget]: { command: run, dependsOn: ['bddgen'], cache: true, inputs, outputs: [output] },\n [`${e2eTarget}-ui`]: { command: `${run} --ui`, dependsOn: ['bddgen'], cache: false, continuous: true },\n [`${e2eTarget}-headed`]: { command: `${run} --headed`, dependsOn: ['bddgen'], cache: false, outputs: [output] },\n [`${e2eTarget}-debug`]: { command: `${run} --debug`, dependsOn: ['bddgen'], cache: false, continuous: true },\n lint: { command: `npx eslint ${root} --config ${root}/eslint.config.mjs` },\n },\n });\n generateFiles(tree, path.join(__dirname, 'files', 'playwright-bdd'), root, {\n ...options,\n name,\n e2eTarget,\n ciTarget,\n projectRoot: root,\n workspaceRootRelative,\n serveCommandJson: JSON.stringify(\n buildServeCommand(tree, options.project, `${options.project}:serve`, 'http://localhost:4200'),\n ),\n rootEslintConfig:\n ['eslint.config.mjs', 'eslint.config.js', 'eslint.config.cjs'].find((file) => tree.exists(file)) ??\n 'eslint.config.mjs',\n });\n updateJson(tree, 'nx.json', (json) => {\n json.plugins ??= [];\n if (\n !json.plugins.some(\n (entry: string | { plugin: string }) =>\n (typeof entry === 'string' ? entry : entry.plugin) === '@nx/playwright/plugin',\n )\n ) {\n json.plugins.push({ plugin: '@nx/playwright/plugin', options: { targetName: 'e2e', ciTargetName: '' } });\n }\n return json;\n });\n const install = addDependenciesToPackageJson(\n tree,\n {},\n {\n '@nx/playwright': nxVersion,\n '@playwright/test': manifest.devDependencies?.['@playwright/test'] || '1.64.1',\n 'playwright-bdd': '9.2.1',\n },\n );\n await formatFiles(tree);\n return options.skipInstall ? () => undefined : install;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"playwright-bdd.js","sourceRoot":"","sources":["../../../../../../libs/nx-cucumber/src/generators/project/playwright-bdd.ts"],"names":[],"mappings":";;AAmBA,sEAsIC;;AAzJD,uCAcoB;AACpB,wDAAkC;AAClC,mCAAoG;AAG7F,KAAK,UAAU,6BAA6B,CAAC,IAAU,EAAE,OAAkC;IAChG,IAAA,iCAAwB,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,KAAK,KAAK,CAAC;IACzC,IAAI,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,eAAe,KAAK,SAAS,CAAC,EAAE,CAAC;QACvF,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,uBAAuB,CAAC;IAC3D,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;QAC7B,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YAChF,MAAM,IAAI,KAAK,CAAC,uFAAuF,CAAC,CAAC;QAC3G,CAAC;IACH,CAAC;IACD,IAAI,aAAiC,CAAC;IACtC,IAAI,OAAO,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;QAC1C,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrF,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,IAAI,aAAa,KAAK,EAAE,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;YAChH,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAC7E,CAAC;QACD,gFAAgF;QAChF,gFAAgF;QAChF,IAAA,iCAAwB,EAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACxC,aAAa,GAAG,OAAO,CAAC;IAC1B,CAAC;IACD,MAAM,IAAI,GAAG,IAAA,qCAA6B,EAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,IAAA,2BAAkB,EAAC,IAAI,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,IAAA,sBAAa,EAAC,OAAO,CAAC,SAAS,IAAI,IAAA,+BAAuB,EAAC,IAAI,CAAC,CAAC,CAAC;IACpF,MAAM,IAAI,GACR,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB;QACxE,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,IAAI,SAAS,EAAE;QAClC,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,IAAI,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,8CAA8C,CAAC,CAAC;IACjH,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,mDAAmD,CAAC,CAAC;IAC3F,MAAM,qBAAqB,GAAG,IAAA,uBAAc,EAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,IAAA,iBAAQ,EAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAChD,kFAAkF;IAClF,MAAM,SAAS,GAAW,IAAA,qBAAY,EAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC;IACnF,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5G,MAAM,cAAc,GAAG,CAAC,IAAA,iBAAQ,EAAC,IAAI,EAAE,SAAS,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CACnE,CAAC,KAAkC,EAAE,EAAE,CACrC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,uBAAuB,CACjF,CAAC;IACF,MAAM,SAAS,GAAW,OAAO,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACrH,MAAM,cAAc,GAClB,OAAO,cAAc,KAAK,QAAQ;QAChC,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,YAAY,IAAI,QAAQ,CAAC;QACpD,CAAC,CAAC,cAAc;YACd,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,EAAE,CAAC;IACX,MAAM,QAAQ,GAAW,cAAc,IAAI,GAAG,SAAS,KAAK,CAAC;IAC7D,MAAM,MAAM,GAAG;QACb,SAAS;QACT,aAAa;QACb,gCAAgC;QAChC,EAAE,oBAAoB,EAAE,CAAC,kBAAkB,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,EAAE;QAClF,EAAE,GAAG,EAAE,IAAI,EAAE;KACd,CAAC;IACF,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/F,MAAM,MAAM,GAAG,GAAG,IAAI,wBAAwB,CAAC;IAC/C,MAAM,MAAM,GAAG,uBAAuB,MAAM,EAAE,CAAC;IAC/C,MAAM,GAAG,GAAG,gCAAgC,MAAM,EAAE,CAAC;IACrD,MAAM,MAAM,GAAG,4BAA4B,IAAI,EAAE,CAAC;IAClD,IAAA,gCAAuB,EAAC,IAAI,EAAE,IAAI,EAAE;QAClC,IAAI;QACJ,UAAU,EAAE,GAAG,IAAI,MAAM;QACzB,WAAW,EAAE,aAAa;QAC1B,oBAAoB,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAChG,OAAO,EAAE;YACP,MAAM,EAAE;gBACN,OAAO,EAAE,MAAM;gBACf,KAAK,EAAE,IAAI;gBACX,MAAM;gBACN,OAAO,EAAE,CAAC,6BAA6B,CAAC;aACzC;YACD,8EAA8E;YAC9E,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;YACjH,gGAAgG;YAChG,8EAA8E;YAC9E,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;YACzG,CAAC,GAAG,SAAS,KAAK,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,OAAO,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE;YACtG,CAAC,GAAG,SAAS,SAAS,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,WAAW,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;YAC/G,CAAC,GAAG,SAAS,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,UAAU,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE;YAC5G,IAAI,EAAE,EAAE,OAAO,EAAE,cAAc,IAAI,aAAa,IAAI,oBAAoB,EAAE;SAC3E;KACF,CAAC,CAAC;IACH,IAAA,sBAAa,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,gBAAgB,CAAC,EAAE,IAAI,EAAE;QACzE,GAAG,OAAO;QACV,KAAK;QACL,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;QACpC,mBAAmB,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;QAClH,IAAI;QACJ,SAAS;QACT,QAAQ;QACR,WAAW,EAAE,IAAI;QACjB,qBAAqB;QACrB,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAC9B,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,yBAAiB,EAAC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,QAAQ,EAAE,uBAAuB,CAAC,CAC3G;QACD,gBAAgB,EACd,CAAC,mBAAmB,EAAE,kBAAkB,EAAE,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAChG,mBAAmB;KACtB,CAAC,CAAC;IACH,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,MAAM,IAAI,IAAI,CAAC,cAAc,EAAE,6BAA6B,EAAE,2BAA2B,CAAC,EAAE,CAAC;YAChG,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC;QACD,IAAA,sBAAa,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,oBAAoB,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,IAAA,mBAAU,EAAC,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;QACnC,IAAI,CAAC,OAAO,KAAK,EAAE,CAAC;QACpB,IACE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAChB,CAAC,KAAkC,EAAE,EAAE,CACrC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,uBAAuB,CACjF,EACD,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,uBAAuB,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3G,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAA,qCAA4B,EAC1C,IAAI,EACJ,EAAE,EACF;QACE,gBAAgB,EAAE,SAAS;QAC3B,kBAAkB,EAAE,QAAQ,CAAC,eAAe,EAAE,CAAC,kBAAkB,CAAC,IAAI,QAAQ;QAC9E,gBAAgB,EAAE,OAAO;KAC1B,CACF,CAAC;IACF,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IACxB,OAAO,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;AACzD,CAAC","sourcesContent":["import {\n addDependenciesToPackageJson,\n addProjectConfiguration,\n formatFiles,\n generateFiles,\n getWorkspaceLayout,\n getProjects,\n normalizePath,\n offsetFromRoot,\n readJson,\n readJsonFile,\n readProjectConfiguration,\n Tree,\n updateJson,\n} from '@nx/devkit';\nimport * as path from 'node:path';\nimport { buildServeCommand, defaultProjectDirectory, normalizeGeneratedProjectName } from './names';\nimport { CucumberJsGeneratorSchema } from './schema';\n\nexport async function playwrightBddProjectGenerator(tree: Tree, options: CucumberJsGeneratorSchema) {\n readProjectConfiguration(tree, options.project);\n const isApi = options.testType === 'api';\n if (!isApi && (options.baseUrl !== undefined || options.webServerTarget !== undefined)) {\n throw new Error('baseUrl and webServerTarget require --test-type=api.');\n }\n const baseUrl = options.baseUrl ?? 'http://localhost:3000';\n if (isApi) {\n const url = new URL(baseUrl);\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password) {\n throw new Error('baseUrl must be an HTTP(S) URL without credentials. Use API_TOKEN for authentication.');\n }\n }\n let serverProject: string | undefined;\n if (options.webServerTarget !== undefined) {\n const [project, target, configuration, ...rest] = options.webServerTarget.split(':');\n if (!project || !target || configuration === '' || rest.length || !/^[\\w@./:-]+$/.test(options.webServerTarget)) {\n throw new Error('webServerTarget must be project:target[:configuration].');\n }\n // Devkit's Tree configuration omits plugin-inferred targets. Let Nx resolve the\n // target/configuration at execution time, so inferred backend targets work too.\n readProjectConfiguration(tree, project);\n serverProject = project;\n }\n const name = normalizeGeneratedProjectName(options.project, options.name);\n const layout = getWorkspaceLayout(tree);\n const directory = normalizePath(options.directory || defaultProjectDirectory(name));\n const root =\n layout.appsDir && layout.appsDir !== '.' && !options.ignoreWorkspaceLayout\n ? `${layout.appsDir}/${directory}`\n : directory;\n if (path.isAbsolute(root) || root.split('/').includes('..'))\n throw new Error('Destination must be inside the workspace.');\n if (getProjects(tree).has(name)) throw new Error(`Project \"${name}\" already exists; choose a new project name.`);\n if (tree.exists(root) || tree.children(root).length > 0)\n throw new Error(`Destination \"${root}\" already exists; choose a new project directory.`);\n const workspaceRootRelative = offsetFromRoot(root).replace(/\\/$/, '');\n const manifest = readJson(tree, 'package.json');\n // Match the installed Nx runtime, rather than pinning consumers to our own patch.\n const nxVersion: string = readJsonFile(require.resolve('nx/package.json')).version;\n if (!nxVersion.startsWith('24.')) throw new Error('Playwright-BDD generation requires an Nx 24 workspace.');\n const existingPlugin = (readJson(tree, 'nx.json').plugins ?? []).find(\n (entry: string | { plugin: string }) =>\n (typeof entry === 'string' ? entry : entry.plugin) === '@nx/playwright/plugin',\n );\n const e2eTarget: string = typeof existingPlugin === 'object' ? (existingPlugin.options?.targetName ?? 'e2e') : 'e2e';\n const nativeCiTarget =\n typeof existingPlugin === 'object'\n ? (existingPlugin.options?.ciTargetName ?? 'e2e-ci')\n : existingPlugin\n ? 'e2e-ci'\n : '';\n const ciTarget: string = nativeCiTarget || `${e2eTarget}-ci`;\n const inputs = [\n 'default',\n '^production',\n '{workspaceRoot}/tsconfig*.json',\n { externalDependencies: ['@playwright/test', 'playwright-bdd', '@nx/playwright'] },\n { env: 'CI' },\n ];\n const testInputs = isApi ? [...inputs, { env: 'API_BASE_URL' }, { env: 'API_TOKEN' }] : inputs;\n const config = `${root}/playwright.config.mts`;\n const bddgen = `npx bddgen --config ${config}`;\n const run = `npx playwright test --config ${config}`;\n const output = `{workspaceRoot}/dist/e2e/${root}`;\n addProjectConfiguration(tree, name, {\n root,\n sourceRoot: `${root}/src`,\n projectType: 'application',\n implicitDependencies: [...new Set([options.project, ...(serverProject ? [serverProject] : [])])],\n targets: {\n bddgen: {\n command: bddgen,\n cache: true,\n inputs,\n outputs: [`{projectRoot}/.features-gen`],\n },\n // @nx/playwright/plugin infers the actual e2e task from the generated config.\n [e2eTarget]: { dependsOn: ['bddgen'], inputs: testInputs, outputs: [output], ...(isApi ? { cache: false } : {}) },\n // A native command replaces an inferred atomized aggregator, including its Cloud-only metadata.\n // Generated specs do not exist when Nx first discovers individual test files.\n [ciTarget]: { command: run, dependsOn: ['bddgen'], cache: !isApi, inputs: testInputs, outputs: [output] },\n [`${e2eTarget}-ui`]: { command: `${run} --ui`, dependsOn: ['bddgen'], cache: false, continuous: true },\n [`${e2eTarget}-headed`]: { command: `${run} --headed`, dependsOn: ['bddgen'], cache: false, outputs: [output] },\n [`${e2eTarget}-debug`]: { command: `${run} --debug`, dependsOn: ['bddgen'], cache: false, continuous: true },\n lint: { command: `npx eslint ${root} --config ${root}/eslint.config.mjs` },\n },\n });\n generateFiles(tree, path.join(__dirname, 'files', 'playwright-bdd'), root, {\n ...options,\n isApi,\n baseUrlJson: JSON.stringify(baseUrl),\n apiServeCommandJson: options.webServerTarget ? JSON.stringify(`npx nx run ${options.webServerTarget}`) : undefined,\n name,\n e2eTarget,\n ciTarget,\n projectRoot: root,\n workspaceRootRelative,\n serveCommandJson: JSON.stringify(\n isApi ? '' : buildServeCommand(tree, options.project, `${options.project}:serve`, 'http://localhost:4200'),\n ),\n rootEslintConfig:\n ['eslint.config.mjs', 'eslint.config.js', 'eslint.config.cjs'].find((file) => tree.exists(file)) ??\n 'eslint.config.mjs',\n });\n if (isApi) {\n for (const file of ['src/world.ts', 'src/steps/homepage.steps.ts', 'features/homepage.feature']) {\n tree.delete(`${root}/${file}`);\n }\n generateFiles(tree, path.join(__dirname, 'files', 'playwright-bdd-api'), root, {});\n }\n updateJson(tree, 'nx.json', (json) => {\n json.plugins ??= [];\n if (\n !json.plugins.some(\n (entry: string | { plugin: string }) =>\n (typeof entry === 'string' ? entry : entry.plugin) === '@nx/playwright/plugin',\n )\n ) {\n json.plugins.push({ plugin: '@nx/playwright/plugin', options: { targetName: 'e2e', ciTargetName: '' } });\n }\n return json;\n });\n const install = addDependenciesToPackageJson(\n tree,\n {},\n {\n '@nx/playwright': nxVersion,\n '@playwright/test': manifest.devDependencies?.['@playwright/test'] || '1.64.1',\n 'playwright-bdd': '9.2.1',\n },\n );\n await formatFiles(tree);\n return options.skipInstall ? () => undefined : install;\n}\n"]}
|
|
@@ -11,6 +11,9 @@ const test_run_options_1 = require("../../core/test-run-options");
|
|
|
11
11
|
async function cucumberJsGenerator(tree, options) {
|
|
12
12
|
if (options.testRunner === 'playwright-bdd')
|
|
13
13
|
return (0, playwright_bdd_1.playwrightBddProjectGenerator)(tree, options);
|
|
14
|
+
if (options.testType || options.baseUrl || options.webServerTarget) {
|
|
15
|
+
throw new Error('testType, baseUrl and webServerTarget require --test-runner=playwright-bdd.');
|
|
16
|
+
}
|
|
14
17
|
if (!options.testRunner)
|
|
15
18
|
options.testRunner = test_run_options_1.defaultTestRunner;
|
|
16
19
|
if (!options.configFormat)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../../../../libs/nx-cucumber/src/generators/project/project.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n buildServeCommand,\n defaultProjectDirectory,\n normalizeGeneratedProjectName,\n parseScopedProjectName,\n readPortFromUrl,\n} from './names';\nimport { playwrightBddProjectGenerator } from './playwright-bdd';\nimport {\n addProjectConfiguration,\n formatFiles,\n generateFiles,\n Tree,\n addDependenciesToPackageJson,\n normalizePath,\n offsetFromRoot,\n getWorkspaceLayout,\n readProjectConfiguration,\n updateJson,\n} from '@nx/devkit';\nimport * as path from 'path';\nimport { ConfigFormat, CucumberJsGeneratorSchema } from './schema';\nimport { existsSync } from 'fs';\nimport { defaultTestRunner } from '../../core/test-run-options';\n\nexport async function cucumberJsGenerator(tree: Tree, options: CucumberJsGeneratorSchema) {\n if (options.testRunner === 'playwright-bdd') return playwrightBddProjectGenerator(tree, options);\n if (!options.testRunner) options.testRunner = defaultTestRunner;\n if (!options.configFormat) options.configFormat = 'js';\n assertConfigFormatSupported(tree, options.configFormat);\n ensureProjectExists(tree, options.project);\n options.name = normalizeGeneratedProjectName(options.project, options.name);\n if (!options.directory) options.directory = defaultProjectDirectory(options.name);\n const isPlaywright = options.testRunner === 'playwright';\n const baseUrl = isPlaywright ? 'http://localhost:4200' : undefined;\n const serveTarget = isPlaywright ? `${options.project}:serve` : undefined;\n\n const normalizedDirectory = normalizePath(options.directory);\n const workspaceLayout = getWorkspaceLayout(tree);\n const skipAppsDir = workspaceLayout.appsDir === '.' || options.ignoreWorkspaceLayout;\n const parentDir = workspaceLayout.appsDir && !skipAppsDir ? workspaceLayout.appsDir + '/' : '';\n const projectRoot = `${parentDir}${normalizedDirectory}`;\n const workspaceRootRelative = offsetFromRoot(projectRoot).replace(/\\/$/, '');\n const playwrightTargets =\n isPlaywright && baseUrl && serveTarget ? buildPlaywrightTargets(options.name, projectRoot) : {};\n\n addProjectConfiguration(tree, options.name, {\n root: projectRoot,\n sourceRoot: `${projectRoot}/src`,\n projectType: 'application',\n targets: {\n lint: {\n command: `npx eslint ${projectRoot}`,\n },\n ...playwrightTargets,\n },\n implicitDependencies: [options.project],\n });\n\n const playwrightRequires =\n options.testRunner === 'playwright'\n ? [\n 'node_modules/@gnuechtel/nx-cucumber/src/playwright/playwright-world-default.js',\n 'node_modules/@gnuechtel/nx-cucumber/src/playwright/playwright-hooks.js',\n ]\n : [];\n\n const configFormat = options.configFormat!;\n const configFileName = `cucumber.${configFormat}`;\n const configShapeDir = resolveConfigShapeDir(configFormat);\n const isTypeScript = ['ts', 'mts', 'cts'].includes(configFormat);\n const isEsmModule = ['mjs', 'mts'].includes(configFormat);\n\n const serveCommand =\n isPlaywright && baseUrl && serveTarget ? buildServeCommand(tree, options.project, serveTarget, baseUrl) : '';\n const testCommand = `npx cucumber-js --config ${projectRoot}/${configFileName}`;\n const templateProjectName = parseScopedProjectName(options.project).name;\n\n const substitutions = {\n ...options,\n project: templateProjectName,\n testedProject: options.project,\n workspaceRootRelative,\n rootEslintConfig:\n ['eslint.config.mjs', 'eslint.config.js', 'eslint.config.cjs'].find((file) => tree.exists(file)) ??\n 'eslint.config.mjs',\n projectRoot,\n playwrightRequires: JSON.stringify(playwrightRequires),\n playwrightRequiresArray: playwrightRequires,\n isPlaywright,\n isTypeScript,\n isEsmModule,\n baseUrl: baseUrl || '',\n serveTarget: serveTarget || '',\n port: baseUrl ? readPortFromUrl(baseUrl) : 0,\n serveCommandJson: JSON.stringify(serveCommand),\n testCommandJson: JSON.stringify(testCommand),\n };\n\n generateFiles(tree, path.join(__dirname, 'files', 'all'), projectRoot, substitutions);\n generateFiles(tree, path.join(__dirname, 'files', 'config', configShapeDir), projectRoot, substitutions);\n generateFiles(tree, path.join(__dirname, 'files', options.testRunner), projectRoot, substitutions);\n\n const customWorldFiles = path.join(__dirname, 'files', `${options.testRunner}.custom-world`);\n if (options.customWorld && existsSync(customWorldFiles)) {\n generateFiles(tree, customWorldFiles, projectRoot, substitutions);\n }\n\n registerPlugin(tree);\n\n await formatFiles(tree);\n\n const additionalDevDependencies: Record<string, string> = {\n 'ts-node': '10.9.2',\n 'tsconfig-paths': '4.2.0',\n };\n\n const installTask = addDependenciesToPackageJson(tree, {}, additionalDevDependencies);\n return options.skipInstall ? () => undefined : installTask;\n}\n\nfunction buildPlaywrightTargets(e2eProjectName: string, projectRoot: string) {\n return {\n 'e2e-prepare': {\n cache: false,\n command: buildPlaywrightPrepareCommand(),\n },\n e2e: {\n command: `node ${projectRoot}/run-e2e.js`,\n },\n 'e2e-ci': {\n command: `npx nx run ${e2eProjectName}:e2e-prepare && npx nx run ${e2eProjectName}:e2e`,\n },\n };\n}\n\nfunction buildPlaywrightPrepareCommand() {\n return `node -e \"const { execSync } = require('node:child_process'); const installCommand = process.platform === 'linux' ? 'npx playwright install --with-deps chromium' : 'npx playwright install chromium'; execSync(installCommand, { stdio: 'inherit' });\"`;\n}\n\nfunction ensureProjectExists(tree: Tree, projectName: string) {\n try {\n readProjectConfiguration(tree, projectName);\n } catch {\n throw new Error(`Project \"${projectName}\" does not exist in this workspace.`);\n }\n}\n\nconst TYPESCRIPT_CONFIG_FORMATS: ConfigFormat[] = ['ts', 'mts', 'cts'];\nconst MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG = '12.4.0';\n\n// cucumber-js only loads TypeScript config files (.ts/.mts/.cts) from 12.4.0 onwards\n// (versions 10.0-12.3 reject them with \"Unsupported configuration file extension\").\n// Fail fast with an actionable error instead of letting the user hit that at run time.\nfunction assertConfigFormatSupported(tree: Tree, configFormat: ConfigFormat) {\n if (!TYPESCRIPT_CONFIG_FORMATS.includes(configFormat)) return;\n const cucumberVersion = readInstalledCucumberVersion(tree);\n if (cucumberVersion && isBelowVersion(cucumberVersion, MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG)) {\n throw new Error(\n `Cucumber configuration format \"${configFormat}\" requires @cucumber/cucumber >=${MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG}, ` +\n `but found ${cucumberVersion}. Choose a different --config-format (js, cjs, mjs, json, yaml) ` +\n `or upgrade @cucumber/cucumber.`,\n );\n }\n}\n\nfunction readInstalledCucumberVersion(tree: Tree): string | undefined {\n const packageJsonPath = 'node_modules/@cucumber/cucumber/package.json';\n if (!tree.exists(packageJsonPath)) return undefined;\n try {\n const content = tree.read(packageJsonPath, 'utf-8');\n const version = content ? JSON.parse(content).version : undefined;\n return typeof version === 'string' ? version : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isBelowVersion(version: string, minimum: string): boolean {\n const toParts = (value: string) =>\n value\n .split('-')[0]\n .split('.')\n .map((part) => parseInt(part, 10) || 0);\n const [vMajor, vMinor, vPatch] = toParts(version);\n const [mMajor, mMinor, mPatch] = toParts(minimum);\n if (vMajor !== mMajor) return vMajor < mMajor;\n if (vMinor !== mMinor) return vMinor < mMinor;\n return vPatch < mPatch;\n}\n\nfunction resolveConfigShapeDir(configFormat: ConfigFormat): string {\n if (configFormat === 'json') return 'json';\n if (configFormat === 'yaml' || configFormat === 'yml') return 'yaml';\n // cucumber-js loads .mjs/.mts/.ts via dynamic import (ESM), so they need the\n // import.meta-based shape; .cjs/.cts/.js are require-loaded and stay CommonJS.\n if (configFormat === 'mjs' || configFormat === 'mts' || configFormat === 'ts') return 'esm';\n return 'cjs';\n}\n\nfunction registerPlugin(tree: Tree) {\n if (!tree.exists('nx.json')) return;\n updateJson(tree, 'nx.json', (json) => {\n if (!Array.isArray(json.plugins)) json.plugins = [];\n if (!json.plugins.includes('@gnuechtel/nx-cucumber')) {\n json.plugins.push('@gnuechtel/nx-cucumber');\n }\n return json;\n });\n}\n\nexport default cucumberJsGenerator;\n"]}
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../../../../libs/nx-cucumber/src/generators/project/project.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n buildServeCommand,\n defaultProjectDirectory,\n normalizeGeneratedProjectName,\n parseScopedProjectName,\n readPortFromUrl,\n} from './names';\nimport { playwrightBddProjectGenerator } from './playwright-bdd';\nimport {\n addProjectConfiguration,\n formatFiles,\n generateFiles,\n Tree,\n addDependenciesToPackageJson,\n normalizePath,\n offsetFromRoot,\n getWorkspaceLayout,\n readProjectConfiguration,\n updateJson,\n} from '@nx/devkit';\nimport * as path from 'path';\nimport { ConfigFormat, CucumberJsGeneratorSchema } from './schema';\nimport { existsSync } from 'fs';\nimport { defaultTestRunner } from '../../core/test-run-options';\n\nexport async function cucumberJsGenerator(tree: Tree, options: CucumberJsGeneratorSchema) {\n if (options.testRunner === 'playwright-bdd') return playwrightBddProjectGenerator(tree, options);\n if (options.testType || options.baseUrl || options.webServerTarget) {\n throw new Error('testType, baseUrl and webServerTarget require --test-runner=playwright-bdd.');\n }\n if (!options.testRunner) options.testRunner = defaultTestRunner;\n if (!options.configFormat) options.configFormat = 'js';\n assertConfigFormatSupported(tree, options.configFormat);\n ensureProjectExists(tree, options.project);\n options.name = normalizeGeneratedProjectName(options.project, options.name);\n if (!options.directory) options.directory = defaultProjectDirectory(options.name);\n const isPlaywright = options.testRunner === 'playwright';\n const baseUrl = isPlaywright ? 'http://localhost:4200' : undefined;\n const serveTarget = isPlaywright ? `${options.project}:serve` : undefined;\n\n const normalizedDirectory = normalizePath(options.directory);\n const workspaceLayout = getWorkspaceLayout(tree);\n const skipAppsDir = workspaceLayout.appsDir === '.' || options.ignoreWorkspaceLayout;\n const parentDir = workspaceLayout.appsDir && !skipAppsDir ? workspaceLayout.appsDir + '/' : '';\n const projectRoot = `${parentDir}${normalizedDirectory}`;\n const workspaceRootRelative = offsetFromRoot(projectRoot).replace(/\\/$/, '');\n const playwrightTargets =\n isPlaywright && baseUrl && serveTarget ? buildPlaywrightTargets(options.name, projectRoot) : {};\n\n addProjectConfiguration(tree, options.name, {\n root: projectRoot,\n sourceRoot: `${projectRoot}/src`,\n projectType: 'application',\n targets: {\n lint: {\n command: `npx eslint ${projectRoot}`,\n },\n ...playwrightTargets,\n },\n implicitDependencies: [options.project],\n });\n\n const playwrightRequires =\n options.testRunner === 'playwright'\n ? [\n 'node_modules/@gnuechtel/nx-cucumber/src/playwright/playwright-world-default.js',\n 'node_modules/@gnuechtel/nx-cucumber/src/playwright/playwright-hooks.js',\n ]\n : [];\n\n const configFormat = options.configFormat!;\n const configFileName = `cucumber.${configFormat}`;\n const configShapeDir = resolveConfigShapeDir(configFormat);\n const isTypeScript = ['ts', 'mts', 'cts'].includes(configFormat);\n const isEsmModule = ['mjs', 'mts'].includes(configFormat);\n\n const serveCommand =\n isPlaywright && baseUrl && serveTarget ? buildServeCommand(tree, options.project, serveTarget, baseUrl) : '';\n const testCommand = `npx cucumber-js --config ${projectRoot}/${configFileName}`;\n const templateProjectName = parseScopedProjectName(options.project).name;\n\n const substitutions = {\n ...options,\n project: templateProjectName,\n testedProject: options.project,\n workspaceRootRelative,\n rootEslintConfig:\n ['eslint.config.mjs', 'eslint.config.js', 'eslint.config.cjs'].find((file) => tree.exists(file)) ??\n 'eslint.config.mjs',\n projectRoot,\n playwrightRequires: JSON.stringify(playwrightRequires),\n playwrightRequiresArray: playwrightRequires,\n isPlaywright,\n isTypeScript,\n isEsmModule,\n baseUrl: baseUrl || '',\n serveTarget: serveTarget || '',\n port: baseUrl ? readPortFromUrl(baseUrl) : 0,\n serveCommandJson: JSON.stringify(serveCommand),\n testCommandJson: JSON.stringify(testCommand),\n };\n\n generateFiles(tree, path.join(__dirname, 'files', 'all'), projectRoot, substitutions);\n generateFiles(tree, path.join(__dirname, 'files', 'config', configShapeDir), projectRoot, substitutions);\n generateFiles(tree, path.join(__dirname, 'files', options.testRunner), projectRoot, substitutions);\n\n const customWorldFiles = path.join(__dirname, 'files', `${options.testRunner}.custom-world`);\n if (options.customWorld && existsSync(customWorldFiles)) {\n generateFiles(tree, customWorldFiles, projectRoot, substitutions);\n }\n\n registerPlugin(tree);\n\n await formatFiles(tree);\n\n const additionalDevDependencies: Record<string, string> = {\n 'ts-node': '10.9.2',\n 'tsconfig-paths': '4.2.0',\n };\n\n const installTask = addDependenciesToPackageJson(tree, {}, additionalDevDependencies);\n return options.skipInstall ? () => undefined : installTask;\n}\n\nfunction buildPlaywrightTargets(e2eProjectName: string, projectRoot: string) {\n return {\n 'e2e-prepare': {\n cache: false,\n command: buildPlaywrightPrepareCommand(),\n },\n e2e: {\n command: `node ${projectRoot}/run-e2e.js`,\n },\n 'e2e-ci': {\n command: `npx nx run ${e2eProjectName}:e2e-prepare && npx nx run ${e2eProjectName}:e2e`,\n },\n };\n}\n\nfunction buildPlaywrightPrepareCommand() {\n return `node -e \"const { execSync } = require('node:child_process'); const installCommand = process.platform === 'linux' ? 'npx playwright install --with-deps chromium' : 'npx playwright install chromium'; execSync(installCommand, { stdio: 'inherit' });\"`;\n}\n\nfunction ensureProjectExists(tree: Tree, projectName: string) {\n try {\n readProjectConfiguration(tree, projectName);\n } catch {\n throw new Error(`Project \"${projectName}\" does not exist in this workspace.`);\n }\n}\n\nconst TYPESCRIPT_CONFIG_FORMATS: ConfigFormat[] = ['ts', 'mts', 'cts'];\nconst MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG = '12.4.0';\n\n// cucumber-js only loads TypeScript config files (.ts/.mts/.cts) from 12.4.0 onwards\n// (versions 10.0-12.3 reject them with \"Unsupported configuration file extension\").\n// Fail fast with an actionable error instead of letting the user hit that at run time.\nfunction assertConfigFormatSupported(tree: Tree, configFormat: ConfigFormat) {\n if (!TYPESCRIPT_CONFIG_FORMATS.includes(configFormat)) return;\n const cucumberVersion = readInstalledCucumberVersion(tree);\n if (cucumberVersion && isBelowVersion(cucumberVersion, MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG)) {\n throw new Error(\n `Cucumber configuration format \"${configFormat}\" requires @cucumber/cucumber >=${MINIMUM_CUCUMBER_VERSION_FOR_TS_CONFIG}, ` +\n `but found ${cucumberVersion}. Choose a different --config-format (js, cjs, mjs, json, yaml) ` +\n `or upgrade @cucumber/cucumber.`,\n );\n }\n}\n\nfunction readInstalledCucumberVersion(tree: Tree): string | undefined {\n const packageJsonPath = 'node_modules/@cucumber/cucumber/package.json';\n if (!tree.exists(packageJsonPath)) return undefined;\n try {\n const content = tree.read(packageJsonPath, 'utf-8');\n const version = content ? JSON.parse(content).version : undefined;\n return typeof version === 'string' ? version : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isBelowVersion(version: string, minimum: string): boolean {\n const toParts = (value: string) =>\n value\n .split('-')[0]\n .split('.')\n .map((part) => parseInt(part, 10) || 0);\n const [vMajor, vMinor, vPatch] = toParts(version);\n const [mMajor, mMinor, mPatch] = toParts(minimum);\n if (vMajor !== mMajor) return vMajor < mMajor;\n if (vMinor !== mMinor) return vMinor < mMinor;\n return vPatch < mPatch;\n}\n\nfunction resolveConfigShapeDir(configFormat: ConfigFormat): string {\n if (configFormat === 'json') return 'json';\n if (configFormat === 'yaml' || configFormat === 'yml') return 'yaml';\n // cucumber-js loads .mjs/.mts/.ts via dynamic import (ESM), so they need the\n // import.meta-based shape; .cjs/.cts/.js are require-loaded and stay CommonJS.\n if (configFormat === 'mjs' || configFormat === 'mts' || configFormat === 'ts') return 'esm';\n return 'cjs';\n}\n\nfunction registerPlugin(tree: Tree) {\n if (!tree.exists('nx.json')) return;\n updateJson(tree, 'nx.json', (json) => {\n if (!Array.isArray(json.plugins)) json.plugins = [];\n if (!json.plugins.includes('@gnuechtel/nx-cucumber')) {\n json.plugins.push('@gnuechtel/nx-cucumber');\n }\n return json;\n });\n}\n\nexport default cucumberJsGenerator;\n"]}
|
|
@@ -7,6 +7,9 @@ export type CucumberJsGeneratorSchema = {
|
|
|
7
7
|
name?: string;
|
|
8
8
|
directory?: string;
|
|
9
9
|
testRunner?: TestRunner | 'playwright-bdd';
|
|
10
|
+
testType?: 'browser' | 'api';
|
|
11
|
+
baseUrl?: string;
|
|
12
|
+
webServerTarget?: string;
|
|
10
13
|
configFormat?: ConfigFormat;
|
|
11
14
|
customWorld?: boolean;
|
|
12
15
|
ignoreWorkspaceLayout?: boolean;
|
|
@@ -49,6 +49,19 @@
|
|
|
49
49
|
"type": "boolean",
|
|
50
50
|
"description": "Skip package installation",
|
|
51
51
|
"default": false
|
|
52
|
+
},
|
|
53
|
+
"testType": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"enum": ["browser", "api"],
|
|
56
|
+
"description": "Playwright-BDD test type; defaults to browser. API uses native request fixtures without browsers"
|
|
57
|
+
},
|
|
58
|
+
"baseUrl": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"description": "API-only default base URL, overridden at runtime by API_BASE_URL; defaults to http://localhost:3000"
|
|
61
|
+
},
|
|
62
|
+
"webServerTarget": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"description": "API-only optional Nx project:target[:configuration] to start locally; omitted for an already reachable API"
|
|
52
65
|
}
|
|
53
66
|
},
|
|
54
67
|
"required": ["project"]
|