
Vitest + Testing Library: Writing My First Frontend Tests
My trial-and-error journey introducing frontend testing. Practical patterns for testing React components with Vitest and Testing Library.

My trial-and-error journey introducing frontend testing. Practical patterns for testing React components with Vitest and Testing Library.
Writing test BEFORE code. Red -> Green -> Refactor. The Double-Entry Bookkeeping of Programming.

Tests that inspect internal component state break on every refactor. Testing Library's core philosophy is to test only what the user actually does. Here's why getByRole is the best default, what separates userEvent from fireEvent, and the most common anti-patterns to avoid.

I imported a Server Component inside a Client Component, and it broke everything. Here’s how to use the Composition Pattern (Donut Pattern) to fix it and correctly separate Context Providers.

Obsessively wrapping everything in `useMemo`? It might be hurting your performance. Learn the hidden costs of memoization and when to actually use it.

Vitest is the obvious choice for Vite projects. No wrestling with Jest transform configs. Reuses your existing Vite setup. Jest-compatible API with minimal migration cost.
Testing Library tests behavior, not implementation. Query by role, interact via userEvent, verify what the user sees. Tests stay valid through refactors.
Async tests need waitFor. Any assertion that depends on data fetching, timeouts, or Promise resolution needs to wait. Otherwise you're checking before the async work finishes.
Custom hooks get renderHook. Isolated hook testing without boilerplate wrapper components. Wrap state mutations in act().
Define what you'll test and what you won't. User-facing behavior and business logic: yes. Internal implementation, third-party libraries, styles: no. Chasing 100% coverage on the wrong things burns time and makes tests fragile.
If you're starting from zero, don't try to test everything at once. Find the one thing that scares you most—the feature that, if it broke in production, would cause real damage—and write tests for that first. After you've watched a test catch an actual bug before it shipped, you'll never want to go without them again.