@lynxwall/cucumber-tsflow 7.5.5 → 7.7.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 (107) hide show
  1. package/README.md +287 -234
  2. package/lib/api/convert-configuration.d.ts +1 -0
  3. package/lib/api/convert-configuration.js +2 -0
  4. package/lib/api/convert-configuration.js.map +1 -1
  5. package/lib/api/load-configuration.js +22 -33
  6. package/lib/api/load-configuration.js.map +1 -1
  7. package/lib/api/load-support.d.ts +24 -1
  8. package/lib/api/load-support.js +140 -3
  9. package/lib/api/load-support.js.map +1 -1
  10. package/lib/api/loader-worker.d.ts +25 -0
  11. package/lib/api/loader-worker.js +70 -0
  12. package/lib/api/loader-worker.js.map +1 -0
  13. package/lib/api/parallel-loader.d.ts +31 -0
  14. package/lib/api/parallel-loader.js +169 -0
  15. package/lib/api/parallel-loader.js.map +1 -0
  16. package/lib/api/run-cucumber.js +42 -12
  17. package/lib/api/run-cucumber.js.map +1 -1
  18. package/lib/api/support.js +3 -0
  19. package/lib/api/support.js.map +1 -1
  20. package/lib/api/wrapper.mjs +1 -0
  21. package/lib/bindings/binding-decorator.d.ts +6 -0
  22. package/lib/bindings/binding-decorator.js +14 -0
  23. package/lib/bindings/binding-decorator.js.map +1 -1
  24. package/lib/bindings/binding-registry.d.ts +31 -1
  25. package/lib/bindings/binding-registry.js +95 -47
  26. package/lib/bindings/binding-registry.js.map +1 -1
  27. package/lib/bindings/step-binding.d.ts +37 -0
  28. package/lib/bindings/step-binding.js +23 -0
  29. package/lib/bindings/step-binding.js.map +1 -1
  30. package/lib/bindings/types.js.map +1 -1
  31. package/lib/cli/argv-parser.d.ts +1 -0
  32. package/lib/cli/argv-parser.js +6 -0
  33. package/lib/cli/argv-parser.js.map +1 -1
  34. package/lib/formatter/{step-definition-snippit-syntax → step-definition-snippet-syntax}/tsflow-snippet-syntax.js.map +1 -1
  35. package/lib/index.d.ts +1 -1
  36. package/lib/index.js +1 -1
  37. package/lib/index.js.map +1 -1
  38. package/lib/runtime/coordinator.d.ts +2 -1
  39. package/lib/runtime/coordinator.js +4 -2
  40. package/lib/runtime/coordinator.js.map +1 -1
  41. package/lib/runtime/make-runtime.d.ts +3 -1
  42. package/lib/runtime/make-runtime.js +5 -4
  43. package/lib/runtime/make-runtime.js.map +1 -1
  44. package/lib/runtime/managed-scenario-context.js +2 -32
  45. package/lib/runtime/managed-scenario-context.js.map +1 -1
  46. package/lib/runtime/parallel/adapter.d.ts +4 -1
  47. package/lib/runtime/parallel/adapter.js +10 -2
  48. package/lib/runtime/parallel/adapter.js.map +1 -1
  49. package/lib/runtime/serial/adapter.d.ts +2 -1
  50. package/lib/runtime/serial/adapter.js +13 -3
  51. package/lib/runtime/serial/adapter.js.map +1 -1
  52. package/lib/runtime/test-case-runner.d.ts +4 -1
  53. package/lib/runtime/test-case-runner.js +4 -5
  54. package/lib/runtime/test-case-runner.js.map +1 -1
  55. package/lib/runtime/types.d.ts +2 -0
  56. package/lib/runtime/types.js.map +1 -1
  57. package/lib/runtime/utils.js +0 -6
  58. package/lib/runtime/utils.js.map +1 -1
  59. package/lib/runtime/worker.d.ts +14 -3
  60. package/lib/runtime/worker.js +91 -12
  61. package/lib/runtime/worker.js.map +1 -1
  62. package/lib/snippet.js +1 -1
  63. package/lib/snippet.js.map +1 -1
  64. package/lib/transpilers/esm/vue-sfc-compiler.mjs +14 -333
  65. package/lib/transpilers/esvue.js +6 -9
  66. package/lib/transpilers/esvue.js.map +1 -1
  67. package/lib/transpilers/tsvue-exp.js +6 -9
  68. package/lib/transpilers/tsvue-exp.js.map +1 -1
  69. package/lib/transpilers/tsvue.js +5 -8
  70. package/lib/transpilers/tsvue.js.map +1 -1
  71. package/lib/transpilers/vue-sfc-compiler.d.ts +23 -0
  72. package/lib/transpilers/vue-sfc-compiler.js +242 -0
  73. package/lib/transpilers/vue-sfc-compiler.js.map +1 -0
  74. package/lib/tsconfig.node.tsbuildinfo +1 -1
  75. package/lib/version.d.ts +1 -1
  76. package/lib/version.js +1 -1
  77. package/lib/version.js.map +1 -1
  78. package/package.json +8 -9
  79. package/lib/transpilers/vue-sfc/compiler.d.ts +0 -7
  80. package/lib/transpilers/vue-sfc/compiler.js +0 -22
  81. package/lib/transpilers/vue-sfc/compiler.js.map +0 -1
  82. package/lib/transpilers/vue-sfc/index.d.ts +0 -23
  83. package/lib/transpilers/vue-sfc/index.js +0 -46
  84. package/lib/transpilers/vue-sfc/index.js.map +0 -1
  85. package/lib/transpilers/vue-sfc/main.d.ts +0 -8
  86. package/lib/transpilers/vue-sfc/main.js +0 -258
  87. package/lib/transpilers/vue-sfc/main.js.map +0 -1
  88. package/lib/transpilers/vue-sfc/script.d.ts +0 -5
  89. package/lib/transpilers/vue-sfc/script.js +0 -41
  90. package/lib/transpilers/vue-sfc/script.js.map +0 -1
  91. package/lib/transpilers/vue-sfc/template.d.ts +0 -8
  92. package/lib/transpilers/vue-sfc/template.js +0 -101
  93. package/lib/transpilers/vue-sfc/template.js.map +0 -1
  94. package/lib/transpilers/vue-sfc/types.d.ts +0 -55
  95. package/lib/transpilers/vue-sfc/types.js +0 -3
  96. package/lib/transpilers/vue-sfc/types.js.map +0 -1
  97. package/lib/transpilers/vue-sfc/utils/descriptorCache.d.ts +0 -13
  98. package/lib/transpilers/vue-sfc/utils/descriptorCache.js +0 -68
  99. package/lib/transpilers/vue-sfc/utils/descriptorCache.js.map +0 -1
  100. package/lib/transpilers/vue-sfc/utils/error.d.ts +0 -3
  101. package/lib/transpilers/vue-sfc/utils/error.js +0 -23
  102. package/lib/transpilers/vue-sfc/utils/error.js.map +0 -1
  103. package/lib/transpilers/vue-sfc/utils/query.d.ts +0 -13
  104. package/lib/transpilers/vue-sfc/utils/query.js +0 -36
  105. package/lib/transpilers/vue-sfc/utils/query.js.map +0 -1
  106. /package/lib/formatter/{step-definition-snippit-syntax → step-definition-snippet-syntax}/tsflow-snippet-syntax.d.ts +0 -0
  107. /package/lib/formatter/{step-definition-snippit-syntax → step-definition-snippet-syntax}/tsflow-snippet-syntax.js +0 -0
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # cucumber-tsflow
4
4
 
5
- Provides 'specflow' like bindings for Cucumber-JS 12.2.0 in TypeScript 5.9+.
5
+ Provides 'specflow' like bindings for Cucumber-JS 12.7.0 in TypeScript 5.9+.
6
6
 
7
7
  Supports Vue3 files in cucumber tests.
8
8
 
@@ -12,13 +12,63 @@ This is a detached fork of <https://github.com/timjroberts/cucumber-js-tsflow>.
12
12
 
13
13
  This fork has been drastically modified from the original and will eventually be moved to a new project. In addition, the SpecFlow project has reached [end of life](https://reqnroll.net/news/2025/01/specflow-end-of-life-has-been-announced/), and this project will be rebranded. Further details will be provided in future updates. However, the new project will support the same functionality as cucumber-tsflow while providing additional tools and extensions.
14
14
 
15
+ ## Release Updates (7.7.0)
16
+
17
+ This release focuses on correctness, performance, and code quality improvements across the codebase.
18
+
19
+ ### Bug Fixes
20
+
21
+ - **`throw error()` in `test-case-runner.ts`** — four instances used `console.error()` (which returns `void`) instead of `new Error()`, meaning thrown errors were always `undefined`.
22
+ - **Broken `escapeRegExp` in `runtime/utils.ts`** — the function was a no-op and double-processed intentionally constructed regex syntax. Removed entirely.
23
+ - **Missing hook failure checks in serial adapter** — `runBeforeAllHooks()` and `runAfterAllHooks()` return values were ignored. Added failure propagation so hook errors are reported correctly.
24
+ - **Package exports typo** — trailing apostrophe on the `esbuild-transpiler` export key.
25
+ - **Misspelled folder name** — renamed `step-definition-snippit-syntax` to `step-definition-snippet-syntax` and updated all import references.
26
+
27
+ ### New Features
28
+
29
+ - **Parallel preload** (`parallelLoad` configuration option) — warms transpiler on-disk caches in parallel `worker_threads` before the main support-code load phase. Each worker loads a subset of support files, triggering transpilation and populating the filesystem cache. The main thread's subsequent load (and any parallel child processes) then hit warm caches, significantly reducing startup time for large projects. Set `parallelLoad: true` for automatic thread count or provide an explicit number.
30
+
31
+ ### Performance and Efficiency
32
+
33
+ - **Replaced `underscore` with native methods** — removed all `_.map()`, `_.flatten()`, and `_.filter()` calls in favour of native `Array.prototype` equivalents.
34
+ - **O(1) binding lookup** — added a `Map` index to `BindingRegistry` for constant-time `getStepBindingByCucumberKey()` and `hasBindingForKey()` lookups, replacing linear scans.
35
+ - **Collapsed `updateSupportCodeLibrary` switch** — replaced a 9-case `switch` with a lookup map.
36
+ - **Simplified constructor injection** — replaced a 10-case `switch` in `ManagedScenarioContext` with a single spread call, removing the previous limit of nine context objects.
37
+ - **Extracted `replaceFormatAlias` helper** — deduplicated two identical format-replacement loops in `load-configuration.ts`.
38
+
39
+ ### Removed
40
+
41
+ - `underscore` runtime dependency and `@types/underscore` dev dependency.
42
+ - Empty `src/support_code_library_builder/` directory.
43
+ - Legacy `tslint:disable` comments.
44
+
45
+ ### Documentation
46
+
47
+ - Added `Architecture.md` describing the project's architectural design, execution flow, and component relationships.
48
+
49
+ ## Release Updates (7.6.0)
50
+
51
+ This release adds a new API function for incremental support-code reloading and consolidates the internal Vue SFC compiler.
52
+
53
+ ### `reloadSupport` API
54
+
55
+ - **`reloadSupport(options, changedPaths, environment?)`** — evicts only the changed files (and their dependents) from Node's `require.cache`, then re-requires all support files. Unchanged files resolve instantly from transpiler cache; only changed files pay the full compilation cost. Pass an empty `changedPaths` array to evict and reload all support modules.
56
+ - Designed for use by persistent worker processes such as the companion [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=lynxwall.cucumber-tsflow-vscode), which can call `reloadSupport` when a step file is saved instead of doing a full `loadSupport` on every run.
57
+
58
+ ### Vue SFC compiler consolidation
59
+
60
+ - The CJS Vue SFC compiler (previously a 9-file Vite-plugin-derived implementation in `vue-sfc/`) has been replaced by a single shared `vue-sfc-compiler.ts` that both the CJS transpilers and the ESM loaders delegate to.
61
+ - Removed the `rollup` and `@rollup/pluginutils` dependencies, which were only used by the old CJS implementation.
62
+ - Fixed a bug where image assets referenced in Vue templates (e.g. `<img src="...">`) caused a `SyntaxError: Invalid or unexpected token` in CJS mode. Asset URL transforms are now disabled — `src` attributes remain as literal strings, which is the correct behaviour for unit testing Vue components with `@vue/test-utils`.
63
+ - Fixed duplicate **"Using Experimental Decorators."** console message that appeared twice when `experimentalDecorators: true` was set.
64
+
15
65
  ## Release Updates (7.3.0)
16
66
 
17
67
  With this release, we've finally added support for ESM Modules. For details on the new transpilers/loaders please see: [cucumber-tsflow ESM implementation](https://github.com/LynxWall/cucumber-js-tsflow/blob/master/cucumber-tsflow/src/transpilers/esm/README.md).
18
68
 
19
69
  Along with ESM support, additional updates include:
20
70
 
21
- - Cucumber-JS updated to version 12.2.0
71
+ - Cucumber-JS updated to version 12.2.0 (later updated to 12.7.0 in 7.7.0)
22
72
  - Typescript updated to version 5.9.2
23
73
  - ts-node replaced with ts-node-maintained. For more information, please see the section titled **Node 22+ and ts-node** in the [cucumber-tsflow ESM implementation](https://github.com/LynxWall/cucumber-js-tsflow/blob/master/cucumber-tsflow/src/transpilers/esm/README.md).
24
74
  - Other package updates.
@@ -75,6 +125,8 @@ This fork of cucumber-tsflow provides the following features that extend the ori
75
125
 
76
126
  - Support for Parallel execution of tests.
77
127
 
128
+ - Parallel preload of transpiler caches via the `parallelLoad` configuration option, reducing startup time for large projects.
129
+
78
130
  - A behave-json-formatter that fixes json so it can be used with Behave Pro.
79
131
 
80
132
  - A junit-bamboo formatter that generates xml compatible with the Bamboo JUnit plugin.
@@ -126,9 +178,9 @@ Feature: Example Feature
126
178
  This is an example feature
127
179
 
128
180
  Scenario: Adding two numbers
129
- Given I enter 2 and 8
130
- When checking the results
131
- Then I receive the result 10
181
+ Given I enter 2 and 8
182
+ When checking the results
183
+ Then I receive the result 10
132
184
  ```
133
185
 
134
186
  ### Create the Support Files to support the Feature
@@ -144,27 +196,27 @@ Create a new 'ArithmeticSteps.ts' file:
144
196
  ```javascript
145
197
  // features/ArithmeticSteps.ts
146
198
 
147
- import { binding, given, then } from "@lynxwall/cucumber-tsflow";
199
+ import { binding, given, when, then } from "@lynxwall/cucumber-tsflow";
148
200
 
149
201
  @binding()
150
202
  export default class ArithmeticSteps {
151
203
  private computedResult = 0;
152
204
 
153
- @given('I enter {int} and {int}')
154
- iEnterintAndint(int: number, int2: number): any {
155
- this.computedResult = int + int2;
205
+ @given('I enter {int} and {int}')
206
+ iEnterintAndint(int: number, int2: number): any {
207
+ this.computedResult = int + int2;
156
208
  }
157
209
 
158
- @when('checking the results')
159
- checkingTheResults(): any {
160
- expect(this.computedResult).to.be.greaterThan(0);
161
- }
210
+ @when('checking the results')
211
+ checkingTheResults(): any {
212
+ expect(this.computedResult).to.be.greaterThan(0);
213
+ }
162
214
 
163
- @then('I receive the result {int}')
164
- iReceiveTheResultint(int: number): any {
165
- if (int !== this.computedResult) {
166
- throw new Error('Arithmetic Error');
167
- }
215
+ @then('I receive the result {int}')
216
+ iReceiveTheResultint(int: number): any {
217
+ if (int !== this.computedResult) {
218
+ throw new Error('Arithmetic Error');
219
+ }
168
220
  }
169
221
  }
170
222
  ```
@@ -175,7 +227,7 @@ export default class ArithmeticSteps {
175
227
 
176
228
  All support code, which includes your step definition files along with any test fixtures, utilities and references to source code are transpiled on the fly using transpilers that are included with cucumber-tsflow. This eliminates the requirement to prebuild any test code along with associated management of those builds.
177
229
 
178
- If not using one of the [transpilers](#transpiler-and-vue3-supported) listed below you'll need to implement your own transpiler using guidance found in Cucumber-JS documentation: [Transpiling](https://github.com/cucumber/cucumber-js/blob/v12.2.0/docs/transpiling.md)
230
+ If not using one of the [transpilers](#transpiler-and-vue3-supported) listed below you'll need to implement your own transpiler using guidance found in Cucumber-JS documentation: [Transpiling](https://github.com/cucumber/cucumber-js/blob/v12.7.0/docs/transpiling.md)
179
231
 
180
232
  ## Transpilers and TypeScript
181
233
 
@@ -198,35 +250,35 @@ There are two different bundlers, or transpilers, used in cucumber-tsflow: **ts-
198
250
  The following typescript configuration is used in the ts-node transpilers configured for official decorators:
199
251
 
200
252
  ```typescript
201
- compilerOptions: {
202
- module: 'nodeNext',
203
- target: 'es2022',
204
- strict: true,
205
- allowJs: true,
206
- allowSyntheticDefaultImports: true,
207
- esModuleInterop: true,
208
- experimentalDecorators: false,
209
- resolveJsonModule: true,
210
- skipLibCheck: true,
211
- lib: ['es2022', 'esnext.decorators']
212
- }
213
- ```
214
-
215
- This next typescript configuration is used in the ts-node transpilers configured for official decorators:
253
+ compilerOptions: {
254
+ module: 'nodeNext',
255
+ target: 'es2022',
256
+ strict: true,
257
+ allowJs: true,
258
+ allowSyntheticDefaultImports: true,
259
+ esModuleInterop: true,
260
+ experimentalDecorators: false,
261
+ resolveJsonModule: true,
262
+ skipLibCheck: true,
263
+ lib: ['es2022', 'esnext.decorators']
264
+ }
265
+ ```
266
+
267
+ This next typescript configuration is used in the ts-node transpilers configured for experimental decorators:
216
268
 
217
269
  ```typescript
218
- compilerOptions: {
219
- module: 'nodeNext',
220
- target: 'es2022',
221
- strict: true,
222
- allowJs: true,
223
- allowSyntheticDefaultImports: true,
224
- esModuleInterop: true,
225
- experimentalDecorators: true,
226
- resolveJsonModule: true,
227
- skipLibCheck: true,
228
- lib: ['es2022']
229
- }
270
+ compilerOptions: {
271
+ module: 'nodeNext',
272
+ target: 'es2022',
273
+ strict: true,
274
+ allowJs: true,
275
+ allowSyntheticDefaultImports: true,
276
+ esModuleInterop: true,
277
+ experimentalDecorators: true,
278
+ resolveJsonModule: true,
279
+ skipLibCheck: true,
280
+ lib: ['es2022']
281
+ }
230
282
  ```
231
283
 
232
284
  As you can see the only difference is the setting for experimentalDecorators and the lib imports.
@@ -236,19 +288,19 @@ When test runs are started, the settings from your local tsconfig.json are loade
236
288
  For example, the settings from the cucumber-tsflow vue test project is shown below:
237
289
 
238
290
  ```json
239
- "compilerOptions": {
240
- "baseUrl": ".",
241
- "module": "nodeNext",
242
- "target": "es2022",
243
- "strict": true,
244
- "allowJs": true,
245
- "allowSyntheticDefaultImports": true,
246
- "esModuleInterop": true,
247
- "resolveJsonModule": true,
248
- "skipLibCheck": true,
249
- "lib": ["es2022", "esnext.decorators"],
250
- "typeRoots": ["../../node_modules/@types"]
251
- }
291
+ "compilerOptions": {
292
+ "baseUrl": ".",
293
+ "module": "nodeNext",
294
+ "target": "es2022",
295
+ "strict": true,
296
+ "allowJs": true,
297
+ "allowSyntheticDefaultImports": true,
298
+ "esModuleInterop": true,
299
+ "resolveJsonModule": true,
300
+ "skipLibCheck": true,
301
+ "lib": ["es2022", "esnext.decorators"],
302
+ "typeRoots": ["../../node_modules/@types"]
303
+ }
252
304
  ```
253
305
 
254
306
  These settings are similar to the default transpiler settings, which will not cause an issue.
@@ -263,11 +315,11 @@ Cucumber-tsflow provides two esbuild transpilers: one with esbuild and support f
263
315
 
264
316
  ```typescript
265
317
  const commonOptions: CommonOptions = {
266
- format: 'cjs',
267
- logLevel: 'info',
268
- target: [`es2022`],
269
- minify: false,
270
- sourcemap: 'external'
318
+ format: 'cjs',
319
+ logLevel: 'info',
320
+ target: [`es2022`],
321
+ minify: false,
322
+ sourcemap: 'external'
271
323
  };
272
324
  ```
273
325
 
@@ -281,10 +333,10 @@ When using official decorators the following settings are added using the esbuil
281
333
 
282
334
  ```typescript
283
335
  commonOptions.tsconfigRaw = {
284
- compilerOptions: {
285
- importsNotUsedAsValues: 'remove',
286
- strict: true
287
- }
336
+ compilerOptions: {
337
+ importsNotUsedAsValues: 'remove',
338
+ strict: true
339
+ }
288
340
  };
289
341
  ```
290
342
 
@@ -294,11 +346,11 @@ When using experimental decorators the experimentalDecorators setting is added t
294
346
 
295
347
  ```typescript
296
348
  commonOptions.tsconfigRaw = {
297
- compilerOptions: {
298
- experimentalDecorators: true,
299
- importsNotUsedAsValues: 'remove',
300
- strict: true
301
- }
349
+ compilerOptions: {
350
+ experimentalDecorators: true,
351
+ importsNotUsedAsValues: 'remove',
352
+ strict: true
353
+ }
302
354
  };
303
355
  ```
304
356
 
@@ -338,7 +390,7 @@ You can also add a script to package.json to execute the tests as shown below:
338
390
 
339
391
  ```json
340
392
  "scripts": {
341
- "test": "cucumber-tsflow -p esnode"
393
+ "test": "cucumber-tsflow -p esnode"
342
394
  }
343
395
  ```
344
396
 
@@ -396,20 +448,21 @@ echo $?
396
448
 
397
449
  ## New Configuration options
398
450
 
399
- As mentioned, when using cucumber-tsflow to execute tests all of the configuration options documented here are supported: <https://github.com/cucumber/cucumber-js/blob/v12.2.0/docs/configuration.md>
451
+ As mentioned, when using cucumber-tsflow to execute tests all of the configuration options documented here are supported: <https://github.com/cucumber/cucumber-js/blob/v12.7.0/docs/configuration.md>
400
452
 
401
453
  In addition to cucumber configuration options the following two options have been added:
402
454
 
403
455
  | Name | Type | Repeatable | CLI Option | Description | Default |
404
456
  | ------------------------ | --------- | ---------- | --------------------------- | ------------------------------------------------------------ | ------- |
405
- | `transpiler` | `string` | No | `--transpiler` | Name of the transpiler to use: es-vue, ts-vue, es-node, ts-node, es-vue-esm, es-node-esm, ts-vue-esm, ts-node-esm | none |
406
- | `debugFile` | `string` | No | `--debug-file` | Path to a file with steps for debugging | |
407
- | `enableVueStyle` | `boolean` | No | `--enable-vue-style` | Enable Vue `<style>` block when compiling Vue SFC. | false |
408
- | `experimentalDecorators` | `boolean` | No | `--experimental-decorators` | Enable TypeScript Experimental Decorators. | false |
457
+ | `transpiler` | `string` | No | `--transpiler` | Name of the transpiler to use: es-vue, ts-vue, es-node, ts-node, es-vue-esm, es-node-esm, ts-vue-esm, ts-node-esm | none |
458
+ | `debugFile` | `string` | No | `--debug-file` | Path to a file with steps for debugging | |
459
+ | `enableVueStyle` | `boolean` | No | `--enable-vue-style` | Enable Vue `<style>` block when compiling Vue SFC. | false |
460
+ | `experimentalDecorators` | `boolean` | No | `--experimental-decorators` | Enable TypeScript Experimental Decorators. | false |
461
+ | `parallelLoad` | `boolean \| number` | No | | Pre-warm transpiler caches in parallel worker threads before loading support code. `true` = auto thread count, number = explicit count. | false |
409
462
 
410
463
  ### Transpiler and Vue3 supported
411
464
 
412
- Using TypeScript with cucumber-js requires setting tsconfig.json parameters as described here: [cucumber-js Transpiling](https://github.com/cucumber/cucumber-js/blob/v12.2.0/docs/transpiling.md). In addition, there is no support for transpiling Vue files with cucumber-js.
465
+ Using TypeScript with cucumber-js requires setting tsconfig.json parameters as described here: [cucumber-js Transpiling](https://github.com/cucumber/cucumber-js/blob/v12.7.0/docs/transpiling.md). In addition, there is no support for transpiling Vue files with cucumber-js.
413
466
 
414
467
  As a result, cucumber-tsflow adds several configurations for transpiling TypeScript code using the recommended configuration. In addition, support has been added to transform .vue files during test execution allowing you to test Vue SFC components using cucumber.
415
468
 
@@ -437,27 +490,27 @@ In the table above:
437
490
 
438
491
  **NOTE:** When using Vue transpilers **jsdom** is also loaded globally to support loading and testing Vue SFC components.
439
492
 
440
- ##### Using the transpiler configuration option
493
+ #### Using the transpiler configuration option
441
494
 
442
495
  When configuring cucumber to execute tests you can specify which transpiler to use with the `transpiler` configuration option as shown below:
443
496
 
444
497
  ```json
445
498
  {
446
- "default": {
447
- "transpiler": "es-vue"
448
- }
499
+ "default": {
500
+ "transpiler": "es-vue"
501
+ }
449
502
  }
450
503
  ```
451
504
 
452
- ##### Alternate without using the transpiler option
505
+ #### Alternate without using the transpiler option
453
506
 
454
507
  You can also use the `requireModule` parameter to configure a transpiler. The following example shows how to configure cucumber to use the `esvue` transpiler with the `requireModule` option.
455
508
 
456
509
  ```json
457
510
  {
458
- "default": {
459
- "requireModule": ["@lynxwall/cucumber-tsflow/esvue"]
460
- }
511
+ "default": {
512
+ "requireModule": ["@lynxwall/cucumber-tsflow/esvue"]
513
+ }
461
514
  }
462
515
  ```
463
516
 
@@ -467,45 +520,45 @@ The new `debugFile` configuration option allows you to specify a .ts file with s
467
520
 
468
521
  If using VSCode to edit your project the following launch configurations can be used:
469
522
 
470
- ##### Debug All
523
+ #### Debug All
471
524
 
472
525
  ```json
473
526
  {
474
- "name": "Debug All",
475
- "type": "node",
476
- "request": "launch",
477
- "program": "${workspaceRoot}/node_modules/@lynxwall/cucumber-tsflow/bin/cucumber-tsflow/vue",
478
- "stopOnEntry": true,
479
- "args": ["-p", "esvue"],
480
- "cwd": "${workspaceRoot}",
481
- "runtimeExecutable": null,
482
- "runtimeArgs": ["--nolazy"],
483
- "env": {
484
- "NODE_ENV": "development"
485
- },
486
- "console": "integratedTerminal",
487
- "sourceMaps": true
527
+ "name": "Debug All",
528
+ "type": "node",
529
+ "request": "launch",
530
+ "program": "${workspaceRoot}/node_modules/@lynxwall/cucumber-tsflow/bin/cucumber-tsflow/vue",
531
+ "stopOnEntry": true,
532
+ "args": ["-p", "esvue"],
533
+ "cwd": "${workspaceRoot}",
534
+ "runtimeExecutable": null,
535
+ "runtimeArgs": ["--nolazy"],
536
+ "env": {
537
+ "NODE_ENV": "development"
538
+ },
539
+ "console": "integratedTerminal",
540
+ "sourceMaps": true
488
541
  }
489
542
  ```
490
543
 
491
- ##### Debug Feature
544
+ #### Debug Feature
492
545
 
493
546
  ```json
494
547
  {
495
- "name": "Debug Feature",
496
- "type": "node",
497
- "request": "launch",
498
- "program": "${workspaceRoot}/node_modules/@lynxwall/cucumber-tsflow/bin/cucumber-tsflow/vue",
499
- "stopOnEntry": true,
500
- "args": ["--debug-file", "${file}", "-p", "esvue"],
501
- "cwd": "${workspaceRoot}",
502
- "runtimeExecutable": null,
503
- "runtimeArgs": ["--nolazy"],
504
- "env": {
505
- "NODE_ENV": "development"
506
- },
507
- "console": "integratedTerminal",
508
- "sourceMaps": true
548
+ "name": "Debug Feature",
549
+ "type": "node",
550
+ "request": "launch",
551
+ "program": "${workspaceRoot}/node_modules/@lynxwall/cucumber-tsflow/bin/cucumber-tsflow/vue",
552
+ "stopOnEntry": true,
553
+ "args": ["--debug-file", "${file}", "-p", "esvue"],
554
+ "cwd": "${workspaceRoot}",
555
+ "runtimeExecutable": null,
556
+ "runtimeArgs": ["--nolazy"],
557
+ "env": {
558
+ "NODE_ENV": "development"
559
+ },
560
+ "console": "integratedTerminal",
561
+ "sourceMaps": true
509
562
  }
510
563
  ```
511
564
 
@@ -558,9 +611,9 @@ The following Scenario uses boolean values in the Given and Then statements:
558
611
 
559
612
  ```gherkin
560
613
  Scenario: Boolean type supported
561
- Given I pass true into a step
562
- When checking the boolean value
563
- Then we can see that true was passed in
614
+ Given I pass true into a step
615
+ When checking the boolean value
616
+ Then we can see that true was passed in
564
617
  ```
565
618
 
566
619
  The associated step definition replaces `true` in this scenario with a `{boolean}` expression as shown below:
@@ -568,17 +621,17 @@ The associated step definition replaces `true` in this scenario with a `{boolean
568
621
  ```typescript
569
622
  @given('I pass {boolean} into a step')
570
623
  iPassbooleanIntoAStep(boolean: boolean): any {
571
- this.boolValue = boolean;
624
+ this.boolValue = boolean;
572
625
  }
573
626
 
574
627
  @when('checking the boolean value')
575
628
  checkingTheBooleanValue(): any {
576
- expect(this.boolValue).not.to.be.undefined;
629
+ expect(this.boolValue).not.to.be.undefined;
577
630
  }
578
631
 
579
632
  @then('we can see that {boolean} was passed in')
580
633
  weCanThatbooleanWasPassedIn(boolean: boolean): any {
581
- expect(this.boolValue).to.equal(boolean);
634
+ expect(this.boolValue).to.equal(boolean);
582
635
  }
583
636
  ```
584
637
 
@@ -606,7 +659,7 @@ public givenAValueBasedSearch(searchValue: string): void {
606
659
  }
607
660
  ```
608
661
 
609
- **Note**: Tags added to steps work the same as "Tagged Hooks" documented here: <https://github.com/cucumber/cucumber-js/blob/v12.2.0/docs/support_files/hooks.md>
662
+ **Note**: Tags added to steps work the same as "Tagged Hooks" documented here: <https://github.com/cucumber/cucumber-js/blob/v12.7.0/docs/support_files/hooks.md>
610
663
 
611
664
  ## Hooks
612
665
 
@@ -638,12 +691,12 @@ class MySteps {
638
691
 
639
692
  @beforeStep('@addNumbers')
640
693
  public beforeStep() {
641
- ...
694
+ ...
642
695
  }
643
696
 
644
697
  @afterStep('@addNumbers')
645
698
  public afterStep() {
646
- ...
699
+ ...
647
700
  }
648
701
 
649
702
  @after()
@@ -707,15 +760,15 @@ If it doesn't already exist, create a file named cucumber.json at the root of yo
707
760
 
708
761
  #### Using the behave json formatter
709
762
 
710
- The following example shows how to configure the behave formatter in cucumber.json. The tsflow-snippet-syntax module is configured as the default snippet syntax and does not require configuration. However, you can override the snippet syntax as documented here: <https://github.com/cucumber/cucumber-js/blob/v12.2.0/docs/custom_snippet_syntaxes.md>
763
+ The following example shows how to configure the behave formatter in cucumber.json. The tsflow-snippet-syntax module is configured as the default snippet syntax and does not require configuration. However, you can override the snippet syntax as documented here: <https://github.com/cucumber/cucumber-js/blob/v12.7.0/docs/custom_snippet_syntaxes.md>
711
764
 
712
765
  ```typescript
713
766
  {
714
- "default": {
715
- "format": [
716
- "behave:cucumber_report.json"
717
- ]
718
- }
767
+ "default": {
768
+ "format": [
769
+ "behave:cucumber_report.json"
770
+ ]
771
+ }
719
772
  }
720
773
  ```
721
774
 
@@ -725,11 +778,11 @@ The following example shows how to configure the bamboo junit formatter in cucum
725
778
 
726
779
  ```typescript
727
780
  {
728
- "default": {
729
- "format": [
730
- "junitbamboo:cucumber_report.xml"
731
- ]
732
- }
781
+ "default": {
782
+ "format": [
783
+ "junitbamboo:cucumber_report.xml"
784
+ ]
785
+ }
733
786
  }
734
787
  ```
735
788
 
@@ -756,7 +809,7 @@ Each scenario in a feature will get a new instance of the _Context_ object when
756
809
  - Context classes now support an `initialize()` function that can be defined synchronous or asynchronous. The `initialize()` function is called after the `BeforeAll` hook and before any other hooks or steps. This provides the ability to initialize a scenario context before any tests are executed with support for async operations.
757
810
  - Context classes have always supported a `dispose()` function for cleanup. However, with latest updates the `dispose()` function can be defined synchronously or asynchronously.
758
811
  - versions >= 6.4.0
759
- - The current Cucumber World object is now available as a constructor parameter on all classes defined for Context Injection. For more information on the World object see: [Access to Cucumber.js World object](#access-to-cucumber.js-world-object).
812
+ - The current Cucumber World object is now available as a constructor parameter on all classes defined for Context Injection. For more information on the World object see: [Access to Cucumber.js World object](#access-to-cucumberjs-world-object).
760
813
 
761
814
  ### Using Context Injection
762
815
 
@@ -773,30 +826,30 @@ import { World } from '@cucumber/cucumber';
773
826
  import { EndTestCaseInfo, StartTestCaseInfo } from '@lynxwall/cucumber-tsflow';
774
827
 
775
828
  export class ScenarioContext {
776
- public world: World;
777
- public someValue = '';
778
- private id: string = '';
779
-
780
- constructor(worldObj: World) {
781
- this.world = worldObj;
782
- }
783
- public initialize({ pickle, gherkinDocument }: StartTestCaseInfo): void {
784
- this.id = this.makeid(5);
785
- console.log(`Sync init: ${this.id}`);
786
- console.log(`Start Test Case: ${this.getFeatureAndScenario(gherkinDocument.uri!, pickle.name)}`);
787
- }
788
- public dispose({ pickle, gherkinDocument }: EndTestCaseInfo): void {
789
- console.log(`Sync dispose: ${this.id}`);
790
- console.log(`End Test Case: ${this.getFeatureAndScenario(gherkinDocument.uri!, pickle.name)}`);
791
- }
792
- private getFeatureAndScenario(path: string, scenario: string): string | undefined {
793
- ...
829
+ public world: World;
830
+ public someValue = '';
831
+ private id: string = '';
832
+
833
+ constructor(worldObj: World) {
834
+ this.world = worldObj;
835
+ }
836
+ public initialize({ pickle, gherkinDocument }: StartTestCaseInfo): void {
837
+ this.id = this.makeid(5);
838
+ console.log(`Sync init: ${this.id}`);
839
+ console.log(`Start Test Case: ${this.getFeatureAndScenario(gherkinDocument.uri!, pickle.name)}`);
840
+ }
841
+ public dispose({ pickle, gherkinDocument }: EndTestCaseInfo): void {
842
+ console.log(`Sync dispose: ${this.id}`);
843
+ console.log(`End Test Case: ${this.getFeatureAndScenario(gherkinDocument.uri!, pickle.name)}`);
844
+ }
845
+ private getFeatureAndScenario(path: string, scenario: string): string | undefined {
846
+ ...
794
847
  return `${fileName}: ${scenario.split(' ').join('-')}`;
795
- }
796
- private makeid(length: number) {
797
- ...
798
- return result;
799
- }
848
+ }
849
+ private makeid(length: number) {
850
+ ...
851
+ return result;
852
+ }
800
853
  }
801
854
  ```
802
855
 
@@ -807,39 +860,39 @@ import { World } from '@cucumber/cucumber';
807
860
  import { EndTestCaseInfo, StartTestCaseInfo } from '@lynxwall/cucumber-tsflow';
808
861
 
809
862
  export class ScenarioContext {
810
- public world: World;
811
- public someValue = '';
812
- private id: string = '';
813
-
814
- constructor(worldObj: World) {
815
- this.world = worldObj;
816
- }
817
- public async initialize({ pickle, gherkinDocument }: StartTestCaseInfo): Promise<void> {
818
- this.id = this.makeid(5);
819
- await this.logTest(`Async init: ${this.id}`);
820
- await this.logTest(`Start Test Case: ${this.getFeatureAndScenario(gherkinDocument.uri!, pickle.name)}`);
821
- }
822
- public async dispose({ pickle, gherkinDocument }: EndTestCaseInfo): Promise<void> {
823
- await this.logTest(`Async dispose: ${this.id}`);
824
- await this.logTest(`End Test Case: ${this.getFeatureAndScenario(gherkinDocument.uri!, pickle.name)}`);
825
- }
826
- async logTest(text: string): Promise<void> {
827
- await Promise.resolve(console.log(text));
828
- }
829
- private getFeatureAndScenario(path: string, scenario: string): string | undefined {
830
- ...
863
+ public world: World;
864
+ public someValue = '';
865
+ private id: string = '';
866
+
867
+ constructor(worldObj: World) {
868
+ this.world = worldObj;
869
+ }
870
+ public async initialize({ pickle, gherkinDocument }: StartTestCaseInfo): Promise<void> {
871
+ this.id = this.makeid(5);
872
+ await this.logTest(`Async init: ${this.id}`);
873
+ await this.logTest(`Start Test Case: ${this.getFeatureAndScenario(gherkinDocument.uri!, pickle.name)}`);
874
+ }
875
+ public async dispose({ pickle, gherkinDocument }: EndTestCaseInfo): Promise<void> {
876
+ await this.logTest(`Async dispose: ${this.id}`);
877
+ await this.logTest(`End Test Case: ${this.getFeatureAndScenario(gherkinDocument.uri!, pickle.name)}`);
878
+ }
879
+ async logTest(text: string): Promise<void> {
880
+ await Promise.resolve(console.log(text));
881
+ }
882
+ private getFeatureAndScenario(path: string, scenario: string): string | undefined {
883
+ ...
831
884
  return `${fileName}: ${scenario.split(' ').join('-')}`;
832
- }
885
+ }
833
886
  private makeid(length: number) {
834
- ...
835
- return result;
836
- }
887
+ ...
888
+ return result;
889
+ }
837
890
  }
838
891
  ```
839
892
 
840
893
  **Initialize Binding in Step class:**
841
894
 
842
- - Update the `@binding()` decorator to indicate the types of context objects that are required by the 'binding' class. You can include up to nine separate _Context_ objects.
895
+ - Update the `@binding()` decorator to indicate the types of context objects that are required by the 'binding' class. There is no limit on the number of _Context_ objects.
843
896
  - Define a constructor on the `@binding` class with steps that need access to the shared data that accepts one or more context objects as parameters based on initialization of the `@binding` decorator.
844
897
 
845
898
  **Single Context class example:**
@@ -851,18 +904,18 @@ import { expect } from 'chai';
851
904
 
852
905
  @binding([ScenarioContext])
853
906
  export default class InjectionTestSteps1 {
854
- constructor(private context: ScenarioContext) {}
855
-
856
- @given('The Workspace is available and valid')
857
- theWorkspaceIsAvailableAndValid() {
858
- expect(this.context).not.to.be.undefined;
859
- expect(this.context.world).not.to.be.undefined;
860
- }
861
-
862
- @when('I change the workspace in one step definition class')
863
- whenIChangeTheWorkspaceInOneStep() {
864
- this.context.someValue = 'value changed';
865
- }
907
+ constructor(private context: ScenarioContext) {}
908
+
909
+ @given('The Workspace is available and valid')
910
+ theWorkspaceIsAvailableAndValid() {
911
+ expect(this.context).not.to.be.undefined;
912
+ expect(this.context.world).not.to.be.undefined;
913
+ }
914
+
915
+ @when('I change the workspace in one step definition class')
916
+ whenIChangeTheWorkspaceInOneStep() {
917
+ this.context.someValue = 'value changed';
918
+ }
866
919
  }
867
920
  ```
868
921
 
@@ -876,24 +929,24 @@ import { expect } from 'chai';
876
929
 
877
930
  @binding([ScenarioContext, SyncContext])
878
931
  export default class InjectionTestSteps1 {
879
- constructor(
880
- private context: ScenarioContext,
881
- private syncContext: SyncContext
882
- ) {}
883
-
884
- @given('The Workspace is available and valid')
885
- theWorkspaceIsAvailableAndValid() {
886
- expect(this.context).not.to.be.undefined;
887
- expect(this.context.world).not.to.be.undefined;
888
-
889
- expect(this.syncContext).not.to.be.undefined;
890
- expect(this.syncContext.world).not.to.be.undefined;
891
- }
892
-
893
- @when('I change the workspace in one step definition class')
894
- whenIChangeTheWorkspaceInOneStep() {
895
- this.context.someValue = 'value changed';
896
- }
932
+ constructor(
933
+ private context: ScenarioContext,
934
+ private syncContext: SyncContext
935
+ ) {}
936
+
937
+ @given('The Workspace is available and valid')
938
+ theWorkspaceIsAvailableAndValid() {
939
+ expect(this.context).not.to.be.undefined;
940
+ expect(this.context.world).not.to.be.undefined;
941
+
942
+ expect(this.syncContext).not.to.be.undefined;
943
+ expect(this.syncContext.world).not.to.be.undefined;
944
+ }
945
+
946
+ @when('I change the workspace in one step definition class')
947
+ whenIChangeTheWorkspaceInOneStep() {
948
+ this.context.someValue = 'value changed';
949
+ }
897
950
  }
898
951
  ```
899
952
 
@@ -911,16 +964,16 @@ Starting with version **6.4.0** the Cucumber World object is now passed into a _
911
964
  import { World } from '@cucumber/cucumber';
912
965
 
913
966
  export class ScenarioContext {
914
- public world: World;
915
- public someValue = '';
967
+ public world: World;
968
+ public someValue = '';
916
969
 
917
- constructor(worldObj: World) {
918
- this.world = worldObj;
919
- }
970
+ constructor(worldObj: World) {
971
+ this.world = worldObj;
972
+ }
920
973
 
921
- public dispose(): void {
922
- this.someValue = '';
923
- }
974
+ public dispose(): void {
975
+ this.someValue = '';
976
+ }
924
977
  }
925
978
  ```
926
979
 
@@ -942,8 +995,8 @@ With this approach, you would define a world property on simple _Context_ class
942
995
  import { World } from '@cucumber/cucumber';
943
996
 
944
997
  export class ScenarioContext {
945
- public world!: World;
946
- public someValue = '';
998
+ public world!: World;
999
+ public someValue = '';
947
1000
  }
948
1001
  ```
949
1002
 
@@ -958,14 +1011,14 @@ import { World } from '@cucumber/cucumber';
958
1011
 
959
1012
  @binding([ScenarioContext])
960
1013
  export default class WorldContext {
961
- _worldObj?: World;
1014
+ _worldObj?: World;
962
1015
 
963
- constructor(private context: ScenarioContext) {}
1016
+ constructor(private context: ScenarioContext) {}
964
1017
 
965
- @before()
966
- beforeScenario() {
967
- this.context.world = this._worldObj as World;
968
- }
1018
+ @before()
1019
+ beforeScenario() {
1020
+ this.context.world = this._worldObj as World;
1021
+ }
969
1022
  }
970
1023
  ```
971
1024