@sun-asterisk/sungen 2.3.0 → 2.4.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.
- package/README.md +12 -13
- package/dist/cli/index.js +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-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/interaction-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.js +0 -13
- package/dist/generators/test-generator/patterns/interaction-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/table-patterns.d.ts +9 -0
- package/dist/generators/test-generator/patterns/table-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/table-patterns.js +94 -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 -4
- 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 -6
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-review.md +21 -0
- package/{src/orchestrator/templates/ai-instructions/claude-cmd-make-test.md → dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md} +2 -2
- 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 +12 -43
- package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +67 -239
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +40 -240
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +104 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-viewpoint.md +186 -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 -7
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-review.md +24 -0
- package/{src/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md → dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md} +3 -3
- 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 +12 -43
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +67 -214
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +40 -240
- 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 +186 -0
- package/dist/orchestrator/templates/readme.md +4 -4
- package/package.json +1 -1
- package/src/cli/index.ts +1 -1
- 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-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/interaction-patterns.ts +0 -14
- package/src/generators/test-generator/patterns/table-patterns.ts +98 -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 -4
- 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 -6
- package/src/orchestrator/templates/ai-instructions/claude-cmd-review.md +21 -0
- package/{dist/orchestrator/templates/ai-instructions/claude-cmd-make-test.md → src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md} +2 -2
- 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 +12 -43
- package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +67 -239
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +40 -240
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +104 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-viewpoint.md +186 -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 -7
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-review.md +24 -0
- package/{dist/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md → src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md} +3 -3
- 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 +12 -43
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +67 -214
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +40 -240
- 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 +186 -0
- package/src/orchestrator/templates/readme.md +4 -4
- 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/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
|
@@ -1,287 +1,140 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sungen-selector-fix
|
|
3
|
-
description: 'Selector generation and fixing strategy
|
|
3
|
+
description: 'Selector generation and fixing strategy — explore live page, generate selectors.yaml, validate, auto-fix. Auto-loaded by run-test command.'
|
|
4
4
|
user-invocable: false
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## When to Generate
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Selectors are generated during `/sungen:make-test`, NOT during `/sungen:make-tc`. This ensures selectors are always validated against the live page.
|
|
9
|
+
Selectors are generated during `/sungen:run-test`, NOT during `/sungen:create-test`.
|
|
12
10
|
|
|
13
11
|
---
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
## Step 1: Authenticate & Snapshot
|
|
16
14
|
|
|
17
15
|
1. Read `baseURL` from `playwright.config.ts`
|
|
18
16
|
2. `browser_navigate` to `baseURL`
|
|
19
|
-
3. If redirected to login
|
|
20
|
-
|
|
21
|
-
4. Once confirmed, `browser_navigate` to the target page and take `browser_snapshot`
|
|
17
|
+
3. If redirected to login → ask user to log in manually via MCP browser
|
|
18
|
+
4. Navigate to target page → `browser_snapshot`
|
|
22
19
|
|
|
23
|
-
**Never use `sungen makeauth`.**
|
|
24
|
-
**Never use `browser_evaluate` to inject cookies or localStorage.** Use `browser_evaluate` only to read DOM info (e.g. detect `data-testid` attributes, check element properties).
|
|
20
|
+
**Never use `sungen makeauth`.** Never use `browser_evaluate` to inject cookies.
|
|
25
21
|
|
|
26
22
|
---
|
|
27
23
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
**Never guess or infer selector names from Gherkin labels. Always copy exact values from the snapshot.**
|
|
24
|
+
## Step 2: Build Element Catalog
|
|
31
25
|
|
|
32
|
-
|
|
26
|
+
**Never guess names from Gherkin labels. Copy exact values from snapshot.**
|
|
33
27
|
|
|
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)
|
|
28
|
+
Catalog all accessible elements from snapshot: buttons, links, headings, inputs, regions, images.
|
|
40
29
|
|
|
41
|
-
Then check for `data-testid` attributes
|
|
30
|
+
Then check for `data-testid` attributes:
|
|
42
31
|
```js
|
|
43
|
-
// browser_evaluate — read-only, safe:
|
|
44
32
|
Array.from(document.querySelectorAll('[data-testid]'))
|
|
45
33
|
.map(e => ({ testid: e.dataset.testid, tag: e.tagName, text: e.textContent.trim().slice(0, 60) }))
|
|
46
34
|
```
|
|
47
35
|
|
|
48
36
|
---
|
|
49
37
|
|
|
50
|
-
|
|
38
|
+
## Step 3: Map Gherkin Labels → Selectors
|
|
51
39
|
|
|
52
|
-
|
|
40
|
+
Selector priority (use first applicable):
|
|
53
41
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
| Priority | type | When to use |
|
|
42
|
+
| Priority | type | When |
|
|
57
43
|
|---|---|---|
|
|
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
|
|
64
|
-
|
|
65
|
-
#### The exact name rule
|
|
44
|
+
| 1 | `testid` | `data-testid` exists |
|
|
45
|
+
| 2 | `role` + exact name | Interactive elements |
|
|
46
|
+
| 3 | `placeholder` | Input with placeholder |
|
|
47
|
+
| 4 | `label` | Form field with `<label>` |
|
|
48
|
+
| 5 | `locator` (CSS) | No accessible name |
|
|
49
|
+
| 6 | `text` | Static text only |
|
|
66
50
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
```yaml
|
|
70
|
-
# BAD — name inferred from Gherkin label, not from snapshot
|
|
71
|
-
notification bell:
|
|
72
|
-
type: 'role'
|
|
73
|
-
value: 'button'
|
|
74
|
-
name: 'Notification Bell'
|
|
75
|
-
|
|
76
|
-
# GOOD — exact name from snapshot: button "Notifications"
|
|
77
|
-
notification bell:
|
|
78
|
-
type: 'role'
|
|
79
|
-
value: 'button'
|
|
80
|
-
name: 'Notifications'
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
#### When there is no accessible name
|
|
84
|
-
|
|
85
|
-
Use a `locator` with a CSS attribute selector or ARIA role:
|
|
51
|
+
**Exact name rule**: copy name character-for-character from snapshot. Never infer from Gherkin label.
|
|
86
52
|
|
|
53
|
+
**No accessible name**: use `locator` with CSS/ARIA attribute:
|
|
87
54
|
```yaml
|
|
88
55
|
search field:
|
|
89
56
|
type: 'locator'
|
|
90
57
|
value: '[role="searchbox"]'
|
|
91
|
-
|
|
92
|
-
icon button:
|
|
93
|
-
type: 'locator'
|
|
94
|
-
value: '[aria-label="Close"]'
|
|
95
58
|
```
|
|
96
59
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
### Step 4: Handle Dynamic Content
|
|
100
|
-
|
|
101
|
-
For elements whose text changes between test runs (list items, card data, user-generated content, timestamps):
|
|
102
|
-
|
|
103
|
-
**Never use `type: text` with a specific value** — it breaks when data changes.
|
|
104
|
-
|
|
105
|
-
```yaml
|
|
106
|
-
# BAD — specific text breaks when data changes
|
|
107
|
-
card title:
|
|
108
|
-
type: 'text'
|
|
109
|
-
value: 'Some specific title'
|
|
110
|
-
|
|
111
|
-
# GOOD — structural: first heading inside a card container
|
|
112
|
-
card title:
|
|
113
|
-
type: 'role'
|
|
114
|
-
value: 'heading'
|
|
115
|
-
nth: 1 # skip page-level headings, get first card heading
|
|
60
|
+
**Dynamic content**: never use `type: text` with specific value. Use `testid` or structural `role` + `nth`.
|
|
116
61
|
|
|
117
|
-
|
|
118
|
-
card title:
|
|
119
|
-
type: 'testid'
|
|
120
|
-
value: 'card-title'
|
|
121
|
-
```
|
|
62
|
+
**Multiple matches**: add `nth: 0` for first occurrence.
|
|
122
63
|
|
|
123
|
-
|
|
64
|
+
Auto-infer rules and lookup priority → see `sungen-selector-keys` skill.
|
|
124
65
|
|
|
125
66
|
---
|
|
126
67
|
|
|
127
|
-
|
|
68
|
+
## Step 4: Table Selectors
|
|
128
69
|
|
|
129
|
-
For
|
|
130
|
-
1. Navigate to the **list page** first via MCP browser to find a real record ID
|
|
131
|
-
2. Use that ID in the page selector value
|
|
132
|
-
3. Use `User is on [X] page` — sungen resolves the path from the selector
|
|
70
|
+
For table patterns using the v2.3 syntax, generate table selectors with `columns` config:
|
|
133
71
|
|
|
134
72
|
```yaml
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
73
|
+
users:
|
|
74
|
+
type: 'role'
|
|
75
|
+
value: 'table'
|
|
76
|
+
name: 'Users'
|
|
77
|
+
columns:
|
|
78
|
+
username:
|
|
79
|
+
index: 0
|
|
80
|
+
header: 'Username'
|
|
81
|
+
email:
|
|
82
|
+
index: 1
|
|
83
|
+
header: 'Email'
|
|
84
|
+
status:
|
|
85
|
+
index: 2
|
|
86
|
+
header: 'Status'
|
|
139
87
|
```
|
|
140
88
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
---
|
|
144
|
-
|
|
145
|
-
### Step 5: Handle SPA / Client-side Routing
|
|
89
|
+
**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.
|
|
146
90
|
|
|
147
|
-
|
|
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:
|
|
91
|
+
**Why**: enables exact cell assertion via `cell.nth(index).toHaveText(value)` instead of approximate `cell.filter({ hasText })`.
|
|
152
92
|
|
|
93
|
+
**Row scope Gherkin** — these patterns use the table selector:
|
|
153
94
|
```gherkin
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
When User click [Some Button] button
|
|
158
|
-
...
|
|
95
|
+
Then User see [Username] row in [Users] table with {{user_name}}
|
|
96
|
+
Then User see [Status] column with {{expected_status}}
|
|
97
|
+
When User click [Edit] button in [Users] table with {{user_name}}
|
|
159
98
|
```
|
|
160
99
|
|
|
161
|
-
The "page loaded" check should use a **stable, always-visible element** on that specific page — typically the main page heading.
|
|
162
|
-
|
|
163
100
|
---
|
|
164
101
|
|
|
165
|
-
|
|
102
|
+
## Step 5: Detail Screens with Dynamic IDs
|
|
166
103
|
|
|
167
|
-
|
|
104
|
+
For screens like `/admin/users/:id`:
|
|
105
|
+
1. Navigate to list page via MCP to find a real record ID
|
|
106
|
+
2. Hardcode the ID in page selector
|
|
168
107
|
|
|
169
108
|
```yaml
|
|
170
|
-
|
|
171
|
-
type: '
|
|
172
|
-
value: '
|
|
173
|
-
name: 'Dashboard'
|
|
174
|
-
nth: 0 # first occurrence (desktop nav)
|
|
109
|
+
user detail:
|
|
110
|
+
type: 'page'
|
|
111
|
+
value: '/admin/users/de42d800-0f5a-490e-9dcf-344fedbd34a5'
|
|
175
112
|
```
|
|
176
113
|
|
|
177
|
-
Use `nth: 0` for the first match of dynamic/repeated elements.
|
|
178
|
-
|
|
179
114
|
---
|
|
180
115
|
|
|
181
|
-
|
|
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
|
|
116
|
+
## Step 6: Validate Before Running
|
|
206
117
|
|
|
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:
|
|
118
|
+
**Fix 80%+ of selector issues before first test run.**
|
|
214
119
|
|
|
215
|
-
|
|
120
|
+
After generating `selectors.yaml`, verify each entry against the live snapshot:
|
|
121
|
+
- `role` + `name` → search snapshot for `role "name"`
|
|
122
|
+
- `testid` → `browser_evaluate`: `document.querySelector('[data-testid="xxx"]')`
|
|
123
|
+
- `placeholder` → search snapshot for textbox with placeholder
|
|
124
|
+
- `page` → verify URL path exists
|
|
216
125
|
|
|
217
|
-
|
|
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.**
|
|
126
|
+
Common fixes: name mismatch → copy from snapshot, element in iframe → add `frame`, multiple matches → add `nth` or `exact: true`.
|
|
244
127
|
|
|
245
128
|
---
|
|
246
129
|
|
|
247
|
-
|
|
130
|
+
## Step 7: Run & Fix Loop
|
|
248
131
|
|
|
249
|
-
|
|
132
|
+
Run tests in batches of 20. Group failures by root cause (same selector, same error type). Fix once, verify batch, move to next.
|
|
250
133
|
|
|
251
134
|
```
|
|
252
|
-
|
|
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
|
|
135
|
+
compile → batch run 20 → fix root cause → recompile → re-run failures → next batch
|
|
269
136
|
```
|
|
270
137
|
|
|
271
|
-
|
|
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
|
-
---
|
|
281
|
-
|
|
282
|
-
### Key Rules (from sungen-selector-keys)
|
|
138
|
+
After all batches pass → run ALL tests once for regression check.
|
|
283
139
|
|
|
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
|
|
140
|
+
If still failing after 5 attempts per batch → ask user about direct `.spec.ts` fix.
|