@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.
Files changed (55) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +198 -11
  3. package/adapter/PlaywrightWorld.d.ts +8 -6
  4. package/adapter/PlaywrightWorld.js +21 -8
  5. package/adapter/PlaywrightWorld.js.map +1 -1
  6. package/adapter/Template.d.ts +13 -2
  7. package/adapter/Template.js +57 -8
  8. package/adapter/Template.js.map +1 -1
  9. package/adapter/cucumberAdapter.d.ts +7 -0
  10. package/adapter/cucumberAdapter.js +254 -114
  11. package/adapter/cucumberAdapter.js.map +1 -1
  12. package/adapter/filter.d.ts +8 -0
  13. package/adapter/filter.js +27 -1
  14. package/adapter/filter.js.map +1 -1
  15. package/adapter/gherkin.d.ts +45 -0
  16. package/adapter/gherkin.js +155 -0
  17. package/adapter/gherkin.js.map +1 -0
  18. package/adapter/index.d.ts +2 -0
  19. package/adapter/index.js +2 -0
  20. package/adapter/index.js.map +1 -1
  21. package/adapter/js/PlaywrightWorld.d.ts +8 -6
  22. package/adapter/js/PlaywrightWorld.js +21 -8
  23. package/adapter/js/Template.d.ts +13 -2
  24. package/adapter/js/Template.js +57 -8
  25. package/adapter/js/cucumberAdapter.d.ts +7 -0
  26. package/adapter/js/cucumberAdapter.js +254 -114
  27. package/adapter/js/filter.d.ts +8 -0
  28. package/adapter/js/filter.js +27 -1
  29. package/adapter/js/gherkin.d.ts +45 -0
  30. package/adapter/js/gherkin.js +154 -0
  31. package/adapter/js/index.d.ts +2 -0
  32. package/adapter/js/index.js +2 -0
  33. package/adapter/js/loader.d.ts +9 -1
  34. package/adapter/js/loader.js +35 -15
  35. package/adapter/js/testDetails.d.ts +28 -0
  36. package/adapter/js/testDetails.js +78 -0
  37. package/adapter/js/timeout.d.ts +17 -0
  38. package/adapter/js/timeout.js +24 -0
  39. package/adapter/js/types.d.ts +35 -6
  40. package/adapter/js/withWorld.d.ts +43 -0
  41. package/adapter/js/withWorld.js +16 -0
  42. package/adapter/loader.d.ts +9 -1
  43. package/adapter/loader.js +35 -15
  44. package/adapter/loader.js.map +1 -1
  45. package/adapter/testDetails.d.ts +28 -0
  46. package/adapter/testDetails.js +79 -0
  47. package/adapter/testDetails.js.map +1 -0
  48. package/adapter/timeout.d.ts +17 -0
  49. package/adapter/timeout.js +25 -0
  50. package/adapter/timeout.js.map +1 -0
  51. package/adapter/types.d.ts +35 -6
  52. package/adapter/withWorld.d.ts +43 -0
  53. package/adapter/withWorld.js +17 -0
  54. package/adapter/withWorld.js.map +1 -0
  55. 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
- - [JavaScript / CommonJS Support](#javascript--commonjs-support)
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[]` | Modules to require before step definitions (e.g. `ts-node/register`) |
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 data to console |
109
- | `parameters` | `string` | Cucumber world 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
- **`executeStep(text, extraParam?)`** — programmatically invoke a step by its text:
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
- Use `tags` to translate a Cucumber tag expression into a Playwright `grep` pattern:
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
- ## JavaScript / CommonJS Support
522
+ ## Reports
386
523
 
387
- If your step definitions are plain JavaScript (`.js`), import from the `./js` entrypoint to avoid TypeScript overhead:
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: (data: unknown, details?: {
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
- executeStep(this: TestWorld, text: string, extraParam?: unknown): Promise<void>;
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
- async executeStep(text, extraParam) {
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 { parameters } = await step.getInvocationParameters({ step: { text }, world: this });
31
- try {
32
- await step.code.apply(this, [...parameters, extraParam]);
33
- }
34
- catch (err) {
35
- throw new Error(`Step failed: ${text}`, { cause: err });
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;AAGlG,MAAa,SAAS;IAClB,GAAG,CAA2B;IAC9B,MAAM,CAAyF;IAC/F,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,KAAK,CAAC,WAAW,CAAkB,IAAY,EAAE,UAAoB;QACjE,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,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3F,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5D,CAAC;IACL,CAAC;CACJ;AAjCD,8BAiCC;AAED,MAAa,eAAgB,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;AAdD,0CAcC"}
1
+ {"version":3,"file":"PlaywrightWorld.js","sourceRoot":"","sources":["../src/PlaywrightWorld.ts"],"names":[],"mappings":"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"}
@@ -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: unknown[]) => string): (...args: unknown[]) => string;
21
+ export declare function Template(scenario: (...args: any[]) => string): (...args: unknown[]) => string;
@@ -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 scenario = template(...args);
17
- const steps = scenario
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
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Template.js","sourceRoot":"","sources":["../src/Template.ts"],"names":[],"mappings":";;AAWA,4BAaC;AAtBD;;;;;;;;GAQG;AACH,SAAgB,QAAQ,CAAC,QAAwC;IAC7D,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE;QACvB,KAAK,EAAE,KAAK,WAAW,QAAwC,EAAE,KAAgB,EAAE,IAAe;YAC9F,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;YACnC,MAAM,KAAK,GAAG,QAAQ;iBACjB,KAAK,CAAC,IAAI,CAAC;iBACX,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;iBACxB,MAAM,CAAC,OAAO,CAAC,CAAC;YACrB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACvB,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;QACL,CAAC;KACJ,CAAC,CAAC;AACP,CAAC"}
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;