Skip to content

React Component Testing with Cypress

This lesson covers Cypress component testing specifically for React: setup, cy.mount(), passing props, and testing components that use hooks and context.

Mounting a React Component

The @cypress/react mount function (exposed as cy.mount() after setup) renders a React component into a real DOM using your project's actual React version and configuration, letting you interact with and assert on it exactly like any other Cypress test.

import Counter from './Counter';

it('increments the count when clicked', () => {
  cy.mount(<Counter initialCount={0} />);
  cy.get('[data-cy="count"]').should('have.text', '0');
  cy.get('[data-cy="increment"]').click();
  cy.get('[data-cy="count"]').should('have.text', '1');
});

This test never visits a page, Counter is mounted and tested entirely on its own.

React Component Testing Syntax

cy.mount(<MyComponent prop="value" />);
cy.mount(<Provider store={store}><MyComponent /></Provider>);
  • Pass props directly as JSX attributes, exactly like using the component normally.
  • Wrap a component in any required context providers (Redux, React Router, theme providers) as needed.
  • Component spec files typically use a .cy.jsx/.cy.tsx extension, colocated with the component.
  • cy.mount() re-renders on each call, useful for testing prop changes across multiple mounts.

React Component Testing Cheat Sheet

Common patterns for testing React components with Cypress.

Goal Approach
Test a component with props cy.mount(<Component prop={value} />)
Test a component needing context Wrap in the relevant <Provider> before mounting
Test a callback prop was called cy.stub().as('name') passed as the prop
Test a component using React Router Wrap in <MemoryRouter> for isolated routing
Test a component using hooks Mount normally; hooks run as part of the real render

Testing Components That Need Context

Components relying on React Context (theme, auth state, Redux store) need that context available during the mount, provided by wrapping the component in the relevant provider directly within the test, or via a custom mount wrapper command shared across the suite.

Cypress.Commands.add('mountWithProviders', (component) => {
  return cy.mount(
    <ThemeProvider theme={defaultTheme}>
      {component}
    </ThemeProvider>
  );
});

// usage
cy.mountWithProviders(<PriceTag amount={25} />);

Testing Components That Use React Router

A component calling useNavigate() or <Link> needs a router context to render without throwing. <MemoryRouter> provides a lightweight, isolated router suitable for component tests, without needing a full browser history or real routes.

import { MemoryRouter } from 'react-router-dom';

cy.mount(
  <MemoryRouter initialEntries={['/products/42']}>
    <ProductLink id={42} />
  </MemoryRouter>
);

Common Mistakes

  • Mounting a component that requires context/providers directly, without wrapping it, causing a render error.
  • Testing Redux/Context state management logic entirely through component tests instead of also having focused unit tests for reducers/selectors.
  • Forgetting cy.mount() re-renders fresh each call, and not accounting for that when testing prop updates across multiple mounts.
  • Using full E2E cy.visit() patterns out of habit when a direct component mount would be faster and more focused.

Key Takeaways

  • cy.mount() renders a React component directly using your project's real React setup.
  • Components needing context or routing must be wrapped in the relevant provider during the test.
  • cy.stub() works well as a callback prop for asserting on component-triggered events.
  • Component tests complement, but don't replace, focused unit tests for pure logic like reducers.

Pro Tip

Create one small mountWithProviders() custom command early in a React project using Cypress component testing, wrapping the common providers (theme, router, store) your components typically need, this removes repetitive wrapper boilerplate from every single component spec file.