Testing

5 questions found

What is React Testing Library and how does its approach to testing differ from testing internal implementation details?

Beginner
React Testing Library encourages testing a component the way an actual user would interact with it, such as finding a button by its visible text and clicking it, rather than checking internal details like a component's specific state values. This makes tests more reliable, since they keep passing even if the internal code changes, as long as the actual user experience stays the same.
import { render, screen, fireEvent } from '@testing-library/react';

test('button increments count when clicked', () => {
  render(<Counter />);
  const button = screen.getByText('Count: 0');
  fireEvent.click(button);
  expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
Real-world example A team's test for a counter button keeps passing even after they rewrite the component from using useState to useReducer internally, since the test only ever checked what the user actually sees and clicks on the screen.

Common follow-ups: Why is testing implementation details, like internal state, considered a less reliable approach?;What is the difference between getByText and queryByText when an element might not exist?

Custom Hooks;Error Boundaries

How would you test a component that fetches data when it first appears on the screen?

Intermediate
You typically mock the actual fetch function or API call so your test does not depend on a real network request, providing fake sample data instead, then use React Testing Library's asynchronous utilities, like waitFor or findBy queries, to wait for the component to finish updating after the fake data resolves.
test('shows user name after loading', async () => {
  jest.spyOn(global, 'fetch').mockResolvedValue({
    json: () => Promise.resolve({ name: 'Alice' }),
  });

  render(<UserProfile userId={1} />);
  const name = await screen.findByText('Alice');
  expect(name).toBeInTheDocument();
});
Real-world example A team writes a reliable, fast test for their user profile component by mocking the fetch call with fake sample data, avoiding the need for a real, slow, and unpredictable network request during every test run.

Common follow-ups: Why is mocking network requests generally preferred over making real API calls during tests?;What is the difference between findBy and waitFor when testing asynchronous behavior?

Data Fetching (React Query & SWR);Effects & Lifecycle

What is snapshot testing in React, and what are its benefits and drawbacks?

Intermediate
Snapshot testing saves a recorded version of a component's rendered output the first time a test runs, and future test runs compare the current output against that saved snapshot, flagging any unexpected difference. It quickly catches accidental changes, but can become noisy if snapshots are updated carelessly without actually reviewing what changed.
import renderer from 'react-test-renderer';

test('button renders correctly', () => {
  const tree = renderer.create(<Button label="Click Me" />).toJSON();
  expect(tree).toMatchSnapshot();
});
Real-world example A team catches an accidental styling change to their shared Button component through a failing snapshot test, prompting them to carefully review whether the change was intentional before approving the updated snapshot.

Common follow-ups: Why can snapshot tests sometimes give a false sense of security if updated too casually?;When is snapshot testing a genuinely good fit compared to more specific assertions?

Design Patterns in React;React DevTools & Debugging

How would you write an end to end test that checks a full user flow across multiple pages, such as logging in and viewing a dashboard?

Advanced
Tools like Cypress or Playwright run your actual app in a real browser and simulate a real user's actions across multiple pages, such as typing into a login form, clicking submit, and checking that the dashboard page eventually shows the expected content, testing the entire flow exactly as a real user would experience it.
// A simplified Cypress test
cy.visit('/login');
cy.get('input[name=email]').type('user@example.com');
cy.get('input[name=password]').type('password123');
cy.get('button[type=submit]').click();
cy.url().should('include', '/dashboard');
cy.contains('Welcome back').should('be.visible');
Real-world example A team writes an end to end test simulating a customer logging in and reaching their dashboard, catching a real bug where a recent change accidentally broke the redirect after a successful login, something a smaller unit test would not have caught.

Common follow-ups: How is an end to end test different from a unit test or a component test?;Why do end to end tests usually run slower than smaller, more focused tests?

Server Actions & Data Mutations;Routing

What is the difference between a unit test and a component test in a React app?

Beginner
A unit test checks a small, isolated piece of logic, like a single function that formats a price, completely on its own. A component test renders an actual React component and checks that it behaves correctly, often simulating user interactions like clicks and typing, giving you confidence that the component works as a whole.
// Unit test, testing a plain function
test('formats price correctly', () => {
  expect(formatPrice(9.5)).toBe('$9.50');
});

// Component test, testing a full rendered component
test('shows formatted price', () => {
  render(<PriceTag amount={9.5} />);
  expect(screen.getByText('$9.50')).toBeInTheDocument();
});
Real-world example A team writes a quick unit test for their price formatting function, and a separate component test to confirm the PriceTag component actually displays that formatted price correctly to the user on screen.

Common follow-ups: Why is it useful to have both kinds of tests instead of relying on just one type?;How much of an app's total test coverage should typically be unit tests versus component tests?

Custom Hooks;Design Patterns in React