80%
DefinitionTests give confidence to change code.
Unit: one function/module in isolation · Vitest, Jest
Integration: pieces together: API + DB, component + hooks · Supertest, Testing Library, test DB
End-to-end: the real app in a browser · Playwright, Cypress
TipTest behaviour, not implementation details — tests should survive a refactor that keeps behaviour the same.
Mock: replaces a dependency and records calls.
Mock the boundaries (network, time, randomness), not your own logic.
Fake timers (
vi.useFakeTimers()) for debounce/timeout code.Query priority:
getByRole → getByLabelText → getByText → getByTestId (last resort).getBy throws if missing, queryBy returns null (use it to assert absence), findBy waits (async).Mock the network with MSW so components use their real data-fetching code.
Use a separate test database; reset or seed it per test file.
E2E: test the critical paths (sign-up, checkout, payment), not every edge case.
Coverage is a guide, not a goal — 100% coverage with weak assertions proves little.
TDD: write a failing test (red), make it pass (green), clean up (refactor).
ReviseMany unit, some integration, few E2E.