A little helper to unit test React components in the open source Cypress.io E2E test runner v4.5.0+
- 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/cypressfor the samefindBy,queryBycommands, 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 | β | β |
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-scriptsdo:
// 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 insrcfolder 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 |
| 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 |
| portal | Component test for ReactDOM.createPortal feature |
| react-bootstrap | Confirms react-bootstrap components are working |
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 |
To find more examples, see GitHub topic cypress-react-unit-test-example
You can pass additional styles, css files and external stylesheets to load, see docs/styles.md for full list.
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 Visual Testing plugin from these component tests. This repo uses Percy.io visual diffing service as a GitHub pull request check.
The old v3 master branch is available as branch v3
- the
cy.mountis 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
