Testinghigh

React Testing Library

React Testing Library (RTL) tests components from the user's perspective — finding elements by accessible roles, text, and labels rather than implementation details like component names or state. Its philosophy: 'The more your tests resemble the way your software is used, the more confidence they give you.'

Memory anchor

RTL is a mystery shopper — they don't inspect the kitchen (implementation); they sit at the table, read the menu (accessible labels), order food (user events), and check if the right dish arrives (assertions).

Expected depth

Core API: render(<Component />) returns a container. Queries prioritize: getByRole > getByLabelText > getByText > getByTestId (last resort). userEvent simulates real user interactions (typing, clicking) with event propagation, preferred over fireEvent. act() ensures all state updates and effects are processed before assertions. waitFor() handles async updates. screen is the recommended way to access queries: screen.getByRole('button', { name: 'Submit' }).

Deep — senior internals

RTL renders into a real DOM (jsdom), not a shallow render, giving higher confidence that components integrate correctly. renderHook() tests custom hooks without wrapper components. For async testing: findBy* queries combine getBy* with waitFor(), retrying until the element appears or a timeout hits. MSW (Mock Service Worker) intercepts network requests at the service worker level for realistic API mocking. Testing Server Components requires different tools since they run on the server — use integration tests or the framework's testing utilities (e.g., Next.js test mode).

🎤Interview-ready answer

React Testing Library tests from the user's perspective using accessible queries — getByRole, getByLabelText, getByText. I use userEvent over fireEvent for realistic interactions, waitFor for async updates, and MSW for API mocking. The key principle is testing behavior, not implementation — I never query by component name or internal state. For custom hooks, I use renderHook.

Common trap

Testing implementation details like state values, component instances, or internal methods. When you refactor (changing state structure, extracting hooks), these tests break even though behavior is unchanged. Test what the user sees and does.