Testing Fundamentals
Testing React Components
Test React components the way users interact with them — through rendered output and user events.
React Testing Library Philosophy
React Testing Library is built on one principle: test your components the way users interact with them.
Users don't care about component state. They care about what they see and what they can do. Testing Library encourages you to query the DOM the way a user would — by visible text, by role, by label — not by implementation details like state variables or internal methods.
Setup
Install @testing-library/react, @testing-library/jest-dom, and @testing-library/user-event. Configure jsdom environment in vitest.config.ts and import jest-dom matchers in a setup file.
Rendering and Querying
Use render() to mount components and screen to query the rendered output. The screen object provides all query methods.
Query Priority
Use queries in this order (most to least semantic):
- getByRole — finds by ARIA role (button, heading, textbox, link). Preferred.
- getByLabelText — finds form inputs by their label.
- getByText — finds by visible text content.
- getByPlaceholderText — finds input by placeholder.
- getByTestId — last resort, requires adding data-testid attributes.
User Interactions
Use userEvent from @testing-library/user-event for realistic user interactions. It simulates real browser events more accurately than the lower-level fireEvent.
Async Testing
Many components make async operations (fetches, timers). Use findBy queries (return promises) or waitFor to wait for async state changes.
Key Takeaways
- Test what users see and do — not component state or implementation details
- Query priority: getByRole > getByLabelText > getByText > getByTestId
- Use userEvent for interactions — it simulates real browser events more accurately than fireEvent
- Use findBy queries for async content — they return promises and wait for the element to appear
Example
// Complete test for a LoginForm component