Web Component Testing
Purpose
Plan the component-test layer: rendered components exercised the way users interact with them — accessible queries, real events via user-event, network mocked at the boundary with MSW — asserting behavior, not implementation detail. Sits between web-unit-testing and playwright-e2e.
When to Use
- When components carry interaction logic worth verifying (forms, tables, dialogs, gated UI).
- When existing component tests are brittle (implementation-coupled, snapshot-heavy) or missing.
- Not for pure logic (
web-unit-testing) or cross-page journeys (playwright-e2e).
Inputs
- The component inventory, prioritized by interaction complexity and risk.
- Unit-layer runner decision (
web-unit-testing) — component tests share it (jsdom environment).
- API shapes for MSW handlers (
web-api-integration).
Discovery Questions
- Which components have behavior worth testing (conditional rendering, validation UX, async states) vs purely presentational?
- What shared render setup is needed (providers: theme, router, query client)?
- Which API interactions should MSW model, and where do handler defaults live?
- What genuinely needs a real browser (layout, CSS, focus subtleties, portals under real stacking) — and is therefore E2E scope?
Responsibilities
- Set the query discipline:
getByRole (with accessible name) first, then label/text; data-testid as the escape hatch — this makes tests double as accessibility probes (web-accessibility).
- Use user-event for interaction (typing, clicking, keyboard) over firing synthetic events directly.
- Mock the network at the boundary with MSW: shared handler defaults mirroring real API shapes, per-test overrides for error/empty/slow cases — components don't get their fetch layer stubbed internally.
- Test behavior contracts: what renders for which state (loading/error/empty/data), what happens on interaction — never internal state, hooks call counts, or DOM structure incidentals.
- Provide a shared render helper wrapping required providers so tests stay terse and consistent.
- Constrain snapshots to small, intentional cases (if any); assert specifics instead.
- Cover async UX properly:
findBy*/waitFor instead of arbitrary sleeps; assert accessible loading/error states (web-error-handling).
Required Workflow
- Prioritize components by interaction risk.
- Build the shared render helper + MSW handler baseline.
- Write behavior tests per priority component, covering data/loading/error/empty and key interactions.
- Route real-browser concerns to
playwright-e2e explicitly.
- Wire into CI beside the unit layer; record coverage decisions.
Decision Rules
- If the assertion needs
getByRole gymnastics because the component isn't accessible — fix the component, not the query.
- If the test breaks when internals refactor without behavior change, it's testing the wrong thing.
- jsdom can't verify real layout/painting/focus edge cases — don't fake it; escalate that case to E2E.
- Empty/error states are test cases, not afterthoughts.
Rules
- Component tests run in CI on every push with the unit layer.
- No mocking of the component under test's children by default — mock boundaries (network, time), not the tree.
- Deterministic: MSW-controlled responses, fake timers where needed, no live endpoints.
Anti-Patterns
- Snapshot files nobody reads, regenerated on every diff.
- Asserting on CSS classes/DOM structure instead of user-visible behavior.
- Stubbing
fetch/axios per test instead of MSW at the boundary.
- Re-testing every prop permutation better covered by a unit test of the logic.
Validation Checklist
Definition of Done
A recorded component-testing plan — priorities, shared setup, MSW boundary, role-first query conventions, and state coverage — yielding tests that survive refactors and double as accessibility checks.
Related Skills
web-unit-testing, playwright-e2e, web-accessibility, web-api-integration, web-error-handling, web-forms, ../../testing-strategy.
Related Knowledge
../../../knowledge/ (interaction-critical components).
Related References
../../../references/web/testing/ (render helper, MSW patterns — when populated).
Context Loading Guidance
- Requires: component priorities, API shapes, unit-layer decisions.
- Does not require: deployment detail, full source tree.
- May load:
web-accessibility for query/name expectations; playwright-e2e for the layer boundary.
- Stop when: conventions and priority coverage are recorded.
Token Efficiency Guidance
Define conventions and the shared setup once; per-component plans are one line each (component → states → interactions).
1---2name: web-component-testing3description: Use to plan component tests — React Testing Library with user-event, accessible queries (getByRole first), MSW for network boundaries, testing behavior not implementation, and knowing jsdom's limits (real-browser behavior belongs to Playwright). Avoid snapshot overuse.4---56# Web Component Testing78## Purpose910Plan the component-test layer: rendered components exercised the way users interact with them — accessible queries, real events via user-event, network mocked at the boundary with MSW — asserting behavior, not implementation detail. Sits between `web-unit-testing` and `playwright-e2e`.1112## When to Use1314- When components carry interaction logic worth verifying (forms, tables, dialogs, gated UI).15- When existing component tests are brittle (implementation-coupled, snapshot-heavy) or missing.16- **Not** for pure logic (`web-unit-testing`) or cross-page journeys (`playwright-e2e`).1718## Inputs1920- The component inventory, prioritized by interaction complexity and risk.21- Unit-layer runner decision (`web-unit-testing`) — component tests share it (jsdom environment).22- API shapes for MSW handlers (`web-api-integration`).2324## Discovery Questions2526- Which components have behavior worth testing (conditional rendering, validation UX, async states) vs purely presentational?27- What shared render setup is needed (providers: theme, router, query client)?28- Which API interactions should MSW model, and where do handler defaults live?29- What genuinely needs a real browser (layout, CSS, focus subtleties, portals under real stacking) — and is therefore E2E scope?3031## Responsibilities3233- Set the **query discipline**: `getByRole` (with accessible name) first, then label/text; `data-testid` as the escape hatch — this makes tests double as accessibility probes (`web-accessibility`).34- Use **user-event** for interaction (typing, clicking, keyboard) over firing synthetic events directly.35- Mock the **network at the boundary with MSW**: shared handler defaults mirroring real API shapes, per-test overrides for error/empty/slow cases — components don't get their fetch layer stubbed internally.36- Test **behavior contracts**: what renders for which state (loading/error/empty/data), what happens on interaction — never internal state, hooks call counts, or DOM structure incidentals.37- Provide a **shared render helper** wrapping required providers so tests stay terse and consistent.38- Constrain **snapshots** to small, intentional cases (if any); assert specifics instead.39- Cover **async UX** properly: `findBy*`/`waitFor` instead of arbitrary sleeps; assert accessible loading/error states (`web-error-handling`).4041## Required Workflow42431. Prioritize components by interaction risk.442. Build the shared render helper + MSW handler baseline.453. Write behavior tests per priority component, covering data/loading/error/empty and key interactions.464. Route real-browser concerns to `playwright-e2e` explicitly.475. Wire into CI beside the unit layer; record coverage decisions.4849## Decision Rules5051- If the assertion needs `getByRole` gymnastics because the component isn't accessible — fix the component, not the query.52- If the test breaks when internals refactor without behavior change, it's testing the wrong thing.53- jsdom can't verify real layout/painting/focus edge cases — don't fake it; escalate that case to E2E.54- Empty/error states are test cases, not afterthoughts.5556## Rules5758- Component tests run in CI on every push with the unit layer.59- No mocking of the component under test's children by default — mock boundaries (network, time), not the tree.60- Deterministic: MSW-controlled responses, fake timers where needed, no live endpoints.6162## Anti-Patterns6364- Snapshot files nobody reads, regenerated on every diff.65- Asserting on CSS classes/DOM structure instead of user-visible behavior.66- Stubbing `fetch`/axios per test instead of MSW at the boundary.67- Re-testing every prop permutation better covered by a unit test of the logic.6869## Validation Checklist7071- [ ] Components prioritized by interaction risk.72- [ ] Shared render helper + MSW baseline planned.73- [ ] Query discipline (role-first) and user-event usage set as convention.74- [ ] Data/loading/error/empty states covered for priority components.75- [ ] Real-browser cases explicitly routed to E2E.76- [ ] CI wiring recorded.7778## Definition of Done7980A recorded component-testing plan — priorities, shared setup, MSW boundary, role-first query conventions, and state coverage — yielding tests that survive refactors and double as accessibility checks.8182## Related Skills8384`web-unit-testing`, `playwright-e2e`, `web-accessibility`, `web-api-integration`, `web-error-handling`, `web-forms`, `../../testing-strategy`.8586## Related Knowledge8788`../../../knowledge/` (interaction-critical components).8990## Related References9192`../../../references/web/testing/` (render helper, MSW patterns — when populated).9394## Context Loading Guidance9596- **Requires:** component priorities, API shapes, unit-layer decisions.97- **Does not require:** deployment detail, full source tree.98- **May load:** `web-accessibility` for query/name expectations; `playwright-e2e` for the layer boundary.99- **Stop when:** conventions and priority coverage are recorded.100101## Token Efficiency Guidance102103Define conventions and the shared setup once; per-component plans are one line each (component → states → interactions).