@sun-asterisk/sungen 2.3.1 → 2.4.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 (90) hide show
  1. package/README.md +10 -11
  2. package/dist/cli/index.js +1 -1
  3. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +1 -1
  4. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +5 -1
  5. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +7 -1
  6. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +5 -1
  7. package/dist/generators/test-generator/patterns/table-patterns.d.ts +9 -0
  8. package/dist/generators/test-generator/patterns/table-patterns.d.ts.map +1 -1
  9. package/dist/generators/test-generator/patterns/table-patterns.js +94 -98
  10. package/dist/generators/test-generator/patterns/table-patterns.js.map +1 -1
  11. package/dist/generators/test-generator/patterns/types.d.ts +2 -0
  12. package/dist/generators/test-generator/patterns/types.d.ts.map +1 -1
  13. package/dist/generators/test-generator/step-mapper.d.ts +13 -0
  14. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  15. package/dist/generators/test-generator/step-mapper.js +80 -0
  16. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  17. package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
  18. package/dist/orchestrator/ai-rules-updater.js +8 -6
  19. package/dist/orchestrator/ai-rules-updater.js.map +1 -1
  20. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  21. package/dist/orchestrator/project-initializer.js +33 -2
  22. package/dist/orchestrator/project-initializer.js.map +1 -1
  23. package/dist/orchestrator/screen-manager.js +1 -1
  24. package/dist/orchestrator/screen-manager.js.map +1 -1
  25. package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +5 -5
  26. package/{src/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md → dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md} +7 -7
  27. package/dist/orchestrator/templates/ai-instructions/claude-cmd-review.md +21 -0
  28. package/{src/orchestrator/templates/ai-instructions/claude-cmd-make-test.md → dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md} +2 -2
  29. package/dist/orchestrator/templates/ai-instructions/claude-config.md +65 -12
  30. package/dist/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +128 -52
  31. package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +9 -40
  32. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +67 -239
  33. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +40 -208
  34. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +104 -0
  35. package/dist/orchestrator/templates/ai-instructions/claude-skill-viewpoint.md +186 -0
  36. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +4 -4
  37. package/dist/orchestrator/templates/ai-instructions/{copilot-cmd-make-tc.md → copilot-cmd-create-test.md} +8 -8
  38. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-review.md +24 -0
  39. package/{src/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md → dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md} +3 -3
  40. package/dist/orchestrator/templates/ai-instructions/copilot-config.md +66 -13
  41. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +128 -52
  42. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +9 -40
  43. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +67 -214
  44. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +40 -208
  45. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +104 -0
  46. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint.md +186 -0
  47. package/dist/orchestrator/templates/readme.md +4 -4
  48. package/package.json +1 -1
  49. package/src/cli/index.ts +1 -1
  50. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +1 -1
  51. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +5 -1
  52. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +7 -1
  53. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +5 -1
  54. package/src/generators/test-generator/patterns/table-patterns.ts +98 -111
  55. package/src/generators/test-generator/patterns/types.ts +2 -0
  56. package/src/generators/test-generator/step-mapper.ts +87 -1
  57. package/src/orchestrator/ai-rules-updater.ts +8 -6
  58. package/src/orchestrator/project-initializer.ts +38 -2
  59. package/src/orchestrator/screen-manager.ts +1 -1
  60. package/src/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +5 -5
  61. package/{dist/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md → src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md} +7 -7
  62. package/src/orchestrator/templates/ai-instructions/claude-cmd-review.md +21 -0
  63. package/{dist/orchestrator/templates/ai-instructions/claude-cmd-make-test.md → src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md} +2 -2
  64. package/src/orchestrator/templates/ai-instructions/claude-config.md +65 -12
  65. package/src/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +128 -52
  66. package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +9 -40
  67. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +67 -239
  68. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +40 -208
  69. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +104 -0
  70. package/src/orchestrator/templates/ai-instructions/claude-skill-viewpoint.md +186 -0
  71. package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +4 -4
  72. package/src/orchestrator/templates/ai-instructions/{copilot-cmd-make-tc.md → copilot-cmd-create-test.md} +8 -8
  73. package/src/orchestrator/templates/ai-instructions/copilot-cmd-review.md +24 -0
  74. package/{dist/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md → src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md} +3 -3
  75. package/src/orchestrator/templates/ai-instructions/copilot-config.md +66 -13
  76. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +128 -52
  77. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +9 -40
  78. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +67 -214
  79. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +40 -208
  80. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +104 -0
  81. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint.md +186 -0
  82. package/src/orchestrator/templates/readme.md +4 -4
  83. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +0 -2
  84. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +0 -2
  85. package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-review.md +0 -228
  86. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-review.md +0 -228
  87. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +0 -2
  88. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +0 -2
  89. package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-review.md +0 -228
  90. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-review.md +0 -228
package/README.md CHANGED
@@ -218,13 +218,12 @@ Feature: Login Screen
218
218
  | Pattern | Example |
219
219
  |---|---|
220
220
  | Column exists | `User see [Email] column in [Users] table` |
221
- | Row exists | `User see [Users] table row with {{name}}` |
222
- | No row | `User see [Users] table has no row with {{name}}` |
223
- | Row count | `User see [Users] table with {{count}} rows` |
224
- | Cell by filter | `User see [Users] table row with {{name}} has [Status] with {{status}}` |
225
- | Cell by index | `User see [Users] table row 1 [Name] cell with {{name}}` |
226
- | Action in row | `User click [Edit] in [Users] table row with {{name}}` |
221
+ | Row exists | `User see [Username] row in [Users] table with {{name}}` |
222
+ | Row hidden | `User see [Username] row in [Users] table with {{name}} is hidden` |
223
+ | Row count | `User see [Users] table with {{count}}` |
227
224
  | Empty table | `User see [Users] table is empty` |
225
+ | Cell value | `User see [Status] column with {{status}}` (row scoped) |
226
+ | Action in row | `User click [Edit] button in [Users] table with {{name}}` |
228
227
 
229
228
  ### Scope
230
229
 
@@ -336,11 +335,11 @@ specs/generated/<name>/
336
335
 
337
336
  Full documentation at **[sungen.sun-asterisk.vn](https://sungen.sun-asterisk.vn)**
338
337
 
339
- - **[Installation Guide](https://sungen.sun-asterisk.vn/docs/guides/installation)** — Windows (Git Bash + VS Code + Copilot), macOS, Linux
340
- - **[Quick Start](https://sungen.sun-asterisk.vn/docs/guides/quick-start)** — From zero to running tests
341
- - **[Selector YAML Guide](https://sungen.sun-asterisk.vn/docs/guides/selector-override)** — NFC keys, auto-infer, Japanese/Vietnamese support
342
- - **[Tips & Troubleshooting](https://sungen.sun-asterisk.vn/docs/guides/tips)** — When AI gets stuck fixing tests
343
- - **[Gherkin Dictionary](https://sungen.sun-asterisk.vn/docs/gherkin/gherkin-dictionary)** — Full grammar, all 18 patterns, compiler rules, formal BNF
338
+ - **[Installation Guide](https://sun-asterisk.github.io/sungen/docs/guides/installation)** — Windows (Git Bash + VS Code + Copilot), macOS, Linux
339
+ - **[Quick Start](https://sun-asterisk.github.io/sungen/docs/guides/quick-start)** — From zero to running tests
340
+ - **[Selector YAML Guide](https://sun-asterisk.github.io/sungen/docs/guides/selector-override)** — NFC keys, auto-infer, Japanese/Vietnamese support
341
+ - **[Tips & Troubleshooting](https://sun-asterisk.github.io/sungen/docs/guides/tips)** — When AI gets stuck fixing tests
342
+ - **[Gherkin Patterns](https://sun-asterisk.github.io/sungen/docs/gherkin/patterns)** — Full grammar, all patterns, compiler rules
344
343
 
345
344
  ---
346
345
 
package/dist/cli/index.js CHANGED
@@ -16,7 +16,7 @@ async function main() {
16
16
  program
17
17
  .name('sungen')
18
18
  .description('Deterministic E2E Test Compiler — Gherkin + Selectors → Playwright')
19
- .version('2.3.1');
19
+ .version('2.4.0');
20
20
  // Global options
21
21
  program
22
22
  .option('-v, --verbose', 'Enable verbose logging');
@@ -1,2 +1,2 @@
1
1
  { const tableRow = {{> locator}}.getByRole('row').filter({ hasText: '{{escapeQuotes filterValue}}' });
2
- await tableRow.getByRole('button', { name: '{{escapeQuotes elementName}}' }).{{action}}(); }
2
+ await tableRow.getByRole('{{elementRole}}', { name: '{{escapeQuotes elementName}}' }).{{action}}(); }
@@ -1 +1,5 @@
1
- await expect({{> locator}}.getByRole('columnheader', { name: '{{escapeQuotes columnName}}' })).toBeVisible();
1
+ {{~#if isGiven}}
2
+ await {{> locator}}.getByRole('columnheader', { name: '{{escapeQuotes columnName}}' }).waitFor();
3
+ {{~else}}
4
+ await expect({{> locator}}.getByRole('columnheader', { name: '{{escapeQuotes columnName}}' })).toBeVisible();
5
+ {{~/if}}
@@ -1 +1,7 @@
1
- await expect({{> locator}}.getByRole('row').filter({ hasText: '{{escapeQuotes filterValue}}' })).toBeVisible();
1
+ {{~#if isGiven}}
2
+ const tableRow = {{> locator}}.getByRole('row').filter({ hasText: '{{escapeQuotes filterValue}}' });
3
+ await tableRow.waitFor();
4
+ {{~else}}
5
+ const tableRow = {{> locator}}.getByRole('row').filter({ hasText: '{{escapeQuotes filterValue}}' });
6
+ await expect(tableRow).toBeVisible();
7
+ {{~/if}}
@@ -1 +1,5 @@
1
- await expect({{> locator}}.getByRole('row').filter({ hasText: '{{escapeQuotes filterValue}}' })).toHaveCount(0);
1
+ {{~#if isGiven}}
2
+ await {{> locator}}.getByRole('row').filter({ hasText: '{{escapeQuotes filterValue}}' }).waitFor({ state: 'hidden' });
3
+ {{~else}}
4
+ await expect({{> locator}}.getByRole('row').filter({ hasText: '{{escapeQuotes filterValue}}' })).toHaveCount(0);
5
+ {{~/if}}
@@ -1,6 +1,15 @@
1
1
  /**
2
2
  * Table Patterns
3
3
  * Handles: table row assertions, table cell lookups, actions in table rows
4
+ *
5
+ * Syntax (v2.3 final):
6
+ * - User see [Col] column in [Table] table # column exists
7
+ * - User see [Ref] row in [Table] table with {{value}} # row exists (enters row scope)
8
+ * - User see [Ref] row in [Table] table with {{value}} is hidden # row hidden
9
+ * - User see [Table] table with {{count}} # row count
10
+ * - User see [Table] table is empty # empty table
11
+ * - User see [Col] column with {{value}} # cell value (row scoped — handled in step-mapper)
12
+ * - User click [Act] button in [Table] table with {{filter}} # action in row
4
13
  */
5
14
  import { StepPattern } from './types';
6
15
  export declare const tablePatterns: StepPattern[];
@@ -1 +1 @@
1
- {"version":3,"file":"table-patterns.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/patterns/table-patterns.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,eAAO,MAAM,aAAa,EAAE,WAAW,EAmOtC,CAAC"}
1
+ {"version":3,"file":"table-patterns.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/patterns/table-patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,WAAW,EAAkB,MAAM,SAAS,CAAC;AAkBtD,eAAO,MAAM,aAAa,EAAE,WAAW,EA6LtC,CAAC"}
@@ -2,54 +2,82 @@
2
2
  /**
3
3
  * Table Patterns
4
4
  * Handles: table row assertions, table cell lookups, actions in table rows
5
+ *
6
+ * Syntax (v2.3 final):
7
+ * - User see [Col] column in [Table] table # column exists
8
+ * - User see [Ref] row in [Table] table with {{value}} # row exists (enters row scope)
9
+ * - User see [Ref] row in [Table] table with {{value}} is hidden # row hidden
10
+ * - User see [Table] table with {{count}} # row count
11
+ * - User see [Table] table is empty # empty table
12
+ * - User see [Col] column with {{value}} # cell value (row scoped — handled in step-mapper)
13
+ * - User click [Act] button in [Table] table with {{filter}} # action in row
5
14
  */
6
15
  Object.defineProperty(exports, "__esModule", { value: true });
7
16
  exports.tablePatterns = void 0;
17
+ /** Helper: check if current step is in a Given context */
18
+ function isGivenContext(context) {
19
+ return context.effectiveKeyword === 'Given';
20
+ }
21
+ /** Map Gherkin element type to Playwright ARIA role */
22
+ const typeToRole = {
23
+ button: 'button',
24
+ link: 'link',
25
+ checkbox: 'checkbox',
26
+ icon: 'img',
27
+ image: 'img',
28
+ radio: 'radio',
29
+ switch: 'switch',
30
+ };
8
31
  exports.tablePatterns = [
9
- // "User see [Users] table with {{count}} rows" (preferred)
10
- // Also accepts: "User see [Users] table has {{count}} rows" (backward compat)
32
+ // "User see [Table] table with {{count}}" — row count (no "rows" keyword needed)
11
33
  {
12
34
  name: 'table-row-count',
13
35
  matcher: (step) => {
14
- return /\btable\s+(?:has|with)\b/i.test(step.text) &&
15
- /\}\}\s*rows?\b/i.test(step.text) &&
16
- !!step.dataRef;
36
+ return step.elementType === 'table' &&
37
+ /\btable\s+with\b/i.test(step.text) &&
38
+ !!step.dataRef &&
39
+ !/\brow\b/i.test(step.text) &&
40
+ !/\bcolumn\b/i.test(step.text) &&
41
+ !/\bempty\b/i.test(step.text);
17
42
  },
18
43
  resolver: (step, context) => {
19
44
  const resolved = context.selectorResolver.resolveSelector(step.selectorRef, context.featureName, 'table', step.nth);
20
45
  const count = context.dataResolver.resolveData(step.dataRef, context.featureName);
46
+ const isGiven = isGivenContext(context);
21
47
  return {
22
48
  templateName: 'table-row-count',
23
- data: { ...resolved, expectedCount: count },
24
- comment: `Assert ${step.selectorRef} table has ${count} rows`,
49
+ data: { ...resolved, expectedCount: count, isGiven },
50
+ comment: `${isGiven ? 'Wait' : 'Assert'} ${step.selectorRef} table has ${count} rows`,
25
51
  };
26
52
  },
27
53
  priority: 16,
28
54
  },
29
- // "User see [Users] table has [Email] column" (backward compat)
30
- // Preferred: "User see [Email] column in [Users] table" (parent scoping)
55
+ // "User see [Col] column in [Table] table"
31
56
  {
32
57
  name: 'table-column-exists',
33
58
  matcher: (step) => {
34
- return /\btable\s+has\b/i.test(step.text) &&
35
- /\bcolumn\b/i.test(step.text);
59
+ return /\bcolumn\s+in\b/i.test(step.text) &&
60
+ /\btable\b/i.test(step.text) &&
61
+ !step.dataRef;
36
62
  },
37
63
  resolver: (step, context) => {
38
- // Extract column name from second [bracket] reference
64
+ // brackets[0] = Col, brackets[1] = Table
39
65
  const brackets = step.text.match(/\[([^\]]+)\]/g) || [];
40
- const columnName = brackets.length >= 2
66
+ const columnName = brackets[0]?.replace(/[\[\]]/g, '') || 'Unknown';
67
+ const tableName = brackets.length >= 2
41
68
  ? brackets[1].replace(/[\[\]]/g, '')
42
- : 'Unknown';
43
- const resolved = context.selectorResolver.resolveSelector(step.selectorRef, context.featureName, 'table', step.nth);
69
+ : brackets[0]?.replace(/[\[\]]/g, '') || '';
70
+ const resolved = context.selectorResolver.resolveSelector(tableName, context.featureName, 'table', step.nth);
71
+ const isGiven = isGivenContext(context);
44
72
  return {
45
73
  templateName: 'table-column-exists',
46
- data: { ...resolved, columnName },
47
- comment: `Assert ${step.selectorRef} table has ${columnName} column`,
74
+ data: { ...resolved, columnName, isGiven },
75
+ comment: `${isGiven ? 'Wait' : 'Assert'} ${columnName} column in ${tableName} table`,
48
76
  };
49
77
  },
50
78
  priority: 16,
51
79
  },
52
- // "User see [Users] table is empty"
80
+ // "User see [Table] table is empty"
53
81
  {
54
82
  name: 'table-is-empty',
55
83
  matcher: (step) => {
@@ -57,136 +85,104 @@ exports.tablePatterns = [
57
85
  },
58
86
  resolver: (step, context) => {
59
87
  const resolved = context.selectorResolver.resolveSelector(step.selectorRef, context.featureName, 'table', step.nth);
88
+ const isGiven = isGivenContext(context);
60
89
  return {
61
90
  templateName: 'table-empty',
62
- data: { ...resolved },
63
- comment: `Assert ${step.selectorRef} table is empty`,
91
+ data: { ...resolved, isGiven },
92
+ comment: `${isGiven ? 'Wait' : 'Assert'} ${step.selectorRef} table is empty`,
64
93
  };
65
94
  },
66
95
  priority: 16,
67
96
  },
68
- // "User see [Users] table row with {{name}} has [Status] with {{value}}"
97
+ // "User see [Ref] row in [Table] table with {{value}}" — row exists (enters row scope)
69
98
  {
70
- name: 'table-cell-by-filter',
99
+ name: 'table-row-exists',
71
100
  matcher: (step) => {
72
- return /\btable\s+row\s+with\b/i.test(step.text) &&
73
- /\bhas\b/i.test(step.text);
101
+ return step.elementType === 'row' &&
102
+ /\bin\b.*\btable\b/i.test(step.text) &&
103
+ /\bwith\b/i.test(step.text) &&
104
+ !!step.dataRef &&
105
+ !/\bis\s+hidden\b/i.test(step.text);
74
106
  },
75
107
  resolver: (step, context) => {
76
- // Extract: [Table] table row with {{filter}} has [Col] with {{value}}
108
+ // brackets[0] = Ref (row label), brackets[1] = Table
77
109
  const brackets = step.text.match(/\[([^\]]+)\]/g) || [];
78
- const tableName = brackets[0]?.replace(/[\[\]]/g, '') || '';
79
- const columnName = brackets.length >= 2
110
+ const rowLabel = brackets[0]?.replace(/[\[\]]/g, '') || '';
111
+ const tableName = brackets.length >= 2
80
112
  ? brackets[1].replace(/[\[\]]/g, '')
81
113
  : '';
82
- // Extract data refs: first is filter, second is cell value
83
- const dataRefs = step.text.match(/\{\{([^}]+)\}\}/g) || [];
84
- const filterRef = dataRefs[0]?.replace(/\{\{|\}\}/g, '') || '';
85
- const valueRef = dataRefs.length >= 2
86
- ? dataRefs[1].replace(/\{\{|\}\}/g, '')
87
- : '';
88
- const filterValue = filterRef
89
- ? context.dataResolver.resolveData(filterRef, context.featureName)
90
- : '';
91
- const cellValue = valueRef
92
- ? context.dataResolver.resolveData(valueRef, context.featureName)
93
- : '';
94
114
  const resolved = context.selectorResolver.resolveSelector(tableName, context.featureName, 'table', step.nth);
115
+ const filterValue = context.dataResolver.resolveData(step.dataRef, context.featureName);
116
+ const isGiven = isGivenContext(context);
95
117
  return {
96
- templateName: 'table-cell-by-filter',
97
- data: { ...resolved, filterValue, columnName, cellValue },
98
- comment: `Assert ${tableName} table row with ${filterRef} has ${columnName} = ${valueRef}`,
118
+ templateName: 'table-row-exists',
119
+ data: { ...resolved, filterValue, isGiven },
120
+ comment: `${isGiven ? 'Wait' : 'Assert'} ${rowLabel} row in ${tableName} table with ${step.dataRef}`,
99
121
  };
100
122
  },
101
123
  priority: 17,
102
124
  },
103
- // "User see [Users] table row 1 [Name] cell with {{value}}"
125
+ // "User see [Ref] row in [Table] table with {{value}} is hidden"
104
126
  {
105
- name: 'table-cell-by-index',
127
+ name: 'table-row-hidden',
106
128
  matcher: (step) => {
107
- return /\btable\s+row\s+\d+\b/i.test(step.text) &&
108
- /\bcell\b/i.test(step.text);
129
+ return step.elementType === 'row' &&
130
+ /\bin\b.*\btable\b/i.test(step.text) &&
131
+ /\bwith\b/i.test(step.text) &&
132
+ !!step.dataRef &&
133
+ /\bis\s+hidden\b/i.test(step.text);
109
134
  },
110
135
  resolver: (step, context) => {
136
+ // brackets[0] = Ref (row label), brackets[1] = Table
111
137
  const brackets = step.text.match(/\[([^\]]+)\]/g) || [];
112
- const tableName = brackets[0]?.replace(/[\[\]]/g, '') || '';
113
- const columnName = brackets.length >= 2
138
+ const rowLabel = brackets[0]?.replace(/[\[\]]/g, '') || '';
139
+ const tableName = brackets.length >= 2
114
140
  ? brackets[1].replace(/[\[\]]/g, '')
115
141
  : '';
116
- const rowMatch = step.text.match(/\brow\s+(\d+)\b/i);
117
- const rowIndex = rowMatch ? parseInt(rowMatch[1], 10) : 1;
118
- const cellValue = step.dataRef
119
- ? context.dataResolver.resolveData(step.dataRef, context.featureName)
120
- : '';
121
142
  const resolved = context.selectorResolver.resolveSelector(tableName, context.featureName, 'table', step.nth);
122
- return {
123
- templateName: 'table-cell-by-index',
124
- data: { ...resolved, rowIndex, columnName, cellValue },
125
- comment: `Assert ${tableName} table row ${rowIndex} ${columnName} cell = ${step.dataRef}`,
126
- };
127
- },
128
- priority: 17,
129
- },
130
- // "User see [Users] table row with {{name}}" (preferred)
131
- // Also accepts: "User see [Users] table has row with {{name}}" (backward compat)
132
- {
133
- name: 'table-row-exists',
134
- matcher: (step) => {
135
- return /\btable\s+(?:has\s+)?row\s+with\b/i.test(step.text) && !!step.dataRef;
136
- },
137
- resolver: (step, context) => {
138
- const resolved = context.selectorResolver.resolveSelector(step.selectorRef, context.featureName, 'table', step.nth);
139
- const filterValue = context.dataResolver.resolveData(step.dataRef, context.featureName);
140
- return {
141
- templateName: 'table-row-exists',
142
- data: { ...resolved, filterValue },
143
- comment: `Assert ${step.selectorRef} table has row with ${step.dataRef}`,
144
- };
145
- },
146
- priority: 18,
147
- },
148
- // "User see [Users] table has no row with {{name}}"
149
- {
150
- name: 'table-row-not-exists',
151
- matcher: (step) => {
152
- return /\btable\s+has\s+no\s+row\s+with\b/i.test(step.text) && !!step.dataRef;
153
- },
154
- resolver: (step, context) => {
155
- const resolved = context.selectorResolver.resolveSelector(step.selectorRef, context.featureName, 'table', step.nth);
156
143
  const filterValue = context.dataResolver.resolveData(step.dataRef, context.featureName);
144
+ const isGiven = isGivenContext(context);
157
145
  return {
158
146
  templateName: 'table-row-not-exists',
159
- data: { ...resolved, filterValue },
160
- comment: `Assert ${step.selectorRef} table has no row with ${step.dataRef}`,
147
+ data: { ...resolved, filterValue, isGiven },
148
+ comment: `${isGiven ? 'Wait' : 'Assert'} ${rowLabel} row in ${tableName} table is hidden`,
161
149
  };
162
150
  },
163
151
  priority: 19,
164
152
  },
165
- // "User click [Edit] in [Users] table row with {{name}}"
153
+ // "User click [Act] button in [Table] table with {{filter}}" — action in row
166
154
  {
167
155
  name: 'table-action-in-row',
168
156
  matcher: (step) => {
169
- return /\bin\b.*\btable\s+row\s+with\b/i.test(step.text);
157
+ return /\bin\b.*\btable\b/i.test(step.text) &&
158
+ /\bwith\b/i.test(step.text) &&
159
+ !!step.dataRef &&
160
+ step.elementType !== 'column' &&
161
+ step.elementType !== 'row' &&
162
+ step.elementType !== 'table';
170
163
  },
171
164
  resolver: (step, context) => {
165
+ // brackets[0] = Act (element name), brackets[1] = Table
172
166
  const brackets = step.text.match(/\[([^\]]+)\]/g) || [];
173
167
  const elementName = brackets[0]?.replace(/[\[\]]/g, '') || '';
174
168
  const tableName = brackets.length >= 2
175
169
  ? brackets[1].replace(/[\[\]]/g, '')
176
170
  : '';
177
- const dataRefs = step.text.match(/\{\{([^}]+)\}\}/g) || [];
178
- const filterRef = dataRefs[0]?.replace(/\{\{|\}\}/g, '') || '';
179
- const filterValue = filterRef
180
- ? context.dataResolver.resolveData(filterRef, context.featureName)
171
+ const filterValue = step.dataRef
172
+ ? context.dataResolver.resolveData(step.dataRef, context.featureName)
181
173
  : '';
182
174
  const tableResolved = context.selectorResolver.resolveSelector(tableName, context.featureName, 'table', 0);
183
- // Determine action
175
+ // Determine action from step text
184
176
  const actionMatch = step.text.match(/\b(click|check|uncheck)\b/i);
185
177
  const action = actionMatch ? actionMatch[1].toLowerCase() : 'click';
178
+ // Extract element type (word after [Act]) and map to ARIA role
179
+ const elementTypeMatch = step.text.match(/\]\s+([\w-]+)\s+in\b/i);
180
+ const elementType = elementTypeMatch ? elementTypeMatch[1].toLowerCase() : 'button';
181
+ const elementRole = typeToRole[elementType] || elementType;
186
182
  return {
187
183
  templateName: 'table-action-in-row',
188
- data: { ...tableResolved, elementName, filterValue, action },
189
- comment: `${action} ${elementName} in ${tableName} table row with ${filterRef}`,
184
+ data: { ...tableResolved, elementName, filterValue, action, elementRole },
185
+ comment: `${action} ${elementName} in ${tableName} table row with ${step.dataRef}`,
190
186
  };
191
187
  },
192
188
  priority: 17,
@@ -1 +1 @@
1
- {"version":3,"file":"table-patterns.js","sourceRoot":"","sources":["../../../../src/generators/test-generator/patterns/table-patterns.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIU,QAAA,aAAa,GAAkB;IAC1C,2DAA2D;IAC3D,8EAA8E;IAC9E;QACE,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,2BAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC3C,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBACjC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QACxB,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,IAAI,CAAC,WAAY,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAC1D,CAAC;YACF,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,OAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;YAEnF,OAAO;gBACL,YAAY,EAAE,iBAAiB;gBAC/B,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE;gBAC3C,OAAO,EAAE,UAAU,IAAI,CAAC,WAAW,cAAc,KAAK,OAAO;aAC9D,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,gEAAgE;IAChE,yEAAyE;IACzE;QACE,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAClC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,sDAAsD;YACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;YACxD,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC;gBACrC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gBACpC,CAAC,CAAC,SAAS,CAAC;YAEd,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,IAAI,CAAC,WAAY,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAC1D,CAAC;YAEF,OAAO;gBACL,YAAY,EAAE,qBAAqB;gBACnC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE;gBACjC,OAAO,EAAE,UAAU,IAAI,CAAC,WAAW,cAAc,UAAU,SAAS;aACrE,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,oCAAoC;IACpC;QACE,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,IAAI,CAAC,WAAY,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAC1D,CAAC;YAEF,OAAO;gBACL,YAAY,EAAE,aAAa;gBAC3B,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE;gBACrB,OAAO,EAAE,UAAU,IAAI,CAAC,WAAW,iBAAiB;aACrD,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,yEAAyE;IACzE;QACE,IAAI,EAAE,sBAAsB;QAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBACzC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,sEAAsE;YACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;YACxD,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;YAC5D,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC;gBACrC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gBACpC,CAAC,CAAC,EAAE,CAAC;YAEP,2DAA2D;YAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC;YAC3D,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;YAC/D,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC;gBACnC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;gBACvC,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,WAAW,GAAG,SAAS;gBAC3B,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC;gBAClE,CAAC,CAAC,EAAE,CAAC;YACP,MAAM,SAAS,GAAG,QAAQ;gBACxB,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC;gBACjE,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAClD,CAAC;YAEF,OAAO;gBACL,YAAY,EAAE,sBAAsB;gBACpC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE;gBACzD,OAAO,EAAE,UAAU,SAAS,mBAAmB,SAAS,QAAQ,UAAU,MAAM,QAAQ,EAAE;aAC3F,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,4DAA4D;IAC5D;QACE,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBACxC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;YACxD,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;YAC5D,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC;gBACrC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gBACpC,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;YACrD,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAE1D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO;gBAC5B,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC;gBACrE,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAClD,CAAC;YAEF,OAAO;gBACL,YAAY,EAAE,qBAAqB;gBACnC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE;gBACtD,OAAO,EAAE,UAAU,SAAS,cAAc,QAAQ,IAAI,UAAU,WAAW,IAAI,CAAC,OAAO,EAAE;aAC1F,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,yDAAyD;IACzD,iFAAiF;IACjF;QACE,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QAChF,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,IAAI,CAAC,WAAY,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAC1D,CAAC;YACF,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,OAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;YAEzF,OAAO;gBACL,YAAY,EAAE,kBAAkB;gBAChC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE;gBAClC,OAAO,EAAE,UAAU,IAAI,CAAC,WAAW,uBAAuB,IAAI,CAAC,OAAO,EAAE;aACzE,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,oDAAoD;IACpD;QACE,IAAI,EAAE,sBAAsB;QAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QAChF,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,IAAI,CAAC,WAAY,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAC1D,CAAC;YACF,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,OAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;YAEzF,OAAO;gBACL,YAAY,EAAE,sBAAsB;gBACpC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE;gBAClC,OAAO,EAAE,UAAU,IAAI,CAAC,WAAW,0BAA0B,IAAI,CAAC,OAAO,EAAE;aAC5E,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,yDAAyD;IACzD;QACE,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,iCAAiC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3D,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;YACxD,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;YAC9D,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC;gBACpC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gBACpC,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC;YAC3D,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;YAC/D,MAAM,WAAW,GAAG,SAAS;gBAC3B,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC;gBAClE,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CAC5D,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC,CAC3C,CAAC;YAEF,mBAAmB;YACnB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAEpE,OAAO;gBACL,YAAY,EAAE,qBAAqB;gBACnC,IAAI,EAAE,EAAE,GAAG,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE;gBAC5D,OAAO,EAAE,GAAG,MAAM,IAAI,WAAW,OAAO,SAAS,mBAAmB,SAAS,EAAE;aAChF,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;CACF,CAAC"}
1
+ {"version":3,"file":"table-patterns.js","sourceRoot":"","sources":["../../../../src/generators/test-generator/patterns/table-patterns.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;GAYG;;;AAIH,0DAA0D;AAC1D,SAAS,cAAc,CAAC,OAAuB;IAC7C,OAAO,OAAO,CAAC,gBAAgB,KAAK,OAAO,CAAC;AAC9C,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,GAA2B;IACzC,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE,KAAK;IACX,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;CACjB,CAAC;AAEW,QAAA,aAAa,GAAkB;IAC1C,iFAAiF;IACjF;QACE,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,IAAI,CAAC,WAAW,KAAK,OAAO;gBAC5B,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBACnC,CAAC,CAAC,IAAI,CAAC,OAAO;gBACd,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC3B,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC9B,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,IAAI,CAAC,WAAY,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAC1D,CAAC;YACF,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,OAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;YAEnF,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;YACxC,OAAO;gBACL,YAAY,EAAE,iBAAiB;gBAC/B,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE;gBACpD,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,cAAc,KAAK,OAAO;aACtF,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,2CAA2C;IAC3C;QACE,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAClC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC5B,CAAC,IAAI,CAAC,OAAO,CAAC;QACvB,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,yCAAyC;YACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;YACxD,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC;YACpE,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC;gBACpC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gBACpC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;YAE9C,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAClD,CAAC;YAEF,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;YACxC,OAAO;gBACL,YAAY,EAAE,qBAAqB;gBACnC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE;gBAC1C,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,UAAU,cAAc,SAAS,QAAQ;aACrF,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,oCAAoC;IACpC;QACE,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,IAAI,CAAC,WAAY,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAC1D,CAAC;YAEF,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;YACxC,OAAO;gBACL,YAAY,EAAE,aAAa;gBAC3B,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE;gBAC9B,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,iBAAiB;aAC7E,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,uFAAuF;IACvF;QACE,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,IAAI,CAAC,WAAW,KAAK,KAAK;gBAC1B,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBACpC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC3B,CAAC,CAAC,IAAI,CAAC,OAAO;gBACd,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,qDAAqD;YACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;YACxD,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;YAC3D,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC;gBACpC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gBACpC,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAClD,CAAC;YACF,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,OAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;YAEzF,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;YACxC,OAAO;gBACL,YAAY,EAAE,kBAAkB;gBAChC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE;gBAC3C,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,QAAQ,WAAW,SAAS,eAAe,IAAI,CAAC,OAAO,EAAE;aACrG,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,iEAAiE;IACjE;QACE,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,IAAI,CAAC,WAAW,KAAK,KAAK;gBAC1B,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBACpC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC3B,CAAC,CAAC,IAAI,CAAC,OAAO;gBACd,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,qDAAqD;YACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;YACxD,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;YAC3D,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC;gBACpC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gBACpC,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CACvD,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAClD,CAAC;YACF,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,OAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;YAEzF,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;YACxC,OAAO;gBACL,YAAY,EAAE,sBAAsB;gBACpC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE;gBAC3C,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,QAAQ,WAAW,SAAS,kBAAkB;aAC1F,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;IAED,6EAA6E;IAC7E;QACE,IAAI,EAAE,qBAAqB;QAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAChB,OAAO,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBACpC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC3B,CAAC,CAAC,IAAI,CAAC,OAAO;gBACd,IAAI,CAAC,WAAW,KAAK,QAAQ;gBAC7B,IAAI,CAAC,WAAW,KAAK,KAAK;gBAC1B,IAAI,CAAC,WAAW,KAAK,OAAO,CAAC;QACtC,CAAC;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC1B,wDAAwD;YACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;YACxD,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;YAC9D,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC;gBACpC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gBACpC,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO;gBAC9B,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC;gBACrE,CAAC,CAAC,EAAE,CAAC;YAEP,MAAM,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,eAAe,CAC5D,SAAS,EAAE,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC,CAC3C,CAAC;YAEF,kCAAkC;YAClC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAEpE,+DAA+D;YAC/D,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAClE,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;YACpF,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC;YAE3D,OAAO;gBACL,YAAY,EAAE,qBAAqB;gBACnC,IAAI,EAAE,EAAE,GAAG,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE;gBACzE,OAAO,EAAE,GAAG,MAAM,IAAI,WAAW,OAAO,SAAS,mBAAmB,IAAI,CAAC,OAAO,EAAE;aACnF,CAAC;QACJ,CAAC;QACD,QAAQ,EAAE,EAAE;KACb;CACF,CAAC"}
@@ -37,6 +37,8 @@ export interface PatternContext {
37
37
  screenName?: string;
38
38
  featurePath?: string;
39
39
  scenarioSteps?: ParsedStep[];
40
+ /** Effective Gherkin keyword (Given/When/Then), resolved from And/But */
41
+ effectiveKeyword?: string;
40
42
  }
41
43
  /**
42
44
  * Step pattern definition
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/patterns/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC;AAEtE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,KAAK,UAAU,CAAC;AAEzF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,KAAK,gBAAgB,CAAC;AAE9F;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,CAAC;IACjD,cAAc,EAAE,GAAG,CAAC;IACpB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,EAAE,YAAY,CAAC;IAC3B,aAAa,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,MAAM,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,UAAU,EAAE,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/patterns/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC;AAEtE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,KAAK,UAAU,CAAC;AAEzF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,KAAK,gBAAgB,CAAC;AAE9F;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,CAAC;IACjD,cAAc,EAAE,GAAG,CAAC;IACpB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,YAAY,EAAE,YAAY,CAAC;IAC3B,aAAa,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,MAAM,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,UAAU,EAAE,CAAC;IAC7B,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
@@ -22,6 +22,11 @@ export declare class StepMapper {
22
22
  private currentScenarioSteps?;
23
23
  private inDialogScope;
24
24
  private inFrameScope;
25
+ /** Tracks the last primary keyword (Given/When/Then) for resolving And/But */
26
+ private lastPrimaryKeyword;
27
+ /** Row scope: when active, column assertions are scoped to this row */
28
+ private inRowScope;
29
+ private rowScopeTable;
25
30
  constructor(options?: {
26
31
  verbose?: boolean;
27
32
  baseURL?: string;
@@ -46,6 +51,14 @@ export declare class StepMapper {
46
51
  * Uses pattern registry first, falls back to AI if enabled
47
52
  */
48
53
  mapStep(step: ParsedStep): MappedStep | Promise<MappedStep>;
54
+ /**
55
+ * Generate column assertion scoped to the current row.
56
+ * Uses columns config for exact cell targeting (nth), or filter fallback.
57
+ *
58
+ * With columns: await expect(tableRow.getByRole('cell').nth(index)).toHaveText('value');
59
+ * Without: await expect(tableRow.getByRole('cell').filter({ hasText: 'value' })).toBeVisible();
60
+ */
61
+ private generateRowScopedColumnAssertion;
49
62
  /**
50
63
  * Create pattern context for generators
51
64
  */
@@ -1 +1 @@
1
- {"version":3,"file":"step-mapper.d.ts","sourceRoot":"","sources":["../../../src/generators/test-generator/step-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAO/C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,oBAAoB,CAAC,CAAe;IAC5C,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,YAAY,CAAkB;gBAE1B,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO;IAkBlI;;OAEG;IACH,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAMlE;;OAEG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAM1C;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,IAAI;IAQ7C;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IA2F3D;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAmB7B"}
1
+ {"version":3,"file":"step-mapper.d.ts","sourceRoot":"","sources":["../../../src/generators/test-generator/step-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAO/C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,oBAAoB,CAAC,CAAe;IAC5C,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,YAAY,CAAkB;IACtC,8EAA8E;IAC9E,OAAO,CAAC,kBAAkB,CAAmB;IAC7C,uEAAuE;IACvE,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,aAAa,CAAc;gBAEvB,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO;IAkBlI;;OAEG;IACH,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAMlE;;OAEG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAM1C;;OAEG;IACH,kBAAkB,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,IAAI;IAW7C;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAmH3D;;;;;;OAMG;IACH,OAAO,CAAC,gCAAgC;IA8CxC;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAoB7B"}
@@ -49,6 +49,11 @@ class StepMapper {
49
49
  this.verbose = false;
50
50
  this.inDialogScope = false;
51
51
  this.inFrameScope = false;
52
+ /** Tracks the last primary keyword (Given/When/Then) for resolving And/But */
53
+ this.lastPrimaryKeyword = 'Given';
54
+ /** Row scope: when active, column assertions are scoped to this row */
55
+ this.inRowScope = false;
56
+ this.rowScopeTable = '';
52
57
  this.verbose = options.verbose ?? false;
53
58
  this.baseURL = options.baseURL || null; // null means path-only navigation
54
59
  this.featureName = options.featureName;
@@ -88,6 +93,9 @@ class StepMapper {
88
93
  // Reset dialog and frame scope at the start of each new scenario
89
94
  this.inDialogScope = false;
90
95
  this.inFrameScope = false;
96
+ this.inRowScope = false;
97
+ this.rowScopeTable = '';
98
+ this.lastPrimaryKeyword = 'Given';
91
99
  this.templateEngine.resetBaseContext();
92
100
  }
93
101
  /**
@@ -96,6 +104,11 @@ class StepMapper {
96
104
  */
97
105
  mapStep(step) {
98
106
  this.stepCounter++;
107
+ // Track effective keyword: And/But inherit from previous Given/When/Then
108
+ const keyword = step.keyword.trim();
109
+ if (keyword === 'Given' || keyword === 'When' || keyword === 'Then') {
110
+ this.lastPrimaryKeyword = keyword;
111
+ }
99
112
  // Frame scope directives — intercept before pattern matching
100
113
  if (/\bswitch(?:es)?\s+to\b/i.test(step.text) &&
101
114
  (step.elementType === 'frame' || step.elementType === 'iframe')) {
@@ -164,10 +177,26 @@ class StepMapper {
164
177
  this.templateEngine.setBaseContext(contextVars);
165
178
  return { code: '', comment: `Enter dialog scope${step.selectorRef ? ': ' + step.selectorRef : ''}` };
166
179
  }
180
+ // Row-scoped column assertion: "User see [Col] column with {{value}}"
181
+ // Must be checked BEFORE pattern matching (like dialog/frame scope)
182
+ if (this.inRowScope && step.elementType === 'column' &&
183
+ !!step.dataRef && /\bwith\b/i.test(step.text) &&
184
+ !/\btable\b/i.test(step.text)) {
185
+ return this.generateRowScopedColumnAssertion(step);
186
+ }
167
187
  // Try pattern registry first
168
188
  const context = this.createPatternContext();
169
189
  const mappedStep = this.patternRegistry.generateStep(step, context);
170
190
  if (mappedStep) {
191
+ // Enter row scope when a row-in-table step is matched
192
+ if (step.elementType === 'row' && /\bin\b.*\btable\b/i.test(step.text) &&
193
+ /\bwith\b/i.test(step.text) && !/\bis\s+hidden\b/i.test(step.text)) {
194
+ const brackets = step.text.match(/\[([^\]]+)\]/g) || [];
195
+ this.inRowScope = true;
196
+ this.rowScopeTable = brackets.length >= 2
197
+ ? brackets[1].replace(/[\[\]]/g, '')
198
+ : '';
199
+ }
171
200
  if (this.verbose) {
172
201
  console.log(` ✓ Pattern matched: ${step.text.substring(0, 50)}...`);
173
202
  }
@@ -179,6 +208,56 @@ class StepMapper {
179
208
  comment: `Unrecognized step pattern: ${step.text}`,
180
209
  };
181
210
  }
211
+ /**
212
+ * Generate column assertion scoped to the current row.
213
+ * Uses columns config for exact cell targeting (nth), or filter fallback.
214
+ *
215
+ * With columns: await expect(tableRow.getByRole('cell').nth(index)).toHaveText('value');
216
+ * Without: await expect(tableRow.getByRole('cell').filter({ hasText: 'value' })).toBeVisible();
217
+ */
218
+ generateRowScopedColumnAssertion(step) {
219
+ const columnRef = step.selectorRef || '';
220
+ const cellValue = step.dataRef
221
+ ? this.dataResolver.resolveData(step.dataRef, this.featureName)
222
+ : '';
223
+ // Try to find column index from table's columns config
224
+ let columnIndex;
225
+ if (this.rowScopeTable) {
226
+ try {
227
+ const tableResolved = this.selectorResolver.resolveSelector(this.rowScopeTable, this.featureName, 'table', 0);
228
+ const columnKey = columnRef.toLowerCase().normalize('NFC');
229
+ columnIndex = tableResolved.columns?.[columnKey]?.index;
230
+ }
231
+ catch {
232
+ // Table not found — fallback to filter
233
+ }
234
+ }
235
+ const isGiven = this.lastPrimaryKeyword === 'Given';
236
+ const escapedValue = cellValue.replace(/'/g, "\\'");
237
+ let code;
238
+ if (columnIndex !== undefined) {
239
+ // Exact cell: nth(index) + toHaveText
240
+ if (isGiven) {
241
+ code = `await expect(tableRow.getByRole('cell').nth(${columnIndex})).toHaveText('${escapedValue}');`;
242
+ }
243
+ else {
244
+ code = `await expect(tableRow.getByRole('cell').nth(${columnIndex})).toHaveText('${escapedValue}');`;
245
+ }
246
+ }
247
+ else {
248
+ // Fallback: filter by text
249
+ if (isGiven) {
250
+ code = `await tableRow.getByRole('cell').filter({ hasText: '${escapedValue}' }).waitFor();`;
251
+ }
252
+ else {
253
+ code = `await expect(tableRow.getByRole('cell').filter({ hasText: '${escapedValue}' })).toBeVisible();`;
254
+ }
255
+ }
256
+ return {
257
+ code,
258
+ comment: `${isGiven ? 'Wait' : 'Assert'} ${columnRef} column = ${step.dataRef}`,
259
+ };
260
+ }
182
261
  /**
183
262
  * Create pattern context for generators
184
263
  */
@@ -198,6 +277,7 @@ class StepMapper {
198
277
  screenName: this.screenName,
199
278
  featurePath: this.featurePath, // Pass feature path to patterns
200
279
  scenarioSteps: this.currentScenarioSteps || [], // Pass scenario steps for path variables
280
+ effectiveKeyword: this.lastPrimaryKeyword,
201
281
  };
202
282
  }
203
283
  }