A little helper to unit test React components in the open source Cypress.io E2E test runner ALPHA
-
What is this? This package allows you to use Cypress test runner to unit test your React components with zero effort.
-
How is this different from Enzyme? 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.
- some DOM events are not working when running all tests at once #4
- cannot mock server XHR for injected components #5
- cannot spy on
window.alert
#6
Requires Node version 8 or above.
npm install --save-dev cypress cypress-react-unit-test
If you need help configuring bundler, see preprocessors info
Include this plugin from cypress/support/index.js
import 'cypress-react-unit-test'
This adds a new command cy.mount
that can mount a React component. It also overloads cy.get
to accept in addition to selectors React component, returning it. See examples below.
// load Cypress TypeScript definitions for IntelliSense
/// <reference types="cypress" />
// import the component you want to test
import { HelloState } from '../../src/hello-x.jsx'
import React from 'react'
describe('HelloState component', () => {
it('works', () => {
// mount the component under test
cy.mount(<HelloState />)
// start testing!
cy.contains('Hello Spider-man!')
// mounted component can be selected via its name, function, or JSX
// e.g. '@HelloState', HelloState, or <HelloState />
cy.get(HelloState).invoke('setState', { name: 'React' })
cy.get(HelloState)
.its('state')
.should('deep.equal', { name: 'React' })
// check if GUI has rerendered
cy.contains('Hello React!')
})
})
You can add individual style to the mounted component by passing its text as an option
it('can be passed as an option', () => {
const style = `
.component-button {
display: inline-flex;
width: 25%;
flex: 1 0 auto;
}
.component-button.orange button {
background-color: #F5923E;
color: white;
}
`
cy.mount(<Button name="Orange" orange />, { style })
cy.get('.orange button').should(
'have.css',
'background-color',
'rgb(245, 146, 62)',
)
})
Often your component rely on global CSS style imported from the root index.js
or app.js
file
// index.js
import './styles.css'
// bootstrap application
You can read the CSS file and pass it as style
option yourself
cy.readFile('cypress/integration/Button.css').then(style => {
cy.mount(<Button name="Orange" orange />, { style })
})
You can even let Cypress read the file and inject the style
const cssFile = 'cypress/integration/Button.css'
cy.mount(<Button name="Orange" orange />, { cssFile })
See cypress/integration/inject-style-spec.js for more examples.
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"
}
}
}
How can we use features that require transpilation? By using @cypress/webpack-preprocessor - see the plugin configuration in cypress/plugins/index.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
}
}
If you are using Create-React-App v3 or react-scripts
, and want to reuse the built in webpack before ejecting, this module ships with Cypress preprocessor in plugins folder. From the cypress.json
point at the shipped plugin in the node_modules
.
{
"pluginsFile": "node_modules/cypress-react-unit-test/plugins/cra-v3",
"supportFile": "node_modules/cypress-react-unit-test/support"
}
See example repo bahmutov/try-cra-with-unit-test, typical full config with specs and source files in src
folder (before ejecting the app):
{
"fixturesFolder": false,
"pluginsFile": "node_modules/cypress-react-unit-test/plugins/cra-v3",
"supportFile": "node_modules/cypress-react-unit-test/support",
"testFiles": "**/*.spec.js",
"experimentalComponentTesting": true,
"componentFolder": "src"
}
If you already have a plugins file, you can use a file preprocessor that points at CRA's webpack
// your project's Cypress plugin file
const craFilePreprocessor = require('cypress-react-unit-test/plugins/cra-v3/file-preprocessor')
module.exports = on => {
on('file:preprocessor', craFilePreprocessor())
}
Bonus: re-using the config means if you create your application using create-react-app --typescript
, then TypeScript transpile just works out of the box. See bahmutov/try-cra-app-typescript.
If you have your own webpack config, you can use included plugins file to load it. Here is the configuration using the included plugins file and passing the name of the config file via env
variable in the cypress.json
file
{
"pluginsFile": "node_modules/cypress-react-unit-test/plugins/load-webpack",
"env": {
"webpackFilename": "demo/config/webpack.dev.js"
}
}
All components are in src folder. All tests are in cypress/integration folder.
- hello-world-spec.js - testing the simplest React component from hello-world.jsx
- hello-x-spec.js - testing React component with props and state hello-x.jsx
- counter-spec.js clicks on the component and confirms the result
- stateless-spec.js shows testing a stateless component from stateless.jsx
- transpiled-spec.js shows testing a component with class properties syntax from transpiled.jsx
- error-boundary-spec.js shows testing a component acting as an error boundary from error-boundary.jsx
- users-spec.js shows how to observe XHR requests, mock server responses for component users.jsx
- alert-spec.js shows how to spy on
window.alert
calls from your component stateless-alert.jsx
- bahmutov/calculator tests multiple components: calculator App, Button, Display.
- bahmutov/react-todo-with-hooks branch
added-tests
- bahmutov/test-redux-examples branch
mount2
- bahmutov/test-react-hooks-animations react hooks with spring animations test
To find more examples, see GitHub topic cypress-react-unit-test-example
To get started with this repo, compile the plugin's code and the examples code
npm run transpile
npm run build
npm run cy:open
- run TypeScript compiler in watch mode with
npx tsc -w
- run Cypress with
npx cypress open
and select the spec you want to work with - edit
lib/index.ts
where all the magic happens
Uses Percy.io visual diffing service as a GitHub pull request check.
Same feature for unit testing components from other frameworks using Cypress