@sun-asterisk/sungen 2.1.0 → 2.2.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 (173) hide show
  1. package/README.md +78 -51
  2. package/dist/cli/index.js +1 -1
  3. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +6 -1
  4. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
  5. package/dist/generators/test-generator/adapters/playwright/templates/scenario.hbs +0 -4
  6. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/drag-action.hbs +1 -0
  7. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +11 -0
  8. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -1
  9. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +1 -1
  10. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/toggle-action.hbs +1 -0
  11. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +0 -1
  12. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +0 -1
  13. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +0 -1
  14. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +0 -1
  15. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +0 -1
  16. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-filter-assertion.hbs +0 -1
  17. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +0 -1
  18. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +0 -1
  19. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +0 -1
  20. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +0 -1
  21. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +0 -1
  22. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +0 -1
  23. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-dialog-heading-assertion.hbs +0 -1
  24. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-filter-assertion.hbs +0 -1
  25. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +0 -1
  26. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +0 -1
  27. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/is-hidden-assertion.hbs +0 -1
  28. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +0 -1
  29. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/list-item-count-assertion.hbs +0 -1
  30. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/loading-assertion.hbs +1 -0
  31. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +0 -1
  32. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/page-assertion.hbs +0 -1
  33. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +1 -0
  34. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/sorted-assertion.hbs +1 -0
  35. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +0 -1
  36. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +0 -1
  37. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +0 -1
  38. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +0 -1
  39. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +0 -1
  40. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +0 -1
  41. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +0 -1
  42. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +0 -1
  43. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-dialog-heading-assertion.hbs +0 -1
  44. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-locator-variable-assertion.hbs +0 -1
  45. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +0 -1
  46. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +0 -1
  47. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +0 -1
  48. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -1
  49. package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +25 -0
  50. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  51. package/dist/generators/test-generator/code-generator.js +41 -3
  52. package/dist/generators/test-generator/code-generator.js.map +1 -1
  53. package/dist/generators/test-generator/patterns/assertion-patterns.d.ts.map +1 -1
  54. package/dist/generators/test-generator/patterns/assertion-patterns.js +58 -6
  55. package/dist/generators/test-generator/patterns/assertion-patterns.js.map +1 -1
  56. package/dist/generators/test-generator/patterns/form-patterns.js +3 -3
  57. package/dist/generators/test-generator/patterns/form-patterns.js.map +1 -1
  58. package/dist/generators/test-generator/patterns/interaction-patterns.d.ts.map +1 -1
  59. package/dist/generators/test-generator/patterns/interaction-patterns.js +86 -1
  60. package/dist/generators/test-generator/patterns/interaction-patterns.js.map +1 -1
  61. package/dist/generators/test-generator/patterns/navigation-patterns.js +2 -2
  62. package/dist/generators/test-generator/patterns/navigation-patterns.js.map +1 -1
  63. package/dist/generators/test-generator/template-engine.d.ts +6 -0
  64. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  65. package/dist/generators/test-generator/template-engine.js +1 -0
  66. package/dist/generators/test-generator/template-engine.js.map +1 -1
  67. package/dist/generators/test-generator/utils/selector-resolver.d.ts +15 -8
  68. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  69. package/dist/generators/test-generator/utils/selector-resolver.js +26 -197
  70. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  71. package/dist/orchestrator/project-initializer.d.ts +4 -0
  72. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  73. package/dist/orchestrator/project-initializer.js +49 -4
  74. package/dist/orchestrator/project-initializer.js.map +1 -1
  75. package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +4 -3
  76. package/dist/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md +11 -46
  77. package/dist/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +11 -46
  78. package/dist/orchestrator/templates/ai-instructions/claude-config.md +9 -8
  79. package/dist/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +11 -0
  80. package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +8 -4
  81. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +206 -0
  82. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +19 -21
  83. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +256 -0
  84. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +14 -17
  85. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-make-tc.md +16 -47
  86. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +16 -47
  87. package/dist/orchestrator/templates/ai-instructions/copilot-config.md +8 -7
  88. package/dist/orchestrator/templates/ai-instructions/{copilot-skill-error-mapping.md → github-skill-sungen-error-mapping.md} +14 -3
  89. package/{src/orchestrator/templates/ai-instructions/copilot-skill-gherkin-syntax.md → dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md} +11 -7
  90. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +206 -0
  91. package/dist/orchestrator/templates/ai-instructions/{copilot-skill-selector-keys.md → github-skill-sungen-selector-keys.md} +22 -24
  92. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +256 -0
  93. package/dist/orchestrator/templates/playwright.config.d.ts.map +1 -1
  94. package/dist/orchestrator/templates/playwright.config.js +3 -1
  95. package/dist/orchestrator/templates/playwright.config.js.map +1 -1
  96. package/dist/orchestrator/templates/playwright.config.ts +3 -1
  97. package/dist/orchestrator/templates/readme.md +78 -101
  98. package/package.json +1 -1
  99. package/src/cli/index.ts +1 -1
  100. package/src/generators/test-generator/adapters/adapter-interface.ts +7 -1
  101. package/src/generators/test-generator/adapters/playwright/templates/scenario.hbs +0 -4
  102. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/drag-action.hbs +1 -0
  103. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +11 -0
  104. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -1
  105. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +1 -1
  106. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/toggle-action.hbs +1 -0
  107. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +0 -1
  108. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +0 -1
  109. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +0 -1
  110. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +0 -1
  111. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +0 -1
  112. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-filter-assertion.hbs +0 -1
  113. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +0 -1
  114. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +0 -1
  115. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +0 -1
  116. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +0 -1
  117. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +0 -1
  118. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +0 -1
  119. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-dialog-heading-assertion.hbs +0 -1
  120. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-filter-assertion.hbs +0 -1
  121. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +0 -1
  122. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +0 -1
  123. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/is-hidden-assertion.hbs +0 -1
  124. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +0 -1
  125. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/list-item-count-assertion.hbs +0 -1
  126. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/loading-assertion.hbs +1 -0
  127. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +0 -1
  128. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/page-assertion.hbs +0 -1
  129. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +1 -0
  130. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/sorted-assertion.hbs +1 -0
  131. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +0 -1
  132. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +0 -1
  133. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +0 -1
  134. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +0 -1
  135. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +0 -1
  136. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +0 -1
  137. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +0 -1
  138. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +0 -1
  139. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-dialog-heading-assertion.hbs +0 -1
  140. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-locator-variable-assertion.hbs +0 -1
  141. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +0 -1
  142. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +0 -1
  143. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +0 -1
  144. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -1
  145. package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +25 -0
  146. package/src/generators/test-generator/code-generator.ts +50 -8
  147. package/src/generators/test-generator/patterns/assertion-patterns.ts +62 -6
  148. package/src/generators/test-generator/patterns/form-patterns.ts +3 -3
  149. package/src/generators/test-generator/patterns/interaction-patterns.ts +93 -1
  150. package/src/generators/test-generator/patterns/navigation-patterns.ts +2 -2
  151. package/src/generators/test-generator/template-engine.ts +4 -0
  152. package/src/generators/test-generator/utils/selector-resolver.ts +27 -204
  153. package/src/orchestrator/project-initializer.ts +60 -5
  154. package/src/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +4 -3
  155. package/src/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md +11 -46
  156. package/src/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +11 -46
  157. package/src/orchestrator/templates/ai-instructions/claude-config.md +9 -8
  158. package/src/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +11 -0
  159. package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +8 -4
  160. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +206 -0
  161. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +19 -21
  162. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +256 -0
  163. package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +14 -17
  164. package/src/orchestrator/templates/ai-instructions/copilot-cmd-make-tc.md +16 -47
  165. package/src/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +16 -47
  166. package/src/orchestrator/templates/ai-instructions/copilot-config.md +8 -7
  167. package/src/orchestrator/templates/ai-instructions/{copilot-skill-error-mapping.md → github-skill-sungen-error-mapping.md} +14 -3
  168. package/{dist/orchestrator/templates/ai-instructions/copilot-skill-gherkin-syntax.md → src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md} +11 -7
  169. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +206 -0
  170. package/src/orchestrator/templates/ai-instructions/{copilot-skill-selector-keys.md → github-skill-sungen-selector-keys.md} +22 -24
  171. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +256 -0
  172. package/src/orchestrator/templates/playwright.config.ts +3 -1
  173. package/src/orchestrator/templates/readme.md +78 -101
@@ -0,0 +1,206 @@
1
+ ---
2
+ name: sungen-selector-fix
3
+ description: 'Selector generation and fixing strategy for make-test — explores live page, generates selectors.yaml, auto-fixes on test failure. Use this when generating selectors.yaml from a live page or fixing failing selectors.'
4
+ user-invocable: false
5
+ ---
6
+
7
+ ## Selector Generation & Fix Strategy
8
+
9
+ ### When to Generate Selectors
10
+
11
+ Selectors are generated during `/sungen:make-test`, NOT during `/sungen:make-tc`. This ensures selectors are always validated against the live page.
12
+
13
+ ---
14
+
15
+ ### Step 1: Authenticate
16
+
17
+ 1. Read `baseURL` from `playwright.config.ts`
18
+ 2. `browser_navigate` to `baseURL`
19
+ 3. If redirected to login, ask the user to log in manually:
20
+ > "This page requires login. Please log in using the browser. Confirm when you're done."
21
+ 4. Once confirmed, `browser_navigate` to the target page and take `browser_snapshot`
22
+
23
+ **Never use `sungen makeauth`.** Always let the user log in manually via the MCP browser.
24
+ **Never use `browser_evaluate` to inject cookies or localStorage.** Use `browser_evaluate` only to read DOM info (e.g. detect `data-testid` attributes, check element properties).
25
+
26
+ ---
27
+
28
+ ### Step 2: Build an Element Catalog from the Snapshot
29
+
30
+ **Never guess or infer selector names from Gherkin labels. Always copy exact values from the snapshot.**
31
+
32
+ After taking the snapshot, mentally catalog ALL accessible elements:
33
+
34
+ - **Buttons**: list each `button "..."` with its exact accessible name
35
+ - **Links**: list each `link "..."` with its exact accessible name
36
+ - **Headings**: list each `heading "..."` with level and exact name
37
+ - **Inputs**: list each `textbox`, `searchbox`, `combobox` — note if it has an accessible name or not
38
+ - **Regions/landmarks**: `region "..."`, `navigation "..."`, `dialog "..."`
39
+ - **Images**: `img "..."` with accessible name (alt text)
40
+
41
+ Then check for `data-testid` attributes (more stable than accessible names):
42
+ ```js
43
+ // browser_evaluate — read-only, safe:
44
+ Array.from(document.querySelectorAll('[data-testid]'))
45
+ .map(e => ({ testid: e.dataset.testid, tag: e.tagName, text: e.textContent.trim().slice(0, 60) }))
46
+ ```
47
+
48
+ ---
49
+
50
+ ### Step 3: Map Gherkin Labels → Selectors
51
+
52
+ For each `[Reference]` in the `.feature` file, find the best match in the element catalog.
53
+
54
+ #### Selector priority (use first applicable)
55
+
56
+ | Priority | type | When to use |
57
+ |---|---|---|
58
+ | 1 | `testid` | `data-testid` attribute exists |
59
+ | 2 | `role` + exact name | Interactive elements (button, link, heading) |
60
+ | 3 | `placeholder` | Input with visible placeholder text |
61
+ | 4 | `label` | Form field with `<label>` association |
62
+ | 5 | `locator` (CSS / aria attr) | No accessible name (e.g. bare searchbox, icon button) |
63
+ | 6 | `text` | Static text only — avoid for dynamic/data-driven content |
64
+
65
+ #### The exact name rule
66
+
67
+ Copy the accessible name **character-for-character** from the snapshot. Do not transform, translate, or infer from the Gherkin label.
68
+
69
+ ```yaml
70
+ # BAD — name inferred from Gherkin label, not from snapshot
71
+ notification bell:
72
+ type: 'role'
73
+ value: 'button'
74
+ name: 'Notification Bell'
75
+
76
+ # GOOD — exact name from snapshot: button "Notifications"
77
+ notification bell:
78
+ type: 'role'
79
+ value: 'button'
80
+ name: 'Notifications'
81
+ ```
82
+
83
+ #### When there is no accessible name
84
+
85
+ Use a `locator` with a CSS attribute selector or ARIA role:
86
+
87
+ ```yaml
88
+ search field:
89
+ type: 'locator'
90
+ value: '[role="searchbox"]'
91
+
92
+ icon button:
93
+ type: 'locator'
94
+ value: '[aria-label="Close"]'
95
+ ```
96
+
97
+ ---
98
+
99
+ ### Step 4: Handle Dynamic Content
100
+
101
+ For elements whose text changes between test runs (list items, card data, user-generated content, timestamps):
102
+
103
+ **Never use `type: text` with a specific value** — it breaks when data changes.
104
+
105
+ ```yaml
106
+ # BAD — specific text breaks when data changes
107
+ card title:
108
+ type: 'text'
109
+ value: 'Some specific title'
110
+
111
+ # GOOD — structural: first heading inside a card container
112
+ card title:
113
+ type: 'role'
114
+ value: 'heading'
115
+ nth: 1 # skip page-level headings, get first card heading
116
+
117
+ # BEST — if the app has data-testid
118
+ card title:
119
+ type: 'testid'
120
+ value: 'card-title'
121
+ ```
122
+
123
+ To determine the correct `nth` offset, count how many matching elements appear before the target in the snapshot (e.g. how many headings come before the first card heading).
124
+
125
+ ---
126
+
127
+ ### Step 5: Handle SPA / Client-side Routing
128
+
129
+ Many modern apps (Next.js, Nuxt, SvelteKit, etc.) return the same HTML shell for all URLs and route client-side. `domcontentloaded` fires on the shell before the target page renders.
130
+
131
+ **Symptom**: Tests see a different page than expected (e.g. home page instead of `/dashboard`).
132
+
133
+ **Fix in the feature file**: Add an explicit assertion after navigation to confirm the correct page has loaded before proceeding:
134
+
135
+ ```gherkin
136
+ Scenario: VP-UI-001 Some test
137
+ Given User is on [Dashboard] page
138
+ Then User see [Dashboard Title] heading is visible ← confirms page loaded
139
+ When User click [Some Button] button
140
+ ...
141
+ ```
142
+
143
+ The "page loaded" check should use a **stable, always-visible element** on that specific page — typically the main page heading.
144
+
145
+ ---
146
+
147
+ ### Step 6: Handle Multiple Matches (strict mode)
148
+
149
+ When an element appears more than once (e.g. desktop + mobile nav, repeated list items), add `nth`:
150
+
151
+ ```yaml
152
+ nav link:
153
+ type: 'role'
154
+ value: 'link'
155
+ name: 'Dashboard'
156
+ nth: 0 # first occurrence (desktop nav)
157
+ ```
158
+
159
+ Use `nth: 0` for the first match of dynamic/repeated elements.
160
+
161
+ ---
162
+
163
+ ### Auto-Infer (skip YAML entry)
164
+
165
+ Many elements don't need a YAML entry — sungen auto-infers from the Gherkin label:
166
+
167
+ | Gherkin | Auto-inferred locator |
168
+ |---|---|
169
+ | `[Submit] button` | `getByRole('button', { name: 'Submit' })` |
170
+ | `[Home] link` | `getByRole('link', { name: 'Home' })` |
171
+ | `[Welcome] heading` | `getByRole('heading', { name: 'Welcome' })` |
172
+ | `[Email] field` | `getByPlaceholder('Email')` |
173
+ | `[Success] text` | `getByText('Success')` |
174
+
175
+ **Only add a YAML entry when auto-infer won't work:**
176
+ - The accessible name differs from the Gherkin label
177
+ - Needs `nth` to disambiguate
178
+ - Needs `testid` or CSS locator
179
+ - Is dynamic content (needs structural selector)
180
+ - Is a bare input with no label or placeholder
181
+
182
+ ---
183
+
184
+ ### Fix Loop on Test Failure
185
+
186
+ ```
187
+ attempt = 0
188
+ while attempt < 5:
189
+ compile → run test
190
+ if pass → done
191
+ read error-context.md in test-results/ → check exact snapshot state at failure time
192
+ fix selectors.yaml or test-data.yaml
193
+ recompile → attempt++
194
+ if still failing → ask user about direct .spec.ts fix
195
+ ```
196
+
197
+ **Always read the error context snapshot first** — it shows the exact page state when the test failed, which is more reliable than re-navigating with MCP.
198
+
199
+ ---
200
+
201
+ ### Key Rules (from sungen-selector-keys)
202
+
203
+ - `[Reference]` → lowercase, keep Unicode: `[Search Content]` → `search content:`, `[Thời gian]` → `thời gian:`
204
+ - Keys use **spaces** (not dots) as word separators
205
+ - Same label, different element types → add `--type` suffix
206
+ - Same label, nth occurrence → add `--N` suffix
@@ -1,33 +1,31 @@
1
1
  ---
2
- description: 'Rules for generating correct YAML selector keys from Gherkin [Reference] names. Referenced by other sungen prompts when creating or fixing selectors.yaml files.'
3
- mode: 'agent'
4
- tools: []
2
+ name: sungen-selector-keys
3
+ description: 'Rules for generating correct YAML selector keys from Gherkin [Reference] names. Use this when creating or fixing selectors.yaml files with YAML key generation.'
4
+ user-invocable: false
5
5
  ---
6
6
 
7
7
  ## Key Generation: `[Reference]` → YAML key
8
8
 
9
- Transform: Vietnamese/Japanese ASCII lowercase remove special chars spaces to dots.
9
+ Copy the text from `[Reference]` as-is, then lowercase. Unicode characters (Vietnamese, Japanese, etc.) are preserved.
10
10
 
11
11
  ```
12
12
  [Submit] → submit
13
- [Search Content] → search.content
14
- [User's Profile] → users.profile
15
- [Thời gian] → thoi.gian
16
- [Địa điểm] → dia.diem
17
- [ログイン] → roguin
18
- [パスワード] → pasuwaado
19
- [Page 2] → page.2
20
- [Kudos Detail Modal] → kudos.detail.modal
13
+ [Search Content] → search content
14
+ [User's Profile] → user's profile
15
+ [Thời gian] → thời gian
16
+ [Địa điểm] → địa điểm
17
+ [ログイン] → ログイン
18
+ [パスワード] → パスワード
19
+ [Page 2] → page 2
20
+ [Kudos Detail Modal] → kudos detail modal
21
21
  ```
22
22
 
23
23
  **Rules:**
24
- 1. Remove Vietnamese diacritics: `ằắẳẵặ` → `a`, `đ` → `d`, etc.
25
- 2. Convert Japanese Hiragana/Katakana to Romaji
26
- 3. Lowercase everything
27
- 4. `'s` `s` (apostrophe-s becomes just s)
28
- 5. Remove all special chars except spaces
29
- 6. Trim, then spaces → dots
30
- 7. **NEVER use spaces, underscores, or uppercase in YAML keys**
24
+ 1. Lowercase the text
25
+ 2. Trim leading/trailing whitespace
26
+ 3. Collapse multiple spaces into one
27
+ 4. **Keep all Unicode characters as-is** (Vietnamese diacritics, Japanese, etc.)
28
+ 5. **Keys use spaces** (not dots) as word separators
31
29
 
32
30
  ## Type-Suffixed Keys
33
31
 
@@ -35,12 +33,12 @@ When the same label is used for different element types, add `--type` suffix:
35
33
 
36
34
  ```yaml
37
35
  # [Add Campaign] button AND [Add Campaign] text
38
- add.campaign--button:
36
+ add campaign--button:
39
37
  type: 'role'
40
38
  value: 'button'
41
39
  name: 'Add Campaign'
42
40
 
43
- add.campaign--text:
41
+ add campaign--text:
44
42
  type: 'text'
45
43
  value: 'Add Campaign'
46
44
  ```
@@ -61,11 +59,11 @@ Type aliases (normalized automatically):
61
59
  When targeting a specific occurrence by index, add `--N` suffix:
62
60
 
63
61
  ```yaml
64
- # [Send Thank You] button 3
65
- hay.gui.loi.cam.on--3:
62
+ # [Gửi lời cảm ơn] button 3
63
+ gửi lời cảm ơn--3:
66
64
  type: 'role'
67
65
  value: 'button'
68
- name: 'Send Thank You'
66
+ name: 'Gửi lời cảm ơn'
69
67
  ```
70
68
 
71
69
  ## Lookup Priority
@@ -0,0 +1,256 @@
1
+ ---
2
+ name: sungen-tc-generation
3
+ description: 'Exhaustive test case generation strategy — section-focused, 20+ scenarios per viewpoint per section, Gherkin + test-data only, no selectors. Use this when creating test cases for a screen with Gherkin scenarios.'
4
+ user-invocable: false
5
+ ---
6
+
7
+ ## Test Case Generation Strategy
8
+
9
+ ### Goal
10
+
11
+ Generate **focused, high-quality test cases per screen section** with **at least 20 scenarios per viewpoint category**. Output only `.feature` and `test-data.yaml` — selectors are deferred to `/sungen:make-test`.
12
+
13
+ ### Update Mode (existing test cases)
14
+
15
+ When the `.feature` file already has scenarios, read it first and summarize what exists:
16
+
17
+ > This screen already has **57 scenarios**:
18
+ > - Section: Filters & Search — 22 scenarios (UI: 7, VAL: 8, LOGIC: 5, SEC: 2)
19
+ > - Section: User Table — 23 scenarios (UI: 13, LOGIC: 11, SEC: 3)
20
+ > - Section: Pagination — 12 scenarios (UI: 4, LOGIC: 6, SEC: 2)
21
+ >
22
+ > What would you like to do?
23
+ > 1. **Add new sections** — keep existing, add tests for uncovered sections
24
+ > 2. **Add viewpoints to existing sections** — e.g., more edge cases, more security tests
25
+ > 3. **Replace all** — start fresh
26
+
27
+ For options 1 and 2:
28
+ - Read the existing scenarios to understand current coverage and the highest `VP-<CAT>-<NNN>` number
29
+ - Continue numbering from the next available number (e.g., if last is `VP-UI-024`, start at `VP-UI-025`)
30
+ - **Append** new scenarios to the end of the relevant section — never modify or delete existing scenarios
31
+ - Merge new test-data variables into `test-data.yaml` without overwriting existing ones
32
+
33
+ For option 3:
34
+ - Overwrite both `.feature` and `test-data.yaml` completely
35
+
36
+ ### Page Exploration & Auth
37
+
38
+ Use Playwright MCP to explore the live page. If the page requires authentication:
39
+ 1. `browser_navigate` to `baseURL` (from `playwright.config.ts`)
40
+ 2. If redirected to login, ask the user to log in manually:
41
+ > "This page requires login. Please log in using the browser. Confirm when you're done."
42
+ 3. Once confirmed, `browser_navigate` to the target page and take `browser_snapshot`
43
+
44
+ **Never use `sungen makeauth`.** Always let the user log in manually via the MCP browser.
45
+
46
+ ### Single Screen Focus
47
+
48
+ **One screen = one URL path.** Only generate test cases for elements visible on the target page.
49
+
50
+ - Navigate to the target screen path — do NOT explore sibling paths (e.g., testing `/admin/users` should not scan `/admin/review`)
51
+ - Take ONE snapshot of the target page — do not click links to navigate away
52
+ - If a link goes to a different path, test only that the link is visible and clickable — the destination page is a SEPARATE screen
53
+ - If a modal/dialog opens on the same page, that IS part of this screen
54
+ - Each screen gets its own `qa/screens/<name>/` directory — never mix screens
55
+
56
+ #### Detail screens with dynamic IDs
57
+
58
+ For screens like `/admin/users/:id` or `/products/:slug`:
59
+ 1. Navigate to the **list page** first via MCP browser to find a real record ID
60
+ 2. Use that ID in the page selector value
61
+ 3. Use `User is on [X] page` — sungen resolves the path from the selector
62
+
63
+ ```yaml
64
+ # selectors.yaml — full path with real ID (generated during make-test)
65
+ user detail:
66
+ type: 'page'
67
+ value: '/admin/users/de42d800-0f5a-490e-9dcf-344fedbd34a5'
68
+ ```
69
+
70
+ ```gherkin
71
+ Scenario: VP-UI-001 User detail displays name
72
+ Given User is on [User Detail] page
73
+ And User wait for [User Name] heading is visible
74
+ Then User see [User Name] heading with {{user_name}}
75
+ ```
76
+
77
+ Note: the selector uses a hardcoded ID from the live page. If the record is deleted, update the ID in `selectors.yaml`.
78
+
79
+ ### Section-Focused Approach
80
+
81
+ After exploring the page, identify distinct **sections** based on common UI patterns. Present them as a numbered list and ask the user which to focus on.
82
+
83
+ #### Common Section Patterns
84
+
85
+ Identify which patterns exist on the screen:
86
+
87
+ | Pattern | Elements to look for |
88
+ |---|---|
89
+ | **Header / Navigation** | Logo, nav links, breadcrumbs, user menu, notifications, language selector |
90
+ | **Form** | Input fields, dropdowns, checkboxes, radio buttons, date pickers, file uploads, submit/cancel buttons |
91
+ | **Data Table** | Column headers, sortable columns, row data, row actions, bulk actions, column filters |
92
+ | **Search & Filters** | Search input, filter dropdowns, clear/reset, active filter tags |
93
+ | **Card Grid / List** | Cards with title/image/description, load more, infinite scroll |
94
+ | **Pagination** | Previous/next buttons, page numbers, page size selector, total count |
95
+ | **Tabs / Accordion** | Tab headers, tab panels, expand/collapse |
96
+ | **Modal / Dialog** | Open trigger, close button, form inside modal, confirmation dialog |
97
+ | **Sidebar** | Stats, quick actions, related links, mini widgets |
98
+ | **File Upload** | Drop zone, file picker, progress bar, file list, delete |
99
+ | **Rich Text Editor** | Toolbar, content area, formatting buttons, preview |
100
+ | **Carousel / Slider** | Prev/next arrows, dots/indicators, auto-play, swipe |
101
+
102
+ Example output:
103
+
104
+ > This screen has the following sections:
105
+ > 1. Header (logo, navigation tabs, user menu)
106
+ > 2. Create Form (name, email, role dropdown, department, submit)
107
+ > 3. User Table (columns: name, email, status, actions; sortable, filterable)
108
+ > 4. Pagination (previous/next, page indicator)
109
+ >
110
+ > Which sections do you want to create test cases for? (e.g., "2, 3" or "all")
111
+
112
+ For each selected section, generate **20+ scenarios per applicable viewpoint**. Skip viewpoint categories that don't apply.
113
+
114
+ Present a test plan summary and wait for user confirmation before generating files.
115
+
116
+ ### Viewpoint Categories
117
+
118
+ | VP Category | Description |
119
+ |---|---|
120
+ | **UI/UX** | Default appearance, element visibility, default states |
121
+ | **Validation** | Input validation, error messages, edge cases |
122
+ | **Logic** | Business logic, interactions, state changes |
123
+ | **Security** | Auth guards, injection, permission checks |
124
+
125
+ ### Coverage Checklist per Section Pattern
126
+
127
+ Apply the relevant checklist based on the section pattern:
128
+
129
+ #### Form sections
130
+ - **UI/UX**: All fields visible, labels correct, default values, placeholder text, required indicators
131
+ - **Validation**: Empty submit, each required field empty, invalid format (email, phone, URL), min/max length, special chars, unicode, XSS, SQL injection, whitespace-only, boundary values
132
+ - **Logic**: Successful submit, submit with all optional fields, edit existing record, cancel resets form, field dependencies (show/hide), auto-complete, date range validation
133
+ - **Security**: CSRF protection, unauthorized submit, role-based field visibility, input sanitization
134
+
135
+ #### Data Table sections
136
+ - **UI/UX**: All columns visible, column headers, row data displays correctly, empty state, loading state, action buttons visible
137
+ - **Validation**: N/A (read-only) or inline edit validation
138
+ - **Logic**: Sort ascending/descending per sortable column, filter by each column, search within table, row action menu (edit/delete/view), bulk select, bulk action, row click navigation, column resize
139
+ - **Security**: Cannot access other users' data, action permissions per role, data not exposed in DOM
140
+
141
+ #### Search & Filter sections
142
+ - **UI/UX**: Search field visible, filter buttons visible, clear button state
143
+ - **Validation**: Empty search, special chars, SQL injection, XSS, very long text, unicode/emoji, whitespace, partial match, case insensitive
144
+ - **Logic**: Apply single filter, combine multiple filters, clear single filter, clear all filters, search + filter combined, filter persists across pagination, no results state
145
+ - **Security**: Injection via search, injection via filter params
146
+
147
+ #### Pagination sections
148
+ - **UI/UX**: Page indicator visible, previous disabled on page 1, next enabled
149
+ - **Logic**: Next page, previous page, navigate to last page, boundary (first/last), page indicator updates, data refreshes on navigation
150
+ - **Security**: Filters persist across pages, search persists, cannot access page beyond max
151
+
152
+ #### Modal / Dialog sections
153
+ - **UI/UX**: Modal opens, close button visible, overlay visible, form fields inside modal
154
+ - **Validation**: Submit empty form in modal, field validation inside modal
155
+ - **Logic**: Open modal, close with X, close with Escape, close with overlay click, submit success closes modal, submit error keeps modal open
156
+ - **Security**: Cannot open unauthorized modals, CSRF on modal submit
157
+
158
+ #### Card Grid / List sections
159
+ - **UI/UX**: Cards display all expected fields (title, image, description, metadata), empty state, loading state
160
+ - **Logic**: Click card navigates to detail, load more / infinite scroll, card action buttons (like, share, delete), responsive layout
161
+ - **Security**: User-generated content sanitized, cannot access other users' cards
162
+
163
+ #### Carousel / Slider sections
164
+ - **UI/UX**: Arrows visible, indicators visible, current slide highlighted
165
+ - **Logic**: Next slide, previous slide, wrap at end, auto-play, indicator click navigates, swipe gesture
166
+ - **Security**: N/A
167
+
168
+ #### Tabs / Accordion sections
169
+ - **UI/UX**: All tabs visible, active tab highlighted, default tab selected
170
+ - **Logic**: Switch tabs, content updates per tab, deep link to tab, accordion expand/collapse, only one accordion open at a time
171
+ - **Security**: Tab content respects permissions
172
+
173
+ ### General Coverage Dimensions (aim for 20+ total per viewpoint)
174
+
175
+ **Happy paths (3-5):** Standard flow, all optional fields, minimum required
176
+ **Edge cases (5-8):** Empty, max length, special chars, unicode/CJK/emoji, whitespace, leading/trailing spaces, overflow
177
+ **Boundary values (3-5):** At min/max limit, one above/below, zero/null
178
+ **Negative cases (3-5):** Invalid format, missing required, wrong type, injection attempts
179
+ **State transitions (2-4):** Before/after action, undo, cancel mid-flow
180
+ **Combinatorial (2-4):** Multiple invalid fields, valid+invalid combos, different roles
181
+
182
+ ### SPA Wait-For Steps
183
+
184
+ If the page is an SPA (Next.js, Nuxt, React Router, etc.), add a `wait for` step after navigation:
185
+
186
+ ```gherkin
187
+ Given User is on [Screen] page
188
+ And User wait for [Page Title] heading is visible
189
+ ```
190
+
191
+ For scenarios needing dynamic data, add a second wait:
192
+
193
+ ```gherkin
194
+ And User wait for [Data Element] button is visible
195
+ ```
196
+
197
+ ### Output Files
198
+
199
+ **1. Feature file** — `qa/screens/<screen>/features/<screen>.feature`
200
+
201
+ Group by section, then by viewpoint within each section:
202
+
203
+ ```gherkin
204
+ @auth:role
205
+ Feature: <Screen> Screen
206
+
207
+ # ============================================================
208
+ # Section: Create User Form
209
+ # ============================================================
210
+
211
+ # --- UI/UX (20+) ---
212
+
213
+ Scenario: VP-UI-001 Name field is visible
214
+ ...
215
+
216
+ # --- Validation (20+) ---
217
+
218
+ Scenario: VP-VAL-001 Submit with empty name
219
+ ...
220
+
221
+ # ============================================================
222
+ # Section: User Table
223
+ # ============================================================
224
+
225
+ # --- UI/UX (20+) ---
226
+
227
+ Scenario: VP-UI-025 Table displays all columns
228
+ ...
229
+ ```
230
+
231
+ **Naming convention:** `VP-<CATEGORY>-<NNN>` prefix in Scenario name.
232
+
233
+ **2. Test data file** — `qa/screens/<screen>/test-data/<screen>.yaml`
234
+
235
+ Group variables by section:
236
+
237
+ ```yaml
238
+ # ============================================================
239
+ # Create User Form
240
+ # ============================================================
241
+ valid_name: 'John Doe'
242
+ valid_email: 'john@example.com'
243
+ empty_input: ''
244
+ special_chars: '!@#$%^&*()'
245
+
246
+ # ============================================================
247
+ # User Table
248
+ # ============================================================
249
+ sort_column: 'Name'
250
+ search_term: 'John'
251
+ ```
252
+
253
+ ### Do NOT Generate
254
+
255
+ - `selectors.yaml` — this is created during `/sungen:make-test`
256
+ - Playwright code — sungen compiles Gherkin to Playwright
@@ -20,7 +20,9 @@ export default defineConfig({
20
20
  /* Retry on CI only */
21
21
  retries: process.env.CI ? 2 : 0,
22
22
  /* Opt out of parallel tests on CI. */
23
- workers: process.env.CI ? 1 : undefined,
23
+ workers: process.env.CI ? 1 : 2,
24
+ /* Global timeout per test */
25
+ timeout: 10_000,
24
26
  /* Reporter to use. See https://playwright.dev/docs/test-reporters */
25
27
  reporter: 'html',
26
28
  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */