@qavajs/playwright-runner-adapter 2.3.3 → 2.5.0
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/CHANGELOG.md +39 -0
- package/README.md +198 -11
- package/adapter/PlaywrightWorld.d.ts +8 -6
- package/adapter/PlaywrightWorld.js +21 -8
- package/adapter/PlaywrightWorld.js.map +1 -1
- package/adapter/Template.d.ts +13 -2
- package/adapter/Template.js +57 -8
- package/adapter/Template.js.map +1 -1
- package/adapter/cucumberAdapter.d.ts +7 -0
- package/adapter/cucumberAdapter.js +254 -114
- package/adapter/cucumberAdapter.js.map +1 -1
- package/adapter/filter.d.ts +8 -0
- package/adapter/filter.js +27 -1
- package/adapter/filter.js.map +1 -1
- package/adapter/gherkin.d.ts +45 -0
- package/adapter/gherkin.js +155 -0
- package/adapter/gherkin.js.map +1 -0
- package/adapter/index.d.ts +2 -0
- package/adapter/index.js +2 -0
- package/adapter/index.js.map +1 -1
- package/adapter/js/PlaywrightWorld.d.ts +8 -6
- package/adapter/js/PlaywrightWorld.js +21 -8
- package/adapter/js/Template.d.ts +13 -2
- package/adapter/js/Template.js +57 -8
- package/adapter/js/cucumberAdapter.d.ts +7 -0
- package/adapter/js/cucumberAdapter.js +254 -114
- package/adapter/js/filter.d.ts +8 -0
- package/adapter/js/filter.js +27 -1
- package/adapter/js/gherkin.d.ts +45 -0
- package/adapter/js/gherkin.js +154 -0
- package/adapter/js/index.d.ts +2 -0
- package/adapter/js/index.js +2 -0
- package/adapter/js/loader.d.ts +9 -1
- package/adapter/js/loader.js +35 -15
- package/adapter/js/testDetails.d.ts +28 -0
- package/adapter/js/testDetails.js +78 -0
- package/adapter/js/timeout.d.ts +17 -0
- package/adapter/js/timeout.js +24 -0
- package/adapter/js/types.d.ts +35 -6
- package/adapter/js/withWorld.d.ts +43 -0
- package/adapter/js/withWorld.js +16 -0
- package/adapter/loader.d.ts +9 -1
- package/adapter/loader.js +35 -15
- package/adapter/loader.js.map +1 -1
- package/adapter/testDetails.d.ts +28 -0
- package/adapter/testDetails.js +79 -0
- package/adapter/testDetails.js.map +1 -0
- package/adapter/timeout.d.ts +17 -0
- package/adapter/timeout.js +25 -0
- package/adapter/timeout.js.map +1 -0
- package/adapter/types.d.ts +35 -6
- package/adapter/withWorld.d.ts +43 -0
- package/adapter/withWorld.js +17 -0
- package/adapter/withWorld.js.map +1 -0
- package/package.json +11 -9
package/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,45 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
|
|
|
14
14
|
|
|
15
15
|
:microscope: - experimental
|
|
16
16
|
|
|
17
|
+
## [2.5.0]
|
|
18
|
+
- :beetle: `requireModules` are now required as modules (e.g. `ts-node/register`) resolved from the current working directory instead of being treated as globs
|
|
19
|
+
- :beetle: `worldParameters` config option is passed to the world as `this.parameters`
|
|
20
|
+
- :beetle: `this.attach` accepts media type as a string (`attach(data, 'image/png')`), decodes `;base64` media types and supports readable streams
|
|
21
|
+
- :beetle: `this.log` attaches text to the report (attachment `log` on the current step) instead of printing to stdout
|
|
22
|
+
- :beetle: steps returning `'pending'` fail the scenario (or mark it as fixme with `strict: false`); steps and `Before` hooks returning `'skipped'` skip the scenario
|
|
23
|
+
- :beetle: `After` hooks receive `FAILED` status when a `Before` hook fails; soft assertion failures, undefined, ambiguous and pending steps are reported with their own status
|
|
24
|
+
- :beetle: features with the same name in different files no longer produce duplicate test titles; unnamed features use the file path as title
|
|
25
|
+
- :rocket: undefined step error includes the feature file location and a step definition snippet
|
|
26
|
+
- :rocket: added `tags` config option and `CUCUMBER_TAGS` env variable to select scenarios by tag expression evaluated on Gherkin tags
|
|
27
|
+
- :rocket: added `CUCUMBER_PATHS` env variable to override feature paths
|
|
28
|
+
- :rocket: `executeStep` accepts a doc string (`string`) or data table (`string[][]` / `DataTable`) argument
|
|
29
|
+
- :rocket: `Template` supports data tables and doc strings
|
|
30
|
+
- :rocket: tests and describe blocks are reported at their location in the `.feature` file
|
|
31
|
+
- :rocket: step titles include a preview of their doc string or data table argument
|
|
32
|
+
- :rocket: added `@timeout(ms)` tag to set test timeout and `@retries(n)` feature tag to set retries
|
|
33
|
+
- :rocket: added `withWorld<World>()` helper returning step and hook functions with typed `this`
|
|
34
|
+
- :rocket: added `stepLocation` config option to point steps to the feature file instead of step definitions
|
|
35
|
+
- :rocket: step and hook `{ timeout }` option and `setDefaultTimeout` are applied (no implicit 5s default)
|
|
36
|
+
- :rocket: steps run by `executeStep` and `Template` are shown as nested steps in the report
|
|
37
|
+
- :rocket: invalid tag expressions report their source (`tags()`, `tags` option, `CUCUMBER_TAGS`); tags without `@` are rejected
|
|
38
|
+
- :pencil: replaced `glob` dependency with built-in `fs.globSync`; matched files are loaded in sorted order
|
|
39
|
+
- :pencil: tests no longer depend on external websites
|
|
40
|
+
- :pencil: CI: tests cover all test projects (TS, CommonJS, ESM configs), `CUCUMBER_PATHS` / `CUCUMBER_TAGS`, type checks and a smoke test of the packed package in fresh CommonJS, ESM and TypeScript projects
|
|
41
|
+
- :pencil: CI: publish no longer runs e2e tests
|
|
42
|
+
- :pencil: README: clarified the difference between the main and `./js` entrypoints
|
|
43
|
+
- :pencil: documented and tested supported Cucumber APIs: `defineParameterType`, `setDefinitionFunctionWrapper`, localized Gherkin, Rule tags
|
|
44
|
+
|
|
45
|
+
## [2.4.0]
|
|
46
|
+
- :rocket: added `@lock(name)` tag mapped to playwright test locks (`@lock(-exclusive-)` for the built-in exclusive lock)
|
|
47
|
+
- :rocket: added `@skip(reason)`, `@fixme(reason)`, `@fail(reason)`, `@slow(reason)` tags mapped to playwright test modifiers (reason is optional: `@skip()`)
|
|
48
|
+
- :rocket: added `@annotation(type,description)` tag mapped to playwright test annotations
|
|
49
|
+
- :pencil: special tags (`@lock(...)`, `@annotation(...)`, `@skip(...)`, `@fixme(...)`, `@fail(...)`, `@slow(...)`) are removed from playwright tags
|
|
50
|
+
- :pencil: updated `@cucumber/cucumber` to 13, `@cucumber/gherkin` to 42, `@cucumber/tag-expressions` to 11 and `glob` to 14
|
|
51
|
+
- :pencil: updated dev dependencies: `@playwright/test` 1.65, `@types/node` 26, `typescript` 7
|
|
52
|
+
- :pencil: switched `module` and `moduleResolution` to `nodenext` in `tsconfig.json` and `tsconfig.js.json`
|
|
53
|
+
- :x: dropped Node.js 20 support (`engines.node` is now `>=22`); CI tests against Node.js 22, 24 and 26
|
|
54
|
+
- :pencil: CI: updated `actions/checkout` and `actions/setup-node` to v7, `mikepenz/action-junit-report` to v6; tests also run on push to `main`, `npm audit` gate for production dependencies, junit report requires tests, e2e tests gate npm publish, publish with provenance
|
|
55
|
+
|
|
17
56
|
## [2.3.3]
|
|
18
57
|
- :beetle: fixed named import for `parse` from `@cucumber/tag-expressions` in `filter.ts`
|
|
19
58
|
- :beetle: fixed `attach` method assignment in `PlaywrightWorld` constructor
|
package/README.md
CHANGED
|
@@ -13,14 +13,20 @@ Adapter to run [Cucumber](https://cucumber.io/) BDD tests via the [Playwright](h
|
|
|
13
13
|
- [TestWorld](#testworld)
|
|
14
14
|
- [PlaywrightWorld](#playwrightworld)
|
|
15
15
|
- [Custom World](#custom-world)
|
|
16
|
+
- [Typed Steps](#typed-steps)
|
|
16
17
|
- [Hooks](#hooks)
|
|
17
18
|
- [Step Arguments](#step-arguments)
|
|
18
19
|
- [Template Steps](#template-steps)
|
|
20
|
+
- [Step Results](#step-results)
|
|
19
21
|
- [Filtering Tests](#filtering-tests)
|
|
20
22
|
- [Tag Expressions](#tag-expressions)
|
|
21
23
|
- [Predicate Filter](#predicate-filter)
|
|
24
|
+
- [Annotations, Modifiers and Locks](#annotations-modifiers-and-locks)
|
|
22
25
|
- [Parallelism](#parallelism)
|
|
23
|
-
- [
|
|
26
|
+
- [Reports](#reports)
|
|
27
|
+
- [Entrypoints and JavaScript Support](#entrypoints-and-javascript-support)
|
|
28
|
+
- [Timeouts](#timeouts)
|
|
29
|
+
- [Supported Cucumber APIs](#supported-cucumber-apis)
|
|
24
30
|
- [Limitations](#limitations)
|
|
25
31
|
|
|
26
32
|
---
|
|
@@ -54,10 +60,13 @@ export default defineConfig({
|
|
|
54
60
|
import { defineConfig } from '@playwright/test';
|
|
55
61
|
|
|
56
62
|
export default defineConfig({
|
|
57
|
-
testMatch: 'cucumber.config.ts'
|
|
63
|
+
testMatch: 'cucumber.config.ts',
|
|
64
|
+
fullyParallel: true
|
|
58
65
|
});
|
|
59
66
|
```
|
|
60
67
|
|
|
68
|
+
> All scenarios are defined in a single test file (`cucumber.config.ts`), so without `fullyParallel: true` Playwright runs the whole suite in one worker.
|
|
69
|
+
|
|
61
70
|
**3. Run tests**
|
|
62
71
|
|
|
63
72
|
```bash
|
|
@@ -75,7 +84,11 @@ npx playwright test
|
|
|
75
84
|
| `paths` | `string[]` | Glob patterns for `.feature` files |
|
|
76
85
|
| `require` | `string[]` | Glob patterns for step definition files (CommonJS `require`) |
|
|
77
86
|
| `import` | `string[]` | Glob patterns for step definition files (ESM `import`) |
|
|
78
|
-
| `requireModules` | `string[]` |
|
|
87
|
+
| `requireModules` | `string[]` | Module names or paths (resolved from the current working directory) to require before step definitions (e.g. `ts-node/register`) |
|
|
88
|
+
| `worldParameters` | `unknown` | Value available in steps and hooks as `this.parameters` |
|
|
89
|
+
| `tags` | `string` | Cucumber tag expression selecting scenarios to run |
|
|
90
|
+
| `strict` | `boolean` | Fail scenarios with pending steps (default `true`). When `false` they are marked as `fixme` |
|
|
91
|
+
| `stepLocation` | `'definition' \| 'feature'` | Location reported for steps: step definition code (default) or the step line in the `.feature` file |
|
|
79
92
|
|
|
80
93
|
```typescript
|
|
81
94
|
// cucumber.config.ts
|
|
@@ -84,10 +97,19 @@ import { defineConfig } from '@qavajs/playwright-runner-adapter';
|
|
|
84
97
|
export default defineConfig({
|
|
85
98
|
paths: ['test/features/**/*.feature'],
|
|
86
99
|
require: ['test/step_definitions/**/*.ts'],
|
|
87
|
-
requireModules: [],
|
|
100
|
+
requireModules: ['./test/support/setup.ts'],
|
|
101
|
+
worldParameters: { baseUrl: 'https://example.com' },
|
|
102
|
+
tags: 'not @wip',
|
|
88
103
|
});
|
|
89
104
|
```
|
|
90
105
|
|
|
106
|
+
Environment variables:
|
|
107
|
+
|
|
108
|
+
| Variable | Description |
|
|
109
|
+
|---|---|
|
|
110
|
+
| `CUCUMBER_TAGS` | Tag expression combined with the `tags` option using `and`: `CUCUMBER_TAGS='@smoke' npx playwright test` |
|
|
111
|
+
| `CUCUMBER_PATHS` | Comma-separated feature globs replacing `paths`: `CUCUMBER_PATHS=features/login.feature npx playwright test` |
|
|
112
|
+
|
|
91
113
|
---
|
|
92
114
|
|
|
93
115
|
## World Classes
|
|
@@ -105,17 +127,29 @@ import { TestWorld } from '@qavajs/playwright-runner-adapter';
|
|
|
105
127
|
| `test` | `TestType` | Playwright `test` instance (default or custom) |
|
|
106
128
|
| `expect` | `ExpectType` | Playwright `expect` instance (default or custom) |
|
|
107
129
|
| `attach` | `function` | Attach files/data to the test report |
|
|
108
|
-
| `log` | `function` | Log
|
|
109
|
-
| `parameters` | `
|
|
130
|
+
| `log` | `function` | Log text to the test report (attachment named `log` on the current step) |
|
|
131
|
+
| `parameters` | `unknown` | Value of the `worldParameters` config option |
|
|
110
132
|
| `config` | `any` | Cucumber config object |
|
|
111
133
|
| `supportCodeLibrary` | `any` | Access to the loaded support code library |
|
|
112
134
|
|
|
113
|
-
**`
|
|
135
|
+
**`attach(data, mediaTypeOrOptions?)`** — same signature as in Cucumber:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
await this.attach('plain text'); // text/plain
|
|
139
|
+
await this.attach(JSON.stringify(data), 'application/json');
|
|
140
|
+
await this.attach(screenshot, { mediaType: 'image/png', fileName: 'screenshot.png' });
|
|
141
|
+
await this.attach(base64Png, 'image/png;base64'); // base64 string is decoded
|
|
142
|
+
await this.attach(fs.createReadStream('report.pdf'), 'application/pdf'); // streams are supported
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**`executeStep(text, argument?)`** — programmatically invoke a step by its text. `argument` is passed as a doc string (`string`) or data table (`string[][]` or `DataTable`); any other value is passed as an extra parameter. Each executed step is shown in the report as a nested step of the calling step, and its `{ timeout }` option applies:
|
|
114
146
|
|
|
115
147
|
```typescript
|
|
116
148
|
When('composite step', async function (this: PlaywrightWorld) {
|
|
117
149
|
await this.executeStep('I open the home page');
|
|
118
150
|
await this.executeStep('I click "Login"');
|
|
151
|
+
await this.executeStep('I fill the form', [['username', 'alice'], ['password', 'secret']]);
|
|
152
|
+
await this.executeStep('I set the body', '{"key": "value"}');
|
|
119
153
|
});
|
|
120
154
|
```
|
|
121
155
|
|
|
@@ -197,6 +231,24 @@ The `init` function receives Playwright fixtures as its argument. Its signature
|
|
|
197
231
|
|
|
198
232
|
---
|
|
199
233
|
|
|
234
|
+
### Typed Steps
|
|
235
|
+
|
|
236
|
+
`withWorld<World>()` returns step and hook functions with `this` typed as your world, so you don't need a `this: MyWorld` annotation in every step:
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { withWorld } from '@qavajs/playwright-runner-adapter';
|
|
240
|
+
|
|
241
|
+
const { Given, When, Then, Before, After } = withWorld<MyWorld>();
|
|
242
|
+
|
|
243
|
+
When('I open {string}', async function (url: string) {
|
|
244
|
+
await this.page.goto(url); // `this` is MyWorld
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Cucumber's generic form works too: `When<MyWorld>('I open {string}', async function (url) { ... })`.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
200
252
|
## Hooks
|
|
201
253
|
|
|
202
254
|
All standard Cucumber hooks are supported. Hooks run as named Playwright steps and appear in the trace viewer and HTML report.
|
|
@@ -309,7 +361,45 @@ When('I log in as {string}', Template((username: string) => `
|
|
|
309
361
|
`));
|
|
310
362
|
```
|
|
311
363
|
|
|
312
|
-
Each non-empty line in the returned string is executed as an individual step against the current world. Steps run sequentially; a failure stops the sequence.
|
|
364
|
+
Each non-empty line in the returned string is executed as an individual step against the current world and shown as a nested step in the report. Steps run sequentially; a failure stops the sequence.
|
|
365
|
+
|
|
366
|
+
Steps in a template can have data tables and doc strings, written the same way as in feature files:
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
When('I register as {string}', Template((username: string) => `
|
|
370
|
+
I fill the form
|
|
371
|
+
| username | ${username} |
|
|
372
|
+
| password | secret |
|
|
373
|
+
I set the body
|
|
374
|
+
"""
|
|
375
|
+
{"user": "${username}"}
|
|
376
|
+
"""
|
|
377
|
+
`));
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Step Results
|
|
383
|
+
|
|
384
|
+
Steps and hooks follow Cucumber semantics:
|
|
385
|
+
|
|
386
|
+
- a step returning `'pending'` fails the scenario (or marks it as `fixme` with `strict: false`)
|
|
387
|
+
- a step or `Before` hook returning `'skipped'` skips the rest of the scenario and marks it as skipped
|
|
388
|
+
- an undefined step fails the scenario with its location in the feature file and a ready-to-paste snippet:
|
|
389
|
+
|
|
390
|
+
```
|
|
391
|
+
Step 'I have 5 "apples"' is not defined
|
|
392
|
+
at /project/features/cart.feature:12
|
|
393
|
+
|
|
394
|
+
Implement it with the following snippet:
|
|
395
|
+
|
|
396
|
+
When('I have {int} {string}', async function (int, string) {
|
|
397
|
+
// Write code here that turns the phrase above into concrete actions
|
|
398
|
+
return 'pending';
|
|
399
|
+
});
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
`After` and `AfterStep` hooks receive the actual status (`PASSED`, `FAILED`, `SKIPPED`, `PENDING`, `UNDEFINED`, `AMBIGUOUS`), including failures in `Before` hooks and soft assertions.
|
|
313
403
|
|
|
314
404
|
---
|
|
315
405
|
|
|
@@ -317,7 +407,9 @@ Each non-empty line in the returned string is executed as an individual step aga
|
|
|
317
407
|
|
|
318
408
|
### Tag Expressions
|
|
319
409
|
|
|
320
|
-
|
|
410
|
+
The simplest way to select scenarios is the `tags` [config option](#configuration-reference) and the `CUCUMBER_TAGS` environment variable. They are evaluated against the scenario's Gherkin tags, and scenarios that don't match are not created at all.
|
|
411
|
+
|
|
412
|
+
Use `tags()` to translate a Cucumber tag expression into a Playwright `grep` pattern:
|
|
321
413
|
|
|
322
414
|
```typescript
|
|
323
415
|
// playwright.config.ts
|
|
@@ -331,6 +423,10 @@ export default defineConfig({
|
|
|
331
423
|
|
|
332
424
|
Supports the full [Cucumber tag expression syntax](https://github.com/cucumber/tag-expressions): `and`, `or`, `not`, parentheses.
|
|
333
425
|
|
|
426
|
+
Invalid expressions fail fast with an error naming their source (`tags()`, the `tags` option or `CUCUMBER_TAGS`). Tags written without `@` (e.g. `smoke and not @wip`) are rejected too, because they would silently match nothing.
|
|
427
|
+
|
|
428
|
+
`tags()` is evaluated against Playwright's grep string (titles + tags), so, like Playwright itself, it treats `@words` in feature and scenario titles as tags. Use the `tags` config option when that matters.
|
|
429
|
+
|
|
334
430
|
### Predicate Filter
|
|
335
431
|
|
|
336
432
|
Use `filter` when you need arbitrary logic to select scenarios:
|
|
@@ -348,6 +444,45 @@ The predicate receives the full test name (feature + scenario title + tags) and
|
|
|
348
444
|
|
|
349
445
|
---
|
|
350
446
|
|
|
447
|
+
## Annotations, Modifiers and Locks
|
|
448
|
+
|
|
449
|
+
Gherkin tags are translated into Playwright [test details](https://playwright.dev/docs/test-annotations). The special tags below are consumed: they are removed from the scenario's Playwright tags (and the `tags` annotation), so they don't show up as tags in reports and can't be matched with `grep` / `tags()`. All other tags are kept as Playwright tags.
|
|
450
|
+
|
|
451
|
+
| Tag | Playwright equivalent |
|
|
452
|
+
|---|---|
|
|
453
|
+
| `@skip()` / `@skip(reason)` | skips the scenario — fixtures are not set up |
|
|
454
|
+
| `@fixme()` / `@fixme(reason)` | same as skip, marks the scenario as to be fixed |
|
|
455
|
+
| `@fail()` / `@fail(reason)` | scenario passes only if it fails |
|
|
456
|
+
| `@slow()` / `@slow(reason)` | triples the timeout |
|
|
457
|
+
| `@lock(name)` | `lock: 'name'` — scenarios sharing a lock never run concurrently |
|
|
458
|
+
| `@lock(-exclusive-)` | built-in exclusive lock — runs only when no other test is running |
|
|
459
|
+
| `@annotation(type,description)` | `annotation: { type, description }` — description is optional: `@annotation(flaky)` |
|
|
460
|
+
| `@timeout(ms)` | sets the test timeout, e.g. `@timeout(60000)`; overrides `@slow()`, the last tag wins (scenario over feature) |
|
|
461
|
+
| `@retries(n)` | number of retries for all scenarios of the feature — **Feature only**, using it on a Rule or Scenario is an error |
|
|
462
|
+
|
|
463
|
+
Modifiers are passed as annotations of type `skip`, `fixme`, `fail`, `slow`, which Playwright applies like `test.skip()` and the other modifiers, and the optional reason is shown in the report. Plain tags such as `@skip` or `@slow` are ordinary tags and do nothing. Tags set on a `Feature` or `Rule` apply to all its scenarios.
|
|
464
|
+
|
|
465
|
+
> Gherkin tags may not contain whitespace, so write `@annotation(issue,JIRA-123)` without a space after the comma. Everything after the first comma is the description.
|
|
466
|
+
|
|
467
|
+
```gherkin
|
|
468
|
+
@lock(user-settings)
|
|
469
|
+
Feature: user settings
|
|
470
|
+
|
|
471
|
+
@annotation(issue,JIRA-123)
|
|
472
|
+
Scenario: update settings
|
|
473
|
+
When I update settings
|
|
474
|
+
|
|
475
|
+
@lock(-exclusive-) @slow(full-reset)
|
|
476
|
+
Scenario: reset all data
|
|
477
|
+
When I reset the database
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
Locks are a lighter alternative to splitting scenarios into a separate serial project (see [Parallelism](#parallelism)): only scenarios sharing the same lock are serialized, everything else stays parallel. Locks require `@playwright/test` 1.65+.
|
|
481
|
+
|
|
482
|
+
Runtime annotations can be added from steps via `this.test.info().annotations.push({ type, description })`.
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
351
486
|
## Parallelism
|
|
352
487
|
|
|
353
488
|
Playwright projects let you run subsets of scenarios in parallel or serially:
|
|
@@ -378,13 +513,31 @@ export default defineConfig({
|
|
|
378
513
|
|
|
379
514
|
Tag scenarios that must run serially with `@serial` (or any tag of your choice) and keep everything else fully parallel.
|
|
380
515
|
|
|
516
|
+
To run a single feature or scenario use `CUCUMBER_PATHS=features/login.feature npx playwright test` or `npx playwright test -g "Feature name"`. Passing a `.feature` path as a Playwright CLI argument does not work, because all scenarios are defined in `cucumber.config.ts`.
|
|
517
|
+
|
|
381
518
|
> To get the current worker index inside a step, use `this.test.info().parallelIndex`.
|
|
382
519
|
|
|
383
520
|
---
|
|
384
521
|
|
|
385
|
-
##
|
|
522
|
+
## Reports
|
|
386
523
|
|
|
387
|
-
|
|
524
|
+
- Scenarios are reported at their location in the `.feature` file (Scenario Outline examples point to their example row), so reporters and `--list` show `features/login.feature:12:3`.
|
|
525
|
+
- Steps point to their step definition; set `stepLocation: 'feature'` to point them to the step line in the `.feature` file instead.
|
|
526
|
+
- Steps are reported with a short preview of their argument: `I submit the form [DataTable: | field | value | | username | alice |]`.
|
|
527
|
+
- Features with the same name in different files get the file path appended to their title to keep test titles unique.
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
531
|
+
## Entrypoints and JavaScript Support
|
|
532
|
+
|
|
533
|
+
The package is compiled to CommonJS JavaScript with type declarations, so it works from TypeScript and plain JavaScript, with `require` and `import`. It has two entrypoints with the same API:
|
|
534
|
+
|
|
535
|
+
| Entrypoint | Difference |
|
|
536
|
+
|---|---|
|
|
537
|
+
| `@qavajs/playwright-runner-adapter` | ships source maps |
|
|
538
|
+
| `@qavajs/playwright-runner-adapter/js` | the same build without source maps — stack traces show the compiled `.js` files |
|
|
539
|
+
|
|
540
|
+
Plain JavaScript projects don't need any TypeScript setup with either entrypoint:
|
|
388
541
|
|
|
389
542
|
```javascript
|
|
390
543
|
// cucumber.config.js
|
|
@@ -403,6 +556,40 @@ const { Given, When, Then, PlaywrightWorld } = require('@qavajs/playwright-runne
|
|
|
403
556
|
|
|
404
557
|
---
|
|
405
558
|
|
|
559
|
+
## Timeouts
|
|
560
|
+
|
|
561
|
+
- The Playwright test timeout (`timeout` in `playwright.config.ts`, `@timeout(ms)` or `@slow()` tags) limits the whole scenario.
|
|
562
|
+
- A step or hook `{ timeout }` option limits that single step or hook, as in Cucumber:
|
|
563
|
+
|
|
564
|
+
```typescript
|
|
565
|
+
When('I upload a big file', { timeout: 60_000 }, async function () { /* ... */ });
|
|
566
|
+
Before({ tags: '@db', timeout: 10_000 }, async function () { /* ... */ });
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
- `setDefaultTimeout(ms)` sets the timeout for all steps and hooks without their own `{ timeout }`. Unlike Cucumber, there is no 5 second default: without `setDefaultTimeout` only the Playwright test timeout applies. `-1` disables the timeout for a definition.
|
|
570
|
+
|
|
571
|
+
---
|
|
572
|
+
|
|
573
|
+
## Supported Cucumber APIs
|
|
574
|
+
|
|
575
|
+
| API | Supported |
|
|
576
|
+
|---|---|
|
|
577
|
+
| `Given` / `When` / `Then` / `defineStep` (Cucumber expressions and RegExp) | ✅ |
|
|
578
|
+
| `Before` / `After` / `BeforeStep` / `AfterStep` (named, tagged) | ✅ |
|
|
579
|
+
| `BeforeAll` / `AfterAll` | ✅ once per worker |
|
|
580
|
+
| `setWorldConstructor` | ✅ |
|
|
581
|
+
| `defineParameterType` | ✅ |
|
|
582
|
+
| `setDefinitionFunctionWrapper` (incl. `wrapperOptions`) | ✅ |
|
|
583
|
+
| Data tables, doc strings | ✅ |
|
|
584
|
+
| Scenario Outline, Background, Rule (incl. Rule tags) | ✅ |
|
|
585
|
+
| Localized Gherkin (`# language: de`) | ✅ |
|
|
586
|
+
| `worldParameters`, `tags`, `strict` | ✅ |
|
|
587
|
+
| `setDefaultTimeout`, step and hook `{ timeout }` option | ✅ see [Timeouts](#timeouts) |
|
|
588
|
+
| `setParallelCanAssign` | ❌ see [Limitations](#limitations) |
|
|
589
|
+
| Cucumber formatters (`format`) | ❌ use Playwright [reporters](https://playwright.dev/docs/test-reporters) |
|
|
590
|
+
|
|
591
|
+
---
|
|
592
|
+
|
|
406
593
|
## Limitations
|
|
407
594
|
|
|
408
595
|
- **ES modules** — not supported for Node.js < 22 (where experimental ESM `require` is available). Use CommonJS or TypeScript with `ts-node`.
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { APIRequestContext, Browser, BrowserContext, Page } from '@playwright/test';
|
|
2
|
-
import type { CucumberAdapterConfig, SupportCodeLibrary, WorldOptions } from './types';
|
|
2
|
+
import type { AttachFn, CucumberAdapterConfig, SupportCodeLibrary, WorldOptions } from './types';
|
|
3
3
|
export declare class TestWorld {
|
|
4
4
|
log: (data: unknown) => void;
|
|
5
|
-
attach:
|
|
6
|
-
fileName?: string;
|
|
7
|
-
mediaType?: string;
|
|
8
|
-
}) => Promise<void>;
|
|
5
|
+
attach: AttachFn;
|
|
9
6
|
parameters: unknown;
|
|
10
7
|
config: CucumberAdapterConfig;
|
|
11
8
|
supportCodeLibrary: SupportCodeLibrary;
|
|
12
9
|
test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions>;
|
|
13
10
|
expect: import("@playwright/test").Expect<{}>;
|
|
14
11
|
constructor(options: WorldOptions);
|
|
15
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Execute step by its text
|
|
14
|
+
* @param text - step text
|
|
15
|
+
* @param argument - doc string (`string`), data table (`string[][]` or `DataTable`) or any extra parameter
|
|
16
|
+
*/
|
|
17
|
+
executeStep(this: TestWorld, text: string, argument?: unknown): Promise<void>;
|
|
16
18
|
}
|
|
17
19
|
export declare class PlaywrightWorld extends TestWorld {
|
|
18
20
|
page: Page;
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PlaywrightWorld = exports.TestWorld = void 0;
|
|
4
4
|
const test_1 = require("@playwright/test");
|
|
5
|
+
const gherkin_1 = require("./gherkin");
|
|
6
|
+
const timeout_1 = require("./timeout");
|
|
5
7
|
class TestWorld {
|
|
6
8
|
log;
|
|
7
9
|
attach;
|
|
@@ -17,7 +19,12 @@ class TestWorld {
|
|
|
17
19
|
this.supportCodeLibrary = options.supportCodeLibrary;
|
|
18
20
|
this.config = options.config;
|
|
19
21
|
}
|
|
20
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Execute step by its text
|
|
24
|
+
* @param text - step text
|
|
25
|
+
* @param argument - doc string (`string`), data table (`string[][]` or `DataTable`) or any extra parameter
|
|
26
|
+
*/
|
|
27
|
+
async executeStep(text, argument) {
|
|
21
28
|
const steps = this.supportCodeLibrary.stepDefinitions
|
|
22
29
|
.filter(s => s.matchesStepName(text));
|
|
23
30
|
if (steps.length === 0)
|
|
@@ -27,13 +34,19 @@ class TestWorld {
|
|
|
27
34
|
throw new Error(`Step "${text}" matches multiple step definitions:\n${locations}`);
|
|
28
35
|
}
|
|
29
36
|
const step = steps[0];
|
|
30
|
-
const {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
const { argument: pickleArgument, extra } = (0, gherkin_1.toPickleArgument)(argument);
|
|
38
|
+
const location = step.uri ? { file: step.uri, line: step.line, column: 1 } : undefined;
|
|
39
|
+
// reported as a nested step, so failures inside composite steps point to the exact inner step
|
|
40
|
+
await this.test.step((0, gherkin_1.stepTitle)({ text, argument: pickleArgument }), async () => {
|
|
41
|
+
const { parameters } = await step.getInvocationParameters({ step: { text, argument: pickleArgument }, world: this });
|
|
42
|
+
const args = extra === undefined ? parameters : [...parameters, extra];
|
|
43
|
+
try {
|
|
44
|
+
await (0, timeout_1.runWithTimeout)(() => step.code.apply(this, args), (0, timeout_1.resolveTimeout)(step, this.supportCodeLibrary.defaultTimeout), `Step '${text}' timed out after {timeout} ms\n at ${step.uri}:${step.line}`);
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
throw new Error(`Step failed: ${text}`, { cause: err });
|
|
48
|
+
}
|
|
49
|
+
}, { location });
|
|
37
50
|
}
|
|
38
51
|
}
|
|
39
52
|
exports.TestWorld = TestWorld;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlaywrightWorld.js","sourceRoot":"","sources":["../src/PlaywrightWorld.ts"],"names":[],"mappings":";;;AAAA,2CAAkG;
|
|
1
|
+
{"version":3,"file":"PlaywrightWorld.js","sourceRoot":"","sources":["../src/PlaywrightWorld.ts"],"names":[],"mappings":";;;AAAA,2CAAkG;AAElG,uCAAwD;AACxD,uCAA2D;AAE3D;IACI,GAAG,CAA2B;IAC9B,MAAM,CAAY;IAClB,UAAU,CAAW;IACrB,MAAM,CAAyB;IAC/B,kBAAkB,CAAsB;IACxC,IAAI,GAAG,WAAI,CAAC;IACZ,MAAM,GAAG,aAAM,CAAC;IAEhB,YAAY,OAAqB;QAC7B,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAO,CAAC;QAC9B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAC,kBAAmB,CAAC;QACtD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAO,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW,CAAkB,IAAY,EAAE,QAAkB;QAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,eAAe;aAChD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,kBAAkB,CAAC,CAAC;QACzE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpE,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,yCAAyC,SAAS,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,GAAG,IAAA,0BAAgB,EAAC,QAAQ,CAAC,CAAC;QACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACvF,8FAA8F;QAC9F,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAA,mBAAS,EAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,EAAE,KAAK,IAAI,EAAE;YAC3E,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACrH,MAAM,IAAI,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,EAAE,KAAK,CAAC,CAAC;YACvE,IAAI,CAAC;gBACD,MAAM,IAAA,wBAAc,EAChB,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,EACjC,IAAA,wBAAc,EAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,EAC5D,SAAS,IAAI,wCAAwC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAC/E,CAAC;YACN,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAC5D,CAAC;QACL,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrB,CAAC;CACJ;;AAED,qBAA6B,SAAQ,SAAS;IAC1C,IAAI,CAAQ;IACZ,OAAO,CAAkB;IACzB,OAAO,CAAW;IAClB,WAAW,CAAU;IACrB,OAAO,CAAqB;IAE5B,uGAAuG;IACvG,IAAI,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAyF,EAAE,EAAE;QACnI,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC,CAA4B,CAAC;CACjC"}
|
package/adapter/Template.d.ts
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
|
+
export interface TemplateStep {
|
|
2
|
+
text: string;
|
|
3
|
+
argument?: string | string[][];
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Parse template text into steps. Supports data tables (`| a | b |` lines)
|
|
7
|
+
* and doc strings (`"""` or ``` blocks) placed after a step.
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseTemplate(scenario: string): TemplateStep[];
|
|
1
10
|
/**
|
|
2
11
|
* Define template step
|
|
3
|
-
* @param {string} scenario - multiline string with steps
|
|
12
|
+
* @param {string} scenario - multiline string with steps; steps can have data tables and doc strings
|
|
4
13
|
* @example
|
|
5
14
|
* When('I click {string} and verify {string}', Template((locator, expected) => `
|
|
6
15
|
* I click '${locator}'
|
|
7
16
|
* I expect '${locator} > Value' to equal '${expected}'
|
|
17
|
+
* I fill form
|
|
18
|
+
* | name | John |
|
|
8
19
|
* `));
|
|
9
20
|
*/
|
|
10
|
-
export declare function Template(scenario: (...args:
|
|
21
|
+
export declare function Template(scenario: (...args: any[]) => string): (...args: unknown[]) => string;
|
package/adapter/Template.js
CHANGED
|
@@ -1,25 +1,74 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseTemplate = parseTemplate;
|
|
3
4
|
exports.Template = Template;
|
|
5
|
+
const DOC_STRING_DELIMITERS = ['"""', '```'];
|
|
6
|
+
function parseRow(line) {
|
|
7
|
+
const content = line.replace(/^\|/, '').replace(/(?<!\\)\|$/, '');
|
|
8
|
+
return content
|
|
9
|
+
.split(/(?<!\\)\|/)
|
|
10
|
+
.map(cell => cell.trim().replace(/\\\|/g, '|'));
|
|
11
|
+
}
|
|
12
|
+
function stripIndent(line, indent) {
|
|
13
|
+
const leading = line.length - line.trimStart().length;
|
|
14
|
+
return line.slice(Math.min(indent, leading));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parse template text into steps. Supports data tables (`| a | b |` lines)
|
|
18
|
+
* and doc strings (`"""` or ``` blocks) placed after a step.
|
|
19
|
+
*/
|
|
20
|
+
function parseTemplate(scenario) {
|
|
21
|
+
const lines = scenario.split('\n');
|
|
22
|
+
const steps = [];
|
|
23
|
+
const previousStep = (line) => {
|
|
24
|
+
const step = steps.at(-1);
|
|
25
|
+
if (!step)
|
|
26
|
+
throw new Error(`Template argument "${line.trim()}" must follow a step`);
|
|
27
|
+
return step;
|
|
28
|
+
};
|
|
29
|
+
for (let i = 0; i < lines.length; i++) {
|
|
30
|
+
const line = lines[i];
|
|
31
|
+
const trimmed = line.trim();
|
|
32
|
+
if (!trimmed)
|
|
33
|
+
continue;
|
|
34
|
+
const delimiter = DOC_STRING_DELIMITERS.find(d => trimmed.startsWith(d));
|
|
35
|
+
if (delimiter) {
|
|
36
|
+
const step = previousStep(line);
|
|
37
|
+
const indent = line.indexOf(delimiter);
|
|
38
|
+
const content = [];
|
|
39
|
+
for (i++; i < lines.length && lines[i].trim() !== delimiter; i++) {
|
|
40
|
+
content.push(stripIndent(lines[i], indent));
|
|
41
|
+
}
|
|
42
|
+
step.argument = content.join('\n');
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (trimmed.startsWith('|')) {
|
|
46
|
+
const step = previousStep(line);
|
|
47
|
+
if (!Array.isArray(step.argument))
|
|
48
|
+
step.argument = [];
|
|
49
|
+
step.argument.push(parseRow(trimmed));
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
steps.push({ text: trimmed });
|
|
53
|
+
}
|
|
54
|
+
return steps;
|
|
55
|
+
}
|
|
4
56
|
/**
|
|
5
57
|
* Define template step
|
|
6
|
-
* @param {string} scenario - multiline string with steps
|
|
58
|
+
* @param {string} scenario - multiline string with steps; steps can have data tables and doc strings
|
|
7
59
|
* @example
|
|
8
60
|
* When('I click {string} and verify {string}', Template((locator, expected) => `
|
|
9
61
|
* I click '${locator}'
|
|
10
62
|
* I expect '${locator} > Value' to equal '${expected}'
|
|
63
|
+
* I fill form
|
|
64
|
+
* | name | John |
|
|
11
65
|
* `));
|
|
12
66
|
*/
|
|
13
67
|
function Template(scenario) {
|
|
14
68
|
return new Proxy(scenario, {
|
|
15
69
|
apply: async function (template, world, args) {
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
.split('\n')
|
|
19
|
-
.map(step => step.trim())
|
|
20
|
-
.filter(Boolean);
|
|
21
|
-
for (const step of steps) {
|
|
22
|
-
await world.executeStep(step);
|
|
70
|
+
for (const step of parseTemplate(template(...args))) {
|
|
71
|
+
await world.executeStep(step.text, step.argument);
|
|
23
72
|
}
|
|
24
73
|
},
|
|
25
74
|
});
|
package/adapter/Template.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Template.js","sourceRoot":"","sources":["../src/Template.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Template.js","sourceRoot":"","sources":["../src/Template.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,9 @@
|
|
|
1
|
+
import type { Pickle } from '@cucumber/messages';
|
|
1
2
|
import type { CucumberAdapterConfig } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Create scenario filter from tag expressions keyed by their source (used in error messages),
|
|
5
|
+
* e.g. `{ 'tags option': config.tags, 'CUCUMBER_TAGS env variable': process.env.CUCUMBER_TAGS }`.
|
|
6
|
+
* All expressions must match.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createTagFilter(sources: Record<string, string | undefined>): (pickle: Pickle) => boolean;
|
|
2
9
|
export declare function defineConfig(config: CucumberAdapterConfig): void;
|