@serenity-js/cucumber 3.39.0 → 3.40.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 (32) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/lib/listeners/legacy/gherkin/GherkinParserAdapter.d.ts +31 -0
  3. package/lib/listeners/legacy/gherkin/GherkinParserAdapter.d.ts.map +1 -0
  4. package/lib/listeners/legacy/gherkin/GherkinParserAdapter.js +168 -0
  5. package/lib/listeners/legacy/gherkin/GherkinParserAdapter.js.map +1 -0
  6. package/lib/listeners/legacy/gherkin/index.d.ts +1 -0
  7. package/lib/listeners/legacy/gherkin/index.d.ts.map +1 -1
  8. package/lib/listeners/legacy/gherkin/index.js +1 -0
  9. package/lib/listeners/legacy/gherkin/index.js.map +1 -1
  10. package/lib/listeners/legacy/gherkin/nodes/DataTable.d.ts +1 -1
  11. package/lib/listeners/legacy/gherkin/nodes/Feature.d.ts +1 -1
  12. package/lib/listeners/legacy/gherkin/nodes/Feature.d.ts.map +1 -1
  13. package/lib/listeners/legacy/gherkin/nodes/Location.d.ts +1 -1
  14. package/lib/listeners/legacy/gherkin/nodes/Location.d.ts.map +1 -1
  15. package/lib/listeners/legacy/gherkin/nodes/ScenarioDefinition.d.ts +1 -1
  16. package/lib/listeners/legacy/gherkin/nodes/ScenarioDefinition.d.ts.map +1 -1
  17. package/lib/listeners/legacy/gherkin/nodes/index.d.ts +1 -0
  18. package/lib/listeners/legacy/gherkin/nodes/index.d.ts.map +1 -1
  19. package/lib/listeners/legacy/gherkin/nodes/index.js +1 -0
  20. package/lib/listeners/legacy/gherkin/nodes/index.js.map +1 -1
  21. package/lib/listeners/legacy/index.d.ts.map +1 -1
  22. package/lib/listeners/legacy/index.js +1 -2
  23. package/lib/listeners/legacy/index.js.map +1 -1
  24. package/package.json +5 -5
  25. package/src/listeners/legacy/gherkin/GherkinParserAdapter.ts +184 -0
  26. package/src/listeners/legacy/gherkin/index.ts +1 -0
  27. package/src/listeners/legacy/gherkin/nodes/DataTable.ts +1 -1
  28. package/src/listeners/legacy/gherkin/nodes/Feature.ts +1 -1
  29. package/src/listeners/legacy/gherkin/nodes/Location.ts +1 -1
  30. package/src/listeners/legacy/gherkin/nodes/ScenarioDefinition.ts +1 -1
  31. package/src/listeners/legacy/gherkin/nodes/index.ts +1 -0
  32. package/src/listeners/legacy/index.ts +2 -3
package/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [3.40.0](https://github.com/serenity-js/serenity-js/compare/v3.39.0...v3.40.0) (2026-02-04)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **deps:** update @cucumber/messages to 32.0.1 ([b308f3a](https://github.com/serenity-js/serenity-js/commit/b308f3abb1e7874f9d7aa21a61b3a2b7fe16d3ce))
12
+
13
+
14
+
15
+
16
+
6
17
  # [3.39.0](https://github.com/serenity-js/serenity-js/compare/v3.38.0...v3.39.0) (2026-01-30)
7
18
 
8
19
  **Note:** Version bump only for package @serenity-js/cucumber
@@ -0,0 +1,31 @@
1
+ import type { GherkinDocument } from './nodes';
2
+ /**
3
+ * Adapts the new @cucumber/gherkin Parser to produce output compatible with the old gherkin 5.x format.
4
+ *
5
+ * @private
6
+ */
7
+ export declare class GherkinParserAdapter {
8
+ private readonly parser;
9
+ constructor();
10
+ parse(featureContent: string): GherkinDocument;
11
+ private adaptDocument;
12
+ private adaptFeature;
13
+ private adaptChild;
14
+ private adaptBackground;
15
+ private adaptScenario;
16
+ private adaptScenarioOutline;
17
+ private adaptStep;
18
+ private adaptDataTable;
19
+ private adaptDocString;
20
+ private adaptExamples;
21
+ private adaptTableRow;
22
+ private adaptTag;
23
+ private adaptComment;
24
+ /**
25
+ * Trims the description and returns it, or undefined if the description is empty.
26
+ * The old gherkin 5.x parser returned undefined for empty descriptions, which the mapper
27
+ * then passes directly to constructors using `description && new Description(description)`.
28
+ */
29
+ private trimDescription;
30
+ }
31
+ //# sourceMappingURL=GherkinParserAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GherkinParserAdapter.d.ts","sourceRoot":"","sources":["../../../../src/listeners/legacy/gherkin/GherkinParserAdapter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAgE,eAAe,EAAsE,MAAM,SAAS,CAAC;AAEjL;;;;GAIG;AACH,qBAAa,oBAAoB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmC;;IAS1D,KAAK,CAAC,cAAc,EAAE,MAAM,GAAG,eAAe;IAK9C,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,UAAU;IAelB,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,oBAAoB;IAa5B,OAAO,CAAC,SAAS;IAiBjB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,QAAQ;IAQhB,OAAO,CAAC,YAAY;IAQpB;;;;OAIG;IACH,OAAO,CAAC,eAAe;CAK1B"}
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GherkinParserAdapter = void 0;
4
+ const gherkin_1 = require("@cucumber/gherkin");
5
+ const messages_1 = require("@cucumber/messages");
6
+ /**
7
+ * Adapts the new @cucumber/gherkin Parser to produce output compatible with the old gherkin 5.x format.
8
+ *
9
+ * @private
10
+ */
11
+ class GherkinParserAdapter {
12
+ parser;
13
+ constructor() {
14
+ const createUuid = messages_1.IdGenerator.uuid();
15
+ const builder = new gherkin_1.AstBuilder(createUuid);
16
+ const matcher = new gherkin_1.GherkinClassicTokenMatcher();
17
+ this.parser = new gherkin_1.Parser(builder, matcher);
18
+ }
19
+ parse(featureContent) {
20
+ const newDoc = this.parser.parse(featureContent);
21
+ return this.adaptDocument(newDoc);
22
+ }
23
+ adaptDocument(doc) {
24
+ return {
25
+ type: 'GherkinDocument',
26
+ feature: doc.feature ? this.adaptFeature(doc.feature) : undefined,
27
+ comments: (doc.comments || []).map(c => this.adaptComment(c)),
28
+ };
29
+ }
30
+ adaptFeature(feature) {
31
+ return {
32
+ type: 'Feature',
33
+ location: feature.location,
34
+ tags: feature.tags.map(t => this.adaptTag(t)),
35
+ language: feature.language,
36
+ keyword: feature.keyword,
37
+ name: feature.name,
38
+ description: this.trimDescription(feature.description),
39
+ children: feature.children.map(child => this.adaptChild(child)),
40
+ };
41
+ }
42
+ adaptChild(child) {
43
+ if (child.background) {
44
+ return this.adaptBackground(child.background);
45
+ }
46
+ if (child.scenario) {
47
+ // Check if it's a Scenario Outline by looking at the keyword or examples
48
+ if (child.scenario.keyword === 'Scenario Outline' || child.scenario.keyword === 'Scenario Template' || child.scenario.examples.length > 0) {
49
+ return this.adaptScenarioOutline(child.scenario);
50
+ }
51
+ return this.adaptScenario(child.scenario);
52
+ }
53
+ // Rule children are not supported in the legacy format
54
+ throw new Error('Unsupported feature child type');
55
+ }
56
+ adaptBackground(bg) {
57
+ return {
58
+ type: 'Background',
59
+ location: bg.location,
60
+ tags: [],
61
+ keyword: bg.keyword,
62
+ name: bg.name,
63
+ description: this.trimDescription(bg.description),
64
+ steps: bg.steps.map(s => this.adaptStep(s)),
65
+ };
66
+ }
67
+ adaptScenario(scenario) {
68
+ return {
69
+ type: 'Scenario',
70
+ location: scenario.location,
71
+ tags: scenario.tags.map(t => this.adaptTag(t)),
72
+ keyword: scenario.keyword,
73
+ name: scenario.name,
74
+ description: this.trimDescription(scenario.description),
75
+ steps: scenario.steps.map(s => this.adaptStep(s)),
76
+ };
77
+ }
78
+ adaptScenarioOutline(scenario) {
79
+ return {
80
+ type: 'ScenarioOutline',
81
+ location: scenario.location,
82
+ tags: scenario.tags.map(t => this.adaptTag(t)),
83
+ keyword: scenario.keyword,
84
+ name: scenario.name,
85
+ description: this.trimDescription(scenario.description),
86
+ steps: scenario.steps.map(s => this.adaptStep(s)),
87
+ examples: scenario.examples.map(e => this.adaptExamples(e)),
88
+ };
89
+ }
90
+ adaptStep(step) {
91
+ const result = {
92
+ type: 'Step',
93
+ location: step.location,
94
+ keyword: step.keyword,
95
+ text: step.text,
96
+ };
97
+ if (step.dataTable) {
98
+ result.argument = this.adaptDataTable(step.dataTable);
99
+ }
100
+ else if (step.docString) {
101
+ result.argument = this.adaptDocString(step.docString);
102
+ }
103
+ return result;
104
+ }
105
+ adaptDataTable(dataTable) {
106
+ return {
107
+ type: 'DataTable',
108
+ location: dataTable.location,
109
+ rows: dataTable.rows.map(r => this.adaptTableRow(r)),
110
+ };
111
+ }
112
+ adaptDocString(docString) {
113
+ return {
114
+ type: 'DocString',
115
+ location: docString.location,
116
+ content: docString.content,
117
+ };
118
+ }
119
+ adaptExamples(examples) {
120
+ return {
121
+ type: 'Examples',
122
+ location: examples.location,
123
+ tags: examples.tags.map(t => this.adaptTag(t)),
124
+ keyword: examples.keyword,
125
+ name: examples.name,
126
+ description: this.trimDescription(examples.description),
127
+ tableHeader: this.adaptTableRow(examples.tableHeader),
128
+ tableBody: examples.tableBody.map(r => this.adaptTableRow(r)),
129
+ };
130
+ }
131
+ adaptTableRow(row) {
132
+ return {
133
+ type: 'TableRow',
134
+ location: row.location,
135
+ cells: row.cells.map(c => ({
136
+ type: 'TableCell',
137
+ location: c.location,
138
+ value: c.value,
139
+ })),
140
+ };
141
+ }
142
+ adaptTag(tag) {
143
+ return {
144
+ type: 'Tag',
145
+ location: tag.location,
146
+ name: tag.name,
147
+ };
148
+ }
149
+ adaptComment(comment) {
150
+ return {
151
+ type: 'Comment',
152
+ location: comment.location,
153
+ text: comment.text,
154
+ };
155
+ }
156
+ /**
157
+ * Trims the description and returns it, or undefined if the description is empty.
158
+ * The old gherkin 5.x parser returned undefined for empty descriptions, which the mapper
159
+ * then passes directly to constructors using `description && new Description(description)`.
160
+ */
161
+ trimDescription(description) {
162
+ const trimmed = description?.trim();
163
+ // Return undefined for empty descriptions to match old gherkin 5.x behavior
164
+ return trimmed || undefined;
165
+ }
166
+ }
167
+ exports.GherkinParserAdapter = GherkinParserAdapter;
168
+ //# sourceMappingURL=GherkinParserAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GherkinParserAdapter.js","sourceRoot":"","sources":["../../../../src/listeners/legacy/gherkin/GherkinParserAdapter.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  export * from './feature-files';
2
+ export * from './GherkinParserAdapter';
2
3
  export * from './model';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/listeners/legacy/gherkin/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/listeners/legacy/gherkin/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,wBAAwB,CAAC;AACvC,cAAc,SAAS,CAAC"}
@@ -15,5 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./feature-files"), exports);
18
+ __exportStar(require("./GherkinParserAdapter"), exports);
18
19
  __exportStar(require("./model"), exports);
19
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/listeners/legacy/gherkin/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,0CAAwB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/listeners/legacy/gherkin/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,yDAAuC;AACvC,0CAAwB"}
@@ -4,7 +4,7 @@ import type { TableRow } from './TableRow';
4
4
  * @private
5
5
  */
6
6
  export interface DataTable extends StepArgument {
7
- type: 'DocString';
7
+ type: 'DataTable';
8
8
  rows: TableRow[];
9
9
  }
10
10
  //# sourceMappingURL=DataTable.d.ts.map
@@ -10,7 +10,7 @@ export interface Feature extends ASTNode {
10
10
  language: string;
11
11
  keyword: string;
12
12
  name: string;
13
- description: string;
13
+ description?: string;
14
14
  children: ScenarioDefinition[];
15
15
  }
16
16
  //# sourceMappingURL=Feature.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Feature.d.ts","sourceRoot":"","sources":["../../../../../src/listeners/legacy/gherkin/nodes/Feature.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC;;GAEG;AACH,MAAM,WAAW,OAAQ,SAAQ,OAAO;IACpC,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;CAClC"}
1
+ {"version":3,"file":"Feature.d.ts","sourceRoot":"","sources":["../../../../../src/listeners/legacy/gherkin/nodes/Feature.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC;;GAEG;AACH,MAAM,WAAW,OAAQ,SAAQ,OAAO;IACpC,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;CAClC"}
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export interface Location {
5
5
  line: number;
6
- column: number;
6
+ column?: number;
7
7
  }
8
8
  //# sourceMappingURL=Location.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Location.d.ts","sourceRoot":"","sources":["../../../../../src/listeners/legacy/gherkin/nodes/Location.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAClB"}
1
+ {"version":3,"file":"Location.d.ts","sourceRoot":"","sources":["../../../../../src/listeners/legacy/gherkin/nodes/Location.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,QAAQ;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB"}
@@ -9,7 +9,7 @@ export interface ScenarioDefinition extends ASTNode {
9
9
  tags: Tag[];
10
10
  keyword: string;
11
11
  name: string;
12
- description: string;
12
+ description?: string;
13
13
  steps: Step[];
14
14
  }
15
15
  //# sourceMappingURL=ScenarioDefinition.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ScenarioDefinition.d.ts","sourceRoot":"","sources":["../../../../../src/listeners/legacy/gherkin/nodes/ScenarioDefinition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,OAAO;IAC/C,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,iBAAiB,CAAC;IACpD,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,IAAI,EAAE,CAAC;CACjB"}
1
+ {"version":3,"file":"ScenarioDefinition.d.ts","sourceRoot":"","sources":["../../../../../src/listeners/legacy/gherkin/nodes/ScenarioDefinition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEjC;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,OAAO;IAC/C,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,iBAAiB,CAAC;IACpD,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,IAAI,EAAE,CAAC;CACjB"}
@@ -2,6 +2,7 @@ export * from './Background';
2
2
  export * from './Comment';
3
3
  export * from './DataTable';
4
4
  export * from './DocString';
5
+ export * from './Examples';
5
6
  export * from './Feature';
6
7
  export * from './GherkinDocument';
7
8
  export * from './Location';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/listeners/legacy/gherkin/nodes/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/listeners/legacy/gherkin/nodes/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,QAAQ,CAAC;AACvB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,OAAO,CAAC"}
@@ -18,6 +18,7 @@ __exportStar(require("./Background"), exports);
18
18
  __exportStar(require("./Comment"), exports);
19
19
  __exportStar(require("./DataTable"), exports);
20
20
  __exportStar(require("./DocString"), exports);
21
+ __exportStar(require("./Examples"), exports);
21
22
  __exportStar(require("./Feature"), exports);
22
23
  __exportStar(require("./GherkinDocument"), exports);
23
24
  __exportStar(require("./Location"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/listeners/legacy/gherkin/nodes/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,4CAA0B;AAC1B,8CAA4B;AAC5B,8CAA4B;AAC5B,4CAA0B;AAC1B,oDAAkC;AAClC,6CAA2B;AAC3B,6CAA2B;AAC3B,uDAAqC;AACrC,oDAAkC;AAClC,yCAAuB;AACvB,iDAA+B;AAC/B,8CAA4B;AAC5B,6CAA2B;AAC3B,wCAAsB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/listeners/legacy/gherkin/nodes/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,4CAA0B;AAC1B,8CAA4B;AAC5B,8CAA4B;AAC5B,6CAA2B;AAC3B,4CAA0B;AAC1B,oDAAkC;AAClC,6CAA2B;AAC3B,6CAA2B;AAC3B,uDAAqC;AACrC,oDAAkC;AAClC,yCAAuB;AACvB,iDAA+B;AAC/B,8CAA4B;AAC5B,6CAA2B;AAC3B,wCAAsB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/listeners/legacy/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,KAAK,EAAE,YAAY,EAAQ,MAAM,0BAA0B,CAAC;AAOnE;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,GAAG,GAAG,CA8BlF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/listeners/legacy/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,KAAK,EAAE,YAAY,EAAQ,MAAM,0BAA0B,CAAC;AAMnE;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,GAAG,GAAG,CA8BlF"}
@@ -4,7 +4,6 @@ exports.createListener = createListener;
4
4
  const core_1 = require("@serenity-js/core");
5
5
  const gherkin_1 = require("./gherkin");
6
6
  const notifier_1 = require("./notifier");
7
- const Gherkin = require("gherkin");
8
7
  /**
9
8
  * Creates a listener for Cucumber.js 0.x-6.x
10
9
  *
@@ -14,7 +13,7 @@ const Gherkin = require("gherkin");
14
13
  function createListener(serenity, moduleLoader) {
15
14
  const version = moduleLoader.versionOf('cucumber');
16
15
  try {
17
- const cucumber = moduleLoader.require('cucumber'), notifier = new notifier_1.Notifier(serenity), mapper = new gherkin_1.FeatureFileMapper(), resultMapper = new notifier_1.ResultMapper(serenity), cache = new gherkin_1.Cache(), loader = new gherkin_1.FeatureFileLoader(new gherkin_1.FeatureFileParser(new Gherkin.Parser()), mapper, cache);
16
+ const cucumber = moduleLoader.require('cucumber'), notifier = new notifier_1.Notifier(serenity), mapper = new gherkin_1.FeatureFileMapper(), resultMapper = new notifier_1.ResultMapper(serenity), cache = new gherkin_1.Cache(), loader = new gherkin_1.FeatureFileLoader(new gherkin_1.FeatureFileParser(new gherkin_1.GherkinParserAdapter()), mapper, cache);
18
17
  return require(`./cucumber-${version.major()}`)({
19
18
  serenity,
20
19
  notifier,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/listeners/legacy/index.ts"],"names":[],"mappings":";;AAeA,wCA8BC;AA5CD,4CAAuD;AAIvD,uCAA2F;AAC3F,yCAAoD;AACpD,mCAAoC;AAEpC;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,QAAkB,EAAE,YAA0B;IAEzE,MAAM,OAAO,GAAI,YAAY,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAEpD,IAAI,CAAC;QACD,MACI,QAAQ,GAAU,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,EAClD,QAAQ,GAAW,IAAI,mBAAQ,CAAC,QAAQ,CAAC,EACzC,MAAM,GAAY,IAAI,2BAAiB,EAAE,EACzC,YAAY,GAAM,IAAI,uBAAY,CAAC,QAAQ,CAAC,EAC5C,KAAK,GAAa,IAAI,eAAK,EAAwB,EACnD,MAAM,GAAY,IAAI,2BAAiB,CACnC,IAAI,2BAAiB,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,EAC3C,MAAM,EACN,KAAK,CACR,CAAC;QAEN,OAAO,OAAO,CAAC,cAAe,OAAO,CAAC,KAAK,EAAG,EAAE,CAAC,CAAC;YAC9C,QAAQ;YACR,QAAQ;YACR,MAAM;YACN,YAAY;YACZ,KAAK;YACL,MAAM;YACN,QAAQ;SACX,CAAC,CAAC;IACP,CAAC;IACD,OAAO,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,yBAAkB,CAAC,oBAAqB,OAAO,CAAC,QAAQ,EAAG,uBAAuB,EAAE,KAAK,CAAC,CAAC;IACzG,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/listeners/legacy/index.ts"],"names":[],"mappings":";;AAcA,wCA8BC;AA3CD,4CAAuD;AAIvD,uCAAiH;AACjH,yCAAoD;AAEpD;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,QAAkB,EAAE,YAA0B;IAEzE,MAAM,OAAO,GAAI,YAAY,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAEpD,IAAI,CAAC;QACD,MACI,QAAQ,GAAU,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,EAClD,QAAQ,GAAW,IAAI,mBAAQ,CAAC,QAAQ,CAAC,EACzC,MAAM,GAAY,IAAI,2BAAiB,EAAE,EACzC,YAAY,GAAM,IAAI,uBAAY,CAAC,QAAQ,CAAC,EAC5C,KAAK,GAAa,IAAI,eAAK,EAAwB,EACnD,MAAM,GAAY,IAAI,2BAAiB,CACnC,IAAI,2BAAiB,CAAC,IAAI,8BAAoB,EAAE,CAAC,EACjD,MAAM,EACN,KAAK,CACR,CAAC;QAEN,OAAO,OAAO,CAAC,cAAe,OAAO,CAAC,KAAK,EAAG,EAAE,CAAC,CAAC;YAC9C,QAAQ;YACR,QAAQ;YACR,MAAM;YACN,YAAY;YACZ,KAAK;YACL,MAAM;YACN,QAAQ;SACX,CAAC,CAAC;IACP,CAAC;IACD,OAAO,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,yBAAkB,CAAC,oBAAqB,OAAO,CAAC,QAAQ,EAAG,uBAAuB,EAAE,KAAK,CAAC,CAAC;IACzG,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serenity-js/cucumber",
3
- "version": "3.39.0",
3
+ "version": "3.40.0",
4
4
  "description": "Serenity/JS test runner adapter for seamless integration with any version of Cucumber.js, facilitating BDD-style test automation and leveraging Serenity/JS reporting capabilities",
5
5
  "author": {
6
6
  "name": "Jan Molak",
@@ -50,10 +50,10 @@
50
50
  "node": "^20 || ^22 || ^24"
51
51
  },
52
52
  "dependencies": {
53
- "@cucumber/messages": "26.0.1",
54
- "@serenity-js/core": "3.39.0",
53
+ "@cucumber/gherkin": "38.0.0",
54
+ "@cucumber/messages": "32.0.1",
55
+ "@serenity-js/core": "3.40.0",
55
56
  "cli-table3": "0.6.5",
56
- "gherkin": "5.1.0",
57
57
  "tiny-types": "1.24.3"
58
58
  },
59
59
  "peerDependencies": {
@@ -79,5 +79,5 @@
79
79
  "ts-node": "10.9.2",
80
80
  "typescript": "5.9.3"
81
81
  },
82
- "gitHead": "253c63474dd24f3850a0f34b6d5f42559049a25c"
82
+ "gitHead": "185b8435cf6e87b8a54f10944da3e652227ecb6e"
83
83
  }
@@ -0,0 +1,184 @@
1
+ import { AstBuilder, GherkinClassicTokenMatcher, Parser } from '@cucumber/gherkin';
2
+ import type * as messages from '@cucumber/messages';
3
+ import { IdGenerator } from '@cucumber/messages';
4
+
5
+ import type { Background, Comment, DataTable, DocString, Examples, Feature, GherkinDocument, Scenario, ScenarioDefinition, ScenarioOutline, Step, TableRow, Tag } from './nodes';
6
+
7
+ /**
8
+ * Adapts the new @cucumber/gherkin Parser to produce output compatible with the old gherkin 5.x format.
9
+ *
10
+ * @private
11
+ */
12
+ export class GherkinParserAdapter {
13
+ private readonly parser: Parser<messages.GherkinDocument>;
14
+
15
+ constructor() {
16
+ const createUuid = IdGenerator.uuid();
17
+ const builder = new AstBuilder(createUuid);
18
+ const matcher = new GherkinClassicTokenMatcher();
19
+ this.parser = new Parser(builder, matcher);
20
+ }
21
+
22
+ parse(featureContent: string): GherkinDocument {
23
+ const newDoc = this.parser.parse(featureContent);
24
+ return this.adaptDocument(newDoc);
25
+ }
26
+
27
+ private adaptDocument(doc: messages.GherkinDocument): GherkinDocument {
28
+ return {
29
+ type: 'GherkinDocument',
30
+ feature: doc.feature ? this.adaptFeature(doc.feature) : undefined,
31
+ comments: (doc.comments || []).map(c => this.adaptComment(c)),
32
+ };
33
+ }
34
+
35
+ private adaptFeature(feature: messages.Feature): Feature {
36
+ return {
37
+ type: 'Feature',
38
+ location: feature.location,
39
+ tags: feature.tags.map(t => this.adaptTag(t)),
40
+ language: feature.language,
41
+ keyword: feature.keyword,
42
+ name: feature.name,
43
+ description: this.trimDescription(feature.description),
44
+ children: feature.children.map(child => this.adaptChild(child)),
45
+ };
46
+ }
47
+
48
+ private adaptChild(child: messages.FeatureChild): ScenarioDefinition {
49
+ if (child.background) {
50
+ return this.adaptBackground(child.background);
51
+ }
52
+ if (child.scenario) {
53
+ // Check if it's a Scenario Outline by looking at the keyword or examples
54
+ if (child.scenario.keyword === 'Scenario Outline' || child.scenario.keyword === 'Scenario Template' || child.scenario.examples.length > 0) {
55
+ return this.adaptScenarioOutline(child.scenario);
56
+ }
57
+ return this.adaptScenario(child.scenario);
58
+ }
59
+ // Rule children are not supported in the legacy format
60
+ throw new Error('Unsupported feature child type');
61
+ }
62
+
63
+ private adaptBackground(bg: messages.Background): Background {
64
+ return {
65
+ type: 'Background',
66
+ location: bg.location,
67
+ tags: [],
68
+ keyword: bg.keyword,
69
+ name: bg.name,
70
+ description: this.trimDescription(bg.description),
71
+ steps: bg.steps.map(s => this.adaptStep(s)),
72
+ };
73
+ }
74
+
75
+ private adaptScenario(scenario: messages.Scenario): Scenario {
76
+ return {
77
+ type: 'Scenario',
78
+ location: scenario.location,
79
+ tags: scenario.tags.map(t => this.adaptTag(t)),
80
+ keyword: scenario.keyword,
81
+ name: scenario.name,
82
+ description: this.trimDescription(scenario.description),
83
+ steps: scenario.steps.map(s => this.adaptStep(s)),
84
+ };
85
+ }
86
+
87
+ private adaptScenarioOutline(scenario: messages.Scenario): ScenarioOutline {
88
+ return {
89
+ type: 'ScenarioOutline',
90
+ location: scenario.location,
91
+ tags: scenario.tags.map(t => this.adaptTag(t)),
92
+ keyword: scenario.keyword,
93
+ name: scenario.name,
94
+ description: this.trimDescription(scenario.description),
95
+ steps: scenario.steps.map(s => this.adaptStep(s)),
96
+ examples: scenario.examples.map(e => this.adaptExamples(e)),
97
+ };
98
+ }
99
+
100
+ private adaptStep(step: messages.Step): Step {
101
+ const result: Step = {
102
+ type: 'Step',
103
+ location: step.location,
104
+ keyword: step.keyword,
105
+ text: step.text,
106
+ };
107
+
108
+ if (step.dataTable) {
109
+ result.argument = this.adaptDataTable(step.dataTable);
110
+ } else if (step.docString) {
111
+ result.argument = this.adaptDocString(step.docString);
112
+ }
113
+
114
+ return result;
115
+ }
116
+
117
+ private adaptDataTable(dataTable: messages.DataTable): DataTable {
118
+ return {
119
+ type: 'DataTable',
120
+ location: dataTable.location,
121
+ rows: dataTable.rows.map(r => this.adaptTableRow(r)),
122
+ };
123
+ }
124
+
125
+ private adaptDocString(docString: messages.DocString): DocString {
126
+ return {
127
+ type: 'DocString',
128
+ location: docString.location,
129
+ content: docString.content,
130
+ };
131
+ }
132
+
133
+ private adaptExamples(examples: messages.Examples): Examples {
134
+ return {
135
+ type: 'Examples',
136
+ location: examples.location,
137
+ tags: examples.tags.map(t => this.adaptTag(t)),
138
+ keyword: examples.keyword,
139
+ name: examples.name,
140
+ description: this.trimDescription(examples.description),
141
+ tableHeader: this.adaptTableRow(examples.tableHeader),
142
+ tableBody: examples.tableBody.map(r => this.adaptTableRow(r)),
143
+ };
144
+ }
145
+
146
+ private adaptTableRow(row: messages.TableRow): TableRow {
147
+ return {
148
+ type: 'TableRow',
149
+ location: row.location,
150
+ cells: row.cells.map(c => ({
151
+ type: 'TableCell',
152
+ location: c.location,
153
+ value: c.value,
154
+ })),
155
+ };
156
+ }
157
+
158
+ private adaptTag(tag: messages.Tag): Tag {
159
+ return {
160
+ type: 'Tag',
161
+ location: tag.location,
162
+ name: tag.name,
163
+ };
164
+ }
165
+
166
+ private adaptComment(comment: messages.Comment): Comment {
167
+ return {
168
+ type: 'Comment',
169
+ location: comment.location,
170
+ text: comment.text,
171
+ };
172
+ }
173
+
174
+ /**
175
+ * Trims the description and returns it, or undefined if the description is empty.
176
+ * The old gherkin 5.x parser returned undefined for empty descriptions, which the mapper
177
+ * then passes directly to constructors using `description && new Description(description)`.
178
+ */
179
+ private trimDescription(description: string | undefined): string | undefined {
180
+ const trimmed = description?.trim();
181
+ // Return undefined for empty descriptions to match old gherkin 5.x behavior
182
+ return trimmed || undefined;
183
+ }
184
+ }
@@ -1,2 +1,3 @@
1
1
  export * from './feature-files';
2
+ export * from './GherkinParserAdapter';
2
3
  export * from './model';
@@ -5,6 +5,6 @@ import type { TableRow } from './TableRow';
5
5
  * @private
6
6
  */
7
7
  export interface DataTable extends StepArgument {
8
- type: 'DocString';
8
+ type: 'DataTable';
9
9
  rows: TableRow[];
10
10
  }
@@ -11,6 +11,6 @@ export interface Feature extends ASTNode {
11
11
  language: string;
12
12
  keyword: string;
13
13
  name: string;
14
- description: string;
14
+ description?: string;
15
15
  children: ScenarioDefinition[];
16
16
  }
@@ -3,5 +3,5 @@
3
3
  */
4
4
  export interface Location {
5
5
  line: number;
6
- column: number;
6
+ column?: number;
7
7
  }
@@ -10,6 +10,6 @@ export interface ScenarioDefinition extends ASTNode {
10
10
  tags: Tag[];
11
11
  keyword: string;
12
12
  name: string;
13
- description: string;
13
+ description?: string;
14
14
  steps: Step[];
15
15
  }
@@ -2,6 +2,7 @@ export * from './Background';
2
2
  export * from './Comment';
3
3
  export * from './DataTable';
4
4
  export * from './DocString';
5
+ export * from './Examples';
5
6
  export * from './Feature';
6
7
  export * from './GherkinDocument';
7
8
  export * from './Location';
@@ -3,9 +3,8 @@ import { ConfigurationError } from '@serenity-js/core';
3
3
  import type { ModuleLoader, Path } from '@serenity-js/core/lib/io';
4
4
 
5
5
  import type { FeatureFileMap} from './gherkin';
6
- import { Cache, FeatureFileLoader, FeatureFileMapper, FeatureFileParser } from './gherkin';
6
+ import { Cache, FeatureFileLoader, FeatureFileMapper, FeatureFileParser, GherkinParserAdapter } from './gherkin';
7
7
  import { Notifier, ResultMapper } from './notifier';
8
- import Gherkin = require('gherkin');
9
8
 
10
9
  /**
11
10
  * Creates a listener for Cucumber.js 0.x-6.x
@@ -25,7 +24,7 @@ export function createListener(serenity: Serenity, moduleLoader: ModuleLoader):
25
24
  resultMapper = new ResultMapper(serenity),
26
25
  cache = new Cache<Path, FeatureFileMap>(),
27
26
  loader = new FeatureFileLoader(
28
- new FeatureFileParser(new Gherkin.Parser()),
27
+ new FeatureFileParser(new GherkinParserAdapter()),
29
28
  mapper,
30
29
  cache,
31
30
  );