playwright-architect
Architectural lens above the existing tactical
playwright-testing. Decides
locator philosophy, Page Object boundaries, fixture composition,
and the CI-vs-local split before the first test is written.
The playwright-testing skill handles concrete assertions,
selectors, and visual-regression mechanics once the design is
locked.
When to use
- A new Playwright suite is starting and the directory shape, fixture
hierarchy, and locator strategy are unsettled.
- An existing suite has flake > 2 % runs, slow CI (> 10 min), or a
god-test file mixing unrelated journeys.
- A second app / surface (admin, mobile-web, embedded widget) needs
to share fixtures with the main suite.
- German triggers: "Playwright Setup planen", "Page Objects schneiden",
"warum flaket der Test?".
Do NOT use when:
- A single test fails and the question is the assertion or selector
— route to
playwright-testing.
- The platform is mobile-native (Detox, Appium, Maestro) — route to
mobile-e2e-strategy.
- Unit / component tests are the question — Playwright is the wrong
tool; route to the stack-specific testing skill.
Procedure
1. Inspect the suite, pick the locator philosophy
Review existing tests for current locator patterns; the established
strategy wins unless it is the "last resort" tier. One philosophy
per suite, written into CONTRIBUTING-tests.md:
| Strategy |
When |
getByRole + accessible name |
Default — couples tests to the user contract, not markup |
data-testid |
Legacy markup, third-party widgets, hash-suffixed CSS modules |
Text content (getByText) |
Static marketing pages, copy-stable surfaces |
| CSS / XPath |
Last resort — every use is a debt entry |
Mixing strategies inside one test file is the smell — pick one and
fall back only with comment.
2. Cut Page Object boundaries
A Page Object owns: (a) one URL or one logical surface (modal,
drawer), (b) the locators on that surface, (c) the actions a
user can perform there. It does NOT own assertions about other
surfaces or test setup. Boundary rule: if two POs need to call
each other, introduce a flow object (SignupFlow) above them.
3. Compose fixtures, don't inherit
Playwright fixtures stack via test.extend(). Three layers max:
| Layer |
Owns |
| Base |
Browser, context, storageState, network mocks |
| Auth |
Logged-in user states (admin, member, guest) |
| Domain |
Pre-seeded entities for a journey |
Deeper stacks become un-debuggable; flatten by extracting helpers.
4. Plan flake prevention before the first failure
Bake in: auto-retry on network idle, soft assertions for parallel
checks, deterministic seed data, time freezing (page.clock),
explicit expect.poll() for eventual consistency, no
waitForTimeout ever. If a test needs sleep, the fixture is
wrong.
5. Split CI vs local execution
Local: headed browser, single worker, slowMo enabled, video off,
trace-on-retry. CI: headless, sharded workers (2–8), trace-on-first-retry,
video-on-failure, Github reporter + HTML. Document both in
playwright.config.ts; do not let local config leak into CI.
Output format
Return:
- Locator + Page Object plan — chosen strategy, PO list with surface
and action count, flow objects when ≥ 2 POs collaborate.
- Fixture composition — base / auth / domain layer with what each
layer sets up.
- Parallelism + flake budget — worker count, shard strategy,
isolation, target flake ceiling, CI-vs-local config delta.
Concrete shape:
Suite: <name>
Locator strategy: <getByRole | data-testid | text | mixed (justified)>
Page Objects: <list with surface owned + action count>
Flow objects: <list — only when ≥ 2 POs collaborate>
Fixture layers: base / auth / domain — each with what it sets up
Parallelism: <workers, shards, isolation strategy>
Flake budget: ≤ 1 % failure on green main; alert threshold
CI-vs-local: <key config delta, one bullet each>
Gotcha
page.waitForSelector is almost always wrong — expect(locator).toBeVisible()
has built-in retry. The former teaches devs to think "wait, then
assert" instead of "auto-retry assertion".
- Storage-state reuse across workers requires cookie domain
isolation; the same
auth.json across two browsers in parallel
shares a session and corrupts state.
- Visual regression in CI requires identical fonts and renderer —
pin the Docker image, never run visual tests against host
Chromium.
- One Page Object per URL looks clean but creates god-objects
for SPA routes; cut by user surface, not by
pathname.
Do NOT
- Do NOT cite this skill alongside
playwright-testing
in the same step — they sit at different tiers; pick one per phase.
- Do NOT design suites for component tests with this skill —
Playwright Component Testing has different fixture rules; route
there instead.
- Do NOT promise zero flake; budget for ≤ 1 % and instrument the
metric. Zero is a goal that disguises silent retries.
- Do NOT push the architecture into the tracker as code AC — output
is a design note for refinement, not implementation steps.
1---2name: playwright-architect3description: Use when shaping a Playwright suite — locator strategy, Page Object boundaries, fixture composition, flake-prevention architecture, CI-vs-local split — even on 'design our E2E tests'.4---56# playwright-architect78> Architectural lens **above** the existing tactical9> [`playwright-testing`](../playwright-testing/SKILL.md). Decides10> locator philosophy, Page Object boundaries, fixture composition,11> and the CI-vs-local split *before* the first test is written.12> The `playwright-testing` skill handles concrete assertions,13> selectors, and visual-regression mechanics once the design is14> locked.1516## When to use1718- A new Playwright suite is starting and the directory shape, fixture19 hierarchy, and locator strategy are unsettled.20- An existing suite has flake > 2 % runs, slow CI (> 10 min), or a21 god-test file mixing unrelated journeys.22- A second app / surface (admin, mobile-web, embedded widget) needs23 to share fixtures with the main suite.24- German triggers: "Playwright Setup planen", "Page Objects schneiden",25 "warum flaket der Test?".2627Do NOT use when:2829- A single test fails and the question is the assertion or selector30 — route to [`playwright-testing`](../playwright-testing/SKILL.md).31- The platform is mobile-native (Detox, Appium, Maestro) — route to32 [`mobile-e2e-strategy`](../mobile-e2e-strategy/SKILL.md).33- Unit / component tests are the question — Playwright is the wrong34 tool; route to the stack-specific testing skill.3536## Procedure3738### 1. Inspect the suite, pick the locator philosophy3940Review existing tests for current locator patterns; the established41strategy wins unless it is the "last resort" tier. One philosophy42per suite, written into `CONTRIBUTING-tests.md`:4344| Strategy | When |45|---|---|46| `getByRole` + accessible name | Default — couples tests to the user contract, not markup |47| `data-testid` | Legacy markup, third-party widgets, hash-suffixed CSS modules |48| Text content (`getByText`) | Static marketing pages, copy-stable surfaces |49| CSS / XPath | Last resort — every use is a debt entry |5051Mixing strategies inside one test file is the smell — pick one and52fall back only with comment.5354### 2. Cut Page Object boundaries5556A Page Object owns: (a) one URL or one logical surface (modal,57drawer), (b) the locators on that surface, (c) the **actions** a58user can perform there. It does NOT own assertions about other59surfaces or test setup. Boundary rule: if two POs need to call60each other, introduce a **flow object** (`SignupFlow`) above them.6162### 3. Compose fixtures, don't inherit6364Playwright fixtures stack via `test.extend()`. Three layers max:6566| Layer | Owns |67|---|---|68| Base | Browser, context, storageState, network mocks |69| Auth | Logged-in user states (admin, member, guest) |70| Domain | Pre-seeded entities for a journey |7172Deeper stacks become un-debuggable; flatten by extracting helpers.7374### 4. Plan flake prevention before the first failure7576Bake in: auto-retry on network idle, soft assertions for parallel77checks, deterministic seed data, time freezing (`page.clock`),78explicit `expect.poll()` for eventual consistency, no79`waitForTimeout` ever. If a test needs `sleep`, the fixture is80wrong.8182### 5. Split CI vs local execution8384Local: headed browser, single worker, slowMo enabled, video off,85trace-on-retry. CI: headless, sharded workers (2–8), trace-on-first-retry,86video-on-failure, Github reporter + HTML. Document both in87`playwright.config.ts`; do not let local config leak into CI.8889## Output format9091Return:92931. Locator + Page Object plan — chosen strategy, PO list with surface94 and action count, flow objects when ≥ 2 POs collaborate.952. Fixture composition — base / auth / domain layer with what each96 layer sets up.973. Parallelism + flake budget — worker count, shard strategy,98 isolation, target flake ceiling, CI-vs-local config delta.99100Concrete shape:101102```103Suite: <name>104Locator strategy: <getByRole | data-testid | text | mixed (justified)>105Page Objects: <list with surface owned + action count>106Flow objects: <list — only when ≥ 2 POs collaborate>107Fixture layers: base / auth / domain — each with what it sets up108Parallelism: <workers, shards, isolation strategy>109Flake budget: ≤ 1 % failure on green main; alert threshold110CI-vs-local: <key config delta, one bullet each>111```112113## Gotcha114115- `page.waitForSelector` is almost always wrong — `expect(locator).toBeVisible()`116 has built-in retry. The former teaches devs to think "wait, then117 assert" instead of "auto-retry assertion".118- Storage-state reuse across workers requires cookie domain119 isolation; the same `auth.json` across two browsers in parallel120 shares a session and corrupts state.121- Visual regression in CI requires identical fonts and renderer —122 pin the Docker image, never run visual tests against host123 Chromium.124- One Page Object per URL **looks** clean but creates god-objects125 for SPA routes; cut by *user surface*, not by `pathname`.126127## Do NOT128129- Do NOT cite this skill alongside [`playwright-testing`](../playwright-testing/SKILL.md)130 in the same step — they sit at different tiers; pick one per phase.131- Do NOT design suites for component tests with this skill —132 Playwright Component Testing has different fixture rules; route133 there instead.134- Do NOT promise zero flake; budget for ≤ 1 % and instrument the135 metric. Zero is a goal that disguises silent retries.136- Do NOT push the architecture into the tracker as code AC — output137 is a design note for refinement, not implementation steps.