Skip to main content

Setting Up Cypress for React Components

Setting up Cypress component testing for React requires just a few configuration steps: install Cypress, enable component testing, point to your webpack configuration (or let Cypress auto-detect it), and run a setup command. Modern Cypress (v10+) makes this process seamless, especially if you're using Create React App, Vite, or Next.js.

I've set up Cypress in projects ranging from small prototypes to applications with hundreds of components, and the configuration is remarkably consistent. This guide covers the standard setup for common React project types and common gotchas.

Prerequisites

You'll need:

  • A React project (created with Create React App, Vite, Next.js, or a custom webpack setup)
  • Node.js 14 or higher
  • npm or yarn

Cypress component testing works best with React 16.8+ (hooks era), though it supports earlier versions.

Installing Cypress

Start by installing Cypress as a dev dependency:

npm install --save-dev cypress

Or with yarn:

yarn add --dev cypress

This installs the Cypress binary and CLI. The first time you run Cypress, it downloads the Cypress application (~200 MB).

Initializing Component Testing

Run Cypress to trigger the initialization wizard:

npx cypress open

This opens the Cypress Launchpad (the main Cypress UI). Choose "Component Testing" when prompted. Cypress will:

  1. Create a cypress.config.js file in your project root
  2. Create a cypress folder with support and components directories
  3. Detect your bundler (webpack, Vite, etc.) and suggest configuration

If Cypress detects your bundler (e.g., you're using Create React App), it auto-configures most settings. If it doesn't, you'll see a prompt to manually specify your bundler configuration.

Example: Create React App Setup

For a Create React App project, here's a minimal cypress.config.js:

// cypress.config.js
const { defineConfig } = require('cypress')

module.exports = defineConfig({
component: {
devServer: {
framework: 'react',
bundler: 'webpack',
// CRA automatically uses the built-in webpack config
},
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
supportFile: 'cypress/support/component.js',
},
})

CRA is special because Cypress can use CRA's built-in webpack configuration, so no additional bundler setup is needed.

Example: Vite Setup

For Vite projects, the config is similarly minimal:

// cypress.config.js
const { defineConfig } = require('cypress')

module.exports = defineConfig({
component: {
devServer: {
framework: 'react',
bundler: 'vite',
},
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
supportFile: 'cypress/support/component.js',
},
})

Vite configuration is auto-detected from your vite.config.js, so Cypress reuses it.

Creating the Component Support File

Cypress creates a cypress/support/component.js file that runs before each component test. This is where you can mount global providers (Redux, Theme, etc.) that all components need:

// cypress/support/component.js
import React from 'react'
import { mount } from 'cypress/react'

// Optional: Import a theme provider or global styles
import { ThemeProvider } from 'my-theme-library'

// Custom mount command that wraps components with providers
Cypress.Commands.add('mountWithProviders', (component, options = {}) => {
const wrapped = (
<ThemeProvider theme={options.theme || 'light'}>
{component}
</ThemeProvider>
)
return mount(wrapped, options)
})

This custom command (which we'll explore more in article 8) is a convenience that avoids wrapping every test's component in the provider.

If your project uses TypeScript, create a tsconfig.json in the cypress folder to help with type hints:

{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"noImplicitAny": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"types": ["cypress", "node"]
}
}

Also, Cypress provides type definitions via /// <reference types="cypress" /> at the top of test files, or by adding cypress to the types array in your tsconfig.json.

Creating Your First Test File

Create a test file in your src folder, following the naming convention *.cy.js (or *.cy.ts for TypeScript):

// src/components/Button.cy.js
import { mount } from 'cypress/react'
import Button from './Button'

describe('Button Component', () => {
it('renders with text and handles click', () => {
const handleClick = cy.stub()
mount(<Button onClick={handleClick} label="Click me" />)

// Component should render
cy.get('button').should('exist')
cy.get('button').should('contain', 'Click me')

// Click should trigger the handler
cy.get('button').click()
cy.wrap(handleClick).should('have.been.called')
})
})

Running Component Tests

To run tests interactively (with the visual Cypress UI):

npx cypress open --component

This opens the Cypress Launchpad, lists all .cy.js files found, and lets you click on a test to run it and watch in real-time.

To run tests headless (for CI/CD):

npx cypress run --component

To run a specific test file:

npx cypress run --component --spec "src/components/Button.cy.js"

Common Configuration Options

Here are key cypress.config.js options for component testing:

module.exports = defineConfig({
component: {
devServer: {
framework: 'react',
bundler: 'webpack', // or 'vite'
},
// Files matching this pattern are treated as component tests
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
// File to load before each test
supportFile: 'cypress/support/component.js',
// Timeout for cy.mount and other commands
defaultCommandTimeout: 4000,
// Screenshot directory for failures
screenshotOnRunFailure: true,
},
})

Troubleshooting Common Setup Issues

"Module not found" errors: Ensure your bundler config (webpack, Vite) is correctly configured. Cypress mirrors your project's bundler, so if your app builds, Cypress should too.

TypeScript errors in tests: Add /// <reference types="cypress" /> at the top of test files, or add "cypress" to the types array in cypress/tsconfig.json.

Components not rendering: Verify that your component imports are correct and that dependencies are installed. Check the Cypress browser console (DevTools) for import errors.

Webpack build errors: If using a custom webpack config, ensure cypress.config.js points to it. You can pass a webpackConfig object in the devServer object.

Key Takeaways

  • Cypress component testing setup is straightforward: install Cypress, run the initialization wizard, and let Cypress auto-detect your bundler.
  • For Create React App and Vite, Cypress auto-configures most settings; for custom webpack, you may need to specify the config manually.
  • The cypress/support/component.js file is where you configure global providers and custom mount commands.
  • Test files should follow the *.cy.js naming convention and live alongside your components.
  • Use cy.open --component for interactive testing and cy.run --component for CI/CD.

Frequently Asked Questions

Do I need to eject Create React App to use Cypress component testing?

No. Cypress uses CRA's built-in webpack configuration, so no ejection is needed. The setup works out of the box.

Can I use Cypress component testing with TypeScript?

Yes, fully. TypeScript components and test files are supported. Add type hints with /// <reference types="cypress" /> or update your tsconfig.json to include "cypress" in the types array.

What if my project uses a custom webpack config?

Point Cypress to your webpack config in cypress.config.js:

webpackConfig: require('./webpack.config.js')

Cypress will merge this with its defaults.

How do I set up environment variables for tests?

Add an env object to your cypress.config.js:

module.exports = defineConfig({
env: {
apiUrl: 'http://localhost:3000',
},
// ...
})

Access them in tests with Cypress.env('apiUrl').

Can I use Cypress component testing with Next.js?

Yes. Cypress supports Next.js with built-in detection. Use bundler: 'webpack' and point to your Next.js config, or use Cypress's auto-detection.

Further Reading