Testing (Vitest + Playwright)

Pathrule2 Rules • 2 Memories • 1 Skill

A layered testing setup that splits fast unit and component tests in Vitest from end-to-end browser tests in Playwright. It pushes assertions toward observable behavior and role-based selectors so tests survive refactors, and it wires both suites into CI with coverage, retries, and trace artifacts.

Suggested path map

Pathrule places each piece on the matching path, so your assistant only sees it where it belongs. This is the scoping you get on import; you can adjust it in your workspace.

/ workspace root
Two-layer test stack: Vitest units, Playwright e2e
testing-vitest-playwright-review
e2e/
Select by role and accessible name, not CSS
Playwright CI config: parallel, retries, traces, sharding
src/
Test observable behavior, not implementation

Rules

2
Select by role and accessible name, not CSS/e2ehighadvisoryPlaywright locators must follow the role-first hierarchy; CSS and XPath are last resort.
1End-to-end tests must locate elements the way a user or screen reader does, so they survive markup and styling refactors.
2 
3- Reach for `getByRole(name)` first; it is Playwright's recommended locator and doubles as an accessibility check.
4- Fall back in order to `getByLabel`, `getByPlaceholder`, `getByText`, then `getByTestId` only when no semantic handle exists.
5- Do not select by CSS class, tag chains, or XPath; these break on every redesign.
6- Add `data-testid` to the element, not a wrapper, when a test id is genuinely needed.
Test observable behavior, not implementation/srchighadvisoryAssert on rendered output and public contracts, never on internal state or private methods.
1Unit and component tests must verify what a user or caller observes, so they catch regressions without breaking on internal refactors.
2 
3- Assert on rendered DOM, returned values, and emitted events; query with `@testing-library` role and label helpers.
4- Do not assert on component internal state, private methods, or spy call counts when an observable effect exists.
5- Prefer `await screen.findByRole(...)` and `userEvent` interactions over reaching into instances.
6- Reserve mocks for true boundaries (network, time, randomness); never mock the unit under test.

Memories

2
Two-layer test stack: Vitest units, Playwright e2e/rootVitest 4.1 owns fast unit/component tests; Playwright owns real-browser end-to-end flows.
1We run two distinct layers so each test sits at the right altitude. Keep them separate; do not drive full app flows from Vitest or unit-test pure logic through Playwright.
2 
3- Unit and component tests live in `/src` next to source or in `/tests`, run under Vitest 4.1 with `environment: 'jsdom'` (or `happy-dom`) and `@testing-library/react`.
4- End-to-end tests live in `/e2e`, run under `@playwright/test` against a real browser via the `webServer` config that boots the app.
5- Vitest 4 defaults coverage to `v8`; set `coverage.include` explicitly since `coverage.all` was removed in v4.
6- Heavy component-interaction tests can use Vitest Browser Mode (stable since v4) instead of jsdom when DOM fidelity matters.
7 
8See /e2e for the Playwright selector rule and /src for the behavior-testing rule.
Playwright CI config: parallel, retries, traces, sharding/e2eHow the e2e suite is wired for stable, debuggable CI runs.
1Our `playwright.config.ts` is tuned so CI failures are reproducible and fast. Match these settings when adding projects or jobs.
2 
3- `fullyParallel: true`, `workers` left to default locally and capped in CI, `retries: process.env.CI ? 2 : 0`.
4- `trace: 'on-first-retry'` so a failing test ships a full trace (network, DOM snapshots, timeline) without slowing green runs.
5- `webServer` boots the app with `reuseExistingServer: !process.env.CI` so local runs reuse a running dev server and CI always starts clean.
6- Large suites split across runners with `--shard=index/total`; merge the blob reports afterward for one HTML report.
7- Open the Trace Viewer (`npx playwright show-trace`) before editing any flaky test.

Skills

1
testing-vitest-playwright-review/rootPre-merge checklist for Vitest unit tests and Playwright e2e tests.
1---
2name: testing-vitest-playwright-review
3description: Review checklist for any change that adds or edits Vitest unit/component tests or Playwright e2e tests. Confirms tests assert behavior, use stable role-based selectors, and run reliably in CI.
4---
5 
6# Testing (Vitest + Playwright) review
7 
8- [ ] New logic and components have Vitest tests; new user flows have a Playwright e2e test.
9- [ ] Assertions target observable output (rendered DOM, return values, events), not internal state or private methods.
10- [ ] Component queries use `@testing-library` role/label helpers and `userEvent`, not container DOM traversal.
11- [ ] Playwright locators follow the hierarchy: `getByRole` first, then label/placeholder/text, `getByTestId` last, no raw CSS or XPath.
12- [ ] Mocks are limited to real boundaries (network, time, randomness); the unit under test is never mocked.
13- [ ] Async work is awaited via `findBy*` / web-first `expect` assertions, with no fixed `sleep`/`waitForTimeout` waits.
14- [ ] Vitest `coverage.include` is set and coverage does not regress; provider is `v8`.
15- [ ] Playwright config keeps `trace: 'on-first-retry'`, CI `retries: 2`, `fullyParallel`, and a `webServer` entry.
16- [ ] Tests are deterministic and isolated: one context per e2e test, no shared mutable fixtures, no order dependence.
17- [ ] CI runs both suites and uploads Playwright traces/reports as artifacts.

Why this pattern

AI-generated tests often assert on implementation details and brittle CSS selectors, so they break on every refactor while missing real user-facing regressions.

Built for Frontend and full-stack teams running Vitest for units and Playwright for end-to-end on a TypeScript codebase..

Keeps your assistant from:

  • Brittle e2e tests pinned to CSS classes or DOM structure instead of accessible roles
  • Unit tests that assert on internal state, private methods, or call counts instead of observable output
  • Flaky CI runs with no traces, no retries, and no parallelism or sharding
License
Apache-2.0
Version
1.0.0
Updated
2026-06-09
View source