@sun-asterisk/sungen 2.2.2 → 2.3.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 (105) hide show
  1. package/README.md +66 -37
  2. package/dist/cli/commands/update.d.ts +3 -0
  3. package/dist/cli/commands/update.d.ts.map +1 -0
  4. package/dist/cli/commands/update.js +21 -0
  5. package/dist/cli/commands/update.js.map +1 -0
  6. package/dist/cli/index.js +3 -1
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/generators/gherkin-parser/index.d.ts +2 -0
  9. package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
  10. package/dist/generators/gherkin-parser/index.js +17 -3
  11. package/dist/generators/gherkin-parser/index.js.map +1 -1
  12. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-accept-action.hbs +1 -0
  13. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-dismiss-action.hbs +1 -0
  14. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-fill-action.hbs +1 -0
  15. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/alert-text-assertion.hbs +8 -0
  16. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/attribute-assertion.hbs +3 -0
  17. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-value-assertion.hbs +1 -0
  18. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +12 -1
  19. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +12 -1
  20. package/dist/generators/test-generator/patterns/assertion-patterns.d.ts.map +1 -1
  21. package/dist/generators/test-generator/patterns/assertion-patterns.js +95 -57
  22. package/dist/generators/test-generator/patterns/assertion-patterns.js.map +1 -1
  23. package/dist/generators/test-generator/patterns/index.d.ts +9 -0
  24. package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
  25. package/dist/generators/test-generator/patterns/index.js +32 -0
  26. package/dist/generators/test-generator/patterns/index.js.map +1 -1
  27. package/dist/generators/test-generator/patterns/interaction-patterns.d.ts +1 -1
  28. package/dist/generators/test-generator/patterns/interaction-patterns.d.ts.map +1 -1
  29. package/dist/generators/test-generator/patterns/interaction-patterns.js +56 -1
  30. package/dist/generators/test-generator/patterns/interaction-patterns.js.map +1 -1
  31. package/dist/generators/test-generator/patterns/table-patterns.d.ts.map +1 -1
  32. package/dist/generators/test-generator/patterns/table-patterns.js +8 -5
  33. package/dist/generators/test-generator/patterns/table-patterns.js.map +1 -1
  34. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  35. package/dist/generators/test-generator/utils/selector-resolver.js +16 -0
  36. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  37. package/dist/orchestrator/ai-rules-updater.d.ts +13 -0
  38. package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -0
  39. package/dist/orchestrator/ai-rules-updater.js +157 -0
  40. package/dist/orchestrator/ai-rules-updater.js.map +1 -0
  41. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  42. package/dist/orchestrator/project-initializer.js +2 -27
  43. package/dist/orchestrator/project-initializer.js.map +1 -1
  44. package/dist/orchestrator/screen-manager.d.ts +1 -0
  45. package/dist/orchestrator/screen-manager.d.ts.map +1 -1
  46. package/dist/orchestrator/screen-manager.js +70 -3
  47. package/dist/orchestrator/screen-manager.js.map +1 -1
  48. package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +18 -9
  49. package/dist/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md +11 -4
  50. package/dist/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +11 -6
  51. package/dist/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +22 -9
  52. package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +170 -24
  53. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +118 -12
  54. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +16 -2
  55. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +124 -71
  56. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +13 -5
  57. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-make-tc.md +12 -4
  58. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +11 -6
  59. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +22 -9
  60. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +170 -24
  61. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +93 -12
  62. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +16 -2
  63. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +124 -72
  64. package/dist/orchestrator/templates/readme.md +13 -8
  65. package/package.json +1 -1
  66. package/src/cli/commands/update.ts +18 -0
  67. package/src/cli/index.ts +3 -1
  68. package/src/generators/gherkin-parser/index.ts +20 -3
  69. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-accept-action.hbs +1 -0
  70. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-dismiss-action.hbs +1 -0
  71. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-fill-action.hbs +1 -0
  72. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/alert-text-assertion.hbs +8 -0
  73. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/attribute-assertion.hbs +3 -0
  74. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-value-assertion.hbs +1 -0
  75. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +12 -1
  76. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +12 -1
  77. package/src/generators/test-generator/patterns/assertion-patterns.ts +106 -65
  78. package/src/generators/test-generator/patterns/index.ts +41 -0
  79. package/src/generators/test-generator/patterns/interaction-patterns.ts +58 -1
  80. package/src/generators/test-generator/patterns/table-patterns.ts +8 -5
  81. package/src/generators/test-generator/utils/selector-resolver.ts +16 -0
  82. package/src/orchestrator/ai-rules-updater.ts +139 -0
  83. package/src/orchestrator/project-initializer.ts +2 -32
  84. package/src/orchestrator/screen-manager.ts +72 -3
  85. package/src/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +18 -9
  86. package/src/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md +11 -4
  87. package/src/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +11 -6
  88. package/src/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +22 -9
  89. package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +170 -24
  90. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +118 -12
  91. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +16 -2
  92. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +124 -71
  93. package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +13 -5
  94. package/src/orchestrator/templates/ai-instructions/copilot-cmd-make-tc.md +12 -4
  95. package/src/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +11 -6
  96. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +22 -9
  97. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +170 -24
  98. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +93 -12
  99. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +16 -2
  100. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +124 -72
  101. package/src/orchestrator/templates/readme.md +13 -8
  102. package/docs/gherkin standards/gherkin-core-standard.md +0 -428
  103. package/docs/gherkin standards/gherkin-core-standard.vi.md +0 -513
  104. package/docs/gherkin-dictionary.md +0 -1071
  105. package/docs/makeauth.md +0 -225
@@ -33,6 +33,46 @@ For options 1 and 2:
33
33
  For option 3:
34
34
  - Overwrite both `.feature` and `test-data.yaml` completely
35
35
 
36
+ ### Requirements-Driven Generation
37
+
38
+ When `qa/screens/<screen>/requirements/` exists, use it as the **primary source** for test case generation. This produces higher quality tests because requirements contain exact validation messages, field constraints, business rules, and states.
39
+
40
+ #### Reading Requirements
41
+
42
+ 1. **`spec.md`** (primary) — structured screen specification:
43
+ - **Sections** → map directly to test case sections
44
+ - **Fields table** → generate boundary value tests (min/max constraints), required field tests, format tests
45
+ - **Validation Rules table** → generate exact assertion tests using the error messages as `{{test_data}}` values
46
+ - **Actions table** → generate interaction tests (click, submit, navigate)
47
+ - **States table** → generate state transition tests (loading, error, success, disabled)
48
+ - **Business Rules** → generate logic tests (limits, permissions, conditional behavior)
49
+ - **Accessibility** → generate tab-order and aria tests
50
+
51
+ 2. **`ui/`** (supplementary) — screenshots, mockups, design images:
52
+ - Read images to understand layout, element positions, visual states
53
+ - Cross-reference with spec.md — identify elements visible in UI but missing from spec
54
+ - Use for UI/UX viewpoint tests (element visibility, placement, responsive)
55
+
56
+ 3. **`notes.md`** (supplementary) — free-form edge cases, decisions, known issues:
57
+ - Extract edge cases → add to test coverage
58
+ - Flag known issues → add TODO scenarios
59
+
60
+ #### How Requirements Improve Each Viewpoint
61
+
62
+ | Viewpoint | Without Requirements | With Requirements |
63
+ |-----------|---------------------|-------------------|
64
+ | **UI/UX** | "see [Field] is visible" (generic) | "see [Field] field" + verify label, placeholder, default from spec |
65
+ | **Validation** | "submit empty → see error" (vague) | "submit empty email → see {{email_required_error}}" with exact message from spec |
66
+ | **Logic** | Based on observed page behavior | Business rules drive specific tests (lockout after N attempts, session expiry) |
67
+ | **Security** | Generic injection tests | Role-based tests from auth requirements, permission-specific scenarios |
68
+
69
+ #### Merging Requirements + Live Page
70
+
71
+ If the user also explores the live page:
72
+ - **Verify** spec.md against actual page — flag mismatches (e.g., field in spec but not on page)
73
+ - **Supplement** — discover elements on page not in spec (e.g., footer links, tooltips)
74
+ - **Exact text** — capture actual placeholder text, button labels, error messages from live page and update test-data accordingly
75
+
36
76
  ### Page Exploration & Auth
37
77
 
38
78
  Use Playwright MCP to explore the live page. If the page requires authentication:
@@ -55,26 +95,7 @@ Use Playwright MCP to explore the live page. If the page requires authentication
55
95
 
56
96
  #### Detail screens with dynamic IDs
57
97
 
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`.
98
+ For screens like `/admin/users/:id` or `/products/:slug`, write Gherkin normally (`User is on [User Detail] page`). The real ID will be resolved during `/sungen-make-test` when selectors are generated from the live page. See `sungen-selector-fix` skill for details.
78
99
 
79
100
  ### Section-Focused Approach
80
101
 
@@ -113,72 +134,90 @@ For each selected section, generate **20+ scenarios per applicable viewpoint**.
113
134
 
114
135
  Present a test plan summary and wait for user confirmation before generating files.
115
136
 
137
+ ### Assertion Quality Rules
138
+
139
+ **CRITICAL** — these rules prevent shallow, low-value test cases:
140
+
141
+ 1. **NEVER use `is visible`** — `User see [T] type` already asserts visibility. Writing `is visible` is redundant noise. Only use `is hidden` to assert something is NOT shown.
142
+ 2. **Group related assertions** — one scenario can have 3-7 `Then/And` steps. Don't waste a whole scenario on one element. Group elements that verify the same concern.
143
+ 3. **Assert content, not just existence** — verify values, text, states, not just "it's there":
144
+ - `User see [Title] heading with {{page_title}}` — verify text
145
+ - `User see [Email] field with {{default_email}}` — verify default value
146
+ - `User see [Submit] button is disabled` — verify state
147
+ - `User see [Error] message with {{error_text}}` — verify exact error
148
+ 4. **Every assertion must have test value** — if you write `User see [T] type`, ask: what EXACTLY should the user see? Add `with {{value}}` or `is state` whenever the expected content/state is known.
149
+
150
+ **Bad** (shallow — just checks existence):
151
+ ```gherkin
152
+ Scenario: VP-UI-001 Email field is visible
153
+ Given User is on [Login] page
154
+ Then User see [Email] field is visible
155
+
156
+ Scenario: VP-UI-002 Password field is visible
157
+ Given User is on [Login] page
158
+ Then User see [Password] field is visible
159
+ ```
160
+
161
+ **Good** (rich — verifies content, states, groups related checks):
162
+ ```gherkin
163
+ Scenario: VP-UI-001 Login form displays all fields with correct defaults
164
+ Given User is on [Login] page
165
+ Then User see [Login] heading with {{login_title}}
166
+ And User see [Email] field
167
+ And User see [Password] field
168
+ And User see [Remember me] checkbox is unchecked
169
+ And User see [Submit] button is enabled
170
+ And User see [Forgot password] link
171
+ ```
172
+
116
173
  ### Viewpoint Categories
117
174
 
118
175
  | VP Category | Description |
119
176
  |---|---|
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".** |
177
+ | **UI/UX** | Default appearance, default values/text, default states. Group related elements per scenario. |
178
+ | **Validation** | Input validation, error messages, edge cases. **Assert exact error messages via `User see [T] with {{error_var}}`**store texts in test-data.yaml. |
122
179
  | **Logic** | Business logic, interactions, state changes |
123
180
  | **Security** | Auth guards, injection, permission checks |
124
181
 
125
182
  ### Coverage Checklist per Section Pattern
126
183
 
127
- Apply the relevant checklist based on the section pattern:
128
-
129
184
  #### 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
185
+ - **UI/UX**: All fields + labels + default values in 1-2 grouped scenarios. Default states (button enabled/disabled, checkbox unchecked). Placeholder text via `with {{placeholder}}`.
186
+ - **Validation**: Empty submit verify all error messages. Each required field empty individually verify specific error. Invalid formats → verify specific error. Boundary values (min/max length). Special chars, unicode, XSS, SQL injection.
187
+ - **Logic**: Successful submit verify success state/redirect. Edit existing verify pre-filled values. Cancel verify form resets. Field dependencies (show/hide).
188
+ - **Security**: Unauthorized submit, role-based field visibility, input sanitization
135
189
 
136
190
  #### 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
191
+ - **UI/UX**: All column headers in one scenario (`User see [Col] column in [Table] table`). Row data displays with correct values. Empty state message. Action buttons per row.
192
+ - **Logic**: Sort ascending/descending. Filter by column. Search. Row actions (edit/delete/view). Bulk select + action.
193
+ - **Security**: Action permissions per role
141
194
 
142
195
  #### 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
196
+ - **UI/UX**: Search field + filter buttons + clear button states in one scenario
197
+ - **Validation**: Empty search, special chars, injection, long text, unicode
198
+ - **Logic**: Apply/clear single filter, combine filters, no results state with message
199
+ - **Security**: Injection via search/filter params
147
200
 
148
201
  #### 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
202
+ - **UI/UX**: Page indicator + button states (previous disabled on page 1, next enabled)
203
+ - **Logic**: Navigate pages, boundary behavior, indicator updates
152
204
 
153
205
  #### 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
206
+ - **UI/UX**: Modal content + all fields + close button in one scenario
207
+ - **Validation**: Field validation inside modal with exact errors
208
+ - **Logic**: Open/close methods (X, Escape, overlay), submit success/error behavior
168
209
 
169
210
  #### 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
211
+ - **UI/UX**: All tab labels + active tab highlighted + default tab content
212
+ - **Logic**: Switch tabs verify content changes, accordion expand/collapse
173
213
 
174
214
  ### General Coverage Dimensions (aim for 20+ total per viewpoint)
175
215
 
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
216
+ **Happy paths (3-5):** Standard flow with full assertion of result state
217
+ **Edge cases (5-8):** Empty, max length, special chars, unicode, whitespace, boundary values
218
+ **Negative cases (3-5):** Invalid format, missing required, wrong type, exact error messages
219
+ **State transitions (2-4):** Before/after action, verify both old and new state
220
+ **Combinatorial (2-4):** Multiple invalid fields, valid+invalid combos
182
221
 
183
222
  ### SPA Wait-For Steps
184
223
 
@@ -209,24 +248,37 @@ Feature: <Screen> Screen
209
248
  # Section: Create User Form
210
249
  # ============================================================
211
250
 
212
- # --- UI/UX (20+) ---
251
+ # --- UI/UX ---
213
252
 
214
- Scenario: VP-UI-001 Name field is visible
215
- ...
253
+ Scenario: VP-UI-001 Form displays all fields with correct defaults
254
+ Given User is on [Create User] page
255
+ Then User see [Create User] heading with {{form_title}}
256
+ And User see [Name] field
257
+ And User see [Email] field
258
+ And User see [Role] dropdown with {{default_role}}
259
+ And User see [Submit] button is disabled
260
+ And User see [Cancel] button is enabled
216
261
 
217
- # --- Validation (20+) ---
262
+ # --- Validation ---
218
263
 
219
- Scenario: VP-VAL-001 Submit with empty name
220
- ...
264
+ Scenario: VP-VAL-001 Submit with all empty fields shows errors
265
+ Given User is on [Create User] page
266
+ When User click [Submit] button
267
+ Then User see [Name error] message with {{name_required_error}}
268
+ And User see [Email error] message with {{email_required_error}}
221
269
 
222
270
  # ============================================================
223
271
  # Section: User Table
224
272
  # ============================================================
225
273
 
226
- # --- UI/UX (20+) ---
274
+ # --- UI/UX ---
227
275
 
228
- Scenario: VP-UI-025 Table displays all columns
229
- ...
276
+ Scenario: VP-UI-010 Table displays all columns
277
+ Given User is on [Users] page
278
+ Then User see [Name] column in [Users] table
279
+ And User see [Email] column in [Users] table
280
+ And User see [Status] column in [Users] table
281
+ And User see [Actions] column in [Users] table
230
282
  ```
231
283
 
232
284
  **Naming convention:** `VP-<CATEGORY>-<NNN>` prefix in Scenario name.
@@ -15,7 +15,11 @@ sungen generate → compiles Gherkin + selectors + data → Playwright .spec.ts
15
15
  ├── qa/screens/<name>/
16
16
  │ ├── features/ # .feature files (Gherkin)
17
17
  │ ├── selectors/ # Element locator YAML mappings
18
- └── test-data/ # Test data YAML values
18
+ ├── test-data/ # Test data YAML values
19
+ │ └── requirements/ # Screen specs, UI designs, notes
20
+ │ ├── spec.md # Structured screen specification
21
+ │ ├── ui/ # Screenshots, mockups, design images
22
+ │ └── notes.md # Edge cases, decisions (optional)
19
23
  ├── specs/
20
24
  │ └── generated/ # Auto-generated Playwright tests
21
25
  ├── .claude/
@@ -53,7 +57,7 @@ Use AI commands (Claude Code or GitHub Copilot) to drive the workflow:
53
57
  |---|---|
54
58
  | `/sungen:add-screen` | `/sungen-add-screen` |
55
59
 
56
- Scaffolds `qa/screens/<name>/` with empty feature, selectors, and test-data files, then asks if you want to create test cases.
60
+ Scaffolds `qa/screens/<name>/` with empty feature, selectors, test-data, and requirements files. Fill `requirements/spec.md` with screen specs before creating test cases for higher quality output.
57
61
 
58
62
  ### Step 2: Create test cases
59
63
 
@@ -62,10 +66,11 @@ Scaffolds `qa/screens/<name>/` with empty feature, selectors, and test-data file
62
66
  | `/sungen:make-tc login` | `/sungen-make-tc login` |
63
67
 
64
68
  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`
69
+ 1. Reads `requirements/spec.md` for screen specs (fields, validation, business rules, states)
70
+ 2. Optionally explores the live page via Playwright MCP to verify and supplement
71
+ 3. Identifies screen sections asks user which to focus on
72
+ 4. Generates **20+ scenarios per viewpoint** (UI/UX, Validation, Logic, Security) for each section
73
+ 5. Confirms test plan before generating `.feature` + `test-data.yaml`
69
74
 
70
75
  ### Step 3: Compile & run tests
71
76
 
@@ -136,8 +141,8 @@ User <action> [<Target>] <type> with {{<Value>}}
136
141
  | Assert text | `User see [Title] heading with {{title}}` |
137
142
  | Assert state | `User see [Submit] button is disabled` |
138
143
  | 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` |
144
+ | Table row | `User see [Users] table row with {{name}}` |
145
+ | Table column | `User see [Email] column in [Users] table` |
141
146
 
142
147
  States: `hidden` `visible` `disabled` `enabled` `checked` `unchecked` `focused` `empty` `loading` `selected`
143
148
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sun-asterisk/sungen",
3
- "version": "2.2.2",
3
+ "version": "2.3.0",
4
4
  "description": "Deterministic E2E Test Compiler - Gherkin + Selectors → Playwright tests",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,18 @@
1
+ import { Command } from 'commander';
2
+
3
+ export function registerUpdateCommand(program: Command): void {
4
+ program
5
+ .command('update')
6
+ .description('Update AI rules, commands, and skills to the latest version')
7
+ .option('--dry-run', 'Show what would be updated without making changes')
8
+ .action(async (options: { dryRun?: boolean }) => {
9
+ try {
10
+ const { AIRulesUpdater } = require('../../orchestrator/ai-rules-updater');
11
+ const updater = new AIRulesUpdater(process.cwd());
12
+ await updater.update(options.dryRun ?? false);
13
+ } catch (error) {
14
+ console.error('❌ Update failed:', error);
15
+ process.exit(1);
16
+ }
17
+ });
18
+ }
package/src/cli/index.ts CHANGED
@@ -9,6 +9,7 @@ import { registerInitCommand } from './commands/init';
9
9
  import { registerAddCommand } from './commands/add';
10
10
  import { registerGenerateCommand } from './commands/generate';
11
11
  import { registerMakeauthCommand } from './commands/makeauth';
12
+ import { registerUpdateCommand } from './commands/update';
12
13
 
13
14
  async function main() {
14
15
  const program = new Command();
@@ -16,7 +17,7 @@ async function main() {
16
17
  program
17
18
  .name('sungen')
18
19
  .description('Deterministic E2E Test Compiler — Gherkin + Selectors → Playwright')
19
- .version('2.2.2');
20
+ .version('2.3.0');
20
21
 
21
22
  // Global options
22
23
  program
@@ -27,6 +28,7 @@ async function main() {
27
28
  registerAddCommand(program);
28
29
  registerGenerateCommand(program);
29
30
  registerMakeauthCommand(program);
31
+ registerUpdateCommand(program);
30
32
 
31
33
  await program.parseAsync(process.argv);
32
34
  }
@@ -14,6 +14,8 @@ export interface ParsedStep {
14
14
  elementType?: string; // Element type after [Selector] e.g., "button", "text", "link", "field"
15
15
  nth?: number; // Positional index from "[Element] field 3" → 3 (0 = not specified)
16
16
  featurePath?: string; // NEW: Feature path for page type (e.g., "/", "/dashboard")
17
+ parentRef?: string; // Parent scope reference: "in [Parent Name] parentType" → parentRef = "Parent Name"
18
+ parentType?: string; // Parent scope type: table, list, section, dialog, form
17
19
  }
18
20
 
19
21
  export interface ParsedScenario {
@@ -122,7 +124,20 @@ export class GherkinParser {
122
124
  * Parse a single step and extract selector/data references
123
125
  */
124
126
  private parseStep(step: Messages.Step): ParsedStep {
125
- const text = step.text;
127
+ let text = step.text;
128
+
129
+ // === Extract parent scoping: "in [Parent Name] parentType" ===
130
+ // Must be extracted first so the parent [brackets] don't interfere with target selector extraction.
131
+ // Valid parent types: table, list, section, dialog, form
132
+ const parentMatch = text.match(/\s+in\s+\[([^\]]+)\]\s+(table|list|section|dialog|form)\b/i);
133
+ let parentRef: string | undefined;
134
+ let parentType: string | undefined;
135
+ if (parentMatch) {
136
+ parentRef = parentMatch[1];
137
+ parentType = parentMatch[2].toLowerCase();
138
+ // Remove parent scoping from text so it doesn't interfere with other parsing
139
+ text = text.slice(0, parentMatch.index) + text.slice(parentMatch.index! + parentMatch[0].length);
140
+ }
126
141
 
127
142
  // Extract selector reference: [Email Address] or [login:email_field] (legacy)
128
143
  // Support natural language and legacy formats
@@ -146,7 +161,7 @@ export class GherkinParser {
146
161
  elementType = elementTypeMatch ? elementTypeMatch[1].toLowerCase() : undefined;
147
162
  } else {
148
163
  // Extract final word if it's a known type (page, button, field, etc)
149
- const finalWordMatch = text.match(/\b(page|button|field|link|text|checkbox|radio|select|dropdown|modal|dialog|message|error|warning|success|alert|table|list|list-item|listitem|row)\b$/i);
164
+ const finalWordMatch = text.match(/\b(page|button|field|link|text|checkbox|radio|select|dropdown|modal|dialog|drawer|message|error|warning|success|alert|table|list|list-item|listitem|row|search|option|slider|toggle|tab|breadcrumb|overlay|step|section|card|item|icon|image|header|label|badge|tooltip|tag|menuitem|cell|column|uploader|date-picker|key)\b$/i);
150
165
  elementType = finalWordMatch ? finalWordMatch[1].toLowerCase() : undefined;
151
166
  }
152
167
 
@@ -159,12 +174,14 @@ export class GherkinParser {
159
174
 
160
175
  return {
161
176
  keyword: step.keyword.trim(),
162
- text,
177
+ text: step.text, // Preserve original text (with parent scoping) for pattern matching
163
178
  selectorRef,
164
179
  dataRef,
165
180
  value,
166
181
  elementType,
167
182
  nth,
183
+ parentRef,
184
+ parentType,
168
185
  };
169
186
  }
170
187
 
@@ -0,0 +1 @@
1
+ page.once('dialog', dialog => dialog.accept());
@@ -0,0 +1 @@
1
+ page.once('dialog', dialog => dialog.dismiss());
@@ -0,0 +1 @@
1
+ page.once('dialog', dialog => dialog.accept('{{escapeQuotes fillValue}}'));
@@ -0,0 +1,8 @@
1
+ const dialogPromise{{stepCounter}} = new Promise<string>(resolve => {
2
+ page.once('dialog', dialog => {
3
+ resolve(dialog.message());
4
+ dialog.accept();
5
+ });
6
+ });
7
+ // Trigger the dialog action, then:
8
+ // expect(await dialogPromise{{stepCounter}}).toContain('{{escapeQuotes dataValue}}');
@@ -0,0 +1,3 @@
1
+ {{#if pattern}}await expect({{> locator}}).toHaveAttribute('{{attribute}}', /{{dataValue}}/);
2
+ {{else}}await expect({{> locator}}).toHaveAttribute('{{attribute}}', '{{dataValue}}');
3
+ {{/if}}
@@ -0,0 +1 @@
1
+ await expect({{> locator}}).toHaveValue('{{escapeQuotes dataValue}}');
@@ -1,3 +1,13 @@
1
+ {{#if parentLocator}}{{parentLocator}}.{{#switch strategy~}}
2
+ {{~#case 'testid'}}getByTestId('{{value}}'){{/case~}}
3
+ {{~#case 'role'}}{{#if name}}getByRole('{{role}}', { name: '{{escapeQuotes name}}'{{#if exact}}, exact: true{{/if}} }){{else}}getByRole('{{role}}'{{#if exact}}, { exact: true }{{/if}}){{/if}}{{/case~}}
4
+ {{~#case 'placeholder'}}getByPlaceholder('{{escapeQuotes value}}'{{#if exact}}, { exact: true }{{/if}}){{/case~}}
5
+ {{~#case 'label'}}getByLabel('{{escapeQuotes value}}'{{#if exact}}, { exact: true }{{/if}}){{/case~}}
6
+ {{~#case 'text'}}getByText('{{escapeQuotes value}}'{{#if exact}}, { exact: true }{{/if}}){{/case~}}
7
+ {{~#case 'locator'}}locator('{{value}}'){{/case~}}
8
+ {{~#case 'id'}}locator('{{value}}'){{/case~}}
9
+ {{~#default}}locator('{{value}}'){{/default~}}
10
+ {{~/switch}}{{else~}}
1
11
  {{#if scope}}{{pageRoot}}.getByLabel('{{escapeQuotes scope}}').{{#switch strategy~}}
2
12
  {{~#case 'testid'}}getByTestId('{{value}}'){{/case~}}
3
13
  {{~#case 'role'}}{{#if name}}getByRole('{{role}}', { name: '{{escapeQuotes name}}'{{#if exact}}, exact: true{{/if}} }){{else}}getByRole('{{role}}'{{#if exact}}, { exact: true }{{/if}}){{/if}}{{/case~}}
@@ -16,4 +26,5 @@
16
26
  {{~#case 'locator'}}{{> locator-strategies/locator}}{{/case~}}
17
27
  {{~#case 'id'}}{{> locator-strategies/id}}{{/case~}}
18
28
  {{~#default}}{{> locator-strategies/default}}{{/default~}}
19
- {{~/switch}}{{/if}}
29
+ {{~/switch}}{{/if~}}
30
+ {{/if}}
@@ -1,3 +1,13 @@
1
+ {{#if parentLocator}}{{parentLocator}}.{{#switch strategy~}}
2
+ {{~#case 'testid'}}getByTestId('{{value}}'){{/case~}}
3
+ {{~#case 'role'}}{{#if name}}getByRole('{{role}}', { name: '{{escapeQuotes name}}'{{#if exact}}, exact: true{{/if}} }){{else}}getByRole('{{role}}'{{#if exact}}, { exact: true }{{/if}}){{/if}}{{/case~}}
4
+ {{~#case 'placeholder'}}getByPlaceholder('{{escapeQuotes value}}'{{#if exact}}, { exact: true }{{/if}}){{/case~}}
5
+ {{~#case 'label'}}getByLabel('{{escapeQuotes value}}'{{#if exact}}, { exact: true }{{/if}}){{/case~}}
6
+ {{~#case 'text'}}getByText('{{escapeQuotes value}}'{{#if exact}}, { exact: true }{{/if}}){{/case~}}
7
+ {{~#case 'locator'}}locator('{{value}}'){{/case~}}
8
+ {{~#case 'id'}}locator('{{value}}'){{/case~}}
9
+ {{~#default}}locator('{{value}}'){{/default~}}
10
+ {{~/switch}}{{> locator-nth}}{{else~}}
1
11
  {{#if scope}}{{pageRoot}}.getByLabel('{{escapeQuotes scope}}').{{#switch strategy~}}
2
12
  {{~#case 'testid'}}getByTestId('{{value}}'){{/case~}}
3
13
  {{~#case 'role'}}{{#if name}}getByRole('{{role}}', { name: '{{escapeQuotes name}}'{{#if exact}}, exact: true{{/if}} }){{else}}getByRole('{{role}}'{{#if exact}}, { exact: true }{{/if}}){{/if}}{{/case~}}
@@ -16,4 +26,5 @@
16
26
  {{~#case 'locator'}}{{> locator-strategies/locator}}{{/case~}}
17
27
  {{~#case 'id'}}{{> locator-strategies/id}}{{/case~}}
18
28
  {{~#default}}{{> locator-strategies/default}}{{/default~}}
19
- {{~/switch}}{{> locator-nth}}{{/if}}
29
+ {{~/switch}}{{> locator-nth}}{{/if~}}
30
+ {{/if}}