@sun-asterisk/sungen 2.3.1 → 2.4.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.
- package/README.md +10 -11
- package/dist/cli/index.js +1 -1
- package/dist/generators/gherkin-parser/index.d.ts +8 -0
- package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
- package/dist/generators/gherkin-parser/index.js +12 -0
- package/dist/generators/gherkin-parser/index.js.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +5 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-match-data.hbs +15 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +7 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +5 -1
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/index.js +2 -1
- package/dist/generators/test-generator/patterns/index.js.map +1 -1
- package/dist/generators/test-generator/patterns/table-patterns.d.ts +12 -0
- package/dist/generators/test-generator/patterns/table-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/table-patterns.js +142 -98
- package/dist/generators/test-generator/patterns/table-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/types.d.ts +2 -0
- package/dist/generators/test-generator/patterns/types.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.d.ts +13 -0
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.js +80 -0
- package/dist/generators/test-generator/step-mapper.js.map +1 -1
- package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
- package/dist/orchestrator/ai-rules-updater.js +8 -6
- package/dist/orchestrator/ai-rules-updater.js.map +1 -1
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +33 -2
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/screen-manager.js +1 -1
- package/dist/orchestrator/screen-manager.js.map +1 -1
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +5 -5
- package/{src/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md → dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md} +7 -7
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-review.md +21 -0
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +32 -0
- package/dist/orchestrator/templates/ai-instructions/claude-config.md +65 -12
- package/dist/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +128 -52
- package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +15 -39
- package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +72 -259
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +57 -205
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +104 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-viewpoint.md +188 -0
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +4 -4
- package/dist/orchestrator/templates/ai-instructions/{copilot-cmd-make-tc.md → copilot-cmd-create-test.md} +8 -8
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-review.md +24 -0
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +35 -0
- package/dist/orchestrator/templates/ai-instructions/copilot-config.md +66 -13
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +128 -52
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +15 -39
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +72 -234
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +57 -205
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +104 -0
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint.md +188 -0
- package/dist/orchestrator/templates/readme.md +85 -22
- package/package.json +1 -1
- package/src/cli/index.ts +1 -1
- package/src/generators/gherkin-parser/index.ts +23 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +5 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-match-data.hbs +15 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +7 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +5 -1
- package/src/generators/test-generator/patterns/index.ts +2 -1
- package/src/generators/test-generator/patterns/table-patterns.ts +155 -111
- package/src/generators/test-generator/patterns/types.ts +2 -0
- package/src/generators/test-generator/step-mapper.ts +87 -1
- package/src/orchestrator/ai-rules-updater.ts +8 -6
- package/src/orchestrator/project-initializer.ts +38 -2
- package/src/orchestrator/screen-manager.ts +1 -1
- package/src/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +5 -5
- package/{dist/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md → src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md} +7 -7
- package/src/orchestrator/templates/ai-instructions/claude-cmd-review.md +21 -0
- package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +32 -0
- package/src/orchestrator/templates/ai-instructions/claude-config.md +65 -12
- package/src/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +128 -52
- package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +15 -39
- package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +72 -259
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +57 -205
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +104 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-viewpoint.md +188 -0
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +4 -4
- package/src/orchestrator/templates/ai-instructions/{copilot-cmd-make-tc.md → copilot-cmd-create-test.md} +8 -8
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-review.md +24 -0
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +35 -0
- package/src/orchestrator/templates/ai-instructions/copilot-config.md +66 -13
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +128 -52
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +15 -39
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +72 -234
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +57 -205
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +104 -0
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-viewpoint.md +188 -0
- package/src/orchestrator/templates/readme.md +85 -22
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +0 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +0 -2
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +0 -29
- package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-review.md +0 -228
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +0 -32
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-review.md +0 -228
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +0 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +0 -2
- package/src/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +0 -29
- package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-review.md +0 -228
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +0 -32
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-review.md +0 -228
|
@@ -1,287 +1,125 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sungen-selector-fix
|
|
3
|
-
description: 'Selector
|
|
3
|
+
description: 'Selector fixing strategy — diagnose failures, explore live page targeted, fix broken selectors. Auto-loaded by run-test command.'
|
|
4
4
|
user-invocable: false
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Strategy: Fix Only What Breaks
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Most selectors auto-infer from Gherkin element types (see `sungen-selector-keys` skill). Only add YAML entries for selectors that fail during test execution.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**Minimal `selectors.yaml`**: page selectors (required), overrides for elements where auto-infer doesn't work. Never generate a full page catalog upfront.
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
## Step 1: Diagnose Failures
|
|
16
16
|
|
|
17
|
-
|
|
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`
|
|
17
|
+
Parse Playwright error output to categorize failures:
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
| Error pattern | Root cause | Fix target |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| `No element found` / `strict mode violation` | Selector mismatch | `selectors.yaml` |
|
|
22
|
+
| `toBeVisible` timeout | Wrong name or missing element | `selectors.yaml` |
|
|
23
|
+
| `toHaveText` / `toHaveValue` mismatch | Wrong expected data | `test-data.yaml` |
|
|
24
|
+
| `page.goto` error | Wrong URL | page selector in `selectors.yaml` |
|
|
25
|
+
| `frame` error | Element inside iframe | add `frame` field |
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
**Group by root cause** — if 5 tests fail because `[Submit]` button has a different name, that's 1 fix, not 5.
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
**Check `test-results/` first** — Playwright captures failure screenshots automatically. Use these to diagnose before any MCP exploration.
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
---
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
## Step 2: Targeted MCP Exploration
|
|
33
34
|
|
|
34
|
-
|
|
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)
|
|
35
|
+
Only when `test-results/` screenshots are insufficient:
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
1. Read `baseURL` from `playwright.config.ts`
|
|
38
|
+
2. `browser_navigate` to target page
|
|
39
|
+
3. If redirected to login → ask user to log in manually via MCP browser
|
|
40
|
+
4. Take **ONE** `browser_snapshot` — fix all broken selectors from this single snapshot
|
|
41
|
+
|
|
42
|
+
**Never use `sungen makeauth`.** Never use `browser_evaluate` to inject cookies.
|
|
47
43
|
|
|
48
44
|
---
|
|
49
45
|
|
|
50
|
-
|
|
46
|
+
## Step 3: Fix Broken Selectors
|
|
51
47
|
|
|
52
|
-
For each
|
|
48
|
+
For each failed selector, find the correct locator from the snapshot:
|
|
53
49
|
|
|
54
|
-
|
|
50
|
+
Selector priority (use first applicable):
|
|
55
51
|
|
|
56
|
-
| Priority | type | When
|
|
52
|
+
| Priority | type | When |
|
|
57
53
|
|---|---|---|
|
|
58
|
-
| 1 | `testid` | `data-testid`
|
|
59
|
-
| 2 | `role` + exact name | Interactive elements
|
|
60
|
-
| 3 | `placeholder` | Input with
|
|
61
|
-
| 4 | `label` | Form field with `<label>`
|
|
62
|
-
| 5 | `locator` (CSS
|
|
63
|
-
| 6 | `text` | Static text only
|
|
54
|
+
| 1 | `testid` | `data-testid` exists |
|
|
55
|
+
| 2 | `role` + exact name | Interactive elements |
|
|
56
|
+
| 3 | `placeholder` | Input with placeholder |
|
|
57
|
+
| 4 | `label` | Form field with `<label>` |
|
|
58
|
+
| 5 | `locator` (CSS) | No accessible name |
|
|
59
|
+
| 6 | `text` | Static text only |
|
|
64
60
|
|
|
65
|
-
|
|
61
|
+
**Exact name rule**: copy name character-for-character from snapshot. Never infer from Gherkin label.
|
|
66
62
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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'
|
|
63
|
+
Check for `data-testid` attributes if role-based matching fails:
|
|
64
|
+
```js
|
|
65
|
+
Array.from(document.querySelectorAll('[data-testid]'))
|
|
66
|
+
.map(e => ({ testid: e.dataset.testid, tag: e.tagName, text: e.textContent.trim().slice(0, 60) }))
|
|
81
67
|
```
|
|
82
68
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
type: 'locator'
|
|
90
|
-
value: '[role="searchbox"]'
|
|
91
|
-
|
|
92
|
-
icon button:
|
|
93
|
-
type: 'locator'
|
|
94
|
-
value: '[aria-label="Close"]'
|
|
95
|
-
```
|
|
69
|
+
Common fixes:
|
|
70
|
+
- Name mismatch → copy exact name from snapshot
|
|
71
|
+
- Multiple matches → add `nth` or `exact: true`
|
|
72
|
+
- No accessible name → use `testid` or `locator` (CSS)
|
|
73
|
+
- Element in iframe → add `frame` field
|
|
74
|
+
- Dynamic content → use `testid` or structural `role` + `nth`
|
|
96
75
|
|
|
97
76
|
---
|
|
98
77
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
For elements whose text changes between test runs (list items, card data, user-generated content, timestamps):
|
|
78
|
+
## Step 4: Table Selectors
|
|
102
79
|
|
|
103
|
-
|
|
80
|
+
For table patterns, add table selectors with `columns` config:
|
|
104
81
|
|
|
105
82
|
```yaml
|
|
106
|
-
|
|
107
|
-
card title:
|
|
108
|
-
type: 'text'
|
|
109
|
-
value: 'Some specific title'
|
|
110
|
-
|
|
111
|
-
# GOOD — structural: first heading inside a card container
|
|
112
|
-
card title:
|
|
83
|
+
users:
|
|
113
84
|
type: 'role'
|
|
114
|
-
value: '
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
85
|
+
value: 'table'
|
|
86
|
+
name: 'Users'
|
|
87
|
+
columns:
|
|
88
|
+
username:
|
|
89
|
+
index: 0
|
|
90
|
+
header: 'Username'
|
|
91
|
+
email:
|
|
92
|
+
index: 1
|
|
93
|
+
header: 'Email'
|
|
94
|
+
status:
|
|
95
|
+
index: 2
|
|
96
|
+
header: 'Status'
|
|
121
97
|
```
|
|
122
98
|
|
|
123
|
-
|
|
99
|
+
**How to build `columns`**: count column headers in snapshot (left to right, 0-indexed). Map each `[Col] column` reference from feature file to its index.
|
|
124
100
|
|
|
125
101
|
---
|
|
126
102
|
|
|
127
|
-
|
|
103
|
+
## Step 5: Detail Screens with Dynamic IDs
|
|
128
104
|
|
|
129
|
-
For screens like `/admin/users/:id
|
|
130
|
-
1. Navigate to
|
|
131
|
-
2.
|
|
132
|
-
3. Use `User is on [X] page` — sungen resolves the path from the selector
|
|
105
|
+
For screens like `/admin/users/:id`:
|
|
106
|
+
1. Navigate to list page via MCP to find a real record ID
|
|
107
|
+
2. Hardcode the ID in page selector
|
|
133
108
|
|
|
134
109
|
```yaml
|
|
135
|
-
# selectors.yaml — full path with real ID
|
|
136
110
|
user detail:
|
|
137
111
|
type: 'page'
|
|
138
112
|
value: '/admin/users/de42d800-0f5a-490e-9dcf-344fedbd34a5'
|
|
139
113
|
```
|
|
140
114
|
|
|
141
|
-
Note: the selector uses a hardcoded ID from the live page. If the record is deleted, update the ID in `selectors.yaml`.
|
|
142
|
-
|
|
143
|
-
---
|
|
144
|
-
|
|
145
|
-
### Step 5: Handle SPA / Client-side Routing
|
|
146
|
-
|
|
147
|
-
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.
|
|
148
|
-
|
|
149
|
-
**Symptom**: Tests see a different page than expected (e.g. home page instead of `/dashboard`).
|
|
150
|
-
|
|
151
|
-
**Fix in the feature file**: Add an explicit assertion after navigation to confirm the correct page has loaded before proceeding:
|
|
152
|
-
|
|
153
|
-
```gherkin
|
|
154
|
-
Scenario: VP-UI-001 Some test
|
|
155
|
-
Given User is on [Dashboard] page
|
|
156
|
-
Then User see [Dashboard Title] heading is visible ← confirms page loaded
|
|
157
|
-
When User click [Some Button] button
|
|
158
|
-
...
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
The "page loaded" check should use a **stable, always-visible element** on that specific page — typically the main page heading.
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
### Step 6: Handle Multiple Matches (strict mode)
|
|
166
|
-
|
|
167
|
-
When an element appears more than once (e.g. desktop + mobile nav, repeated list items), add `nth`:
|
|
168
|
-
|
|
169
|
-
```yaml
|
|
170
|
-
nav link:
|
|
171
|
-
type: 'role'
|
|
172
|
-
value: 'link'
|
|
173
|
-
name: 'Dashboard'
|
|
174
|
-
nth: 0 # first occurrence (desktop nav)
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Use `nth: 0` for the first match of dynamic/repeated elements.
|
|
178
|
-
|
|
179
|
-
---
|
|
180
|
-
|
|
181
|
-
### Auto-Infer (skip YAML entry)
|
|
182
|
-
|
|
183
|
-
Many elements don't need a YAML entry — sungen auto-infers from the Gherkin label:
|
|
184
|
-
|
|
185
|
-
| Gherkin | Auto-inferred locator |
|
|
186
|
-
|---|---|
|
|
187
|
-
| `[Submit] button` | `getByRole('button', { name: 'Submit' })` |
|
|
188
|
-
| `[Home] link` | `getByRole('link', { name: 'Home' })` |
|
|
189
|
-
| `[Welcome] heading` / `header` | `getByRole('heading', { name: 'Welcome' })` |
|
|
190
|
-
| `[Email] field` | `getByPlaceholder('Email')` |
|
|
191
|
-
| `[Success] text` / `message` / `label` | `getByText('Success')` |
|
|
192
|
-
| `[Terms] checkbox` | `getByRole('checkbox', { name: 'Terms' })` |
|
|
193
|
-
| `[Global] search` | `getByRole('searchbox', { name: 'Global' })` |
|
|
194
|
-
| `[Vietnam] option` | `getByRole('option', { name: 'Vietnam' })` |
|
|
195
|
-
| `[Price] slider` | `getByRole('slider', { name: 'Price' })` |
|
|
196
|
-
| `[Notification] toggle` | `getByRole('switch', { name: 'Notification' })` |
|
|
197
|
-
| `[Profile] tab` | `getByRole('tab', { name: 'Profile' })` |
|
|
198
|
-
| `[Confirm] dialog` / `modal` / `drawer` | `getByRole('dialog', { name: 'Confirm' })` |
|
|
199
|
-
|
|
200
|
-
**Only add a YAML entry when auto-infer won't work:**
|
|
201
|
-
- The accessible name differs from the Gherkin label
|
|
202
|
-
- Needs `nth` to disambiguate
|
|
203
|
-
- Needs `testid` or CSS locator
|
|
204
|
-
- Is dynamic content (needs structural selector)
|
|
205
|
-
- Is a bare input with no label or placeholder
|
|
206
|
-
|
|
207
|
-
---
|
|
208
|
-
|
|
209
|
-
### Proactive Selector Validation (before running tests)
|
|
210
|
-
|
|
211
|
-
**Most failures are selector mismatches.** Validate selectors against the live page BEFORE running any test — this eliminates slow compile→run→read→fix cycles.
|
|
212
|
-
|
|
213
|
-
After generating `selectors.yaml` (Step 3), verify each entry:
|
|
214
|
-
|
|
215
|
-
#### How to validate
|
|
216
|
-
|
|
217
|
-
Use `browser_evaluate` to check if each selector actually finds an element on the page:
|
|
218
|
-
|
|
219
|
-
```js
|
|
220
|
-
// Validate a role selector
|
|
221
|
-
document.querySelectorAll('[role="button"]').length;
|
|
222
|
-
// or check accessible name
|
|
223
|
-
Array.from(document.querySelectorAll('button'))
|
|
224
|
-
.filter(el => el.textContent.includes('Submit') || el.getAttribute('aria-label')?.includes('Submit'))
|
|
225
|
-
.length;
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
Or use `browser_snapshot` and cross-check:
|
|
229
|
-
1. Read all `[Reference]` entries from `selectors.yaml`
|
|
230
|
-
2. Take a `browser_snapshot`
|
|
231
|
-
3. For each entry, verify the element exists in the snapshot
|
|
232
|
-
4. Fix mismatches immediately — no test run needed
|
|
233
|
-
|
|
234
|
-
#### What to check
|
|
235
|
-
|
|
236
|
-
| Selector type | Validation method |
|
|
237
|
-
|---|---|
|
|
238
|
-
| `role` + `name` | Search snapshot for `role "name"` text |
|
|
239
|
-
| `testid` | `browser_evaluate`: `document.querySelector('[data-testid="xxx"]')` |
|
|
240
|
-
| `placeholder` | Search snapshot for textbox with placeholder |
|
|
241
|
-
| `locator` (CSS) | `browser_evaluate`: `document.querySelector('xxx')` |
|
|
242
|
-
|
|
243
|
-
**Target: fix 80%+ of selector issues before the first test run.**
|
|
244
|
-
|
|
245
115
|
---
|
|
246
116
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
After proactive validation, run tests in **batches of 20** for faster feedback:
|
|
250
|
-
|
|
251
|
-
```
|
|
252
|
-
1. COMPILE — sungen generate --screen <screen>
|
|
253
|
-
|
|
254
|
-
2. BATCH RUN — run 20 tests at a time:
|
|
255
|
-
npx playwright test <spec> --grep "VP-UI-001|VP-UI-002|...|VP-UI-020" --reporter=line
|
|
256
|
-
|
|
257
|
-
3. IF FAILURES in batch:
|
|
258
|
-
a. Group failures by root cause (same selector, same error type)
|
|
259
|
-
b. Fix selectors.yaml or test-data.yaml
|
|
260
|
-
c. Recompile, re-run only failing tests from this batch
|
|
261
|
-
d. If fixed → move to next batch
|
|
262
|
-
|
|
263
|
-
4. NEXT BATCH — repeat with next 20 tests
|
|
264
|
-
|
|
265
|
-
5. FINAL CONFIRMATION — run ALL tests once:
|
|
266
|
-
npx playwright test <spec> --reporter=line
|
|
267
|
-
|
|
268
|
-
6. If still failing after 5 fix attempts per batch → ask user about direct .spec.ts fix
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
#### Grouping failures by root cause
|
|
272
|
-
|
|
273
|
-
Common patterns where 1 fix resolves many failures:
|
|
274
|
-
- **Same selector** — e.g., all `[Email Error]` tests fail → fix once
|
|
275
|
-
- **Same error type** — e.g., all `strict mode violation` → add `exact: true` or `nth`
|
|
276
|
-
- **Same assertion** — e.g., all `toHaveText` on inputs fail → change Gherkin pattern
|
|
277
|
-
|
|
278
|
-
Fix the root cause first, verify with the batch, then move on.
|
|
279
|
-
|
|
280
|
-
---
|
|
117
|
+
## Step 6: Fix Loop
|
|
281
118
|
|
|
282
|
-
|
|
119
|
+
After fixing selectors:
|
|
120
|
+
1. Recompile: `sungen generate --screen <screen>`
|
|
121
|
+
2. Re-run only failing tests: `npx playwright test --grep "VP-XXX-001|VP-XXX-002" --reporter=line`
|
|
122
|
+
3. If new failures → repeat (max 3 attempts)
|
|
123
|
+
4. After all fixes → run ALL tests once for regression check
|
|
283
124
|
|
|
284
|
-
|
|
285
|
-
- Keys use **spaces** (not dots) as word separators
|
|
286
|
-
- Same label, different element types → add `--type` suffix
|
|
287
|
-
- Same label, nth occurrence → add `--N` suffix
|
|
125
|
+
If still failing after 3 attempts → ask user for guidance.
|