QA Testing (Playwright)
High-signal, cost-aware E2E testing for web applications.
Core docs:
Quick Reference
| Need |
Go to |
| Run the Playwright workflow |
## Workflow |
| Apply defaults and authoring rules |
## Defaults and ## Authoring Rules |
| Debug flaky or blocked runs |
## Debugging Checklist and ## Execution Preflight (High ROI) |
| Decide tool fit, selectors, flake triage order, sharding cost |
## Expert Judgment |
| Load templates and references |
## Navigation |
Defaults
- Keep E2E thin: protect critical user journeys only; push coverage down (unit/integration/contract).
- Locator priority:
getByRole → getByLabel/getByText → getByTestId (fallback).
- Waiting: rely on Playwright auto-wait + web-first assertions; no sleeps/time-based waits.
- Isolation: tests must run alone, in parallel, and in any order; eliminate shared mutable state.
- Local execution posture: choose one server topology first (shared dev stack or Playwright-managed
webServer), then triage with an exact spec or named batch plus --workers=1.
- Flake posture: retries are a debugging tool; treat rerun-pass as a failure signal and fix root cause.
- CI flakes: prefer built-in
failOnFlakyTests; use a custom reporter only for older Playwright versions.
- CI posture: smoke gate on PRs; shard/parallelize regression on schedule; always keep artifacts (trace/video/screenshot).
- Oracle posture: assert the user outcome; do not wait on incidental network requests when the visible result can be verified directly.
- AI posture: use Playwright codegen / test agents / MCP for scaffolding and exploration, then harden assertions and fixtures manually.
- Browser MCP: Playwright MCP for test generation + accessibility; Chrome DevTools MCP for performance / network / console debugging. See
references/playwright-mcp.md.
- CLI posture: for high-throughput coding agents, prefer
@playwright/cli (shell commands) over Playwright MCP — roughly 4x fewer tokens per task (~27k vs ~114k tokens/task per third-party benchmarks; as of 2026-07-11, verify at https://playwright.dev/docs/getting-started-cli). Use MCP when persistent browser state and rich introspection are needed.
- Local iteration posture: use
npx playwright test --only-changed=main to run only tests affected by uncommitted/branch changes during authoring; it is a heuristic over the import graph, so always run the full suite (or the deploy-gate replay) before merging — never treat --only-changed green as release-ready signal.
Quick Start
| Command |
Purpose |
npm init playwright@latest |
Initialize Playwright |
npx playwright test |
Run all tests |
npx playwright test --grep @smoke |
Run smoke tests |
npx playwright test --project=chromium |
Run a single project |
npx playwright test --ui |
Debug with UI mode |
npx playwright test --debug |
Step through a test |
npx playwright codegen |
Record a flow and bootstrap a test |
npx playwright init-agents --loop=claude |
Initialize test agents for Claude Code |
npx playwright test --fail-on-flaky-tests |
Fail CI if any test is flaky |
npx playwright show-trace trace.zip |
Inspect trace artifacts |
npx playwright show-report |
Inspect HTML report |
npx playwright trace <trace.zip> |
Analyze trace from CLI (v1.59+) |
npx playwright test --only-changed=main |
Run only tests affected by changes since main (heuristic — always follow with a full run before release) |
Local Execution Topology
Use this order by default:
- Start one shared local dev stack if the repo already provides it; prefer reusing it with
--no-server over spawning a fresh app per rerun.
- Reproduce with one exact spec or one named batch and
--workers=1.
- Fix and rerun the smallest affected scope.
- Run the deploy-gate replay only after the targeted scope is green.
Default suite tiers:
- Smoke: PR gate and fastest signal.
- Targeted batch/spec: local triage and deflake work.
- Deploy-gate replay: dependency-chain or critical-journey replay for release confidence.
Avoid local full-suite reruns as the first move unless the job is explicitly “prove deploy readiness now.”
When to Use
- E2E tests for web applications
- Test user authentication flows
- Verify form submissions
- Test responsive designs
- Automate browser interactions
- Set up Playwright in CI/CD
When NOT to Use
| Scenario |
Use Instead |
| Unit testing |
Jest, Vitest, pytest |
| API contracts |
qa-api-testing-contracts |
| Load testing |
k6, Locust, Artillery |
| Mobile native |
Appium |
| Pure business-logic or data-transform correctness |
Unit tests — a browser adds latency and flake with zero extra confidence |
| Cross-team API contract drift |
Consumer-driven contract tests, not a UI click-path proxy |
| Component-level visual/interaction isolation at scale |
Storybook + Chromatic/Percy, or Playwright component testing only if you accept experimental-API churn (see Defaults) |
| Thousands of input-combination fuzzing |
Property-based testing at the unit layer; E2E cannot afford the runtime |
Expert Judgment
When Playwright Is the Wrong Tool
Playwright (or any browser E2E tool) is the wrong choice when a faster, cheaper layer already proves the same risk:
- If the bug class can be caught by a type system, unit test, or schema/contract check, push it down — E2E is the most expensive test layer per assertion (browser boot, network, rendering).
- If the "user journey" is actually an internal API call with no meaningful UI branching, test the API directly (
request fixture or a dedicated API-testing skill) and skip the browser.
- If you are testing a third-party surface you do not control (payment provider hosted page, OAuth consent screen), do not chase it with E2E; mock the boundary and test your own integration contract instead — third-party UI changes make these tests flaky by design, not by mistake.
- If the same risk is already covered by a component test or visual snapshot at a fraction of the cost, do not duplicate it in E2E "just to be safe" — duplicate coverage without duplicate risk is waste, not thoroughness.
Selector-Strategy Decision Rule
Pick the locator in this order, and stop at the first one that resolves unambiguously to exactly one element:
getByRole with an accessible name — this is what a screen reader and a real user both key off, so it survives markup refactors.
getByLabel / getByText — use when there is no meaningful role (plain text, decorative containers) but the visible copy is stable.
getByTestId — use only when the element has no stable role/label (e.g., a canvas, a drag handle, a duplicate-name list item) or when semantic locators would force asserting on implementation detail (raw CSS class, generated ID).
Never fall back to raw CSS or XPath as a first resort — they are a signal that the markup itself may need an accessibility fix, not just a test workaround.
Flakiness Triage Order (Fastest Signal First)
Before touching a single assertion, classify the failure in this order — each step is strictly cheaper than the next, so do not skip ahead:
- Selector ambiguity — trace shows the locator resolved to 0 or 2+ elements. Fix the locator, not the wait.
- Missing wait / race — trace shows the action fired before the element was actionable. Replace with a web-first assertion; never add a fixed sleep.
- State leakage — failure only reproduces after other tests ran (parallel workers, shared fixtures, undropped test data). Fix isolation before touching this test's own code.
- Environment — only fails in CI, not locally; look at concurrency, cold start, CPU starvation, and container resource limits before assuming a product bug.
- Product regression — only after 1-4 are ruled out with trace evidence, treat the failure as reflecting the app under test and file/fix accordingly.
Retries mask all five of these; use
retries to gather evidence (trace/video) on the first CI run, but treat "passed on retry" as an unresolved defect, not a pass. See template-playwright-fail-on-flaky-reporter.js.
CI Parallelism Economics (Worked Example)
Sharding trades machine-cost for wall-clock time; the math to decide is straightforward. Given a suite that takes T minutes single-threaded and N shards each with M machine-minutes of fixed overhead (checkout, install, browser download):
- Wall-clock per shard ≈
T/N + M.
- Total machine-minutes billed ≈
N × (T/N + M) = T + N×M.
Example: T = 60 min, M = 3 min fixed overhead per shard/job.
- 1 shard: wall-clock = 63 min, billed = 63 machine-minutes.
- 4 shards: wall-clock = 60/4 + 3 = 18 min, billed = 4 × 18 = 72 machine-minutes.
- 12 shards: wall-clock = 60/12 + 3 = 8 min, billed = 12 × 8 = 96 machine-minutes.
Sharding always costs more total machine-minutes (because fixed overhead is paid N times) — the return is faster PR feedback, not lower spend. The judgment call: shard the PR-gate smoke suite (wall-clock matters, suite is small so N×M stays small) and run the full regression unsharded or lightly sharded on a schedule (spend matters more than latency there). Re-derive this ratio with your own T and M before picking a shard count — do not copy N=4 by convention.
Authoring Rules
Locator Strategy
// 1. Role locators (preferred)
await page.getByRole('button', { name: 'Sign in' }).click();
// 2. Label/text locators
await page.getByLabel('Email').fill('user@example.com');
// 3. Test IDs (fallback)
await page.getByTestId('user-avatar').click();
Flake Control
- Avoid sleeps; use Playwright auto-wait
- Use retries as signal, not a crutch
- Prefer built-in
failOnFlakyTests in CI
- Capture trace/screenshot/video on failure
- Prefer user-like interactions; avoid
force: true
Workflow
- Write the smallest test that proves the user outcome (intent + oracle).
- Make execution topology explicit before triage: shared dev stack vs Playwright
webServer, plus exact start/stop commands.
- Reproduce with one exact spec or named batch before expanding scope.
- Stabilize locators and assertions before adding more steps.
- Make state explicit: seed per test/worker, clean up deterministically, and verify auth/subscription/test-data reset paths for stateful apps.
- Mock or isolate third-party boundaries where they are not part of the user-facing oracle.
- In CI: shard/parallelize, capture artifacts, and fail fast on rerun-pass flakes.
Debugging Checklist
If something is flaky:
- Open trace and error artifacts first; identify whether the failure is selector ambiguity, missing wait, state leakage, or the wrong server topology.
- If the trace lands on login or an unexpected redirect, classify
auth-state before changing assertions.
- If browser logs show
429 or Retry-After on side endpoints, decide whether that request is part of the oracle or only noise.
- Replace brittle selectors with semantic locators; replace sleeps with
expect(...), an auth-aware navigation helper, or a targeted readiness assertion.
- Remove waits on incidental requests; assert the visible route, action, or content outcome instead.
- Reduce global timeouts; add scoped timeouts only when the product truly needs it — prefer a per-action timeout or
test.step(name, fn, { timeout }) over raising timeout in playwright.config.ts.
- If it only fails in CI, look for concurrency, cold-start, CPU starvation, and environment differences.
Do / Avoid
Make tests independent and deterministic
Use network mocking for third-party deps
Run smoke E2E on PRs; full regression on schedule
"Test everything E2E" as default
Weakening assertions to "fix" flakes
Auto-healing that weakens assertions
Execution Preflight (High ROI)
Run this preflight before expensive E2E runs to prevent avoidable failures.
Preflight Checklist
- Repository shape:
- Confirm working directory and expected app root exist.
- Verify spec paths before execution (
rg --files tests/e2e | rg <target>).
- Port/process hygiene:
- Check and clear stale dev server port before run (example:
lsof -i :3001).
- Avoid parallel local servers colliding with Playwright
webServer.
- If the repo provides a shared dev-server helper, prefer it and run Playwright with
--no-server during local deflake work.
- Command validity:
- Validate CLI flags for current tool versions before batch runs.
- Prefer exact spec paths, named batches, or
--grep over broad globs during triage.
- Record the cleanup/kill command for the chosen local stack before starting a long replay.
- Artifact expectations:
- Confirm result artifact paths exist before reading (
test -f <error-context.md>).
- If artifact path missing, inspect latest
test-results index first.
Mandatory Sandbox/Port Decisions
Before running Playwright in constrained environments (sandboxed terminals, CI containers, shared dev hosts), decide and document:
- Bind host/port: confirm whether app server must use
127.0.0.1 or 0.0.0.0, and verify selected port is free.
- Server-topology decision: shared dev server versus Playwright
webServer; never run both accidentally.
- Escalation path: if bind attempts fail with
EPERM/EACCES, escalate immediately instead of retry loops.
- Long-flow timeout budget: set explicit per-test timeout for API-heavy flows (generation/checkout/report) instead of inflating global timeout.
- Build lock hygiene: clear stale
.next/lock and terminate stale build/dev PIDs before rerun.
Triage Sequence (Fastest Signal)
- Reproduce one failing test or named batch with
--workers=1 on the chosen server topology.
- Capture trace/video/screenshot for that failure.
- Classify the failure: environment, auth-state, state-sync, optional network, degraded mode, or product regression.
- Fix the determinism root cause.
- Re-run the targeted spec or batch.
- Only then run the deploy-gate replay or broad regression.
Stateful App Failure Classes
auth-state: protected route unexpectedly redirects to login or loses storage/session state.
state-sync: backend reset or webhook succeeded, but UI has not converged yet.
optional-network: a side request failed, but the user-visible oracle may still be correct.
degraded-mode: rate limits or fallback UX activated and should be asserted intentionally.
Failure Patterns to Treat as Environment, Not Product Bugs
EADDRINUSE on Playwright web server port
- Missing spec/result paths from stale assumptions
- Shell glob expansion failures for bracketed route segments
Resources
| Resource |
Purpose |
| references/playwright-mcp.md |
MCP & AI testing |
| references/playwright-patterns.md |
Advanced patterns |
| references/playwright-ci.md |
CI configurations |
| references/playwright-authentication.md |
Auth patterns and session management |
| references/visual-regression-testing.md |
Visual regression strategies |
| references/api-testing-playwright.md |
API testing with APIRequestContext |
| references/playwright-preflight-sandbox.md |
Sandbox/port preflight and escalation decisions |
| data/sources.json |
Documentation links |
Templates
| Template |
Purpose |
| assets/template-playwright-e2e-review-checklist.md |
E2E review checklist |
| assets/template-playwright-fail-on-flaky-reporter.js |
Fail CI on rerun-pass flakes |
| assets/template-playwright-preflight-checklist.md |
Preflight checklist for port/sandbox/timeouts |
ASCII Flow
Playwright testing request
-> Confirm app root, server topology, ports, auth state, and target spec
-> Author the smallest user-outcome test with semantic locators
-> Isolate fixtures, storage, network, third parties, and worker state
-> Reproduce with one spec or grep and workers=1 before widening
-> Debug using trace, screenshots, video, console, and network evidence
-> Gate PR or deploy only after flakes are classified and fixed
Navigation
## Workflow, ## Debugging Checklist, and ## Execution Preflight (High ROI) for the baseline sequence
## Expert Judgment for tool-fit, selector, flake-triage-order, and CI-sharding-economics decision rules
## Resources and ## Templates for deeper materials
## Related Skills for strategy, frontend, and CI handoffs
Related Skills
Verification Gate
Before delivering output, you MUST verify:
Fact-Checking
- Known bugs, regressions, framework/compiler/runtime footguns, and version-specific crash or workaround guidance must be verified against current primary web sources before being treated as current fact.
- Use web search or web fetch to verify current external facts, versions, pricing, deadlines, regulations, or platform behavior before final answers.
- Prefer primary sources; report source links and dates for volatile information.
- If web access is unavailable, state the limitation and mark guidance as unverified.
Learnings Loop
Before applying this skill on a non-trivial task, read learnings.consolidated.md in this directory (and learnings.md if present).
After applying it, if you encountered a pattern worth remembering, a mistake worth preventing, or a domain fact that surprised you, append one dated bullet to learnings.md via agents-skills-feedback-loop/scripts/append_learning.py. Do not modify SKILL.md itself.
1---
2name: qa-testing-playwright
3description: "Builds and debugs Playwright E2E suites. Use when authoring browser tests, fixing flakes, or hardening Playwright CI and locator strategy."
4compatibility: Portable core. Works on Claude Code and Codex.
5version: "1.2"
6last_validated: 2026-07-11
7---
8
9# QA Testing (Playwright)
10
11High-signal, cost-aware E2E testing for web applications.
12
13Core docs:
14- https://playwright.dev/docs/best-practices
15- https://playwright.dev/docs/locators
16- https://playwright.dev/docs/auth
17- https://playwright.dev/docs/api-testing
18- https://playwright.dev/docs/test-retries
19- https://playwright.dev/docs/test-snapshots
20- https://playwright.dev/docs/trace-viewer
21- https://playwright.dev/docs/test-sharding
22- https://playwright.dev/docs/ci
23- https://playwright.dev/docs/pom
24- https://playwright.dev/docs/test-agents
25- https://playwright.dev/docs/clock
26- https://playwright.dev/docs/getting-started-cli
27- https://playwright.dev/docs/release-notes (verify current version before pinning — as of 2026-07-11 it is 1.61.1)
28
29## Quick Reference
30
31| Need | Go to |
32|------|-------|
33| Run the Playwright workflow | `## Workflow` |
34| Apply defaults and authoring rules | `## Defaults` and `## Authoring Rules` |
35| Debug flaky or blocked runs | `## Debugging Checklist` and `## Execution Preflight (High ROI)` |
36| Decide tool fit, selectors, flake triage order, sharding cost | `## Expert Judgment` |
37| Load templates and references | `## Navigation` |
38
39## Defaults
40
41- Keep E2E thin: protect critical user journeys only; push coverage down (unit/integration/contract).
42- Locator priority: `getByRole` → `getByLabel`/`getByText` → `getByTestId` (fallback).
43- Waiting: rely on Playwright auto-wait + web-first assertions; no sleeps/time-based waits.
44- Isolation: tests must run alone, in parallel, and in any order; eliminate shared mutable state.
45- Local execution posture: choose one server topology first (shared dev stack or Playwright-managed `webServer`), then triage with an exact spec or named batch plus `--workers=1`.
46- Flake posture: retries are a debugging tool; treat rerun-pass as a failure signal and fix root cause.
47- CI flakes: prefer built-in `failOnFlakyTests`; use a custom reporter only for older Playwright versions.
48- CI posture: smoke gate on PRs; shard/parallelize regression on schedule; always keep artifacts (trace/video/screenshot).
49- Oracle posture: assert the user outcome; do not wait on incidental network requests when the visible result can be verified directly.
50- AI posture: use Playwright codegen / test agents / MCP for scaffolding and exploration, then harden assertions and fixtures manually.
51- Browser MCP: Playwright MCP for test generation + accessibility; Chrome DevTools MCP for performance / network / console debugging. See `references/playwright-mcp.md`.
52- CLI posture: for high-throughput coding agents, prefer `@playwright/cli` (shell commands) over Playwright MCP — roughly 4x fewer tokens per task (~27k vs ~114k tokens/task per third-party benchmarks; as of 2026-07-11, verify at https://playwright.dev/docs/getting-started-cli). Use MCP when persistent browser state and rich introspection are needed.
53- Local iteration posture: use `npx playwright test --only-changed=main` to run only tests affected by uncommitted/branch changes during authoring; it is a heuristic over the import graph, so always run the full suite (or the deploy-gate replay) before merging — never treat `--only-changed` green as release-ready signal.
54
55## Quick Start
56
57| Command | Purpose |
58|---------|---------|
59| `npm init playwright@latest` | Initialize Playwright |
60| `npx playwright test` | Run all tests |
61| `npx playwright test --grep @smoke` | Run smoke tests |
62| `npx playwright test --project=chromium` | Run a single project |
63| `npx playwright test --ui` | Debug with UI mode |
64| `npx playwright test --debug` | Step through a test |
65| `npx playwright codegen` | Record a flow and bootstrap a test |
66| `npx playwright init-agents --loop=claude` | Initialize test agents for Claude Code |
67| `npx playwright test --fail-on-flaky-tests` | Fail CI if any test is flaky |
68| `npx playwright show-trace trace.zip` | Inspect trace artifacts |
69| `npx playwright show-report` | Inspect HTML report |
70| `npx playwright trace <trace.zip>` | Analyze trace from CLI (v1.59+) |
71| `npx playwright test --only-changed=main` | Run only tests affected by changes since `main` (heuristic — always follow with a full run before release) |
72
73## Local Execution Topology
74
75Use this order by default:
76
771. Start one shared local dev stack if the repo already provides it; prefer reusing it with `--no-server` over spawning a fresh app per rerun.
782. Reproduce with one exact spec or one named batch and `--workers=1`.
793. Fix and rerun the smallest affected scope.
804. Run the deploy-gate replay only after the targeted scope is green.
81
82Default suite tiers:
83
84- Smoke: PR gate and fastest signal.
85- Targeted batch/spec: local triage and deflake work.
86- Deploy-gate replay: dependency-chain or critical-journey replay for release confidence.
87
88Avoid local full-suite reruns as the first move unless the job is explicitly “prove deploy readiness now.”
89
90## When to Use
91
92- E2E tests for web applications
93- Test user authentication flows
94- Verify form submissions
95- Test responsive designs
96- Automate browser interactions
97- Set up Playwright in CI/CD
98
99## When NOT to Use
100
101| Scenario | Use Instead |
102|----------|-------------|
103| Unit testing | Jest, Vitest, pytest |
104| API contracts | [qa-api-testing-contracts](../qa-api-testing-contracts/SKILL.md) |
105| Load testing | k6, Locust, Artillery |
106| Mobile native | Appium |
107| Pure business-logic or data-transform correctness | Unit tests — a browser adds latency and flake with zero extra confidence |
108| Cross-team API contract drift | Consumer-driven contract tests, not a UI click-path proxy |
109| Component-level visual/interaction isolation at scale | Storybook + Chromatic/Percy, or Playwright component testing only if you accept experimental-API churn (see Defaults) |
110| Thousands of input-combination fuzzing | Property-based testing at the unit layer; E2E cannot afford the runtime |
111
112## Expert Judgment
113
114### When Playwright Is the Wrong Tool
115
116Playwright (or any browser E2E tool) is the wrong choice when a faster, cheaper layer already proves the same risk:
117- If the bug class can be caught by a type system, unit test, or schema/contract check, push it down — E2E is the most expensive test layer per assertion (browser boot, network, rendering).
118- If the "user journey" is actually an internal API call with no meaningful UI branching, test the API directly (`request` fixture or a dedicated API-testing skill) and skip the browser.
119- If you are testing a third-party surface you do not control (payment provider hosted page, OAuth consent screen), do not chase it with E2E; mock the boundary and test your own integration contract instead — third-party UI changes make these tests flaky by design, not by mistake.
120- If the same risk is already covered by a component test or visual snapshot at a fraction of the cost, do not duplicate it in E2E "just to be safe" — duplicate coverage without duplicate risk is waste, not thoroughness.
121
122### Selector-Strategy Decision Rule
123
124Pick the locator in this order, and stop at the first one that resolves unambiguously to exactly one element:
1251. `getByRole` with an accessible name — this is what a screen reader and a real user both key off, so it survives markup refactors.
1262. `getByLabel` / `getByText` — use when there is no meaningful role (plain text, decorative containers) but the visible copy is stable.
1273. `getByTestId` — use only when the element has no stable role/label (e.g., a canvas, a drag handle, a duplicate-name list item) or when semantic locators would force asserting on implementation detail (raw CSS class, generated ID).
128Never fall back to raw CSS or XPath as a first resort — they are a signal that the markup itself may need an accessibility fix, not just a test workaround.
129
130### Flakiness Triage Order (Fastest Signal First)
131
132Before touching a single assertion, classify the failure in this order — each step is strictly cheaper than the next, so do not skip ahead:
1331. **Selector ambiguity** — trace shows the locator resolved to 0 or 2+ elements. Fix the locator, not the wait.
1342. **Missing wait / race** — trace shows the action fired before the element was actionable. Replace with a web-first assertion; never add a fixed sleep.
1353. **State leakage** — failure only reproduces after other tests ran (parallel workers, shared fixtures, undropped test data). Fix isolation before touching this test's own code.
1364. **Environment** — only fails in CI, not locally; look at concurrency, cold start, CPU starvation, and container resource limits before assuming a product bug.
1375. **Product regression** — only after 1-4 are ruled out with trace evidence, treat the failure as reflecting the app under test and file/fix accordingly.
138Retries mask all five of these; use `retries` to gather evidence (trace/video) on the first CI run, but treat "passed on retry" as an unresolved defect, not a pass. See `template-playwright-fail-on-flaky-reporter.js`.
139
140### CI Parallelism Economics (Worked Example)
141
142Sharding trades machine-cost for wall-clock time; the math to decide is straightforward. Given a suite that takes `T` minutes single-threaded and `N` shards each with `M` machine-minutes of fixed overhead (checkout, install, browser download):
143- Wall-clock per shard ≈ `T/N + M`.
144- Total machine-minutes billed ≈ `N × (T/N + M) = T + N×M`.
145
146Example: `T = 60` min, `M = 3` min fixed overhead per shard/job.
147- 1 shard: wall-clock = 63 min, billed = 63 machine-minutes.
148- 4 shards: wall-clock = 60/4 + 3 = 18 min, billed = 4 × 18 = 72 machine-minutes.
149- 12 shards: wall-clock = 60/12 + 3 = 8 min, billed = 12 × 8 = 96 machine-minutes.
150
151Sharding always costs more total machine-minutes (because fixed overhead is paid N times) — the return is faster PR feedback, not lower spend. The judgment call: shard the PR-gate smoke suite (wall-clock matters, suite is small so `N×M` stays small) and run the full regression unsharded or lightly sharded on a schedule (spend matters more than latency there). Re-derive this ratio with your own `T` and `M` before picking a shard count — do not copy `N=4` by convention.
152
153## Authoring Rules
154
155### Locator Strategy
156
157```typescript
158// 1. Role locators (preferred)
159await page.getByRole('button', { name: 'Sign in' }).click();
160
161// 2. Label/text locators
162await page.getByLabel('Email').fill('user@example.com');
163
164// 3. Test IDs (fallback)
165await page.getByTestId('user-avatar').click();
166```
167
168### Flake Control
169
170- Avoid sleeps; use Playwright auto-wait
171- Use retries as signal, not a crutch
172- Prefer built-in `failOnFlakyTests` in CI
173- Capture trace/screenshot/video on failure
174- Prefer user-like interactions; avoid `force: true`
175
176## Workflow
177
178- Write the smallest test that proves the user outcome (intent + oracle).
179- Make execution topology explicit before triage: shared dev stack vs Playwright `webServer`, plus exact start/stop commands.
180- Reproduce with one exact spec or named batch before expanding scope.
181- Stabilize locators and assertions before adding more steps.
182- Make state explicit: seed per test/worker, clean up deterministically, and verify auth/subscription/test-data reset paths for stateful apps.
183- Mock or isolate third-party boundaries where they are not part of the user-facing oracle.
184- In CI: shard/parallelize, capture artifacts, and fail fast on rerun-pass flakes.
185
186## Debugging Checklist
187
188If something is flaky:
189- Open trace and error artifacts first; identify whether the failure is selector ambiguity, missing wait, state leakage, or the wrong server topology.
190- If the trace lands on login or an unexpected redirect, classify `auth-state` before changing assertions.
191- If browser logs show `429` or `Retry-After` on side endpoints, decide whether that request is part of the oracle or only noise.
192- Replace brittle selectors with semantic locators; replace sleeps with `expect(...)`, an auth-aware navigation helper, or a targeted readiness assertion.
193- Remove waits on incidental requests; assert the visible route, action, or content outcome instead.
194- Reduce global timeouts; add scoped timeouts only when the product truly needs it — prefer a per-action timeout or `test.step(name, fn, { timeout })` over raising `timeout` in `playwright.config.ts`.
195- If it only fails in CI, look for concurrency, cold-start, CPU starvation, and environment differences.
196
197## Do / Avoid
198
199- Make tests independent and deterministic
200- Use network mocking for third-party deps
201- Run smoke E2E on PRs; full regression on schedule
202
203- "Test everything E2E" as default
204- Weakening assertions to "fix" flakes
205- Auto-healing that weakens assertions
206
207## Execution Preflight (High ROI)
208
209Run this preflight before expensive E2E runs to prevent avoidable failures.
210
211### Preflight Checklist
212
2131. Repository shape:
214- Confirm working directory and expected app root exist.
215- Verify spec paths before execution (`rg --files tests/e2e | rg <target>`).
216
2172. Port/process hygiene:
218- Check and clear stale dev server port before run (example: `lsof -i :3001`).
219- Avoid parallel local servers colliding with Playwright `webServer`.
220- If the repo provides a shared dev-server helper, prefer it and run Playwright with `--no-server` during local deflake work.
221
2223. Command validity:
223- Validate CLI flags for current tool versions before batch runs.
224- Prefer exact spec paths, named batches, or `--grep` over broad globs during triage.
225- Record the cleanup/kill command for the chosen local stack before starting a long replay.
226
2274. Artifact expectations:
228- Confirm result artifact paths exist before reading (`test -f <error-context.md>`).
229- If artifact path missing, inspect latest `test-results` index first.
230
231### Mandatory Sandbox/Port Decisions
232
233Before running Playwright in constrained environments (sandboxed terminals, CI containers, shared dev hosts), decide and document:
234
235- Bind host/port: confirm whether app server must use `127.0.0.1` or `0.0.0.0`, and verify selected port is free.
236- Server-topology decision: shared dev server versus Playwright `webServer`; never run both accidentally.
237- Escalation path: if bind attempts fail with `EPERM`/`EACCES`, escalate immediately instead of retry loops.
238- Long-flow timeout budget: set explicit per-test timeout for API-heavy flows (generation/checkout/report) instead of inflating global timeout.
239- Build lock hygiene: clear stale `.next/lock` and terminate stale build/dev PIDs before rerun.
240
241### Triage Sequence (Fastest Signal)
242
2431. Reproduce one failing test or named batch with `--workers=1` on the chosen server topology.
2442. Capture trace/video/screenshot for that failure.
2453. Classify the failure: environment, auth-state, state-sync, optional network, degraded mode, or product regression.
2464. Fix the determinism root cause.
2475. Re-run the targeted spec or batch.
2486. Only then run the deploy-gate replay or broad regression.
249
250### Stateful App Failure Classes
251
252- `auth-state`: protected route unexpectedly redirects to login or loses storage/session state.
253- `state-sync`: backend reset or webhook succeeded, but UI has not converged yet.
254- `optional-network`: a side request failed, but the user-visible oracle may still be correct.
255- `degraded-mode`: rate limits or fallback UX activated and should be asserted intentionally.
256
257### Failure Patterns to Treat as Environment, Not Product Bugs
258
259- `EADDRINUSE` on Playwright web server port
260- Missing spec/result paths from stale assumptions
261- Shell glob expansion failures for bracketed route segments
262
263
264## Resources
265
266| Resource | Purpose |
267|----------|---------|
268| [references/playwright-mcp.md](references/playwright-mcp.md) | MCP & AI testing |
269| [references/playwright-patterns.md](references/playwright-patterns.md) | Advanced patterns |
270| [references/playwright-ci.md](references/playwright-ci.md) | CI configurations |
271| [references/playwright-authentication.md](references/playwright-authentication.md) | Auth patterns and session management |
272| [references/visual-regression-testing.md](references/visual-regression-testing.md) | Visual regression strategies |
273| [references/api-testing-playwright.md](references/api-testing-playwright.md) | API testing with APIRequestContext |
274| [references/playwright-preflight-sandbox.md](references/playwright-preflight-sandbox.md) | Sandbox/port preflight and escalation decisions |
275| [data/sources.json](data/sources.json) | Documentation links |
276
277## Templates
278
279| Template | Purpose |
280|----------|---------|
281| [assets/template-playwright-e2e-review-checklist.md](assets/template-playwright-e2e-review-checklist.md) | E2E review checklist |
282| [assets/template-playwright-fail-on-flaky-reporter.js](assets/template-playwright-fail-on-flaky-reporter.js) | Fail CI on rerun-pass flakes |
283| [assets/template-playwright-preflight-checklist.md](assets/template-playwright-preflight-checklist.md) | Preflight checklist for port/sandbox/timeouts |
284
285## ASCII Flow
286
287```text
288Playwright testing request
289 -> Confirm app root, server topology, ports, auth state, and target spec
290 -> Author the smallest user-outcome test with semantic locators
291 -> Isolate fixtures, storage, network, third parties, and worker state
292 -> Reproduce with one spec or grep and workers=1 before widening
293 -> Debug using trace, screenshots, video, console, and network evidence
294 -> Gate PR or deploy only after flakes are classified and fixed
295```
296
297## Navigation
298
299- `## Workflow`, `## Debugging Checklist`, and `## Execution Preflight (High ROI)` for the baseline sequence
300- `## Expert Judgment` for tool-fit, selector, flake-triage-order, and CI-sharding-economics decision rules
301- `## Resources` and `## Templates` for deeper materials
302- `## Related Skills` for strategy, frontend, and CI handoffs
303
304## Related Skills
305
306| Skill | Purpose |
307|-------|---------|
308| [qa-testing-strategy](../qa-testing-strategy/SKILL.md) | Overall test strategy |
309| [software-frontend](../software-frontend/SKILL.md) | Frontend development |
310| [ops-devops-platform](../ops-devops-platform/SKILL.md) | CI/CD integration |
311
312## Verification Gate
313
314Before delivering output, you MUST verify:
315
316- [ ] If a Playwright project exists, provide the exact test command to run and execute it when the environment is available; otherwise mark execution as unverified.
317- [ ] Generated selectors follow the stated locator priority unless the page makes that impossible.
318- [ ] The output avoids sleep-based waits and names the readiness assertion or trace/debug artifact to inspect.
319- [ ] Every referenced test file, config file, and command path exists in the repo or is explicitly marked as proposed.
320
321## Fact-Checking
322
323- Known bugs, regressions, framework/compiler/runtime footguns, and version-specific crash or workaround guidance must be verified against current primary web sources before being treated as current fact.
324- Use web search or web fetch to verify current external facts, versions, pricing, deadlines, regulations, or platform behavior before final answers.
325- Prefer primary sources; report source links and dates for volatile information.
326- If web access is unavailable, state the limitation and mark guidance as unverified.
327
328## Learnings Loop
329
330Before applying this skill on a non-trivial task, read `learnings.consolidated.md` in this directory (and `learnings.md` if present).
331
332After applying it, if you encountered a pattern worth remembering, a mistake worth preventing, or a domain fact that surprised you, append one dated bullet to `learnings.md` via `agents-skills-feedback-loop/scripts/append_learning.py`. Do not modify `SKILL.md` itself.
333