You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: extension/templates/platforms/web.md
+22-1Lines changed: 22 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -92,7 +92,7 @@ A React component `<LoginForm>` does NOT generate a `.LoginForm` CSS class. Chec
92
92
Tailwind classes like `.flex`, `.mt-4`, `.bg-blue-600` match dozens of elements. Use semantic attributes (`#id`, `[title]`, `[data-testid]`, `[placeholder]`) instead.
1. Prefer `id`, `name`, `title`, `placeholder`, `data-testid`, `type` attributes — **only if the attribute actually exists in source code** (open the file and verify!)
96
96
2. Find a **semantic class** unique to the element (e.g. `.submit-btn`, NOT `.flex`)
97
97
3. If only Tailwind classes exist, use context combo: `.parent-class button[title='xxx']`
98
98
4. Last resort: ask the developer to add `data-testid` or `id`
@@ -112,6 +112,26 @@ Custom components like `<Select>`, `<Modal>`, `<DatePicker>` do NOT appear as CS
112
112
- ❌ `name:xxx` — desktop-only selector, NOT for Web
113
113
- ❌ Bare tag selectors (`div`, `span`, `button` with no attributes)
114
114
115
+
**Pitfall 12 Bare `button` selector (CRITICAL):**
116
+
Writing `"target": "button"` with no attributes is forbidden. Playwright matches the **first** button in the DOM, which may be a hidden button, an icon button, or the wrong button entirely. This is the most common cause of wrong-element clicks that appear to succeed (no error) but operate the wrong control.
117
+
118
+
| ❌ Forbidden | Why wrong | ✅ Correct approach |
119
+
|---|---|---|
120
+
|`"target": "button"`| Matches ANY button, usually wrong one | Read source: use `button[type='submit']`, `#btn-register`, `.btn-life-book` etc. |
121
+
|`"target": "span"`| Matches ANY span | Use `#id` or semantic class |
122
+
123
+
> **Iron rule:** Every `click` target MUST have at least one attribute constraint. Bare tag selectors (`button`, `a`, `div`, `span`) are FORBIDDEN without exception.
When using `[title='xxx']`, `[aria-label='xxx']`, `[data-testid='xxx']`, `[placeholder='xxx']`:
128
+
129
+
1.**MUST open the source file first** and confirm the attribute exists on that element
130
+
2.**NEVER guess attribute values** from the element's visible text or purpose
131
+
3.`[title]` is a tooltip attribute — many icon buttons in React/Vue apps do NOT have it
132
+
133
+
> Typical mistake: seeing a "财务报表" navigation button and writing `button[title='财务报表']` — but the button has no `title` attribute in source code → 10s timeout on every run.
134
+
115
135
**Pitfall 7 `:contains()` causes SyntaxError:**
116
136
`:contains()` is jQuery-only syntax. Playwright and modern CSS engines do NOT support it. Any selector with `:contains()` throws `SyntaxError: Failed to execute` and aborts the entire scenario. Use `#id`, `.class`, or `[attribute]` selectors instead.
117
137
@@ -281,6 +301,7 @@ Do NOT put multiple independent dialog interactions in one scenario. Each distin
281
301
**Check 1 Flow decision:** For each page with 2 scenarios that ALL require login first:
282
302
- YES that page MUST have `"flow": true` AND non-first scenarios MUST NOT contain login steps
283
303
- NO no flow needed (each scenario independently logs in)
304
+
-**Scan every non-first scenario in flow pages: if it contains `fill username` / `fill password` / `click login`, DELETE those steps immediately — they belong only in the first scenario**
284
305
285
306
**Check 2 Assert coverage:** For every scenario, does it have at least one `assert_text` step?
286
307
- Screenshot alone is NOT sufficient must have text assertion
0 commit comments