browser-testinglisted
Install: claude install-skill Univers42/claude-deal-with-the-devil
# Browser testing
A passing unit test says a function returns the right value. It does not say the page
renders, the button is reachable, or the console is clean. This closes that gap with
the only evidence that counts for a UI: the thing running.
Uses the Playwright MCP when it is available (`mcp__playwright__*`), and falls back to
Playwright in the repo otherwise.
## 1. Get it running
- `.claude/tools/preflight.sh` — a missing `.env` fails here, not after a browser is
open (`rules/run-safely.md`).
- Start the dev server **as a background task** so its log stays readable, and wait for
the port to actually answer. A fixed `sleep` is a flake generator.
- Never point a destructive flow at a real environment. Local or a disposable fixture,
always.
## 2. Drive it
```text
browser_navigate → browser_snapshot → browser_click / browser_type / browser_fill_form
→ browser_wait_for → browser_snapshot
```
- **`browser_snapshot` before `browser_click`.** The snapshot is the accessibility tree
with the refs you click by; guessing a selector is how this gets flaky.
- **Prefer role and accessible name** over CSS paths. `getByRole('button', {name:
'Save'})` survives a restyle; `.btn-primary > span:nth-child(2)` does not. A selector
that needs the DOM shape is testing the DOM shape.
- **Wait for a condition, never a duration.** `browser_wait_for` on the text or state
you expect. Every `sleep` is a race you decided to lose later.
- **Read the console an