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:
- Create a
cypress.config.jsfile in your project root - Create a
cypressfolder withsupportandcomponentsdirectories - 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.
Configuring TypeScript (Optional but Recommended)
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.jsfile is where you configure global providers and custom mount commands. - Test files should follow the
*.cy.jsnaming convention and live alongside your components. - Use
cy.open --componentfor interactive testing andcy.run --componentfor 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.