Guides test writing for components, hooks, API integrations, and E2E flows. Activates when creating or editing test files, spec files, or when implementing features that need test coverage. Use when writing unit tests, integration tests, E2E tests, deciding what to test, choosing testing strategies, identifying edge cases, setting up mocks, or evaluating test quality. Triggers on questions like "how do I test this", "what tests do I need", "how do I mock this API", "what edge cases am I missing", "should this be a unit or integration test", "how do I write E2E tests for this flow".
Guides test writing for components, hooks, API integrations, and E2E flows. Activates when creating or editing test files, spec files, or when implementing features that need test coverage. Use when writing unit tests, integration tests, E2E tests, deciding what to test, choosing testing strategies, identifying edge cases, setting up mocks, or evaluating test quality. Triggers on questions like "how do I test this", "what tests do I need", "how do I mock this API", "what edge cases am I missing", "should this be a unit or integration test", "how do I write E2E tests for this flow".
Testing Skill
Ensure consistent, meaningful test coverage that catches real bugs without testing implementation details.
Core Principle
Test behavior, not implementation. Cover edge cases systematically. Never skip testing.
Tests exist to catch regressions and document expected behavior. If a test would break from a refactor that doesn't change behavior, it's testing the wrong thing.
Testing Pyramid
Layer
Coverage Target
Tests Per Feature
Purpose
Unit
60-70%
5-15 tests
Individual functions, hooks, components in isolation
Integration
15-25%
3-8 tests
Component interactions, form flows, API integration
E2E
5-15%
1-3 tests
Critical user journeys, happy paths
Decision Tree: What Type of Test?
What are you testing?
│
├─ Pure function (utility, transformer, validator)?
│ └─ UNIT TEST — test inputs → outputs, boundaries, errors
│
├─ Custom hook?
│ └─ UNIT TEST — use renderHook, test state transitions and effects
│
├─ Single component rendering?
│ └─ UNIT TEST — render with props, check output, simulate interactions
│
├─ Multiple components working together?
│ └─ INTEGRATION TEST — render parent, verify child behavior
│
├─ Form with validation and submission?
│ └─ INTEGRATION TEST — fill fields, trigger validation, mock API, verify states
│
├─ Component with API calls?
│ └─ INTEGRATION TEST — mock API, test loading/success/error states
│
├─ Critical user flow (login, checkout, CRUD)?
│ └─ E2E TEST — real browser, test the full journey
│
└─ Visual appearance / layout?
└─ VISUAL TEST — screenshot comparison (if Playwright configured)
Edge Cases Checklist
For every component or feature, systematically check:
Data States
Empty state — no items, null values, empty strings
Single item — boundary between empty and populated
Many items — performance, scrolling, pagination
Invalid data — malformed responses, unexpected types
Stale data — cached data that's outdated
User Interactions
Double-click / rapid interactions — debounce, disable during loading
Implementation details (internal state shape, private methods)
Third-party library internals (trust that React renders, trust that Zod validates)
CSS styling (unless visual regression testing is configured)
Exact error message wording (test for presence, not exact string — unless UX-critical)
Console.log output
TypeScript types at runtime (that's the compiler's job)
Mocking Boundaries
Mock at these boundaries: Don't mock:
├─ Network (MSW for API calls) ├─ Internal functions
├─ Browser APIs (localStorage) ├─ Component children
├─ Time (vi.useFakeTimers) ├─ Utility functions
├─ External services ├─ State management
└─ File system └─ Your own hooks (test them directly)
Rule: Mock at the system boundary, test everything inside.
Test File Conventions
Source file
Test file
UserCard.tsx
UserCard.test.tsx
useAuth.ts
useAuth.test.ts
formatDate.ts
formatDate.test.ts
E2E flows
e2e/checkout.spec.ts
Colocate unit tests with source files
Place E2E tests in e2e/ or tests/e2e/ directory
Use describe blocks matching the feature/component name
Test names describe behavior: "shows error when API fails" not "test error"