{
  "doc": {
    "id": "app/write-tests/component-testing/react/examples",
    "title": "React examples",
    "description": "Learn how to mount a React component, pass data to a React component, test event handlers, and customize cy.mount() for React Router and Redux.",
    "section": "app",
    "source_path": "/llm/markdown/app/write-tests/component-testing/react/examples.md",
    "version": "066c46e056f0f322a0670d2d3aa4e6adaebfe717",
    "updated_at": "2026-09-10T13:30:12.426Z",
    "headings": [
      {
        "id": "app/write-tests/component-testing/react/examples#react-examples",
        "text": "React Examples",
        "level": 1
      },
      {
        "id": "app/write-tests/component-testing/react/examples#passing-data-to-a-component",
        "text": "Passing Data to a Component",
        "level": 2
      },
      {
        "id": "app/write-tests/component-testing/react/examples#testing-event-handlers",
        "text": "Testing Event Handlers",
        "level": 2
      },
      {
        "id": "app/write-tests/component-testing/react/examples#testing-error-states",
        "text": "Testing Error States",
        "level": 2
      },
      {
        "id": "app/write-tests/component-testing/react/examples#testing-error-boundaries",
        "text": "Testing Error Boundaries",
        "level": 3
      },
      {
        "id": "app/write-tests/component-testing/react/examples#custom-mount-commands",
        "text": "Custom Mount Commands",
        "level": 2
      },
      {
        "id": "app/write-tests/component-testing/react/examples#customizing-cy-mount",
        "text": "Customizing cy.mount()",
        "level": 3
      },
      {
        "id": "app/write-tests/component-testing/react/examples#react-router",
        "text": "React Router",
        "level": 3
      },
      {
        "id": "app/write-tests/component-testing/react/examples#redux",
        "text": "Redux",
        "level": 3
      }
    ]
  },
  "chunks": [
    {
      "id": "app/write-tests/component-testing/react/examples#passing-data-to-a-component",
      "doc_id": "app/write-tests/component-testing/react/examples",
      "heading": "Passing Data to a Component",
      "heading_level": 2,
      "content_markdown": "## Passing Data to a Component\n\nYou can pass props to a component by setting them on the JSX passed into `cy.mount()`:\n\n```\nit('mounts', () => {\n  cy.mount(<Stepper initial={100} />)\n  //Stepper should have initial count of 100\n  cy.get('[data-cy=counter]').should('have.text', '100')\n})\n```\n",
      "section": "app",
      "anchors": [
        "passing-data-to-a-component"
      ],
      "path": "/llm/json/chunked/app/write-tests/component-testing/react/examples.json",
      "token_estimate": 55
    },
    {
      "id": "app/write-tests/component-testing/react/examples#testing-event-handlers",
      "doc_id": "app/write-tests/component-testing/react/examples",
      "heading": "Testing Event Handlers",
      "heading_level": 2,
      "content_markdown": "## Testing Event Handlers\n\nPass a Cypress [spy](/llm/markdown/app/guides/stubs-spies-and-clocks.md#Spies) to an event prop and validate it was called:\n\n```\nit('clicking + fires a change event with the incremented value', () => {\n  const onChangeSpy = cy.spy().as('onChangeSpy')\n  cy.mount(<Stepper onChange={onChangeSpy} />)\n  cy.get('[data-cy=increment]').click()\n  cy.get('@onChangeSpy').should('have.been.calledWith', 1)\n})\n```\n",
      "section": "app",
      "anchors": [
        "testing-event-handlers"
      ],
      "path": "/llm/json/chunked/app/write-tests/component-testing/react/examples.json",
      "token_estimate": 57
    },
    {
      "id": "app/write-tests/component-testing/react/examples#testing-error-states",
      "doc_id": "app/write-tests/component-testing/react/examples",
      "heading": "Testing Error States",
      "heading_level": 2,
      "content_markdown": "## Testing Error States\n\n`cy.mount()` is an asynchronous Cypress command: it _enqueues_ the mount and returns immediately, before the component ever renders. When a component throws during render, the error surfaces as an uncaught exception rather than as a synchronous throw.\n\nBy default Cypress fails the test on any uncaught exception, so to assert on a render error you listen for it with [`cy.on('uncaught:exception')`](/llm/markdown/api/cypress-api/catalog-of-events.md#Uncaught-Exceptions) and return `false` to prevent Cypress from failing the test:\n\n```\nimport { UserProfile } from './UserProfile'\n\nit('surfaces a render error', () => {\n  cy.on('uncaught:exception', (err) => {\n    // Assert on the error thrown during render...\n    expect(err.message).to.include('user is required')\n\n    // ...and return false so Cypress does not fail the test.\n    return false\n  })\n\n  cy.mount(<UserProfile />)\n})\n```\n\n### Testing Error Boundaries\n\nThe recommended way to handle render errors in React is an [Error Boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary), which renders fallback UI via `getDerivedStateFromError()`. You can mount a component wrapped in your Error Boundary and assert that the fallback UI is displayed:\n\n```\n// ErrorBoundary.cy.jsx\nimport { ErrorBoundary } from './ErrorBoundary'\n\nconst errorMessage = 'I crashed!'\nconst ChildWithError = () => {\n  throw new Error(errorMessage)\n}\n\nit('displays the fallback UI on error', () => {\n  // An Error Boundary renders fallback UI, but it does NOT stop the error\n  // from propagating to Cypress as an uncaught exception. Cypress fails on\n  // uncaught exceptions by default, so we must still suppress that behavior.\n  cy.on('uncaught:exception', (err) => {\n    // Only suppress the specific error we expect.\n    expect(err.message).to.include(errorMessage)\n\n    return false\n  })\n\n  cy.mount(\n    <ErrorBoundary name=\"ChildWithError\">\n      <ChildWithError />\n    </ErrorBoundary>\n  )\n\n  cy.get('header h1').should('contain', 'Something went wrong.')\n})\n```\n\nWhere `ErrorBoundary` renders fallback UI from `getDerivedStateFromError()`:\n\n```\n// ErrorBoundary.jsx\nimport React from 'react'\n\nexport class ErrorBoundary extends React.Component {\n  constructor(props) {\n    super(props)\n    this.state = { error: null }\n  }\n\n  static getDerivedStateFromError(error) {\n    return { error }\n  }\n\n  render() {\n    const { name } = this.props\n    const { error } = this.state\n\n    if (error) {\n      return (\n        <header>\n          <h1>Something went wrong.</h1>\n          <h2>{`${name} failed to load`}</h2>\n        </header>\n      )\n    }\n\n    return this.props.children\n  }\n}\n```\n",
      "section": "app",
      "anchors": [
        "testing-error-states"
      ],
      "path": "/llm/json/chunked/app/write-tests/component-testing/react/examples.json",
      "token_estimate": 448
    },
    {
      "id": "app/write-tests/component-testing/react/examples#testing-error-boundaries",
      "doc_id": "app/write-tests/component-testing/react/examples",
      "heading": "Testing Error Boundaries",
      "heading_level": 3,
      "content_markdown": "### Testing Error Boundaries\n\nThe recommended way to handle render errors in React is an [Error Boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary), which renders fallback UI via `getDerivedStateFromError()`. You can mount a component wrapped in your Error Boundary and assert that the fallback UI is displayed:\n\n```\n// ErrorBoundary.cy.jsx\nimport { ErrorBoundary } from './ErrorBoundary'\n\nconst errorMessage = 'I crashed!'\nconst ChildWithError = () => {\n  throw new Error(errorMessage)\n}\n\nit('displays the fallback UI on error', () => {\n  // An Error Boundary renders fallback UI, but it does NOT stop the error\n  // from propagating to Cypress as an uncaught exception. Cypress fails on\n  // uncaught exceptions by default, so we must still suppress that behavior.\n  cy.on('uncaught:exception', (err) => {\n    // Only suppress the specific error we expect.\n    expect(err.message).to.include(errorMessage)\n\n    return false\n  })\n\n  cy.mount(\n    <ErrorBoundary name=\"ChildWithError\">\n      <ChildWithError />\n    </ErrorBoundary>\n  )\n\n  cy.get('header h1').should('contain', 'Something went wrong.')\n})\n```\n\nWhere `ErrorBoundary` renders fallback UI from `getDerivedStateFromError()`:\n\n```\n// ErrorBoundary.jsx\nimport React from 'react'\n\nexport class ErrorBoundary extends React.Component {\n  constructor(props) {\n    super(props)\n    this.state = { error: null }\n  }\n\n  static getDerivedStateFromError(error) {\n    return { error }\n  }\n\n  render() {\n    const { name } = this.props\n    const { error } = this.state\n\n    if (error) {\n      return (\n        <header>\n          <h1>Something went wrong.</h1>\n          <h2>{`${name} failed to load`}</h2>\n        </header>\n      )\n    }\n\n    return this.props.children\n  }\n}\n```\n",
      "section": "app",
      "anchors": [
        "testing-error-boundaries"
      ],
      "path": "/llm/json/chunked/app/write-tests/component-testing/react/examples.json",
      "token_estimate": 287
    },
    {
      "id": "app/write-tests/component-testing/react/examples#custom-mount-commands",
      "doc_id": "app/write-tests/component-testing/react/examples",
      "heading": "Custom Mount Commands",
      "heading_level": 2,
      "content_markdown": "## Custom Mount Commands\n\n### Customizing `cy.mount()`\n\nBy default, `cy.mount()` is a simple passthrough to `mount()`, however, you can customize `cy.mount()` to fit your needs. For instance, if you are using providers or other global app-level setups in your React app, you can configure them here.\n\nBelow are a few examples that demonstrate using a custom mount command. These examples can be adjusted for most other providers that you will need to support.\n\n### React Router\n\nIf you have a component that consumes a hook or component from [React Router](https://reactrouter.com/), make sure the component has access to a React Router provider. Below is a sample mount command that uses `MemoryRouter` to wrap the component.\n\n*   cypress/support/component.jsx\n*   cypress/support/component.tsx\n\n```\nimport { mount } from 'cypress/react'\nimport { MemoryRouter } from 'react-router-dom'\n\nCypress.Commands.add('mount', (component, options = {}) => {\n  const { routerProps = { initialEntries: ['/'] }, ...mountOptions } = options\n\n  const wrapped = <MemoryRouter {...routerProps}>{component}</MemoryRouter>\n\n  return mount(wrapped, mountOptions)\n})\n```\n\n```\nimport { mount, MountOptions, MountReturn } from 'cypress/react'\nimport { MemoryRouter, MemoryRouterProps } from 'react-router-dom'\n\ndeclare global {\n  namespace Cypress {\n    interface Chainable {\n      /**\n       * Mounts a React node\n       * @param component React Node to mount\n       * @param options Additional options to pass into mount\n       */\n      mount(\n        component: React.ReactNode,\n        options?: MountOptions & { routerProps?: MemoryRouterProps }\n      ): Cypress.Chainable<MountReturn>\n    }\n  }\n}\n\nCypress.Commands.add('mount', (component, options = {}) => {\n  const { routerProps = { initialEntries: ['/'] }, ...mountOptions } = options\n\n  const wrapped = <MemoryRouter {...routerProps}>{component}</MemoryRouter>\n\n  return mount(wrapped, mountOptions)\n})\n```\n\nTo set up certain scenarios, pass in props that will get passed to `MemoryRouter` in the options. Below is an example test that ensures an active link has the correct class applied to it by initializing the router with `initialEntries` pointed to a particular route:\n\n```\nimport { Navigation } from './Navigation'\n\nit('home link should be active when url is \"/\"', () => {\n  // No need to pass in custom initialEntries as default url is '/'\n  cy.mount(<Navigation />)\n\n  cy.get('a').contains('Home').should('have.class', 'active')\n})\n\nit('login link should be active when url is \"/login\"', () => {\n  cy.mount(<Navigation />, {\n    routerProps: {\n      initialEntries: ['/login'],\n    },\n  })\n\n  cy.get('a').contains('Login').should('have.class', 'active')\n})\n```\n\n### Redux\n\nTo use a component that consumes state or actions from a [Redux](https://react-redux.js.org/) store, create a `mount` command that will wrap your component in a Redux Provider:\n\n*   cypress/support/component.jsx\n*   cypress/support/component.tsx\n\n```\nimport { mount } from 'cypress/react'\nimport { Provider } from 'react-redux'\nimport { getStore } from '../../src/store'\n\nCypress.Commands.add('mount', (component, options = {}) => {\n  // Use the default store if one is not provided\n  const { reduxStore = getStore(), ...mountOptions } = options\n\n  const wrapped = <Provider store={reduxStore}>{component}</Provider>\n\n  return mount(wrapped, mountOptions)\n})\n```\n\n```\nimport { mount, MountOptions, MountReturn } from 'cypress/react'\nimport { Provider } from 'react-redux'\nimport { EnhancedStore } from '@reduxjs/toolkit'\nimport { getStore } from '../../src/store'\nimport { RootState } from './src/StoreState'\n\ndeclare global {\n  namespace Cypress {\n    interface Chainable {\n      /**\n       * Mounts a React node\n       * @param component React Node to mount\n       * @param options Additional options to pass into mount\n       */\n      mount(\n        component: React.ReactNode,\n        options?: MountOptions & { reduxStore?: EnhancedStore<RootState> }\n      ): Cypress.Chainable<MountReturn>\n    }\n  }\n}\n\nCypress.Commands.add('mount', (component, options = {}) => {\n  const { reduxStore = getStore(), ...mountOptions } = options\n\n  const wrapped = <Provider store={reduxStore}>{component}</Provider>\n\n  return mount(wrapped, mountOptions)\n})\n```\n\nThe options param can have a store that is already initialized with data:\n\n```\nimport { getStore } from '../redux/store'\nimport { setUser } from '../redux/userSlice'\nimport { UserProfile } from './UserProfile'\n\nit('User profile should display user name', () => {\n  const user = { name: 'test person' }\n\n  // getStore is a factory method that creates a new store\n  const store = getStore()\n\n  // setUser is an action exported from the user slice\n  store.dispatch(setUser(user))\n\n  cy.mount(<UserProfile />, { reduxStore: store })\n\n  cy.get('div.name').should('have.text', user.name)\n})\n```\n\nThe `getStore` method is a factory method that initializes a new Redux store. It is important that the store be initialized with each new test to ensure changes to the store don't affect other tests.\n",
      "section": "app",
      "anchors": [
        "custom-mount-commands"
      ],
      "path": "/llm/json/chunked/app/write-tests/component-testing/react/examples.json",
      "token_estimate": 896
    },
    {
      "id": "app/write-tests/component-testing/react/examples#customizing-cy-mount",
      "doc_id": "app/write-tests/component-testing/react/examples",
      "heading": "Customizing cy.mount()",
      "heading_level": 3,
      "content_markdown": "### Customizing `cy.mount()`\n\nBy default, `cy.mount()` is a simple passthrough to `mount()`, however, you can customize `cy.mount()` to fit your needs. For instance, if you are using providers or other global app-level setups in your React app, you can configure them here.\n\nBelow are a few examples that demonstrate using a custom mount command. These examples can be adjusted for most other providers that you will need to support.\n",
      "section": "app",
      "anchors": [
        "customizing-cy-mount"
      ],
      "path": "/llm/json/chunked/app/write-tests/component-testing/react/examples.json",
      "token_estimate": 92
    },
    {
      "id": "app/write-tests/component-testing/react/examples#react-router",
      "doc_id": "app/write-tests/component-testing/react/examples",
      "heading": "React Router",
      "heading_level": 3,
      "content_markdown": "### React Router\n\nIf you have a component that consumes a hook or component from [React Router](https://reactrouter.com/), make sure the component has access to a React Router provider. Below is a sample mount command that uses `MemoryRouter` to wrap the component.\n\n*   cypress/support/component.jsx\n*   cypress/support/component.tsx\n\n```\nimport { mount } from 'cypress/react'\nimport { MemoryRouter } from 'react-router-dom'\n\nCypress.Commands.add('mount', (component, options = {}) => {\n  const { routerProps = { initialEntries: ['/'] }, ...mountOptions } = options\n\n  const wrapped = <MemoryRouter {...routerProps}>{component}</MemoryRouter>\n\n  return mount(wrapped, mountOptions)\n})\n```\n\n```\nimport { mount, MountOptions, MountReturn } from 'cypress/react'\nimport { MemoryRouter, MemoryRouterProps } from 'react-router-dom'\n\ndeclare global {\n  namespace Cypress {\n    interface Chainable {\n      /**\n       * Mounts a React node\n       * @param component React Node to mount\n       * @param options Additional options to pass into mount\n       */\n      mount(\n        component: React.ReactNode,\n        options?: MountOptions & { routerProps?: MemoryRouterProps }\n      ): Cypress.Chainable<MountReturn>\n    }\n  }\n}\n\nCypress.Commands.add('mount', (component, options = {}) => {\n  const { routerProps = { initialEntries: ['/'] }, ...mountOptions } = options\n\n  const wrapped = <MemoryRouter {...routerProps}>{component}</MemoryRouter>\n\n  return mount(wrapped, mountOptions)\n})\n```\n\nTo set up certain scenarios, pass in props that will get passed to `MemoryRouter` in the options. Below is an example test that ensures an active link has the correct class applied to it by initializing the router with `initialEntries` pointed to a particular route:\n\n```\nimport { Navigation } from './Navigation'\n\nit('home link should be active when url is \"/\"', () => {\n  // No need to pass in custom initialEntries as default url is '/'\n  cy.mount(<Navigation />)\n\n  cy.get('a').contains('Home').should('have.class', 'active')\n})\n\nit('login link should be active when url is \"/login\"', () => {\n  cy.mount(<Navigation />, {\n    routerProps: {\n      initialEntries: ['/login'],\n    },\n  })\n\n  cy.get('a').contains('Login').should('have.class', 'active')\n})\n```\n",
      "section": "app",
      "anchors": [
        "react-router"
      ],
      "path": "/llm/json/chunked/app/write-tests/component-testing/react/examples.json",
      "token_estimate": 381
    },
    {
      "id": "app/write-tests/component-testing/react/examples#redux",
      "doc_id": "app/write-tests/component-testing/react/examples",
      "heading": "Redux",
      "heading_level": 3,
      "content_markdown": "### Redux\n\nTo use a component that consumes state or actions from a [Redux](https://react-redux.js.org/) store, create a `mount` command that will wrap your component in a Redux Provider:\n\n*   cypress/support/component.jsx\n*   cypress/support/component.tsx\n\n```\nimport { mount } from 'cypress/react'\nimport { Provider } from 'react-redux'\nimport { getStore } from '../../src/store'\n\nCypress.Commands.add('mount', (component, options = {}) => {\n  // Use the default store if one is not provided\n  const { reduxStore = getStore(), ...mountOptions } = options\n\n  const wrapped = <Provider store={reduxStore}>{component}</Provider>\n\n  return mount(wrapped, mountOptions)\n})\n```\n\n```\nimport { mount, MountOptions, MountReturn } from 'cypress/react'\nimport { Provider } from 'react-redux'\nimport { EnhancedStore } from '@reduxjs/toolkit'\nimport { getStore } from '../../src/store'\nimport { RootState } from './src/StoreState'\n\ndeclare global {\n  namespace Cypress {\n    interface Chainable {\n      /**\n       * Mounts a React node\n       * @param component React Node to mount\n       * @param options Additional options to pass into mount\n       */\n      mount(\n        component: React.ReactNode,\n        options?: MountOptions & { reduxStore?: EnhancedStore<RootState> }\n      ): Cypress.Chainable<MountReturn>\n    }\n  }\n}\n\nCypress.Commands.add('mount', (component, options = {}) => {\n  const { reduxStore = getStore(), ...mountOptions } = options\n\n  const wrapped = <Provider store={reduxStore}>{component}</Provider>\n\n  return mount(wrapped, mountOptions)\n})\n```\n\nThe options param can have a store that is already initialized with data:\n\n```\nimport { getStore } from '../redux/store'\nimport { setUser } from '../redux/userSlice'\nimport { UserProfile } from './UserProfile'\n\nit('User profile should display user name', () => {\n  const user = { name: 'test person' }\n\n  // getStore is a factory method that creates a new store\n  const store = getStore()\n\n  // setUser is an action exported from the user slice\n  store.dispatch(setUser(user))\n\n  cy.mount(<UserProfile />, { reduxStore: store })\n\n  cy.get('div.name').should('have.text', user.name)\n})\n```\n\nThe `getStore` method is a factory method that initializes a new Redux store. It is important that the store be initialized with each new test to ensure changes to the store don't affect other tests.\n",
      "section": "app",
      "anchors": [
        "redux"
      ],
      "path": "/llm/json/chunked/app/write-tests/component-testing/react/examples.json",
      "token_estimate": 417
    }
  ]
}