@sun-asterisk/sungen 2.1.1 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +78 -51
  2. package/dist/cli/index.js +1 -1
  3. package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +1 -1
  4. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -1
  5. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +1 -1
  6. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +0 -1
  7. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +0 -1
  8. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +0 -1
  9. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +0 -1
  10. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +0 -1
  11. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-filter-assertion.hbs +0 -1
  12. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +0 -1
  13. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +0 -1
  14. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +0 -1
  15. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +0 -1
  16. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +0 -1
  17. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +0 -1
  18. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-dialog-heading-assertion.hbs +0 -1
  19. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-filter-assertion.hbs +0 -1
  20. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +0 -1
  21. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +0 -1
  22. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/is-hidden-assertion.hbs +0 -1
  23. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +0 -1
  24. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/list-item-count-assertion.hbs +0 -1
  25. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/loading-assertion.hbs +0 -1
  26. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +0 -1
  27. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/page-assertion.hbs +0 -1
  28. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +0 -1
  29. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/sorted-assertion.hbs +0 -1
  30. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +0 -1
  31. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +0 -1
  32. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +0 -1
  33. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +0 -1
  34. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +0 -1
  35. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +0 -1
  36. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +0 -1
  37. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +0 -1
  38. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-dialog-heading-assertion.hbs +0 -1
  39. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-locator-variable-assertion.hbs +0 -1
  40. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +0 -1
  41. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +0 -1
  42. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +0 -1
  43. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -1
  44. package/dist/generators/test-generator/code-generator.d.ts +4 -0
  45. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  46. package/dist/generators/test-generator/code-generator.js +19 -0
  47. package/dist/generators/test-generator/code-generator.js.map +1 -1
  48. package/dist/generators/test-generator/patterns/navigation-patterns.js +2 -2
  49. package/dist/generators/test-generator/patterns/navigation-patterns.js.map +1 -1
  50. package/dist/generators/test-generator/utils/selector-resolver.d.ts +15 -8
  51. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  52. package/dist/generators/test-generator/utils/selector-resolver.js +26 -197
  53. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  54. package/dist/orchestrator/project-initializer.d.ts +8 -0
  55. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  56. package/dist/orchestrator/project-initializer.js +68 -4
  57. package/dist/orchestrator/project-initializer.js.map +1 -1
  58. package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +4 -3
  59. package/dist/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md +11 -46
  60. package/dist/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +11 -46
  61. package/dist/orchestrator/templates/ai-instructions/claude-config.md +9 -8
  62. package/dist/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +29 -0
  63. package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +2 -2
  64. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +206 -0
  65. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +19 -21
  66. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +256 -0
  67. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +14 -17
  68. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-make-tc.md +16 -47
  69. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +16 -47
  70. package/dist/orchestrator/templates/ai-instructions/copilot-config.md +8 -7
  71. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +56 -0
  72. package/{src/orchestrator/templates/ai-instructions/copilot-skill-gherkin-syntax.md → dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md} +5 -5
  73. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +206 -0
  74. package/dist/orchestrator/templates/ai-instructions/{copilot-skill-selector-keys.md → github-skill-sungen-selector-keys.md} +22 -24
  75. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +257 -0
  76. package/dist/orchestrator/templates/playwright.config.d.ts.map +1 -1
  77. package/dist/orchestrator/templates/playwright.config.js +3 -1
  78. package/dist/orchestrator/templates/playwright.config.js.map +1 -1
  79. package/dist/orchestrator/templates/playwright.config.ts +3 -1
  80. package/dist/orchestrator/templates/readme.md +78 -101
  81. package/dist/orchestrator/templates/specs-base.d.ts +4 -0
  82. package/dist/orchestrator/templates/specs-base.d.ts.map +1 -0
  83. package/dist/orchestrator/templates/specs-base.js +70 -0
  84. package/dist/orchestrator/templates/specs-base.js.map +1 -0
  85. package/dist/orchestrator/templates/specs-base.ts +73 -0
  86. package/package.json +1 -1
  87. package/src/cli/index.ts +1 -1
  88. package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +1 -1
  89. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -1
  90. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +1 -1
  91. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +0 -1
  92. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +0 -1
  93. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +0 -1
  94. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +0 -1
  95. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +0 -1
  96. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-filter-assertion.hbs +0 -1
  97. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +0 -1
  98. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +0 -1
  99. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +0 -1
  100. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +0 -1
  101. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +0 -1
  102. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +0 -1
  103. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-dialog-heading-assertion.hbs +0 -1
  104. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-filter-assertion.hbs +0 -1
  105. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +0 -1
  106. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +0 -1
  107. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/is-hidden-assertion.hbs +0 -1
  108. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +0 -1
  109. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/list-item-count-assertion.hbs +0 -1
  110. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/loading-assertion.hbs +0 -1
  111. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +0 -1
  112. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/page-assertion.hbs +0 -1
  113. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +0 -1
  114. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/sorted-assertion.hbs +0 -1
  115. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +0 -1
  116. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +0 -1
  117. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +0 -1
  118. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +0 -1
  119. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +0 -1
  120. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +0 -1
  121. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +0 -1
  122. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +0 -1
  123. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-dialog-heading-assertion.hbs +0 -1
  124. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-locator-variable-assertion.hbs +0 -1
  125. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +0 -1
  126. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +0 -1
  127. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +0 -1
  128. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -1
  129. package/src/generators/test-generator/code-generator.ts +21 -0
  130. package/src/generators/test-generator/patterns/navigation-patterns.ts +2 -2
  131. package/src/generators/test-generator/utils/selector-resolver.ts +27 -204
  132. package/src/orchestrator/project-initializer.ts +84 -5
  133. package/src/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +4 -3
  134. package/src/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md +11 -46
  135. package/src/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +11 -46
  136. package/src/orchestrator/templates/ai-instructions/claude-config.md +9 -8
  137. package/src/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +29 -0
  138. package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +2 -2
  139. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +206 -0
  140. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +19 -21
  141. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +256 -0
  142. package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +14 -17
  143. package/src/orchestrator/templates/ai-instructions/copilot-cmd-make-tc.md +16 -47
  144. package/src/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +16 -47
  145. package/src/orchestrator/templates/ai-instructions/copilot-config.md +8 -7
  146. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +56 -0
  147. package/{dist/orchestrator/templates/ai-instructions/copilot-skill-gherkin-syntax.md → src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md} +5 -5
  148. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +206 -0
  149. package/src/orchestrator/templates/ai-instructions/{copilot-skill-selector-keys.md → github-skill-sungen-selector-keys.md} +22 -24
  150. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +257 -0
  151. package/src/orchestrator/templates/playwright.config.ts +3 -1
  152. package/src/orchestrator/templates/readme.md +78 -101
  153. package/src/orchestrator/templates/specs-base.ts +73 -0
  154. package/dist/orchestrator/templates/ai-instructions/copilot-skill-error-mapping.md +0 -27
  155. package/src/orchestrator/templates/ai-instructions/copilot-skill-error-mapping.md +0 -27
@@ -0,0 +1,257 @@
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. **Must explore live page via MCP to capture actual error messages before writing tests. Use `User see {{error_var}}` pattern — never assert just "is visible".** |
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
+ - **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 — **assert exact error messages via `User see {{error_var}}`**, store texts in test-data.yaml
133
+ - **Logic**: Successful submit, submit with all optional fields, edit existing record, cancel resets form, field dependencies (show/hide), auto-complete, date range validation
134
+ - **Security**: CSRF protection, unauthorized submit, role-based field visibility, input sanitization
135
+
136
+ #### Data Table sections
137
+ - **UI/UX**: All columns visible, column headers, row data displays correctly, empty state, loading state, action buttons visible
138
+ - **Validation**: N/A (read-only) or inline edit validation
139
+ - **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
140
+ - **Security**: Cannot access other users' data, action permissions per role, data not exposed in DOM
141
+
142
+ #### Search & Filter sections
143
+ - **UI/UX**: Search field visible, filter buttons visible, clear button state
144
+ - **Validation**: Empty search, special chars, SQL injection, XSS, very long text, unicode/emoji, whitespace, partial match, case insensitive
145
+ - **Logic**: Apply single filter, combine multiple filters, clear single filter, clear all filters, search + filter combined, filter persists across pagination, no results state
146
+ - **Security**: Injection via search, injection via filter params
147
+
148
+ #### Pagination sections
149
+ - **UI/UX**: Page indicator visible, previous disabled on page 1, next enabled
150
+ - **Logic**: Next page, previous page, navigate to last page, boundary (first/last), page indicator updates, data refreshes on navigation
151
+ - **Security**: Filters persist across pages, search persists, cannot access page beyond max
152
+
153
+ #### Modal / Dialog sections
154
+ - **UI/UX**: Modal opens, close button visible, overlay visible, form fields inside modal
155
+ - **Validation**: Submit empty form in modal, field validation inside modal
156
+ - **Logic**: Open modal, close with X, close with Escape, close with overlay click, submit success closes modal, submit error keeps modal open
157
+ - **Security**: Cannot open unauthorized modals, CSRF on modal submit
158
+
159
+ #### Card Grid / List sections
160
+ - **UI/UX**: Cards display all expected fields (title, image, description, metadata), empty state, loading state
161
+ - **Logic**: Click card navigates to detail, load more / infinite scroll, card action buttons (like, share, delete), responsive layout
162
+ - **Security**: User-generated content sanitized, cannot access other users' cards
163
+
164
+ #### Carousel / Slider sections
165
+ - **UI/UX**: Arrows visible, indicators visible, current slide highlighted
166
+ - **Logic**: Next slide, previous slide, wrap at end, auto-play, indicator click navigates, swipe gesture
167
+ - **Security**: N/A
168
+
169
+ #### Tabs / Accordion sections
170
+ - **UI/UX**: All tabs visible, active tab highlighted, default tab selected
171
+ - **Logic**: Switch tabs, content updates per tab, deep link to tab, accordion expand/collapse, only one accordion open at a time
172
+ - **Security**: Tab content respects permissions
173
+
174
+ ### General Coverage Dimensions (aim for 20+ total per viewpoint)
175
+
176
+ **Happy paths (3-5):** Standard flow, all optional fields, minimum required
177
+ **Edge cases (5-8):** Empty, max length, special chars, unicode/CJK/emoji, whitespace, leading/trailing spaces, overflow
178
+ **Boundary values (3-5):** At min/max limit, one above/below, zero/null
179
+ **Negative cases (3-5):** Invalid format, missing required, wrong type, injection attempts
180
+ **State transitions (2-4):** Before/after action, undo, cancel mid-flow
181
+ **Combinatorial (2-4):** Multiple invalid fields, valid+invalid combos, different roles
182
+
183
+ ### SPA Wait-For Steps
184
+
185
+ If the page is an SPA (Next.js, Nuxt, React Router, etc.), add a `wait for` step after navigation:
186
+
187
+ ```gherkin
188
+ Given User is on [Screen] page
189
+ And User wait for [Page Title] heading is visible
190
+ ```
191
+
192
+ For scenarios needing dynamic data, add a second wait:
193
+
194
+ ```gherkin
195
+ And User wait for [Data Element] button is visible
196
+ ```
197
+
198
+ ### Output Files
199
+
200
+ **1. Feature file** — `qa/screens/<screen>/features/<screen>.feature`
201
+
202
+ Group by section, then by viewpoint within each section:
203
+
204
+ ```gherkin
205
+ @auth:role
206
+ Feature: <Screen> Screen
207
+
208
+ # ============================================================
209
+ # Section: Create User Form
210
+ # ============================================================
211
+
212
+ # --- UI/UX (20+) ---
213
+
214
+ Scenario: VP-UI-001 Name field is visible
215
+ ...
216
+
217
+ # --- Validation (20+) ---
218
+
219
+ Scenario: VP-VAL-001 Submit with empty name
220
+ ...
221
+
222
+ # ============================================================
223
+ # Section: User Table
224
+ # ============================================================
225
+
226
+ # --- UI/UX (20+) ---
227
+
228
+ Scenario: VP-UI-025 Table displays all columns
229
+ ...
230
+ ```
231
+
232
+ **Naming convention:** `VP-<CATEGORY>-<NNN>` prefix in Scenario name.
233
+
234
+ **2. Test data file** — `qa/screens/<screen>/test-data/<screen>.yaml`
235
+
236
+ Group variables by section:
237
+
238
+ ```yaml
239
+ # ============================================================
240
+ # Create User Form
241
+ # ============================================================
242
+ valid_name: 'John Doe'
243
+ valid_email: 'john@example.com'
244
+ empty_input: ''
245
+ special_chars: '!@#$%^&*()'
246
+
247
+ # ============================================================
248
+ # User Table
249
+ # ============================================================
250
+ sort_column: 'Name'
251
+ search_term: 'John'
252
+ ```
253
+
254
+ ### Do NOT Generate
255
+
256
+ - `selectors.yaml` — this is created during `/sungen:make-test`
257
+ - 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. */
@@ -17,11 +17,17 @@ sungen generate → compiles Gherkin + selectors + data → Playwright .spec.ts
17
17
  │ ├── selectors/ # Element locator YAML mappings
18
18
  │ └── test-data/ # Test data YAML values
19
19
  ├── specs/
20
- ├── generated/ # Auto-generated Playwright tests
21
- │ └── .auth/ # Auth storage states
20
+ └── generated/ # Auto-generated Playwright tests
21
+ ├── .claude/
22
+ │ ├── commands/sungen/ # Claude Code slash commands
23
+ │ └── skills/ # Claude Code auto-loaded skills
22
24
  ├── .github/
23
- └── copilot-instructions.md # AI rules for GitHub Copilot
24
- └── CLAUDE.md # AI rules for Claude Code
25
+ ├── copilot-instructions.md # AI rules for GitHub Copilot
26
+ └── prompts/ # Copilot slash commands
27
+ ├── .vscode/
28
+ │ └── settings.json # Copilot auto-attach settings
29
+ ├── CLAUDE.md # AI rules for Claude Code
30
+ └── playwright.config.ts # Playwright config (timeout: 10s, workers: 2)
25
31
  ```
26
32
 
27
33
  ## Workflow
@@ -32,45 +38,50 @@ Step 1 Step 2 Step 3
32
38
  │ /add- │────────▶│ /make-tc │────────▶│ /make- │
33
39
  │ screen │ │ │ │ test │
34
40
  └──────────┘ └──────────┘ └──────────┘
35
- Scaffold Design TCs Compile &
36
- directories & generate run tests
37
- 3 files
41
+ Scaffold Pick sections Generate
42
+ directories design TCs selectors
43
+ generate → compile
44
+ .feature + → run tests
45
+ test-data → auto-fix
38
46
  ```
39
47
 
40
48
  Use AI commands (Claude Code or GitHub Copilot) to drive the workflow:
41
49
 
42
50
  ### Step 1: Add a screen
43
51
 
44
- | Claude Code | GitHub Copilot |
52
+ | Claude Code | GitHub Copilot (VS Code) |
45
53
  |---|---|
46
- | `/sungen:add-screen login /login` | `@workspace /sungen-add-screen login /login` |
54
+ | `/sungen:add-screen` | `/sungen-add-screen` |
47
55
 
48
56
  Scaffolds `qa/screens/<name>/` with empty feature, selectors, and test-data files, then asks if you want to create test cases.
49
57
 
50
58
  ### Step 2: Create test cases
51
59
 
52
- | Claude Code | GitHub Copilot |
60
+ | Claude Code | GitHub Copilot (VS Code) |
53
61
  |---|---|
54
- | `/sungen:make-tc login` | `@workspace /sungen-make-tc login` |
62
+ | `/sungen:make-tc login` | `/sungen-make-tc login` |
55
63
 
56
- AI acts as a **Senior QA Engineer**: explores the live page (via Playwright MCP) or analyzes static designs, gathers test viewpoints (UI/UX, Validation, Logic, Security), and generates the 3 files.
64
+ AI acts as a **Senior QA Engineer**:
65
+ 1. Explores the live page via Playwright MCP (asks user to log in if auth needed)
66
+ 2. Identifies screen sections → asks user which to focus on
67
+ 3. Generates **20+ scenarios per viewpoint** (UI/UX, Validation, Logic, Security) for each section
68
+ 4. Confirms test plan before generating `.feature` + `test-data.yaml`
57
69
 
58
70
  ### Step 3: Compile & run tests
59
71
 
60
- | Claude Code | GitHub Copilot |
72
+ | Claude Code | GitHub Copilot (VS Code) |
61
73
  |---|---|
62
- | `/sungen:make-test login` | `@workspace /sungen-make-test login` |
74
+ | `/sungen:make-test login` | `/sungen-make-test login` |
63
75
 
64
- AI acts as a **Senior Developer**: compiles Gherkin → Playwright `.spec.ts`, runs tests, and auto-fixes selectors/test-data on failure (up to 5 attempts).
76
+ AI acts as a **Senior Developer**:
77
+ 1. Navigates to live page, takes snapshot, verifies DOM properties
78
+ 2. Generates `selectors.yaml` from exact accessible names
79
+ 3. Compiles Gherkin → Playwright `.spec.ts`
80
+ 4. Runs tests, auto-fixes selectors on failure (up to 5 attempts)
65
81
 
66
- ### Auth setup (if needed)
82
+ ### Auth setup
67
83
 
68
- If any page requires authentication, run manually before Step 2:
69
-
70
- ```bash
71
- sungen makeauth admin --url <baseURL>
72
- # Opens browser → login manually → saves specs/.auth/admin.json
73
- ```
84
+ If any page requires authentication, the AI will ask you to **log in manually via the MCP browser** during Step 2 or Step 3. No separate auth command needed.
74
85
 
75
86
  ### Manual CLI commands
76
87
 
@@ -85,7 +96,24 @@ npx playwright test --ui # Interactive mode
85
96
 
86
97
  ---
87
98
 
88
- ## Gherkin Guide
99
+ ## VS Code Copilot Setup
100
+
101
+ Add to `.vscode/settings.json` to auto-load Gherkin syntax when editing `.feature` files:
102
+
103
+ ```json
104
+ {
105
+ "github.copilot.chat.codeGeneration.instructions": [
106
+ {
107
+ "file": ".github/prompts/sungen-gherkin-syntax.prompt.md",
108
+ "applyTo": "**/*.feature"
109
+ }
110
+ ]
111
+ }
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Gherkin Quick Reference
89
117
 
90
118
  ### Syntax
91
119
 
@@ -97,101 +125,50 @@ User <action> [<Target>] <type> with {{<Value>}}
97
125
  - `{{Value}}` → test data reference → lookup in `test-data/*.yaml`
98
126
  - `<type>` → element type: button, link, field, heading, text, etc.
99
127
 
100
- ### Pattern Shapes (17 total)
101
-
102
- #### Actions
103
-
104
- | Pattern | Example |
105
- |---|---|
106
- | Simple click | `User click [Submit] button` |
107
- | Click with data | `User click [Teammate] button with {{name}}` |
108
- | Fill field | `User fill [Email] field with {{email}}` |
109
- | Check/Uncheck | `User check [Remember me] checkbox` |
110
- | Select dropdown | `User select [Country] dropdown with {{country}}` |
111
- | Upload file | `User upload [Avatar] file with {{path}}` |
112
- | Double click | `User double click [Cell] element` |
113
- | Hover | `User hover [Info] icon` |
114
- | Clear | `User clear [Search] field` |
115
-
116
- #### Keyboard
117
-
118
- | Pattern | Example |
119
- |---|---|
120
- | Global key | `User press Escape key` |
121
- | Key on element | `User press Enter on [Search] field` |
122
-
123
- #### Navigation
124
-
125
- | Pattern | Example |
126
- |---|---|
127
- | Open page | `User is on [login] page` |
128
- | See page (URL) | `User see [dashboard] page` |
129
-
130
- #### Wait
131
-
132
- | Pattern | Example |
133
- |---|---|
134
- | Wait timeout | `User wait for 3 seconds` |
135
- | Wait element | `User wait for [Modal] dialog` |
136
- | Wait hidden | `User wait for [Loading] spinner is hidden` |
137
- | Wait with data | `User wait for [Dialog] dialog with {{title}}` |
138
-
139
- #### Assertions
140
-
141
- | Pattern | Example |
142
- |---|---|
143
- | See element | `User see [Welcome] heading` |
144
- | See with value | `User see [Title] heading with {{title}}` |
145
- | State check | `User see [Submit] button is disabled` |
146
- | State + data | `User see [Panel] dialog with {{title}} is hidden` |
147
- | Text contains | `User see [Message] text contains {{partial}}` |
148
-
149
- States: `hidden`, `visible`, `disabled`, `enabled`, `checked`, `unchecked`, `focused`, `empty`
150
-
151
- #### Table
128
+ ### Key Patterns
152
129
 
153
130
  | Pattern | Example |
154
131
  |---|---|
155
- | Row exists | `User see [Users] table has row with {{name}}` |
156
- | No row | `User see [Users] table has no row with {{name}}` |
157
- | Row count | `User see [Users] table has {{count}} rows` |
158
- | Column exists | `User see [Users] table has [Email] column` |
159
- | Cell by filter | `User see [Users] table row with {{name}} has [Status] with {{status}}` |
160
- | Cell by index | `User see [Users] table row 1 [Name] cell with {{name}}` |
161
- | Action in row | `User click [Edit] in [Users] table row with {{name}}` |
162
- | Empty table | `User see [Users] table is empty` |
163
-
164
- #### Scope
165
-
166
- | Pattern | Example |
167
- |---|---|
168
- | Scroll | `User scroll to [Footer] section` |
169
- | Frame enter | `User switch to [Payment] frame` |
170
- | Frame exit | `User switch to [main] frame` |
132
+ | Navigate | `User is on [login] page` |
133
+ | Click | `User click [Submit] button` |
134
+ | Fill | `User fill [Email] field with {{email}}` |
135
+ | Assert visible | `User see [Welcome] heading is visible` |
136
+ | Assert text | `User see [Title] heading with {{title}}` |
137
+ | Assert state | `User see [Submit] button is disabled` |
138
+ | Wait for | `User wait for [Modal] dialog is visible` |
139
+ | Table row | `User see [Users] table has row with {{name}}` |
140
+ | Table column | `User see [Users] table has [Email] column` |
141
+
142
+ States: `hidden` `visible` `disabled` `enabled` `checked` `unchecked` `focused` `empty` `loading` `selected`
171
143
 
172
144
  ### Tags
173
145
 
174
146
  | Tag | Purpose |
175
147
  |---|---|
176
148
  | `@auth:role` | Use Playwright storage state for auth |
149
+ | `@no-auth` | Disable inherited auth for this scenario |
177
150
  | `@steps:name` | Define reusable step group |
178
151
  | `@extend:name` | Inherit steps from another scenario |
179
152
  | `@manual` | Skip scenario in generation |
180
153
 
181
- ### Selector YAML
154
+ ### YAML Selector Keys
155
+
156
+ Keys are **lowercase with spaces**, Unicode preserved:
157
+ - `[Search Content]` → `search content:`
158
+ - `[Thời gian]` → `thời gian:`
159
+ - Same label, different types → `add campaign--button:` / `add campaign--text:`
160
+
161
+ ### Selector Types
182
162
 
183
163
  ```yaml
184
- submit.button:
185
- type: 'role' # testid, role, text, label, placeholder, locator, page
186
- value: 'button' # role name, testid value, CSS selector, etc.
187
- name: 'Submit' # accessible name
188
- nth: 0 # element index, 0-indexed (omit for strict mode)
189
- exact: true # exact name match (avoid "Submit" matching "Submit Form")
190
- scope: 'desktop navigation' # scope to parent landmark
191
- match: 'exact' # exact text match for getByText
164
+ search:
165
+ type: 'placeholder' # testid, role, placeholder, label, text, locator, page
166
+ value: 'Search users' # placeholder text, role name, CSS selector, etc.
167
+ name: 'Search' # accessible name (for role type)
168
+ nth: 0 # element index (for multiple matches)
192
169
  ```
193
170
 
194
- Locator priority: `data-testid` > `role+name` > `label` > `text` > `CSS`
171
+ Priority: `data-testid` > `role+name` > `placeholder` > `label` > `text` > `CSS locator`
195
172
 
196
173
  ---
197
174
 
@@ -0,0 +1,73 @@
1
+ import { test as base, expect } from '@playwright/test';
2
+ import type { BrowserContext, Page } from '@playwright/test';
3
+
4
+ // Share one context per storageState — avoids creating multiple sessions
5
+ // that trigger server rate limiting or session invalidation
6
+ const contextCache = new Map<string, { context: BrowserContext; page: Page }>();
7
+ const GOTO_PATCHED = Symbol('goto-patched');
8
+
9
+ const test = base.extend({
10
+ page: async ({ browser, storageState }, use) => {
11
+ if (storageState) {
12
+ const cacheKey = typeof storageState === 'string' ? storageState : JSON.stringify(storageState);
13
+
14
+ let cached = contextCache.get(cacheKey);
15
+ if (!cached) {
16
+ const context = await browser.newContext({ storageState });
17
+ const page = await context.newPage();
18
+ cached = { context, page };
19
+ contextCache.set(cacheKey, cached);
20
+ }
21
+
22
+ const page = cached.page;
23
+
24
+ // Patch goto once: skip navigation if already on the target path
25
+ if (!(page as any)[GOTO_PATCHED]) {
26
+ const originalGoto = page.goto.bind(page);
27
+ page.goto = async function (url: string, options?: any) {
28
+ try {
29
+ const currentPath = new URL(page.url()).pathname;
30
+ if (currentPath === url || currentPath === url + '/') {
31
+ // Dismiss any open overlays (dropdowns, dialogs) from previous test
32
+ await page.keyboard.press('Escape').catch(() => {});
33
+ await page.locator('body').click({ position: { x: 1, y: 1 }, force: true }).catch(() => {});
34
+
35
+ // Safety check: if a fixed-position overlay (modal/dialog) is still present, full reload
36
+ // eslint-disable-next-line no-eval -- runs in browser context via Playwright
37
+ const hasOverlay = await page.evaluate(`(() => {
38
+ const el = document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2);
39
+ if (!el) return false;
40
+ let current = el;
41
+ while (current && current !== document.body) {
42
+ if (getComputedStyle(current).position === 'fixed') return true;
43
+ current = current.parentElement;
44
+ }
45
+ return false;
46
+ })()`).catch(() => true);
47
+
48
+ if (hasOverlay) {
49
+ return originalGoto(url, options);
50
+ }
51
+ return null as any;
52
+ }
53
+ } catch {
54
+ // page.url() might be about:blank on first run
55
+ }
56
+ return originalGoto(url, options);
57
+ };
58
+ (page as any)[GOTO_PATCHED] = true;
59
+ }
60
+
61
+ await use(page);
62
+ } else {
63
+ // No storageState: fresh context (e.g., unauthenticated tests)
64
+ const context = await browser.newContext();
65
+ const page = await context.newPage();
66
+ await use(page);
67
+ await page.close();
68
+ await context.close();
69
+ }
70
+ },
71
+ });
72
+
73
+ export { test, expect };
@@ -1,27 +0,0 @@
1
- ---
2
- description: 'Playwright and Sungen error to fix mapping. Referenced by other sungen prompts when running or debugging tests.'
3
- mode: 'agent'
4
- tools: []
5
- ---
6
-
7
- ## Playwright Errors → Fix
8
-
9
- | Error | Fix in `selectors.yaml` |
10
- |---|---|
11
- | strict mode violation | add `nth`, `exact: true`, or specific `name` |
12
- | Element is not an input | change `type` or `value` |
13
- | Timeout waiting for selector | fix `type`/`value`/`name` to match element |
14
- | toBeVisible Timeout | verify accessible name or use `testid` |
15
- | toHaveText mismatch | fix in `test-data.yaml` |
16
- | Navigation failed | fix page `value` path |
17
- | not a select | set `variant: 'custom'` |
18
- | Frame not found | fix `frame` value |
19
-
20
- ## Sungen Errors → Fix
21
-
22
- | Error | Fix |
23
- |---|---|
24
- | Unknown step pattern | rewrite `.feature` step to match supported pattern |
25
- | Missing selector | add key to `selectors.yaml` |
26
- | Missing variable | add key to `test-data.yaml` |
27
- | Invalid selector type | use: role/testid/placeholder/label/text/locator/page/upload/frame |
@@ -1,27 +0,0 @@
1
- ---
2
- description: 'Playwright and Sungen error to fix mapping. Referenced by other sungen prompts when running or debugging tests.'
3
- mode: 'agent'
4
- tools: []
5
- ---
6
-
7
- ## Playwright Errors → Fix
8
-
9
- | Error | Fix in `selectors.yaml` |
10
- |---|---|
11
- | strict mode violation | add `nth`, `exact: true`, or specific `name` |
12
- | Element is not an input | change `type` or `value` |
13
- | Timeout waiting for selector | fix `type`/`value`/`name` to match element |
14
- | toBeVisible Timeout | verify accessible name or use `testid` |
15
- | toHaveText mismatch | fix in `test-data.yaml` |
16
- | Navigation failed | fix page `value` path |
17
- | not a select | set `variant: 'custom'` |
18
- | Frame not found | fix `frame` value |
19
-
20
- ## Sungen Errors → Fix
21
-
22
- | Error | Fix |
23
- |---|---|
24
- | Unknown step pattern | rewrite `.feature` step to match supported pattern |
25
- | Missing selector | add key to `selectors.yaml` |
26
- | Missing variable | add key to `test-data.yaml` |
27
- | Invalid selector type | use: role/testid/placeholder/label/text/locator/page/upload/frame |