@lynxwall/cucumber-tsflow 7.2.0 → 7.3.1

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 (77) hide show
  1. package/README.md +59 -35
  2. package/lib/api/load-configuration.js +60 -16
  3. package/lib/api/load-configuration.js.map +1 -1
  4. package/lib/bindings/binding-context.d.ts +40 -4
  5. package/lib/bindings/binding-context.js +50 -6
  6. package/lib/bindings/binding-context.js.map +1 -1
  7. package/lib/bindings/binding-decorator.js +32 -9
  8. package/lib/bindings/binding-decorator.js.map +1 -1
  9. package/lib/bindings/binding-registry.js +10 -0
  10. package/lib/bindings/binding-registry.js.map +1 -1
  11. package/lib/bindings/hook-decorators.js +4 -3
  12. package/lib/bindings/hook-decorators.js.map +1 -1
  13. package/lib/bindings/step-decorators.js +12 -9
  14. package/lib/bindings/step-decorators.js.map +1 -1
  15. package/lib/cli/argv-parser.js +1 -2
  16. package/lib/cli/argv-parser.js.map +1 -1
  17. package/lib/runtime/parallel/worker.js +1 -1
  18. package/lib/runtime/parallel/worker.js.map +1 -1
  19. package/lib/runtime/test-case-runner.d.ts +2 -1
  20. package/lib/runtime/test-case-runner.js +8 -5
  21. package/lib/runtime/test-case-runner.js.map +1 -1
  22. package/lib/transpilers/esbuild-transpiler.d.ts +1 -1
  23. package/lib/transpilers/esbuild-transpiler.js.map +1 -1
  24. package/lib/transpilers/esbuild.js.map +1 -1
  25. package/lib/transpilers/esm/esbuild-transpiler-cjs.js +2174 -0
  26. package/lib/transpilers/esm/esbuild-transpiler.mjs +19 -0
  27. package/lib/transpilers/esm/esbuild.mjs +141 -0
  28. package/lib/transpilers/esm/esmbuild-transpiler.d.ts +4 -0
  29. package/lib/transpilers/esm/esmbuild-transpiler.js +19 -0
  30. package/lib/transpilers/esm/esmbuild-transpiler.js.map +1 -0
  31. package/lib/transpilers/esm/esmbuild.d.ts +12 -0
  32. package/lib/transpilers/esm/esmbuild.js +72 -0
  33. package/lib/transpilers/esm/esmbuild.js.map +1 -0
  34. package/lib/transpilers/esm/esmnode.d.ts +1 -0
  35. package/lib/transpilers/esm/esmnode.js +8 -0
  36. package/lib/transpilers/esm/esmnode.js.map +1 -0
  37. package/lib/transpilers/esm/esmvue.d.ts +1 -0
  38. package/lib/transpilers/esm/esmvue.js +29 -0
  39. package/lib/transpilers/esm/esmvue.js.map +1 -0
  40. package/lib/transpilers/esm/esnode-loader.mjs +9 -0
  41. package/lib/transpilers/esm/esvue-loader.mjs +9 -0
  42. package/lib/transpilers/esm/loader-utils.mjs +356 -0
  43. package/lib/transpilers/esm/tsnode-esm.d.ts +1 -0
  44. package/lib/transpilers/esm/tsnode-esm.js +25 -0
  45. package/lib/transpilers/esm/tsnode-esm.js.map +1 -0
  46. package/lib/transpilers/esm/tsnode-exp-esm.d.ts +1 -0
  47. package/lib/transpilers/esm/tsnode-exp-esm.js +19 -0
  48. package/lib/transpilers/esm/tsnode-exp-esm.js.map +1 -0
  49. package/lib/transpilers/esm/tsnode-loader.mjs +107 -0
  50. package/lib/transpilers/esm/tsnode-service.mjs +40 -0
  51. package/lib/transpilers/esm/tsvue-esm.d.ts +1 -0
  52. package/lib/transpilers/esm/tsvue-esm.js +40 -0
  53. package/lib/transpilers/esm/tsvue-esm.js.map +1 -0
  54. package/lib/transpilers/esm/tsvue-exp-esm.d.ts +1 -0
  55. package/lib/transpilers/esm/tsvue-exp-esm.js +40 -0
  56. package/lib/transpilers/esm/tsvue-exp-esm.js.map +1 -0
  57. package/lib/transpilers/esm/vue-jsdom-setup.mjs +19 -0
  58. package/lib/transpilers/esm/vue-loader.mjs +113 -0
  59. package/lib/transpilers/esm/vue-sfc-compiler.mjs +216 -0
  60. package/lib/transpilers/esnode.js +1 -1
  61. package/lib/transpilers/esnode.js.map +1 -1
  62. package/lib/transpilers/esvue.js +1 -1
  63. package/lib/transpilers/esvue.js.map +1 -1
  64. package/lib/transpilers/tsnode-exp.js +1 -1
  65. package/lib/transpilers/tsnode-exp.js.map +1 -1
  66. package/lib/transpilers/tsnode.js +1 -1
  67. package/lib/transpilers/tsnode.js.map +1 -1
  68. package/lib/transpilers/tsvue-exp.js +1 -1
  69. package/lib/transpilers/tsvue-exp.js.map +1 -1
  70. package/lib/transpilers/tsvue.js +2 -2
  71. package/lib/transpilers/tsvue.js.map +1 -1
  72. package/lib/transpilers/vue-sfc/index.js.map +1 -1
  73. package/lib/tsconfig.node.tsbuildinfo +1 -1
  74. package/lib/version.d.ts +1 -1
  75. package/lib/version.js +1 -1
  76. package/lib/version.js.map +1 -1
  77. package/package.json +27 -17
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # cucumber-tsflow
4
4
 
5
- Provides 'specflow' like bindings for Cucumber-JS 11.3.0 in TypeScript 5.8+.
5
+ Provides 'specflow' like bindings for Cucumber-JS 12.2.0 in TypeScript 5.9+.
6
6
 
7
7
  Supports Vue3 files in cucumber tests.
8
8
 
@@ -12,6 +12,17 @@ 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.3.0)
16
+
17
+ 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
+
19
+ Along with ESM support, additional updates include:
20
+
21
+ - Cucumber-JS updated to version 12.2.0
22
+ - Typescript updated to version 5.9.2
23
+ - 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
+ - Other package updates.
25
+
15
26
  ## Release Updates (7.2.0)
16
27
 
17
28
  With this release, support for **Experimental Decorators** was added for backwards compatibility with any code under test that is using experimental decorators.
@@ -44,7 +55,9 @@ This fork of cucumber-tsflow provides the following features that extend the ori
44
55
  - **2** - Implemented scenarios are passing but there are pending, undefined or unknown scenario steps.
45
56
  - **3** - One or more scenario steps have failed.
46
57
 
47
- - CommonJS transpilers using either esbuild or ts-node.
58
+ - CommonJS transpilers using either esbuild or ts-node-maintained.
59
+
60
+ - [ESM loaders](https://github.com/LynxWall/cucumber-js-tsflow/blob/master/cucumber-tsflow/src/transpilers/esm/README.md) using either esbuild or ts-node-maintained.
48
61
 
49
62
  - Support for both Official and Experimental Decorators in TypeScript.
50
63
 
@@ -160,9 +173,9 @@ export default class ArithmeticSteps {
160
173
 
161
174
  ### Compiling your TypeScript Support Code
162
175
 
163
- 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.
176
+ 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.
164
177
 
165
- 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/v11.3.0/docs/transpiling.md)
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)
166
179
 
167
180
  ## Transpilers and TypeScript
168
181
 
@@ -172,13 +185,15 @@ This section focuses on the configuration used to transpile your test code, and
172
185
 
173
186
  ### CommonJS and ESM
174
187
 
175
- The transpilers included with cucumber-tsflow transpile to **CommonJS** and do not support projects with `"type": "module"` in your `package.json`. However, [esModuleinterop](https://www.typescriptlang.org/tsconfig/#esModuleInterop) is enabled by default, which allows you to write code using ECMAScript (ESM) standards and import ESM modules in your test code.
188
+ As of version 7.3.0, cucumber-tsflow supports projects written in both CommonJS & ESM.
189
+
190
+ Read more about [cucumber-tsflow ESM implementations](./cucumber-tsflow/src/transpilers/esm/README.md).
176
191
 
177
192
  ### TypeScript Configuration
178
193
 
179
194
  There are two different bundlers, or transpilers, used in cucumber-tsflow: **ts-node** and **esbuild**. This section covers the typescript configuration used for each bundler. Included with cucumber-ts are six variations of these transpilers used to support different types of projects. However, there are only two variations of typescript configurations used for each bundler, one that uses official decorators and one that uses experimental decorators.
180
195
 
181
- #### ts-node
196
+ #### ts-node
182
197
 
183
198
  The following typescript configuration is used in the ts-node transpilers configured for official decorators:
184
199
 
@@ -265,12 +280,12 @@ In order to support both official and experimental decorators the esbuild transp
265
280
  When using official decorators the following settings are added using the esbuild tsconfigRaw setting.
266
281
 
267
282
  ```typescript
268
- commonOptions.tsconfigRaw = {
269
- compilerOptions: {
270
- importsNotUsedAsValues: 'remove',
271
- strict: true
272
- }
273
- };
283
+ commonOptions.tsconfigRaw = {
284
+ compilerOptions: {
285
+ importsNotUsedAsValues: 'remove',
286
+ strict: true
287
+ }
288
+ };
274
289
  ```
275
290
 
276
291
  #### Experimental Decorators
@@ -278,13 +293,13 @@ When using official decorators the following settings are added using the esbuil
278
293
  When using experimental decorators the experimentalDecorators setting is added to the tsconfigRaw settings. As mentioned, esbuild does not use tsconfig settings from ts-node or from a tsconfig file. As a result, this is the only option available to turn on experimental decorators when using esbuild.
279
294
 
280
295
  ```typescript
281
- commonOptions.tsconfigRaw = {
282
- compilerOptions: {
283
- experimentalDecorators: true,
284
- importsNotUsedAsValues: 'remove',
285
- strict: true
286
- }
287
- };
296
+ commonOptions.tsconfigRaw = {
297
+ compilerOptions: {
298
+ experimentalDecorators: true,
299
+ importsNotUsedAsValues: 'remove',
300
+ strict: true
301
+ }
302
+ };
288
303
  ```
289
304
 
290
305
  As mentioned at the beginning of this section, there are several transpilers provided, which can be used with your test project. The [transpilers](#transpiler-and-vue3-supported) section below provides information on how to configure your project to use one of these transpilers.
@@ -381,37 +396,46 @@ echo $?
381
396
 
382
397
  ## New Configuration options
383
398
 
384
- 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/v11.3.0/docs/configuration.md>
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>
385
400
 
386
401
  In addition to cucumber configuration options the following two options have been added:
387
402
 
388
403
  | Name | Type | Repeatable | CLI Option | Description | Default |
389
404
  | ------------------------ | --------- | ---------- | --------------------------- | ------------------------------------------------------------ | ------- |
390
- | `transpiler` | `string` | No | `--transpiler` | Name of the transpiler to use: esnode, esvue, tsnode or tsvue | esnode |
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 |
391
406
  | `debugFile` | `string` | No | `--debug-file` | Path to a file with steps for debugging | |
392
407
  | `enableVueStyle` | `boolean` | No | `--enable-vue-style` | Enable Vue `<style>` block when compiling Vue SFC. | false |
393
408
  | `experimentalDecorators` | `boolean` | No | `--experimental-decorators` | Enable TypeScript Experimental Decorators. | false |
394
409
 
395
410
  ### Transpiler and Vue3 supported
396
411
 
397
- Using TypeScript with cucumber-js requires setting tsconfig.json parameters as described here: [cucumber-js Transpiling](https://github.com/cucumber/cucumber-js/blob/v11.3.0/docs/transpiling.md). In addition, there is no support for transpiling Vue files with cucumber-js.
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.
398
413
 
399
414
  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.
400
415
 
401
- **NOTE**: By default, the `<style>` block in Vue SFC components will not be loaded when .vue files are transformed. However, that behavior can be overridden when testing compiled Vue components from a library using the `enableVueStyle` configuration setting.
416
+ By default, the `<style>` block in Vue SFC components will not be loaded when .vue files are transformed. However, that behavior can be overridden when testing compiled Vue components from a library using the `enableVueStyle` configuration setting.
402
417
 
403
418
  Cucumber-TsFlow provides the following transpilers:
404
419
 
405
- | Name | Bundler | Description |
406
- | ---------- | ------- | ------------------------------------------------------------ |
407
- | **esnode** | esbuild | Uses esbuild to transpile TypeScript code for node test execution. |
408
- | **esvue** | esbuild | Uses esbuild to transpile TypeScript code and adds a hook for .vue files, which transforms Vue SFC components into common-JS. **jsdom** is also loaded globally to support loading and testing Vue SFC components. |
409
- | **tsnode** | ts-node | Uses typescript to transpile TypeScript code for node test execution.<br />**NOTE:** When Experimental Decorators are enabled, cucumber-tsflow loads a different transpiler named tsnode-exp. |
410
- | **tsvue** | ts-node | Uses typescript to transpile TypeScript code and adds a hook for .vue files, which transforms Vue SFC components into common-JS. **jsdom** is also loaded globally to support loading and testing Vue SFC components.<br />**NOTE:** When Experimental Decorators are enabled, cucumber-tsflow loads a different transpiler named tsvue-exp. |
420
+ | Name | Transpiler/ Loader | Bundler | Description |
421
+ | --------------- | -------------------- | ------- | ------------------------------------------------------------ |
422
+ | **es‑vue** | esvue | esbuild | Uses esbuild to transpile TypeScript code and adds a hook for .vue files, which transforms Vue SFC components into common-JS. |
423
+ | **es‑node** | esnode | esbuild | Uses esbuild to transpile TypeScript code for node test execution. Output is common-JS. |
424
+ | **es‑vue‑esm** | esvue‑loader | esbuild | Uses esbuild to transpile TypeScript code and adds a hook for .vue files, which transforms Vue SFC components into ESM. |
425
+ | **es‑node‑esm** | esnode‑loader | esbuild | Uses esbuild to transpile TypeScript code for node test execution. Output is ESM. |
426
+ | **ts‑vue** | tsvue or tsvue‑exp | ts‑node | Uses ts-node to transpile TypeScript code and adds a hook for .vue files, which transforms Vue SFC components into common-JS. |
427
+ | **ts‑node** | tsnode or tsnode‑exp | ts‑node | Uses ts-node to transpile TypeScript code for node test execution. Output is common-JS. |
428
+ | **ts‑vue‑esm** | vue‑loader | ts-node | Uses ts-node to transpile TypeScript code and adds a hook for .vue files, which transforms Vue SFC components into ESM. |
429
+ | **ts‑node‑esm** | tsnode‑loader | ts-node | Uses ts-node to transpile TypeScript code for node test execution. Output is ESM. |
411
430
 
412
- <div style="padding: 15px; border: 1px solid transparent; border-color: transparent; margin-bottom: 20px; border-radius: 4px; color: #8a6d3b; background-color: #fcf8e3; border-color: #faebcc;">
413
- <strong><span style="color: #000">Note:</span></strong> The transpilers provide with cucumber-tsflow will only support CommonJS modules. In other words, if your package.json file has 'type: module' you will not be able to use these transpilers. However, you can use ts-node for transpiling as documented here: <a ref='https://github.com/cucumber/cucumber-js/blob/v11.2.0/docs/transpiling.md#esm'>Transpiling</a>
414
- </div>
431
+ In the table above:
432
+
433
+ - **Name** - The name that would be used in cucumber.json configuration.
434
+ - **Transpiler/Loader** - The actual transpiler or loader (esm), that is loaded based on configuration.
435
+ - **NOTE**: When experimental decorators are enabled a transpiler with -exp appended to the name is loaded. For ESM builds loaders are used that use the configuration setting to determine support for experimental decorators.
436
+ - **Bundler** - Main bundler used. ts-node (ts-node-maintained) or esbuild.
437
+
438
+ **NOTE:** When using Vue transpilers **jsdom** is also loaded globally to support loading and testing Vue SFC components.
415
439
 
416
440
  ##### Using the transpiler configuration option
417
441
 
@@ -420,7 +444,7 @@ When configuring cucumber to execute tests you can specify which transpiler to u
420
444
  ```json
421
445
  {
422
446
  "default": {
423
- "transpiler": "esvue"
447
+ "transpiler": "es-vue"
424
448
  }
425
449
  }
426
450
  ```
@@ -582,7 +606,7 @@ public givenAValueBasedSearch(searchValue: string): void {
582
606
  }
583
607
  ```
584
608
 
585
- **Note**: Tags added to steps work the same as "Tagged Hooks" documented here: <https://github.com/cucumber/cucumber-js/blob/v11.3.0/docs/support_files/hooks.md>
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>
586
610
 
587
611
  ## Hooks
588
612
 
@@ -683,7 +707,7 @@ If it doesn't already exist, create a file named cucumber.json at the root of yo
683
707
 
684
708
  #### Using the behave json formatter
685
709
 
686
- 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/v11.2.0/docs/custom_snippet_syntaxes.md>
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>
687
711
 
688
712
  ```typescript
689
713
  {
@@ -13,6 +13,7 @@ const helpers_1 = require("../utils/helpers");
13
13
  const gherkin_manager_1 = __importDefault(require("../gherkin/gherkin-manager"));
14
14
  const ansis_1 = __importDefault(require("ansis"));
15
15
  const console_1 = require("console");
16
+ const path_1 = require("path");
16
17
  /**
17
18
  * Load user-authored configuration to be used in a test run.
18
19
  *
@@ -53,24 +54,67 @@ const loadConfiguration = async (options = {}, environment = {}) => {
53
54
  }
54
55
  const experimentalDecorators = original.experimentalDecorators;
55
56
  global.experimentalDecorators = experimentalDecorators;
56
- switch (original.transpiler) {
57
- case 'esvue':
58
- original.requireModule.push('@lynxwall/cucumber-tsflow/lib/transpilers/esvue');
59
- break;
60
- case 'tsvue': {
61
- const module = experimentalDecorators ? 'tsvue-exp' : 'tsvue';
62
- original.requireModule.push(`@lynxwall/cucumber-tsflow/lib/transpilers/${module}`);
63
- break;
57
+ process.env.CUCUMBER_EXPERIMENTAL_DECORATORS = String(experimentalDecorators); // need to set here so can be accessed in mjs files
58
+ /**
59
+ * Ensures JSDOM environment is initialized before any test files are loaded.
60
+ * This adds the Vue-specific JSDOM setup to the beginning of Cucumber's require array,
61
+ * establishing the DOM environment needed for Vue component testing.
62
+ *
63
+ * Must run before test execution begins (mise en place for Vue testing).
64
+ */
65
+ const initJsDom = () => {
66
+ // Use require.resolve to get the absolute path
67
+ try {
68
+ const setupPath = require.resolve('@lynxwall/cucumber-tsflow/lib/transpilers/esm/vue-jsdom-setup');
69
+ original.require.unshift(setupPath);
64
70
  }
65
- case 'tsnode': {
66
- const module = experimentalDecorators ? 'tsnode-exp' : 'tsnode';
67
- original.requireModule.push(`@lynxwall/cucumber-tsflow/lib/transpilers/${module}`);
68
- break;
71
+ catch (e) {
72
+ // Fallback to relative path from lib directory
73
+ const setupPath = (0, path_1.join)(__dirname, '../../transpilers/esm/vue-jsdom-setup.mjs');
74
+ original.require.unshift(setupPath);
75
+ }
76
+ };
77
+ if (original.transpiler) {
78
+ switch (original.transpiler) {
79
+ case 'es-vue':
80
+ original.requireModule.push('@lynxwall/cucumber-tsflow/lib/transpilers/esvue');
81
+ break;
82
+ case 'ts-vue': {
83
+ const module = experimentalDecorators ? 'tsvue-exp' : 'tsvue';
84
+ original.requireModule.push(`@lynxwall/cucumber-tsflow/lib/transpilers/${module}`);
85
+ break;
86
+ }
87
+ case 'es-node': {
88
+ original.requireModule.push('@lynxwall/cucumber-tsflow/lib/transpilers/esnode');
89
+ break;
90
+ }
91
+ case 'ts-node': {
92
+ const module = experimentalDecorators ? 'tsnode-exp' : 'tsnode';
93
+ original.requireModule.push(`@lynxwall/cucumber-tsflow/lib/transpilers/${module}`);
94
+ break;
95
+ }
96
+ case 'ts-node-esm': {
97
+ original.loader.push(`@lynxwall/cucumber-tsflow/lib/transpilers/esm/tsnode-loader`); // per cucumber docs, we want to add this to the loader for esm
98
+ break;
99
+ }
100
+ case 'es-node-esm': {
101
+ original.loader.push(`@lynxwall/cucumber-tsflow/lib/transpilers/esm/esnode-loader`); // per cucumber docs, we want to add this to the loader for esm
102
+ break;
103
+ }
104
+ case 'ts-vue-esm': {
105
+ original.loader.push(`@lynxwall/cucumber-tsflow/lib/transpilers/esm/vue-loader`); // per cucumber docs, we want to add this to the loader for esm
106
+ initJsDom();
107
+ break;
108
+ }
109
+ case 'es-vue-esm': {
110
+ original.loader.push(`@lynxwall/cucumber-tsflow/lib/transpilers/esm/esvue-loader`); // per cucumber docs, we want to add this to the loader for esm
111
+ initJsDom();
112
+ break;
113
+ }
114
+ default:
115
+ // default sets nothing -- this allows users to not set the transpiler & use their own loaders/transpilers
116
+ break;
69
117
  }
70
- default:
71
- // defaulting to esnode
72
- original.requireModule.push('@lynxwall/cucumber-tsflow/lib/transpilers/esnode');
73
- break;
74
118
  }
75
119
  // set the snippet syntax
76
120
  if (!original.formatOptions.snippetSyntax) {
@@ -1 +1 @@
1
- {"version":3,"file":"load-configuration.js","sourceRoot":"","sources":["../../src/api/load-configuration.ts"],"names":[],"mappings":"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","sourcesContent":["import { ILoadConfigurationOptions } from '@cucumber/cucumber/lib/api/types';\r\nimport { locateFile } from '@cucumber/cucumber/lib/configuration/locate_file';\r\nimport {\r\n\tDEFAULT_CONFIGURATION,\r\n\tfromFile,\r\n\tIConfiguration,\r\n\tparseConfiguration,\r\n\tmergeConfigurations\r\n} from '@cucumber/cucumber/lib/configuration/index';\r\nimport { validateConfiguration } from '@cucumber/cucumber/lib/configuration/validate_configuration';\r\nimport { convertConfiguration } from './convert-configuration';\r\nimport { IRunEnvironment, makeEnvironment } from '@cucumber/cucumber/lib/environment/index';\r\nimport { ITsflowConfiguration } from '../cli/argv-parser';\r\nimport { hasStringValue } from '../utils/helpers';\r\nimport GherkinManager from '../gherkin/gherkin-manager';\r\nimport ansis from 'ansis';\r\nimport { ITsFlowRunConfiguration } from '../runtime/types';\r\nimport { Console } from 'console';\r\n\r\nexport interface ITsflowResolvedConfiguration {\r\n\t/**\r\n\t * The final flat configuration object resolved from the configuration file/profiles plus any extra provided.\r\n\t */\r\n\tuseConfiguration: ITsflowConfiguration;\r\n\t/**\r\n\t * The format that can be passed into `runCucumber`.\r\n\t */\r\n\trunConfiguration: ITsFlowRunConfiguration;\r\n}\r\n\r\n/**\r\n * Load user-authored configuration to be used in a test run.\r\n *\r\n * @public\r\n * @param options - Coordinates required to find configuration.\r\n * @param environment - Project environment.\r\n */\r\nexport const loadConfiguration = async (\r\n\toptions: ILoadConfigurationOptions = {},\r\n\tenvironment: IRunEnvironment = {}\r\n): Promise<ITsflowResolvedConfiguration> => {\r\n\tconst { cwd, env, logger } = makeEnvironment(environment);\r\n\tconst configFile = options.file ?? locateFile(cwd);\r\n\tlet msg = '';\r\n\tif (configFile) {\r\n\t\tmsg = `Loading configuration from \"${configFile}\".`;\r\n\t} else if (configFile === false) {\r\n\t\tmsg = 'Skipping configuration file resolution';\r\n\t} else {\r\n\t\tmsg = 'No configuration file found';\r\n\t}\r\n\t// log this to debug and console\r\n\tconst consoleLogger = new Console(environment.stdout as any, environment.stderr);\r\n\tlogger.debug(msg);\r\n\tconsoleLogger.log(ansis.cyanBright(msg));\r\n\r\n\tconst profileConfiguration = configFile ? await fromFile(logger, cwd, configFile, options.profiles) : {};\r\n\r\n\t// if a feature was passed in on command line it's added\r\n\t// to the provided configuration as paths. We need to clear\r\n\t// any paths from configuration so that only the feature passed\r\n\t// in is executed.\r\n\tconst paths = (options.provided as Partial<IConfiguration>).paths;\r\n\tif (paths && paths?.length > 0) {\r\n\t\tprofileConfiguration.paths = [];\r\n\t}\r\n\r\n\tconst original = mergeConfigurations(\r\n\t\tDEFAULT_CONFIGURATION,\r\n\t\tprofileConfiguration,\r\n\t\tparseConfiguration(logger, 'Provided', options.provided)\r\n\t) as ITsflowConfiguration;\r\n\r\n\t// Get the experimental decorators setting\r\n\tif (original.experimentalDecorators === undefined) {\r\n\t\toriginal.experimentalDecorators = false;\r\n\t}\r\n\tconst experimentalDecorators = original.experimentalDecorators;\r\n\tglobal.experimentalDecorators = experimentalDecorators;\r\n\r\n\tswitch (original.transpiler) {\r\n\t\tcase 'esvue':\r\n\t\t\toriginal.requireModule.push('@lynxwall/cucumber-tsflow/lib/transpilers/esvue');\r\n\t\t\tbreak;\r\n\t\tcase 'tsvue': {\r\n\t\t\tconst module = experimentalDecorators ? 'tsvue-exp' : 'tsvue';\r\n\t\t\toriginal.requireModule.push(`@lynxwall/cucumber-tsflow/lib/transpilers/${module}`);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 'tsnode': {\r\n\t\t\tconst module = experimentalDecorators ? 'tsnode-exp' : 'tsnode';\r\n\t\t\toriginal.requireModule.push(`@lynxwall/cucumber-tsflow/lib/transpilers/${module}`);\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tdefault:\r\n\t\t\t// defaulting to esnode\r\n\t\t\toriginal.requireModule.push('@lynxwall/cucumber-tsflow/lib/transpilers/esnode');\r\n\t\t\tbreak;\r\n\t}\r\n\t// set the snippet syntax\r\n\tif (!original.formatOptions.snippetSyntax) {\r\n\t\toriginal.formatOptions.snippetSyntax = '@lynxwall/cucumber-tsflow/snippet';\r\n\t}\r\n\t// look for behave format\r\n\tfor (let idx = 0; idx < original.format.length; idx++) {\r\n\t\tif (typeof original.format[idx] === 'string') {\r\n\t\t\tconst formatItem = original.format[idx] as string;\r\n\t\t\tif (formatItem.startsWith('behave:')) {\r\n\t\t\t\toriginal.format[idx] = formatItem.replace('behave', '@lynxwall/cucumber-tsflow/behave');\r\n\t\t\t}\r\n\t\t} else if (original.format[idx].length > 0) {\r\n\t\t\tconst formatItem = original.format[idx][0] as string;\r\n\t\t\tif (formatItem.startsWith('behave')) {\r\n\t\t\t\tconst newVal = formatItem.replace('behave', '@lynxwall/cucumber-tsflow/behave');\r\n\t\t\t\toriginal.format[idx] = original.format[idx].length > 1 ? [newVal, original.format[idx][1]] : [newVal];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// look for junitbamboo format\r\n\tfor (let idx = 0; idx < original.format.length; idx++) {\r\n\t\tif (typeof original.format[idx] === 'string') {\r\n\t\t\tconst formatItem = original.format[idx] as string;\r\n\t\t\tif (formatItem.startsWith('junitbamboo:')) {\r\n\t\t\t\toriginal.format[idx] = formatItem.replace('junitbamboo', '@lynxwall/cucumber-tsflow/junitbamboo');\r\n\t\t\t}\r\n\t\t} else if (original.format[idx].length > 0) {\r\n\t\t\tconst formatItem = original.format[idx][0] as string;\r\n\t\t\tif (formatItem.startsWith('junitbamboo')) {\r\n\t\t\t\tconst newVal = formatItem.replace('junitbamboo', '@lynxwall/cucumber-tsflow/junitbamboo');\r\n\t\t\t\toriginal.format[idx] = original.format[idx].length > 1 ? [newVal, original.format[idx][1]] : [newVal];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// check to see if a debugFile was passed in\r\n\tif (hasStringValue(original.debugFile)) {\r\n\t\t// Initialize gherkin manager with path to feature files\r\n\t\tconst gherkin = new GherkinManager();\r\n\t\tawait gherkin.loadFeatures(original.paths);\r\n\t\tconst features = gherkin.findFeaturesByStepFile(original.debugFile);\r\n\t\tif (features.length > 0) {\r\n\t\t\toriginal.paths = [];\r\n\t\t\tfeatures.forEach(x => original.paths.push(x.featureFile));\r\n\t\t} else {\r\n\t\t\t// log a message if the feature path is not found\r\n\t\t\tlogger.warn(ansis.yellow(`\\nUnable to find feature for debugFile: ${original.debugFile}`));\r\n\t\t\tlogger.warn(ansis.yellow('All tests will be executed\\n'));\r\n\t\t}\r\n\t}\r\n\r\n\t// check to see if enable-vue-style was set\r\n\t// if not, default it to false\r\n\tif (original.enableVueStyle === null || original.enableVueStyle === undefined) {\r\n\t\toriginal.enableVueStyle = false;\r\n\t}\r\n\t// set our global parameter used by the Vue transpiler\r\n\t// to determine if Vue Style Blocks should be enabled\r\n\tglobal.enableVueStyle = original.enableVueStyle;\r\n\r\n\tvalidateConfiguration(original, logger);\r\n\tconst runnable = await convertConfiguration(logger, original, env);\r\n\treturn {\r\n\t\tuseConfiguration: original,\r\n\t\trunConfiguration: runnable\r\n\t};\r\n};\r\n"]}
1
+ {"version":3,"file":"load-configuration.js","sourceRoot":"","sources":["../../src/api/load-configuration.ts"],"names":[],"mappings":"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","sourcesContent":["import { ILoadConfigurationOptions } from '@cucumber/cucumber/lib/api/types';\r\nimport { locateFile } from '@cucumber/cucumber/lib/configuration/locate_file';\r\nimport {\r\n\tDEFAULT_CONFIGURATION,\r\n\tfromFile,\r\n\tIConfiguration,\r\n\tparseConfiguration,\r\n\tmergeConfigurations\r\n} from '@cucumber/cucumber/lib/configuration/index';\r\nimport { validateConfiguration } from '@cucumber/cucumber/lib/configuration/validate_configuration';\r\nimport { convertConfiguration } from './convert-configuration';\r\nimport { IRunEnvironment, makeEnvironment } from '@cucumber/cucumber/lib/environment/index';\r\nimport { ITsflowConfiguration } from '../cli/argv-parser';\r\nimport { hasStringValue } from '../utils/helpers';\r\nimport GherkinManager from '../gherkin/gherkin-manager';\r\nimport ansis from 'ansis';\r\nimport { ITsFlowRunConfiguration } from '../runtime/types';\r\nimport { Console } from 'console';\r\nimport { join } from 'path';\r\n\r\nexport interface ITsflowResolvedConfiguration {\r\n\t/**\r\n\t * The final flat configuration object resolved from the configuration file/profiles plus any extra provided.\r\n\t */\r\n\tuseConfiguration: ITsflowConfiguration;\r\n\t/**\r\n\t * The format that can be passed into `runCucumber`.\r\n\t */\r\n\trunConfiguration: ITsFlowRunConfiguration;\r\n}\r\n\r\n/**\r\n * Load user-authored configuration to be used in a test run.\r\n *\r\n * @public\r\n * @param options - Coordinates required to find configuration.\r\n * @param environment - Project environment.\r\n */\r\nexport const loadConfiguration = async (\r\n\toptions: ILoadConfigurationOptions = {},\r\n\tenvironment: IRunEnvironment = {}\r\n): Promise<ITsflowResolvedConfiguration> => {\r\n\tconst { cwd, env, logger } = makeEnvironment(environment);\r\n\tconst configFile = options.file ?? locateFile(cwd);\r\n\tlet msg = '';\r\n\tif (configFile) {\r\n\t\tmsg = `Loading configuration from \"${configFile}\".`;\r\n\t} else if (configFile === false) {\r\n\t\tmsg = 'Skipping configuration file resolution';\r\n\t} else {\r\n\t\tmsg = 'No configuration file found';\r\n\t}\r\n\t// log this to debug and console\r\n\tconst consoleLogger = new Console(environment.stdout as any, environment.stderr);\r\n\tlogger.debug(msg);\r\n\tconsoleLogger.log(ansis.cyanBright(msg));\r\n\r\n\tconst profileConfiguration = configFile ? await fromFile(logger, cwd, configFile, options.profiles) : {};\r\n\r\n\t// if a feature was passed in on command line it's added\r\n\t// to the provided configuration as paths. We need to clear\r\n\t// any paths from configuration so that only the feature passed\r\n\t// in is executed.\r\n\tconst paths = (options.provided as Partial<IConfiguration>).paths;\r\n\tif (paths && paths?.length > 0) {\r\n\t\tprofileConfiguration.paths = [];\r\n\t}\r\n\r\n\tconst original = mergeConfigurations(\r\n\t\tDEFAULT_CONFIGURATION,\r\n\t\tprofileConfiguration,\r\n\t\tparseConfiguration(logger, 'Provided', options.provided)\r\n\t) as ITsflowConfiguration;\r\n\r\n\t// Get the experimental decorators setting\r\n\tif (original.experimentalDecorators === undefined) {\r\n\t\toriginal.experimentalDecorators = false;\r\n\t}\r\n\r\n\tconst experimentalDecorators = original.experimentalDecorators;\r\n\tglobal.experimentalDecorators = experimentalDecorators;\r\n\tprocess.env.CUCUMBER_EXPERIMENTAL_DECORATORS = String(experimentalDecorators); // need to set here so can be accessed in mjs files\r\n\r\n\t/**\r\n\t * Ensures JSDOM environment is initialized before any test files are loaded.\r\n\t * This adds the Vue-specific JSDOM setup to the beginning of Cucumber's require array,\r\n\t * establishing the DOM environment needed for Vue component testing.\r\n\t *\r\n\t * Must run before test execution begins (mise en place for Vue testing).\r\n\t */\r\n\tconst initJsDom = () => {\r\n\t\t// Use require.resolve to get the absolute path\r\n\t\ttry {\r\n\t\t\tconst setupPath = require.resolve('@lynxwall/cucumber-tsflow/lib/transpilers/esm/vue-jsdom-setup');\r\n\t\t\toriginal.require.unshift(setupPath);\r\n\t\t} catch (e) {\r\n\t\t\t// Fallback to relative path from lib directory\r\n\t\t\tconst setupPath = join(__dirname, '../../transpilers/esm/vue-jsdom-setup.mjs');\r\n\t\t\toriginal.require.unshift(setupPath);\r\n\t\t}\r\n\t};\r\n\r\n\tif (original.transpiler) {\r\n\t\tswitch (original.transpiler) {\r\n\t\t\tcase 'es-vue':\r\n\t\t\t\toriginal.requireModule.push('@lynxwall/cucumber-tsflow/lib/transpilers/esvue');\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'ts-vue': {\r\n\t\t\t\tconst module = experimentalDecorators ? 'tsvue-exp' : 'tsvue';\r\n\t\t\t\toriginal.requireModule.push(`@lynxwall/cucumber-tsflow/lib/transpilers/${module}`);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase 'es-node': {\r\n\t\t\t\toriginal.requireModule.push('@lynxwall/cucumber-tsflow/lib/transpilers/esnode');\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase 'ts-node': {\r\n\t\t\t\tconst module = experimentalDecorators ? 'tsnode-exp' : 'tsnode';\r\n\t\t\t\toriginal.requireModule.push(`@lynxwall/cucumber-tsflow/lib/transpilers/${module}`);\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase 'ts-node-esm': {\r\n\t\t\t\toriginal.loader.push(`@lynxwall/cucumber-tsflow/lib/transpilers/esm/tsnode-loader`); // per cucumber docs, we want to add this to the loader for esm\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase 'es-node-esm': {\r\n\t\t\t\toriginal.loader.push(`@lynxwall/cucumber-tsflow/lib/transpilers/esm/esnode-loader`); // per cucumber docs, we want to add this to the loader for esm\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase 'ts-vue-esm': {\r\n\t\t\t\toriginal.loader.push(`@lynxwall/cucumber-tsflow/lib/transpilers/esm/vue-loader`); // per cucumber docs, we want to add this to the loader for esm\r\n\t\t\t\tinitJsDom();\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase 'es-vue-esm': {\r\n\t\t\t\toriginal.loader.push(`@lynxwall/cucumber-tsflow/lib/transpilers/esm/esvue-loader`); // per cucumber docs, we want to add this to the loader for esm\r\n\t\t\t\tinitJsDom();\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tdefault:\r\n\t\t\t\t// default sets nothing -- this allows users to not set the transpiler & use their own loaders/transpilers\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t// set the snippet syntax\r\n\tif (!original.formatOptions.snippetSyntax) {\r\n\t\toriginal.formatOptions.snippetSyntax = '@lynxwall/cucumber-tsflow/snippet';\r\n\t}\r\n\t// look for behave format\r\n\tfor (let idx = 0; idx < original.format.length; idx++) {\r\n\t\tif (typeof original.format[idx] === 'string') {\r\n\t\t\tconst formatItem = original.format[idx] as string;\r\n\t\t\tif (formatItem.startsWith('behave:')) {\r\n\t\t\t\toriginal.format[idx] = formatItem.replace('behave', '@lynxwall/cucumber-tsflow/behave');\r\n\t\t\t}\r\n\t\t} else if (original.format[idx].length > 0) {\r\n\t\t\tconst formatItem = original.format[idx][0] as string;\r\n\t\t\tif (formatItem.startsWith('behave')) {\r\n\t\t\t\tconst newVal = formatItem.replace('behave', '@lynxwall/cucumber-tsflow/behave');\r\n\t\t\t\toriginal.format[idx] = original.format[idx].length > 1 ? [newVal, original.format[idx][1]] : [newVal];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// look for junitbamboo format\r\n\tfor (let idx = 0; idx < original.format.length; idx++) {\r\n\t\tif (typeof original.format[idx] === 'string') {\r\n\t\t\tconst formatItem = original.format[idx] as string;\r\n\t\t\tif (formatItem.startsWith('junitbamboo:')) {\r\n\t\t\t\toriginal.format[idx] = formatItem.replace('junitbamboo', '@lynxwall/cucumber-tsflow/junitbamboo');\r\n\t\t\t}\r\n\t\t} else if (original.format[idx].length > 0) {\r\n\t\t\tconst formatItem = original.format[idx][0] as string;\r\n\t\t\tif (formatItem.startsWith('junitbamboo')) {\r\n\t\t\t\tconst newVal = formatItem.replace('junitbamboo', '@lynxwall/cucumber-tsflow/junitbamboo');\r\n\t\t\t\toriginal.format[idx] = original.format[idx].length > 1 ? [newVal, original.format[idx][1]] : [newVal];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// check to see if a debugFile was passed in\r\n\tif (hasStringValue(original.debugFile)) {\r\n\t\t// Initialize gherkin manager with path to feature files\r\n\t\tconst gherkin = new GherkinManager();\r\n\t\tawait gherkin.loadFeatures(original.paths);\r\n\t\tconst features = gherkin.findFeaturesByStepFile(original.debugFile);\r\n\t\tif (features.length > 0) {\r\n\t\t\toriginal.paths = [];\r\n\t\t\tfeatures.forEach(x => original.paths.push(x.featureFile));\r\n\t\t} else {\r\n\t\t\t// log a message if the feature path is not found\r\n\t\t\tlogger.warn(ansis.yellow(`\\nUnable to find feature for debugFile: ${original.debugFile}`));\r\n\t\t\tlogger.warn(ansis.yellow('All tests will be executed\\n'));\r\n\t\t}\r\n\t}\r\n\r\n\t// check to see if enable-vue-style was set\r\n\t// if not, default it to false\r\n\tif (original.enableVueStyle === null || original.enableVueStyle === undefined) {\r\n\t\toriginal.enableVueStyle = false;\r\n\t}\r\n\t// set our global parameter used by the Vue transpiler\r\n\t// to determine if Vue Style Blocks should be enabled\r\n\tglobal.enableVueStyle = original.enableVueStyle;\r\n\r\n\tvalidateConfiguration(original, logger);\r\n\tconst runnable = await convertConfiguration(logger, original, env);\r\n\r\n\treturn {\r\n\t\tuseConfiguration: original,\r\n\t\trunConfiguration: runnable\r\n\t};\r\n};\r\n"]}
@@ -1,6 +1,40 @@
1
+ /**
2
+ * Step Binding Storage Management
3
+ *
4
+ * This module manages three different storage mechanisms for StepBindings to support both experimental (legacy) and standard (TC39 Stage 3) decorators:
5
+ *
6
+ * 1. Experimental Decorators (global.experimentalDecorators = true):
7
+ * - Uses the 'stepBindings' array
8
+ * - Functions: addStepBindingExp(), getStepBindingsExp()
9
+ *
10
+ * 2. Standard Decorators - Decoration Phase:
11
+ * - Uses context.metadata.stepBindings
12
+ * - Functions: addStepBinding(), getStepBindings()
13
+ *
14
+ * 3. Standard Decorators - Initialization Phase:
15
+ * - Uses 'collectedBindings' array
16
+ * - Functions: collectStepBinding(), getCollectedBindings()
17
+ * - Needed because context.metadata can't be modified during initialization
18
+ *
19
+ * The @binding class decorator determines which storage mechanism to use based on
20
+ * the global.experimentalDecorators flag.
21
+ */
1
22
  import { StepBinding } from './step-binding';
23
+ /**
24
+ * Add a StepBinding to the collection (for standard decorators)
25
+ * Used by method decorators to store bindings that will be processed
26
+ * when the class decorator's initializer runs.
27
+ */
28
+ export declare const collectStepBinding: (binding: StepBinding) => void;
29
+ /**
30
+ * Get all collected bindings and reset the collection
31
+ * Called by the @binding class decorator's initializer to process
32
+ * all method decorators that were applied to the class.
33
+ */
34
+ export declare const getCollectedBindings: () => StepBinding[];
2
35
  /**
3
36
  * Add a StepBinding to a local array for Experimental Decorators
37
+ * Used when global.experimentalDecorators = true
4
38
  *
5
39
  * @param binding StepBinding to add
6
40
  */
@@ -8,6 +42,7 @@ export declare const addStepBindingExp: (binding: StepBinding) => void;
8
42
  /**
9
43
  * Get all step bindings in the local array and then reset
10
44
  * to an empty array if reset = true (default)
45
+ * Used when global.experimentalDecorators = true
11
46
  *
12
47
  * @param context Current DecoratorContext
13
48
  * @param reset Reset metadata on the context. Default=true
@@ -16,14 +51,15 @@ export declare const addStepBindingExp: (binding: StepBinding) => void;
16
51
  export declare const getStepBindingsExp: (reset?: boolean) => StepBinding[];
17
52
  /**
18
53
  * Add a StepBinding to the DecoratorContext metadata
19
- *
20
- * @param context Current DecoratorContext
21
- * @param binding StepBinding to add
54
+ * Used during the decoration phase of standard decorators.
55
+ * Note: This is separate from collectedBindings which is used during initialization.
56
+ * Returns true if successful, false if context not ready
22
57
  */
23
- export declare const addStepBinding: (context: DecoratorContext, binding: StepBinding) => void;
58
+ export declare const addStepBinding: (context: DecoratorContext, binding: StepBinding) => boolean;
24
59
  /**
25
60
  * Get all step bindings in DecoratorContext metadata and then reset
26
61
  * stepBindings in the metadata to an empty array if reset = true (default)
62
+ * Used during the decoration phase of standard decorators.
27
63
  *
28
64
  * @param context Current DecoratorContext
29
65
  * @param reset Reset metadata on the context. Default=true
@@ -1,9 +1,42 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getStepBindings = exports.addStepBinding = exports.getStepBindingsExp = exports.addStepBindingExp = void 0;
3
+ exports.getStepBindings = exports.addStepBinding = exports.getStepBindingsExp = exports.addStepBindingExp = exports.getCollectedBindings = exports.collectStepBinding = void 0;
4
+ /**
5
+ * Storage for experimental decorators (legacy TypeScript decorators).
6
+ * Used when global.experimentalDecorators = true.
7
+ * These decorators don't have access to context.metadata, so we use a module-level array.
8
+ */
4
9
  let stepBindings = null;
10
+ /**
11
+ * Storage for standard decorators (TC39 Stage 3 decorators).
12
+ * Used when global.experimentalDecorators = false.
13
+ * Standard decorators can't always access context.metadata during initialization,
14
+ * so we need this fallback storage for the addInitializer phase.
15
+ */
16
+ let collectedBindings = [];
17
+ /**
18
+ * Add a StepBinding to the collection (for standard decorators)
19
+ * Used by method decorators to store bindings that will be processed
20
+ * when the class decorator's initializer runs.
21
+ */
22
+ const collectStepBinding = (binding) => {
23
+ collectedBindings.push(binding);
24
+ };
25
+ exports.collectStepBinding = collectStepBinding;
26
+ /**
27
+ * Get all collected bindings and reset the collection
28
+ * Called by the @binding class decorator's initializer to process
29
+ * all method decorators that were applied to the class.
30
+ */
31
+ const getCollectedBindings = () => {
32
+ const bindings = [...collectedBindings];
33
+ collectedBindings = [];
34
+ return bindings;
35
+ };
36
+ exports.getCollectedBindings = getCollectedBindings;
5
37
  /**
6
38
  * Add a StepBinding to a local array for Experimental Decorators
39
+ * Used when global.experimentalDecorators = true
7
40
  *
8
41
  * @param binding StepBinding to add
9
42
  */
@@ -16,6 +49,7 @@ exports.addStepBindingExp = addStepBindingExp;
16
49
  /**
17
50
  * Get all step bindings in the local array and then reset
18
51
  * to an empty array if reset = true (default)
52
+ * Used when global.experimentalDecorators = true
19
53
  *
20
54
  * @param context Current DecoratorContext
21
55
  * @param reset Reset metadata on the context. Default=true
@@ -34,19 +68,29 @@ const getStepBindingsExp = (reset = true) => {
34
68
  exports.getStepBindingsExp = getStepBindingsExp;
35
69
  /**
36
70
  * Add a StepBinding to the DecoratorContext metadata
37
- *
38
- * @param context Current DecoratorContext
39
- * @param binding StepBinding to add
71
+ * Used during the decoration phase of standard decorators.
72
+ * Note: This is separate from collectedBindings which is used during initialization.
73
+ * Returns true if successful, false if context not ready
40
74
  */
41
75
  const addStepBinding = (context, binding) => {
42
- if (!context.metadata.stepBindings)
43
- context.metadata.stepBindings = new Array();
76
+ if (!context.metadata.stepBindings) {
77
+ // Check if we can initialize it
78
+ if (context.metadata && typeof context.metadata === 'object') {
79
+ context.metadata.stepBindings = new Array();
80
+ }
81
+ else {
82
+ // Context not ready
83
+ return false;
84
+ }
85
+ }
44
86
  context.metadata.stepBindings.push(binding);
87
+ return true;
45
88
  };
46
89
  exports.addStepBinding = addStepBinding;
47
90
  /**
48
91
  * Get all step bindings in DecoratorContext metadata and then reset
49
92
  * stepBindings in the metadata to an empty array if reset = true (default)
93
+ * Used during the decoration phase of standard decorators.
50
94
  *
51
95
  * @param context Current DecoratorContext
52
96
  * @param reset Reset metadata on the context. Default=true
@@ -1 +1 @@
1
- {"version":3,"file":"binding-context.js","sourceRoot":"","sources":["../../src/bindings/binding-context.ts"],"names":[],"mappings":";;;AAEA,IAAI,YAAY,GAAuB,IAAI,CAAC;AAE5C;;;;GAIG;AACI,MAAM,iBAAiB,GAAG,CAAC,OAAoB,EAAQ,EAAE;IAC/D,IAAI,CAAC,YAAY;QAAE,YAAY,GAAG,IAAI,KAAK,EAAe,CAAC;IAC3D,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC5B,CAAC,CAAC;AAHW,QAAA,iBAAiB,qBAG5B;AAEF;;;;;;;GAOG;AACI,MAAM,kBAAkB,GAAG,CAAC,QAAiB,IAAI,EAAiB,EAAE;IAC1E,IAAI,QAAQ,GAAkB,EAAE,CAAC;IACjC,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7C,QAAQ,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;QAC7B,IAAI,KAAK,EAAE,CAAC;YACX,YAAY,GAAG,IAAI,KAAK,EAAe,CAAC;QACzC,CAAC;IACF,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AATW,QAAA,kBAAkB,sBAS7B;AAEF;;;;;GAKG;AACI,MAAM,cAAc,GAAG,CAAC,OAAyB,EAAE,OAAoB,EAAQ,EAAE;IACvF,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY;QAAE,OAAO,CAAC,QAAQ,CAAC,YAAY,GAAG,IAAI,KAAK,EAAe,CAAC;IAC5F,OAAO,CAAC,QAAQ,CAAC,YAAmC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACrE,CAAC,CAAC;AAHW,QAAA,cAAc,kBAGzB;AAEF;;;;;;;GAOG;AACI,MAAM,eAAe,GAAG,CAAC,OAAyB,EAAE,QAAiB,IAAI,EAAiB,EAAE;IAClG,IAAI,QAAQ,GAAkB,EAAE,CAAC;IACjC,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,YAAkC,CAAC;IACzE,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7C,QAAQ,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;QAC7B,IAAI,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,QAAQ,CAAC,YAAY,GAAG,IAAI,KAAK,EAAe,CAAC;QAC1D,CAAC;IACF,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAVW,QAAA,eAAe,mBAU1B","sourcesContent":["import { StepBinding } from './step-binding';\r\n\r\nlet stepBindings: Array<StepBinding> = null;\r\n\r\n/**\r\n * Add a StepBinding to a local array for Experimental Decorators\r\n *\r\n * @param binding StepBinding to add\r\n */\r\nexport const addStepBindingExp = (binding: StepBinding): void => {\r\n\tif (!stepBindings) stepBindings = new Array<StepBinding>();\r\n\tstepBindings.push(binding);\r\n};\r\n\r\n/**\r\n * Get all step bindings in the local array and then reset\r\n * to an empty array if reset = true (default)\r\n *\r\n * @param context Current DecoratorContext\r\n * @param reset Reset metadata on the context. Default=true\r\n * @returns Array of StepBindings\r\n */\r\nexport const getStepBindingsExp = (reset: boolean = true): StepBinding[] => {\r\n\tlet bindings: StepBinding[] = [];\r\n\tif (stepBindings && stepBindings.length > 0) {\r\n\t\tbindings = [...stepBindings];\r\n\t\tif (reset) {\r\n\t\t\tstepBindings = new Array<StepBinding>();\r\n\t\t}\r\n\t}\r\n\treturn bindings;\r\n};\r\n\r\n/**\r\n * Add a StepBinding to the DecoratorContext metadata\r\n *\r\n * @param context Current DecoratorContext\r\n * @param binding StepBinding to add\r\n */\r\nexport const addStepBinding = (context: DecoratorContext, binding: StepBinding): void => {\r\n\tif (!context.metadata.stepBindings) context.metadata.stepBindings = new Array<StepBinding>();\r\n\t(context.metadata.stepBindings as Array<StepBinding>).push(binding);\r\n};\r\n\r\n/**\r\n * Get all step bindings in DecoratorContext metadata and then reset\r\n * stepBindings in the metadata to an empty array if reset = true (default)\r\n *\r\n * @param context Current DecoratorContext\r\n * @param reset Reset metadata on the context. Default=true\r\n * @returns Array of StepBindings\r\n */\r\nexport const getStepBindings = (context: DecoratorContext, reset: boolean = true): StepBinding[] => {\r\n\tlet bindings: StepBinding[] = [];\r\n\tconst stepBindings = context.metadata.stepBindings as Array<StepBinding>;\r\n\tif (stepBindings && stepBindings.length > 0) {\r\n\t\tbindings = [...stepBindings];\r\n\t\tif (reset) {\r\n\t\t\tcontext.metadata.stepBindings = new Array<StepBinding>();\r\n\t\t}\r\n\t}\r\n\treturn bindings;\r\n};\r\n"]}
1
+ {"version":3,"file":"binding-context.js","sourceRoot":"","sources":["../../src/bindings/binding-context.ts"],"names":[],"mappings":";;;AAuBA;;;;GAIG;AACH,IAAI,YAAY,GAAuB,IAAI,CAAC;AAC5C;;;;;GAKG;AACH,IAAI,iBAAiB,GAAkB,EAAE,CAAC;AAE1C;;;;GAIG;AACI,MAAM,kBAAkB,GAAG,CAAC,OAAoB,EAAQ,EAAE;IAChE,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC,CAAC;AAFW,QAAA,kBAAkB,sBAE7B;AAEF;;;;GAIG;AACI,MAAM,oBAAoB,GAAG,GAAkB,EAAE;IACvD,MAAM,QAAQ,GAAG,CAAC,GAAG,iBAAiB,CAAC,CAAC;IACxC,iBAAiB,GAAG,EAAE,CAAC;IACvB,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAJW,QAAA,oBAAoB,wBAI/B;AAEF;;;;;GAKG;AACI,MAAM,iBAAiB,GAAG,CAAC,OAAoB,EAAQ,EAAE;IAC/D,IAAI,CAAC,YAAY;QAAE,YAAY,GAAG,IAAI,KAAK,EAAe,CAAC;IAC3D,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC5B,CAAC,CAAC;AAHW,QAAA,iBAAiB,qBAG5B;AAEF;;;;;;;;GAQG;AACI,MAAM,kBAAkB,GAAG,CAAC,QAAiB,IAAI,EAAiB,EAAE;IAC1E,IAAI,QAAQ,GAAkB,EAAE,CAAC;IACjC,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7C,QAAQ,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;QAC7B,IAAI,KAAK,EAAE,CAAC;YACX,YAAY,GAAG,IAAI,KAAK,EAAe,CAAC;QACzC,CAAC;IACF,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AATW,QAAA,kBAAkB,sBAS7B;AAEF;;;;;GAKG;AACI,MAAM,cAAc,GAAG,CAAC,OAAyB,EAAE,OAAoB,EAAW,EAAE;IAC1F,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;QACpC,gCAAgC;QAChC,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC9D,OAAO,CAAC,QAAQ,CAAC,YAAY,GAAG,IAAI,KAAK,EAAe,CAAC;QAC1D,CAAC;aAAM,CAAC;YACP,oBAAoB;YACpB,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IACA,OAAO,CAAC,QAAQ,CAAC,YAAmC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpE,OAAO,IAAI,CAAC;AACb,CAAC,CAAC;AAZW,QAAA,cAAc,kBAYzB;AAEF;;;;;;;;GAQG;AACI,MAAM,eAAe,GAAG,CAAC,OAAyB,EAAE,QAAiB,IAAI,EAAiB,EAAE;IAClG,IAAI,QAAQ,GAAkB,EAAE,CAAC;IACjC,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,YAAkC,CAAC;IACzE,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7C,QAAQ,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;QAC7B,IAAI,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,QAAQ,CAAC,YAAY,GAAG,IAAI,KAAK,EAAe,CAAC;QAC1D,CAAC;IACF,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC;AAVW,QAAA,eAAe,mBAU1B","sourcesContent":["/**\r\n * Step Binding Storage Management\r\n *\r\n * This module manages three different storage mechanisms for StepBindings to support both experimental (legacy) and standard (TC39 Stage 3) decorators:\r\n *\r\n * 1. Experimental Decorators (global.experimentalDecorators = true):\r\n * - Uses the 'stepBindings' array\r\n * - Functions: addStepBindingExp(), getStepBindingsExp()\r\n *\r\n * 2. Standard Decorators - Decoration Phase:\r\n * - Uses context.metadata.stepBindings\r\n * - Functions: addStepBinding(), getStepBindings()\r\n *\r\n * 3. Standard Decorators - Initialization Phase:\r\n * - Uses 'collectedBindings' array\r\n * - Functions: collectStepBinding(), getCollectedBindings()\r\n * - Needed because context.metadata can't be modified during initialization\r\n *\r\n * The @binding class decorator determines which storage mechanism to use based on\r\n * the global.experimentalDecorators flag.\r\n */\r\nimport { StepBinding } from './step-binding';\r\n\r\n/**\r\n * Storage for experimental decorators (legacy TypeScript decorators).\r\n * Used when global.experimentalDecorators = true.\r\n * These decorators don't have access to context.metadata, so we use a module-level array.\r\n */\r\nlet stepBindings: Array<StepBinding> = null;\r\n/**\r\n * Storage for standard decorators (TC39 Stage 3 decorators).\r\n * Used when global.experimentalDecorators = false.\r\n * Standard decorators can't always access context.metadata during initialization,\r\n * so we need this fallback storage for the addInitializer phase.\r\n */\r\nlet collectedBindings: StepBinding[] = [];\r\n\r\n/**\r\n * Add a StepBinding to the collection (for standard decorators)\r\n * Used by method decorators to store bindings that will be processed\r\n * when the class decorator's initializer runs.\r\n */\r\nexport const collectStepBinding = (binding: StepBinding): void => {\r\n\tcollectedBindings.push(binding);\r\n};\r\n\r\n/**\r\n * Get all collected bindings and reset the collection\r\n * Called by the @binding class decorator's initializer to process\r\n * all method decorators that were applied to the class.\r\n */\r\nexport const getCollectedBindings = (): StepBinding[] => {\r\n\tconst bindings = [...collectedBindings];\r\n\tcollectedBindings = [];\r\n\treturn bindings;\r\n};\r\n\r\n/**\r\n * Add a StepBinding to a local array for Experimental Decorators\r\n * Used when global.experimentalDecorators = true\r\n *\r\n * @param binding StepBinding to add\r\n */\r\nexport const addStepBindingExp = (binding: StepBinding): void => {\r\n\tif (!stepBindings) stepBindings = new Array<StepBinding>();\r\n\tstepBindings.push(binding);\r\n};\r\n\r\n/**\r\n * Get all step bindings in the local array and then reset\r\n * to an empty array if reset = true (default)\r\n * Used when global.experimentalDecorators = true\r\n *\r\n * @param context Current DecoratorContext\r\n * @param reset Reset metadata on the context. Default=true\r\n * @returns Array of StepBindings\r\n */\r\nexport const getStepBindingsExp = (reset: boolean = true): StepBinding[] => {\r\n\tlet bindings: StepBinding[] = [];\r\n\tif (stepBindings && stepBindings.length > 0) {\r\n\t\tbindings = [...stepBindings];\r\n\t\tif (reset) {\r\n\t\t\tstepBindings = new Array<StepBinding>();\r\n\t\t}\r\n\t}\r\n\treturn bindings;\r\n};\r\n\r\n/**\r\n * Add a StepBinding to the DecoratorContext metadata\r\n * Used during the decoration phase of standard decorators.\r\n * Note: This is separate from collectedBindings which is used during initialization.\r\n * Returns true if successful, false if context not ready\r\n */\r\nexport const addStepBinding = (context: DecoratorContext, binding: StepBinding): boolean => {\r\n\tif (!context.metadata.stepBindings) {\r\n\t\t// Check if we can initialize it\r\n\t\tif (context.metadata && typeof context.metadata === 'object') {\r\n\t\t\tcontext.metadata.stepBindings = new Array<StepBinding>();\r\n\t\t} else {\r\n\t\t\t// Context not ready\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\t(context.metadata.stepBindings as Array<StepBinding>).push(binding);\r\n\treturn true;\r\n};\r\n\r\n/**\r\n * Get all step bindings in DecoratorContext metadata and then reset\r\n * stepBindings in the metadata to an empty array if reset = true (default)\r\n * Used during the decoration phase of standard decorators.\r\n *\r\n * @param context Current DecoratorContext\r\n * @param reset Reset metadata on the context. Default=true\r\n * @returns Array of StepBindings\r\n */\r\nexport const getStepBindings = (context: DecoratorContext, reset: boolean = true): StepBinding[] => {\r\n\tlet bindings: StepBinding[] = [];\r\n\tconst stepBindings = context.metadata.stepBindings as Array<StepBinding>;\r\n\tif (stepBindings && stepBindings.length > 0) {\r\n\t\tbindings = [...stepBindings];\r\n\t\tif (reset) {\r\n\t\t\tcontext.metadata.stepBindings = new Array<StepBinding>();\r\n\t\t}\r\n\t}\r\n\treturn bindings;\r\n};\r\n"]}
@@ -38,9 +38,15 @@ function binding(requiredContextTypes) {
38
38
  // This will get all those bindings and then clear metadata for the next type that's loaded.
39
39
  const allBindings = (0, binding_context_1.getStepBindingsExp)();
40
40
  allBindings.forEach(stepBinding => {
41
- // register the binding
41
+ // For static methods, we need to set the classPrototype to the class itself, not the prototype
42
+ if (stepBinding.stepIsStatic) {
43
+ stepBinding.classPrototype = target;
44
+ }
45
+ else {
46
+ stepBinding.classPrototype = target.prototype;
47
+ }
42
48
  bindingRegistry.registerStepBinding(stepBinding);
43
- // add the step binding to the binding registry
49
+ // Register with cucumber
44
50
  addStepBinding(stepBinding);
45
51
  });
46
52
  };
@@ -61,6 +67,18 @@ function binding(requiredContextTypes) {
61
67
  // add the step binding to the binding registry
62
68
  addStepBinding(stepBinding);
63
69
  });
70
+ // Process pending step bindings after class is decorated
71
+ context.addInitializer(function () {
72
+ // Get all the collected bindings
73
+ const allBindings = (0, binding_context_1.getCollectedBindings)();
74
+ allBindings.forEach(stepBinding => {
75
+ // Set the class prototype and register
76
+ stepBinding.classPrototype = target.prototype;
77
+ bindingRegistry.registerStepBinding(stepBinding);
78
+ // Register with cucumber - call the local addStepBinding function
79
+ addStepBinding(stepBinding);
80
+ });
81
+ });
64
82
  return target;
65
83
  };
66
84
  }
@@ -157,16 +175,21 @@ function bindStepDefinition(stepBinding) {
157
175
  * @param stepBinding The [[StepBinding]] that represents a 'before', or 'after', step definition.
158
176
  */
159
177
  function bindHook(stepBinding) {
160
- // beforeAll and afterAll are called before and after all tests.
161
- // these can be class instance or static functions
162
178
  const globalHookFunction = function () {
163
- // if the function is static we need to add it to the associated class first
164
- if (stepBinding.stepIsStatic && !stepBinding.classPrototype[stepBinding.classPropertyKey]) {
165
- stepBinding.classPrototype[stepBinding.classPropertyKey] = stepBinding.stepFunction;
179
+ // Check if it's a static method
180
+ if (stepBinding.stepIsStatic || !stepBinding.classPrototype[stepBinding.classPropertyKey]) {
181
+ const constructor = stepBinding.classPrototype.constructor;
182
+ if (constructor && constructor[stepBinding.classPropertyKey]) {
183
+ return constructor[stepBinding.classPropertyKey].apply(constructor);
184
+ }
185
+ }
186
+ // For non-static methods
187
+ if (stepBinding.classPrototype[stepBinding.classPropertyKey]) {
188
+ return stepBinding.classPrototype[stepBinding.classPropertyKey].apply(stepBinding.classPrototype);
166
189
  }
167
- return stepBinding.classPrototype[stepBinding.classPropertyKey].apply();
190
+ throw new Error(`Method ${String(stepBinding.classPropertyKey)} not found on class ${stepBinding.classPrototype?.constructor?.name}`);
168
191
  };
169
- // Main binding for all other steps
192
+ // Main binding for all other hooks (before, after, beforeStep, afterStep)
170
193
  const hookFunction = function (arg) {
171
194
  const scenarioContext = global.messageCollector.getHookScenarioContext(arg);
172
195
  if (scenarioContext) {