A little helper to unit test React components in the open source Cypress.io E2E test runner v4.5.0+
Jump to: Comparison, Blog posts, Install, Examples: basic, advanced, full, external, Style options, Code coverage, Visual testing, Common problems
Hi there! We are trying to collect feedback from Cypress users who need component testing. Answer a few questions in this survey about component testing to help us 🙏
- What is this? This package allows you to use Cypress test runner to unit test your React components with zero effort. Here is a typical component testing, notice there is not external URL shown, since it is mounting the component directly.
- How is this different from Enzyme or RTL? It is similar in functionality BUT runs the component in the real browser with full power of Cypress E2E test runner: live GUI, full API, screen recording, CI support, cross-platform, and visual testing. Ohh, and the code coverage is built-in!
- If you like using
@testing-library/react
, you can use@testing-library/cypress
for the samefindBy
,queryBy
commands, see one of the examples in the list below - Read My Vision for Component Tests in Cypress
Feature | Jest / Enzyme / RTL | Cypress + cypress-react-unit-test |
---|---|---|
Test runs in real browser | ❌ | ✅ |
Uses full mount | ❌ | ✅ |
Test speed | 🏎 | as fast as the app works in the browser |
Test can use additional plugins | maybe | use any Cypress plugin |
Test can interact with component | synthetic limited API | use any Cypress command |
Test can be debugged | via terminal and Node debugger | use browser DevTools |
Built-in time traveling debugger | ❌ | Cypress time traveling debugger |
Re-run tests on file or test change | âś… | âś… |
Test output on CI | terminal | terminal, screenshots, videos |
Tests can be run in parallel | âś… | âś… via parallelization |
Test against interface | if using @testing-library/react |
âś… and can use @testing-library/cypress |
Spying and mocking | Jest mocks | Sinon library |
Code coverage | âś… | âś… |
- My Vision for Component Tests in Cypress
- Unit Testing React components with Cypress
- Test React Component with cypress-react-unit-test Example
- Tic-Tac-Toe Component Tests
See issues labeled v4
Requires Node version 8 or above.
npm install --save-dev cypress cypress-react-unit-test
- Include this plugin from your project's
cypress/support/index.js
require('cypress-react-unit-test/support')
- Tell Cypress how your React application is transpiled or bundled (using Webpack), so Cypress can load your components. For example, if you use
react-scripts
(even after ejecting) do:
// cypress/plugins/index.js
module.exports = (on, config) => {
require('cypress-react-unit-test/plugins/react-scripts')(on, config)
// IMPORTANT to return the config object
// with the any changed environment variables
return config
}
See Recipes for more examples.
⚠️ Turn the experimental component support on in yourcypress.json
. You can also specify where component spec files are located. For example, to have them located insrc
folder use:
{
"experimentalComponentTesting": true,
"componentFolder": "src"
}
import React from 'react'
import { mount } from 'cypress-react-unit-test'
import { HelloWorld } from './hello-world.jsx'
describe('HelloWorld component', () => {
it('works', () => {
mount(<HelloWorld />)
// now use standard Cypress commands
cy.contains('Hello World!').should('be.visible')
})
})
Look at the examples in cypress/component folder. Here is the list in progress
Spec | Description |
---|---|
alert-spec.js | Component tries to use window.alert |
counter-set-state | Counter component that uses this.state |
counter-use-hooks | Counter component that uses useState hook |
emotion-spec.js | Confirms the component is using @emotion/core and styles are set |
error-boundary-spec.js | Checks if an error boundary component works |
pure-component-spec.js | Tests stateless component |
stateless-spec.js | Passes Cypress stub to the component, confirms the component calls it on click |
window-spec.js | In the component test, the spec window and the application's window where the component is running should be the same object |
css | Shows that component with import './Button.css' works |
network | Confirms we can use cy.route to stub / spy on component's network calls |
react-book-by-chris-noring | Copied test examples from React Book and adapted for Cypress component tests |
react-tutorial | Tests from official ReactJS tutorial copied and adapted for Cypress component tests |
stub-example | Uses cy.stub as component props |
styles | Add extra styles to the component during testing using style , cssFile or stylesheets mount options |
toggle-example | Testing a toggle component using Cypress DOM commands |
typescript | A spec written in TypeScript |
unmount | Verifies the component's behavior when it is unmounted from the DOM |
use-lodash-fp | Imports and tests methods from lodash/fp dependency |
document-spec | Checks document dimensions from the component |
styled-components | Test components that use styled-components |
plus a few smaller sanity specs in cypress/component/basic folder.
Spec | Description |
---|---|
app-action-example | App actions against components |
context | Confirms components that use React context feature work |
custom-command | Wraps mount in a custom command for convenience |
forward-ref | Tests a component that uses a forward ref feature |
hooks | Tests several components that use React Hooks like useState , useCallback |
lazy-loaded | Confirms components that use React.lazy and dynamic imports work |
material-ui-example | Large components demos from Material UI |
mock-fetch | Test stubs window.fetch used by component in useEffect hook |
mocking-component | Replaced a child component with dummy component during test |
mocking-imports | Stub a named ES6 import using plugin-transform-modules-commonjs with loose: true when transpiled |
react-router-v6 | Example testing a React Router v6 |
renderless | Testing a component that does not need to render itself into the DOM |
set-timeout-example | Control the clock with cy.tick and test loading components that use setTimeout |
testing-lib-example | A spec adopted from @testing-library/react that uses @testing-library/cypress |
timers | Testing components that set timers, adopted from ReactJS Testing recipes |
tutorial | A few tests adopted from ReactJS Tutorial, including Tic-Tac-Toe game |
portal | Component test for ReactDOM.createPortal feature |
react-bootstrap | Confirms react-bootstrap components are working |
select React component | Uses cypress-react-selector to find DOM elements using React component name and state values |
We have several subfolders in examples folder that have complete projects with just their dependencies installed in the root folder.
Folder Name | Description |
---|---|
a11y | Testing components' accessibility using cypress-axe |
react-scripts | A project using react-scripts with component tests in src folder |
react-scripts-folder | A project using react-scripts with component tests in cypress/component |
tailwind | Testing styles built using Tailwind CSS |
sass-and-ts | Example with Webpack, Sass and TypeScript |
snapshots | Component HTML and JSON snapshots using cypress-plugin-snapshots |
visual-sudoku | Visual testing for components using open source plugin cypress-image-snapshot. For larger example with an hour long list of explanation videos, see bahmutov/sudoku. |
visual-testing-with-percy | Visual testing for components using 3rd party service Percy.io |
visual-testing-with-happo | Visual testing for components using 3rd party service Happo |
visual-testing-with-applitools | Visual testing for components using 3rd party service Applitools.com |
using-babel | Bundling specs and loaded source files using project's existing .babelrc file |
webpack-file | Load existing webpack.config.js file |
webpack-options | Using the default Webpack options from @cypress/webpack-preprocessor to transpile JSX specs |
This way of component testing has been verified in a number of forked 3rd party projects.
Repo | Description |
---|---|
try-cra-with-unit-test | Hello world initialized with CRAv3 |
try-cra-app-typescript | Hello world initialized with CRAv3 --typescript |
react-todo-with-hooks | Modern web application using hooks |
test-redux-examples | Example apps copies from official Redux repo and tested as components |
test-react-hooks-animations | Testing React springs fun blob animation |
test-mdx-example | Example testing MDX components using Cypress |
test-apollo | Component testing an application that uses Apollo GraphQL library |
test-xstate-react | XState component testing using Cypress |
test-react-router-v5 | A few tests of React Router v5 |
test-material-ui | Testing Material UI components: date pickers, lists, autocomplete |
test-d3-react-gauge | Testing React D3 gauges |
storybook-code-coverage | Example app where we get 100% code coverage easily with a single integration spec and a few component specs, replacing several tools |
react-loading-skeleton | One to one Storybook tests for React skeleton components. Uses local .babelrc settings without Webpack config |
test-swr | Component test for Zeit SWR hooks for remote data fetching |
emoji-search | Quick component test for a fork of emoji-search |
test-custom-error-boundary | Play with a component that implements error boundary |
Jscrambler-Webpack-React | Example project with its own Webpack config file |
bahmutov/integration-tests | Example based on blog post React Integration Testing: Greater Coverage, Fewer Tests |
mobx-react-typescript-boilerplate | Fork of the official Mobx example, shows clock control |
bahmutov/test-react-hook-form | Testing forms created using react-hook-form |
bahmutov/react-with-rollup | Testing a React application bundled with Rollup by using @bahmutov/cy-rollup preprocessor |
bahmutov/testing-react-example | Described in blog post Test React Component with cypress-react-unit-test Example |
ejected-react-scripts-example | Using component testing after ejecting react-scripts |
tic-tac-toe | Component and unit tests for Tic-Tac-Toe, read Tic-Tac-Toe Component Tests |
To find more examples, see GitHub topic cypress-react-unit-test-example
In most cases, the component already imports its own styles, thus it looks "right" during the test. If you need another CSS, the simplest way is to import it from the spec file:
// src/Footer.spec.js
import './styles/main.css'
import Footer from './Footer'
it('looks right', () => {
// styles are applied
mount(<Footer />)
})
You can pass additional styles, css files and external stylesheets to load, see docs/styles.md for the full list of options.
const todo = {
id: '123',
title: 'Write more tests',
}
mount(<Todo todo={todo} />, {
stylesheets: [
'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css',
],
})
Additional configuration
If your React and React DOM libraries are installed in non-standard paths (think monorepo scenario), you can tell this plugin where to find them. In `cypress.json` specify paths like this:{
"env": {
"cypress-react-unit-test": {
"react": "node_modules/react/umd/react.development.js",
"react-dom": "node_modules/react-dom/umd/react-dom.development.js"
}
}
}
If you are using plugins/cra-v3 it instruments the code on the fly using babel-plugin-istanbul
and generates report using dependency cypress-io/code-coverage (included). If you want to disable code coverage instrumentation and reporting, use --env coverage=false
or CYPRESS_coverage=false
or set in your cypress.json
file
{
"env": {
"coverage": false
}
}
You can use any Cypress Visual Testing plugin to perform visual testing from the component tests. This repo has several example projects, see visual-sudoku, visual-testing-with-percy, visual-testing-with-happo, and visual-testing-with-applitools.
For a larger Do-It-Yourself example with an hour long list of explanation videos, see bahmutov/sudoku repository. There you can also find an example of testing responsive design, as shown in this video.
Node Sass
When using Node Sass styles, tell Cypress to use the system NodeJS rather than its bundled version. In cypress.json
set option:
{
"nodeVersion": "system"
}
Find full example in sass-and-ts folder.
Slow bundling
When you bundle spec file, you are now bundling React, Read DOM and other libraries, which is might be slow. For now, you can disable inline source maps by adding to your Webpack config settings (if available) the following:
const webpackOptions = {
devtool: false,
}
Keep your eye on issue #156 for more information.
If you are using your custom Webpack, this plugin might be missing code coverage information because the code was not instrumented. We try to insert the babel-plugin-istanbul
plugin automatically, but your bundling might not use Babel, or configure it differently, preventing plugin insertion. Please let us know by opening an issue with full reproducible details.
See related issue #141. You can also debug the plugin's behavior by running it with DEBUG
environment variable, see #debugging section.
You can see verbose logs from this plugin by running with environment variable
DEBUG=cypress-react-unit-test
Because finding and modifying Webpack settings while running this plugin is done by find-webpack module, you might want to enable its debug messages too.
DEBUG=cypress-react-unit-test,find-webpack
The old v3 master
branch is available as branch v3
- the
cy.mount
is now simplyimport { mount } from 'cypress-react-unit-test'
- the support file is simply
require('cypress-react-unit-test/support')
Same feature for unit testing components from other frameworks using Cypress