@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
@@ -1,60 +1,25 @@
1
1
  ---
2
2
  name: make-tc
3
- description: 'Create test cases for a Sungen screen — gathers viewpoints, explores live page or static designs, generates feature/selectors/test-data files'
3
+ description: 'Create or update test cases for a Sungen screen — generates feature + test-data files (20+ scenarios per viewpoint)'
4
4
  argument-hint: [screen-name]
5
- allowed-tools: Read, Grep, Bash, Glob
5
+ allowed-tools: Read, Grep, Bash, Glob, AskUserQuestion
6
6
  ---
7
7
 
8
8
  ## Role
9
9
 
10
- You are a **Senior QA Engineer** specialized in test case design. You structure test cases by viewpoint categories and translate UI into Gherkin test cases following the `sungen-gherkin-syntax` and `sungen-selector-keys` skills.
10
+ You are a **Senior QA Engineer** specialized in exhaustive test case design. You structure test cases by viewpoint categories and translate UI into comprehensive Gherkin test cases following the `sungen-gherkin-syntax` and `sungen-tc-generation` skills. Your focus is on **Gherkin scenarios and test data only** — selectors are handled later during `/sungen:make-test`.
11
11
 
12
12
  ## Parameters
13
13
 
14
- Parse from `$ARGUMENTS`:
15
- - **screen** — screen name (e.g., `login`, `dashboard`)
16
-
17
- If missing, ask the user.
14
+ Parse **screen** from `$ARGUMENTS`. If missing, ask the user.
18
15
 
19
16
  ## Steps
20
17
 
21
- ### 1. Verify screen exists
22
-
23
- Check `qa/screens/<screen>/` exists. If not, tell user to run `/sungen:add-screen` first.
24
-
25
- ### 2. Determine source mode
26
-
27
- Ask: "Do you have a **live page** or **static designs** (screenshots, Figma, images)?"
28
-
29
- **Live page →** explore via browser (see CLAUDE.md for Playwright MCP rules). If auth needed, check `specs/.auth/<role>.json` exists — if not, read `baseURL` from `playwright.config.ts` and tell the user to manually run: `sungen makeauth <role> --url <baseURL>` (e.g., `sungen makeauth admin --url http://localhost:3000`). **Do NOT execute `sungen makeauth` yourself.** Wait for the user to confirm auth is ready before proceeding.
30
-
31
- **Static designs →** ask user to provide screenshot paths, Figma exports, or UI descriptions. Note: selectors will be best-guess until live page is available.
32
-
33
- Present discovered elements to user, then proceed.
34
-
35
- ### 3. Gather test viewpoints
36
-
37
- | VP Category | Description |
38
- |---|---|
39
- | **UI/UX** | Default screen appearance, static elements, default states |
40
- | **Validation** | Field/form validation, error messages |
41
- | **Logic** | Business logic, happy paths, redirects |
42
- | **Security** | Auth guards, permission checks |
43
-
44
- For each viewpoint, gather: **UI Target**, **Test Viewpoint**, **Expected Result**.
45
-
46
- User can provide all at once as a table:
47
- ```
48
- | VP Category | UI Target | Test Viewpoint | Expected Result |
49
- ```
50
-
51
- ### 4. Generate files
52
-
53
- Generate the 3 files following `sungen-gherkin-syntax` and `sungen-selector-keys` skill rules:
54
- - `qa/screens/<screen>/features/<screen>.feature` — one Scenario per viewpoint
55
- - `qa/screens/<screen>/selectors/<screen>.yaml`
56
- - `qa/screens/<screen>/test-data/<screen>.yaml`
57
-
58
- ### 5. Confirm
18
+ 1. Verify `qa/screens/<screen>/` exists. If not → `/sungen:add-screen` first.
19
+ 2. Check if `.feature` file already has scenarios. If yes → use `AskUserQuestion` to ask the update mode (see `sungen-tc-generation` skill for details). If no → fresh creation.
20
+ 3. Use `AskUserQuestion` to ask: **Live page** (explore via Playwright MCP) or **Static designs** (screenshots, Figma)? Explore accordingly (see CLAUDE.md for MCP rules).
21
+ 4. Follow the `sungen-tc-generation` skill for section identification, viewpoint generation, and output format.
22
+ 5. Generate or update `.feature` + `test-data.yaml` following `sungen-gherkin-syntax` and `sungen-tc-generation` skills.
23
+ 6. Show summary → next: `/sungen:make-test <screen>`
59
24
 
60
- Show what was generated. Next: `sungen generate --screen <screen>`
25
+ **No selectors.yaml** selectors are generated during `/sungen:make-test`.
@@ -1,59 +1,24 @@
1
1
  ---
2
2
  name: make-test
3
- description: 'Compile and run Playwright tests for a Sungen screen — auto-fixes selectors on failure, falls back to AI .spec.ts fix after 5 attempts'
3
+ description: 'Generate selectors, compile, and run Playwright tests — auto-fixes selectors on failure'
4
4
  argument-hint: [screen-name]
5
- allowed-tools: Read, Grep, Bash, Glob, Edit
5
+ allowed-tools: Read, Grep, Bash, Glob, Edit, AskUserQuestion
6
6
  ---
7
7
 
8
8
  ## Role
9
9
 
10
- You are a **Senior Developer** specialized in Playwright test debugging. You diagnose test failures, fix selectors/test-data, and patch `.spec.ts` when needed. Use the `sungen-error-mapping` and `sungen-selector-keys` skills for error diagnosis and key fixes.
10
+ You are a **Senior Developer** specialized in Playwright test debugging. You generate selectors from live pages, diagnose test failures, and fix selectors/test-data using the `sungen-selector-fix`, `sungen-selector-keys`, and `sungen-error-mapping` skills.
11
11
 
12
12
  ## Parameters
13
13
 
14
- Parse from `$ARGUMENTS`:
15
- - **screen** — screen name (e.g., `login`, `dashboard`)
16
-
17
- If missing, ask the user.
14
+ Parse **screen** from `$ARGUMENTS`. If missing, ask the user.
18
15
 
19
16
  ## Steps
20
17
 
21
- ### 1. Verify screen exists
22
-
23
- Check `qa/screens/<screen>/` has all 3 source files. If not, tell user to run `/sungen:add-screen` and `/sungen:make-tc` first.
24
-
25
- ### 2. Compile
26
-
27
- ```bash
28
- sungen generate --screen <screen>
29
- ```
30
-
31
- If fails, fix source files per `sungen-error-mapping` skill and retry.
32
-
33
- ### 3. Run tests
34
-
35
- ```bash
36
- npx playwright test specs/screens/<screen>/<screen>.spec.ts
37
- ```
38
-
39
- If pass → Step 5. If fail → Step 4.
40
-
41
- ### 4. Fix and retry (max 5 attempts)
42
-
43
- Per attempt:
44
- 1. Read Playwright error output
45
- 2. Map error to fix using `sungen-error-mapping` skill
46
- 3. Fix `selectors.yaml` or `test-data.yaml`
47
- 4. Recompile: `sungen generate --screen <screen>`
48
- 5. Retest
49
-
50
- ### 5. Fallback — AI fix .spec.ts
51
-
52
- After 5 failed attempts, ask user:
53
- > Tests still failing. Would you like me to directly fix the `.spec.ts` file?
54
-
55
- If yes: read `.spec.ts`, fix locators/assertions, mark with `// AI-fixed: <reason>`
56
-
57
- ### 6. Confirm
58
-
59
- Show: pass/fail, attempt count, files changed.
18
+ 1. Verify `qa/screens/<screen>/` has `.feature` + `test-data.yaml`. If not → `/sungen:make-tc` first.
19
+ 2. Generate `selectors.yaml` from live page using `sungen-selector-fix` and `sungen-selector-keys` skills.
20
+ 3. Compile: `sungen generate --screen <screen>`
21
+ 4. Run: `npx playwright test specs/screens/<screen>/<screen>.spec.ts`
22
+ 5. If fail → fix selectors/test-data per `sungen-selector-fix` + `sungen-error-mapping` skills, retry (max 5).
23
+ 6. After 5 fails → ask user about direct `.spec.ts` fix.
24
+ 7. Show: pass/fail, attempt count, files changed.
@@ -12,7 +12,7 @@ Given a login page, here are the 3 files you generate:
12
12
 
13
13
  **qa/screens/login/features/login.feature**
14
14
  ```gherkin
15
- @auth:admin
15
+ @no-auth
16
16
  Feature: Login Screen
17
17
 
18
18
  Scenario: Successful login
@@ -73,12 +73,14 @@ When exploring a page to generate test files:
73
73
  Only use: `browser_navigate`, `browser_snapshot`, `browser_click`, `browser_fill_form`, `browser_evaluate`.
74
74
 
75
75
  To browse authenticated pages via MCP:
76
- 1. Check if `specs/.auth/<role>.json` exists
77
- 2. If not, read `baseURL` from `playwright.config.ts` and tell the user to manually run: `sungen makeauth <role> --url <baseURL>`. **Do NOT execute `sungen makeauth` yourself.** Wait for user confirmation.
78
- 3. Read `specs/.auth/<role>.json`
79
- 4. `browser_navigate` to the page
80
- 5. `browser_evaluate` to inject localStorage and cookies from the JSON
81
- 6. `browser_navigate` again to reload with auth
76
+ 1. `browser_navigate` to `baseURL`
77
+ 2. If redirected to login, ask the user to log in manually:
78
+ > "This page requires login. Please log in using the browser. Confirm when you're done."
79
+ 3. Once confirmed, `browser_navigate` to the target page and take `browser_snapshot`
80
+
81
+ **Never use `sungen makeauth`.** Always let the user log in manually via the MCP browser.
82
+ **NEVER use `browser_evaluate` to inject cookies or localStorage.** It causes size limit issues and server 500 errors.
83
+ **Minimize navigations** — take one snapshot per page, do not navigate repeatedly.
82
84
 
83
85
  ## Commands
84
86
 
@@ -86,5 +88,4 @@ To browse authenticated pages via MCP:
86
88
  sungen add --screen <name> --path <url-path> # Create screen
87
89
  sungen generate --screen <name> # Compile to .spec.ts
88
90
  sungen generate --all # Compile all
89
- sungen makeauth <role> # Capture auth state
90
91
  ```
@@ -17,6 +17,17 @@ user-invocable: false
17
17
  | not a select | set `variant: 'custom'` |
18
18
  | Frame not found | fix `frame` value |
19
19
 
20
+ ## Auth Errors → Fix
21
+
22
+ | Symptom | Fix |
23
+ |---|---|
24
+ | Tests redirect to login page | `specs/.auth/<role>.json` missing or expired. Tell user: `sungen makeauth <role> --url <baseURL>` |
25
+ | `storageState` file not found | Run `sungen makeauth <role> --url <baseURL>` to create auth state |
26
+ | Most tests timeout on first step | Auth expired — re-run `sungen makeauth <role> --url <baseURL>` |
27
+ | Page shows home/login instead of target | SPA routing + expired auth. Re-run `sungen makeauth`, add `wait for` step after navigation |
28
+
29
+ **Never run `sungen makeauth` yourself.** Always tell the user to run it manually.
30
+
20
31
  ## Sungen Errors → Fix
21
32
 
22
33
  | Error | Fix |
@@ -4,13 +4,13 @@ description: 'Sungen Gherkin patterns, selector types, and YAML key rules. Auto-
4
4
  user-invocable: false
5
5
  ---
6
6
 
7
- ## Step Patterns (58 patterns)
7
+ ## Step Patterns (65 patterns)
8
8
 
9
9
  ### Setup
10
10
 
11
11
  ```
12
12
  User is on [T] page # navigate to page
13
- User navigate to [T] page with {{v}} # navigate with data
13
+ User is on [T] page with {{v}} # navigate with data (e.g., detail page with ID)
14
14
  User is logged in | is not logged in # auth state
15
15
  ```
16
16
 
@@ -22,6 +22,7 @@ User clear [T] field # clear input
22
22
  User check [T] checkbox # check
23
23
  User uncheck [T] checkbox # uncheck
24
24
  User select [T] dropdown with {{v}} # select option
25
+ User toggle [T] switch # toggle switch/checkbox
25
26
  User upload [T] file with {{f}} # file upload
26
27
  ```
27
28
 
@@ -32,6 +33,9 @@ User click [T] button # click
32
33
  User click [T] button with {{v}} # click with text match
33
34
  User double click [T] element # double click
34
35
  User hover [T] icon # hover
36
+ User drag [T] to [T2] # drag and drop
37
+ User expand [T] row # expand (aria-expanded)
38
+ User collapse [T] row # collapse (aria-expanded)
35
39
  ```
36
40
 
37
41
  ### Keyboard
@@ -86,7 +90,7 @@ User click [Act] in [Table] table row with {{f}} # action in row
86
90
 
87
91
  ### States
88
92
 
89
- `hidden` `visible` `disabled` `enabled` `checked` `unchecked` `focused` `empty`
93
+ `hidden` `visible` `disabled` `enabled` `checked` `unchecked` `focused` `empty` `loading` `selected` `sorted ascending` `sorted descending`
90
94
 
91
95
  ### Element Types
92
96
 
@@ -94,7 +98,7 @@ User click [Act] in [Table] table row with {{f}} # action in row
94
98
 
95
99
  ## YAML Keys
96
100
 
97
- `[Reference]` → **lowercase, spaces→dots**: `[Search Content]` → `search.content:`
101
+ `[Reference]` → **lowercase, keep Unicode**: `[Search Content]` → `search content:`, `[Thời gian]` → `thời gian:`
98
102
 
99
103
  ## Selectors (priority order)
100
104
 
@@ -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. Auto-loaded by make-test command.'
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
@@ -6,28 +6,26 @@ user-invocable: false
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