Socket
Socket
Sign inDemoInstall

cypress-react-unit-test

Package Overview
Dependencies
876
Maintainers
1
Versions
109
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

cypress-react-unit-test

Unit test React components using Cypress


Version published
Maintainers
1
Weekly downloads
3,339
decreased by-12.55%

Weekly downloads

Readme

Source

cypress-react-unit-test CircleCI Cypress.io tests renovate-app badge

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, Presentations, Install, Examples: basic, advanced, full, external, Mocking, Style options, Code coverage, Visual testing, Common problems, Chat

Survey

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 🙏

TLDR

  • 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.

Example component test

  • 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 same findBy, queryBy commands, see one of the examples in the list below
  • Read My Vision for Component Tests in Cypress

Comparison

FeatureJest / Enzyme / RTLCypress + cypress-react-unit-test
Test runs in real browser
Supports shallow mount
Supports full mount
Test speed🏎as fast as the app works in the browser
Test can use additional pluginsmaybeuse any Cypress plugin
Test can interact with componentsynthetic limited APIuse any Cypress command
Test can be debuggedvia terminal and Node debuggeruse browser DevTools
Built-in time traveling debuggerCypress time traveling debugger
Re-run tests on file or test change
Test output on CIterminalterminal, screenshots, videos
Tests can be run in parallel✅ via parallelization
Test against interfaceif using @testing-library/react✅ and can use @testing-library/cypress
Spying and stubbing methodsJest mocksSinon library
Stubbing imports
Stubbing clock
Code coverage

If you are coming from Jest + RTL world, read Test The Interface Not The Implementation.

If you are coming from Enzyme world, check out the enzyme example.

Blog posts

Curious how we keep this library well-tested and all its examples up-to-date? Read the Testing Pyramids blog post.

Presentations

It is better to see something once than to hear about a thousand times. Watch one of the talks below to see this library in action.

  • Webinar "Component Testing with Cypress and Applitools" video, slides
  • Conference talk "Я вижу что происходит: визуальное тестирование компонентов; I see what is going on" video with Russian narration, slides in English
  • Conference talk "I See What is Going On" from JSNation video, slides
  • Conference talk "Fast and Effective ... End-to-end Tests?" from JSVidCon video, slides

Known problems

See issues labeled v4

Install

Requires Node version 8 or above.

npm install --save-dev cypress cypress-react-unit-test

Init

You can use our command line wizard to give you instructions on configuring this plugin. It will try to determine which framework or bundling tool you are using and give you instructions on right configuration.

cypress-react-unit-test init

Or continue with manual installation:

  1. Include this plugin from your project's cypress/support/index.js
require('cypress-react-unit-test/support')
  1. 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.

  1. ⚠️ Turn the experimental component support on in your cypress.json. You can also specify where component spec files are located. For example, to have them located in src folder use:
{
  "experimentalComponentTesting": true,
  "componentFolder": "src"
}

API

  • mount is the most important function, allows to mount a given React component as a mini web application and interact with it using Cypress commands
  • createMount factory function that creates new mount function with default options
  • unmount removes previously mounted component, mostly useful to test how the component cleans up after itself
  • mountHook mounts a given React Hook in a test component for full testing, see the hooks example

Examples

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 of examples showing various testing scenarios.

Basic examples

SpecDescription
aliasRetrieve mounted component by its name or alias
alert-spec.jsComponent tries to use window.alert
before-hookMount the component from before hook to run multiple tests against it
counter-set-stateCounter component that uses this.state
counter-use-hooksCounter component that uses useState hook
document-specChecks document dimensions from the component
enzymeSeveral specs showing how to recreate Enzyme's setProps, setState, and setContext methods.
emotion-spec.jsConfirms the component is using @emotion/core and styles are set
error-boundary-spec.jsChecks if an error boundary component works
fails-correctlyCypress test fails correctly when interacting with disabled elements
pure-component-spec.jsTests stateless component
stateless-spec.jsPasses Cypress stub to the component, confirms the component calls it on click
windowIn the component test, the spec window and the application's window where the component is running should be the same object
cssShows that component with import './Button.css' works
css modulesShows that component that using css modules styles works
networkConfirms we can use cy.route to stub / spy on component's network calls
no-visitComponent specs cannot call cy.visit
re-renderChecking how the component re-renders when its props change
react-book-by-chris-noringCopied test examples from React Book and adapted for Cypress component tests
react-tutorialTests from official ReactJS tutorial copied and adapted for Cypress component tests
stub-exampleUses cy.stub as component props
stylesAdd extra styles to the component during testing using style, cssFile or stylesheets mount options
toggle-exampleTesting a toggle component using Cypress DOM commands
typescriptA spec written in TypeScript, shows how to use import alias
unmountVerifies the component's behavior when it is unmounted from the DOM
use-lodash-fpImports and tests methods from lodash/fp dependency
styled-componentsTest components that use styled-components

plus a few smaller sanity specs in cypress/component/basic folder.

Advanced examples

SpecDescription
api-testMix REST api tests that use cy-api with component tests
app-action-exampleApp actions against components
contextConfirms components that use React context feature work
custom-commandWraps mount in a custom command for convenience
forward-refTests a component that uses a forward ref feature
hooksTests several components that use React Hooks like useState, useCallback by using mountHook function
lazy-loadedConfirms components that use React.lazy and dynamic imports work
material-ui-exampleLarge components demos from Material UI
mobx-v6Test components with MobX v6 observable
mock-fetchTest stubs window.fetch used by component in useEffect hook
mocking-axiosStubbing methods from a 3rd party component like axios
mocking-componentReplaced a child component with dummy component during test
mocking-importsStub a named ES6 import in various situations
path-aliasesSpecs import components using path aliases defined in the Webpack config
react-router-v6Example testing a React Router v6. Both browser and in memory routers
renderlessTesting a component that does not need to render itself into the DOM
set-timeout-exampleControl the clock with cy.tick and test loading components that use setTimeout
test-retriesThis component is compatible with Cypress Test Retries
testing-lib-exampleA spec adopted from @testing-library/react that uses @testing-library/cypress
timersTesting components that set timers, adopted from ReactJS Testing recipes
tutorialA few tests adopted from ReactJS Tutorial, including Tic-Tac-Toe game
use-local-storageUse hooks to load and save items into localStorage
portalComponent test for ReactDOM.createPortal feature
radioactive-stateTesting components that use radioactive-state library
react-bootstrapConfirms react-bootstrap components are working
select React componentUses cypress-react-selector to find DOM elements using React component name and state values
lazy-loadedUses multiple chunks and async components with React.lazy + React.Suspense.
i18nUsesreact-i18next for localizaiton.
framer-motionUses framer motion for javascript-based animation.
window-envSet additional properties on the window object during test

Full examples

We have several subfolders in examples folder that have complete projects with just their dependencies installed in the root folder.

Folder NameDescription
a11yTesting components' accessibility using cypress-axe
cucumberWriting component tests using Cucumber syntax
react-scripts-folderA project using react-scripts with component tests in cypress/component
react-scriptsA project using react-scripts with component tests in src folder, including the .env files demo.
rollupBundle component and specs using rollup.
sass-and-tsExample with Webpack, Sass and TypeScript
snapshotsComponent HTML and JSON snapshots using cypress-plugin-snapshots
tailwindTesting styles built using Tailwind CSS
using-babelBundling specs and loaded source files using project's existing .babelrc file
visual-sudokuVisual 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-applitoolsVisual testing for components using 3rd party service Applitools.com
visual-testing-with-happoVisual testing for components using 3rd party service Happo
visual-testing-with-percyVisual testing for components using 3rd party service Percy.io
webpack-fileLoad existing webpack.config.js file
webpack-optionsUsing the default Webpack options from @cypress/webpack-preprocessor to transpile JSX specs
rewiredComponent tests for apps that use react-app-rewired

External examples

This way of component testing has been verified in a number of forked 3rd party projects.

RepoVersionDescription
try-cra-with-unit-testcypress-react-unit-test used in try-cra-with-unit-test shortHello world initialized with CRAv3
try-cra-app-typescriptcypress-react-unit-test used in try-cra-app-typescript shortHello world initialized with CRAv3 --typescript
react-todo-with-hookscypress-react-unit-test used in react-todo-with-hooks shortModern web application using hooks
test-redux-examplescypress-react-unit-test used in test-redux-examples shortExample apps copies from official Redux repo and tested as components
test-react-hooks-animationscypress-react-unit-test used in test-react-hooks-animations shortTesting React springs fun blob animation
test-mdx-examplecypress-react-unit-test used in test-mdx-example shortExample testing MDX components using Cypress
test-apollocypress-react-unit-test used in test-apollo shortComponent testing an application that uses Apollo GraphQL library
test-xstate-reactcypress-react-unit-test used in test-xstate-react shortXState component testing using Cypress
test-react-router-v5cypress-react-unit-test used in test-react-router-v5 shortA few tests of React Router v5
test-material-uicypress-react-unit-test used in test-material-ui shortTesting Material UI components: date pickers, lists, autocomplete
test-d3-react-gaugecypress-react-unit-test used in test-d3-react-gauge shortTesting React D3 gauges
storybook-code-coveragecypress-react-unit-test used in storybook-code-coverage shortExample app where we get 100% code coverage easily with a single integration spec and a few component specs, replacing several tools
react-loading-skeletoncypress-react-unit-test used in react-loading-skeleton shortOne to one Storybook tests for React skeleton components. Uses local .babelrc settings without Webpack config
test-swrcypress-react-unit-test used in test-swr shortComponent test for Zeit SWR hooks for remote data fetching
emoji-searchcypress-react-unit-test used in emoji-search shortQuick component test for a fork of emoji-search
test-custom-error-boundarycypress-react-unit-test used in test-custom-error-boundary shortPlay with a component that implements error boundary
Jscrambler-Webpack-Reactcypress-react-unit-test used in Jscrambler-Webpack-React shortExample project with its own Webpack config file
bahmutov/integration-testscypress-react-unit-test used in integration-tests shortExample based on blog post React Integration Testing: Greater Coverage, Fewer Tests
mobx-react-typescript-boilerplatecypress-react-unit-test used in mobx-react-typescript-boilerplate shortFork of the official Mobx example, shows clock control
bahmutov/test-react-hook-formcypress-react-unit-test used in test-react-hook-form shortTesting forms created using react-hook-form
bahmutov/react-with-rollupcypress-react-unit-test used in react-with-rollup shortTesting a React application bundled with Rollup by using @bahmutov/cy-rollup preprocessor
bahmutov/testing-react-examplecypress-react-unit-test used in testing-react-example shortDescribed in blog post Test React Component with cypress-react-unit-test Example
ejected-react-scripts-examplecypress-react-unit-test used in ejected-react-scripts-example shortUsing component testing after ejecting react-scripts
tic-tac-toecypress-react-unit-test used in react-tic-tac-toe-example shortComponent and unit tests for Tic-Tac-Toe, read Tic-Tac-Toe Component Tests
react-hooks-file-uploadcypress-react-unit-test used in react-hooks-file-upload shortUpload a file from the component while stubbing the server
react-query-examplecypress-react-unit-test used in react-query-example shortQuick test example for components that use react-query with mock clock control
react-testing-rails-webpackercypress-react-unit-test used in react-testing-rails-webpacker shortProject that uses @rails/webpacker to bundle files
effective-react-testsTest a component, a Redux store, and a custom React hook

To find more examples, see GitHub topic cypress-react-unit-test-example

Mocking

Using Cypress + cypress-react-unit-test your tests can mock everything:

Options

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 />)
})

Extra styles

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"
    }
  }
}

Code coverage

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
  }
}

Visual testing

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. I explain how to write visual testing using open source tools in this blog post, video talk, and slides.

Common problems

React.lazy does not work

Cypress only servers a single bundle and does not (yet) provide additional bundling. There are several skipped tests in this repo showing the problem. Track #524 for future work.

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.

Slower than Jest

When you use cypress-X-unit-test for component testing, you might notice the tests are slower than using Jest to test the same components. Yes, that's true. A test runner could be made extremely fast if it did nothing, just check out the auchenberg/volkswagen test runner - it is blazing on CI 😉. Of course, Jest does do things, just not inside the real browser environment.

Testing using Jest with its jsdom browser is faster than starting the real browser, loading all libraries, mounting the component and then waiting for the component to actually perform its work in response to the test's actions. But do those tests give you a true confidence that the component is working?

Try this test 🙈

Spoiler: it fails, proof.

const mock = jest.fn()
// render a component that does NOT allow any click events
// using pointerEvents: "none" style
const { getByRole } = render(
  <button style={{ pointerEvents: 'none' }} onClick={mock}>
    text
  </button>,
)
// Jest happily clicks
fireEvent.click(getByRole('button'))
expect(mock).not.toBeCalled()

Cypress test on the other hand fails correctly.

We think that using cypress-X-unit-test runs tests as fast as your application code is, and often you need to think how to slow down the Cypress Test Runner so it does not run away from the component's code, just see our blog posts dealing with test flake.

From the developer's perspective I would ask myself: which tests do I write faster? What happens when a test fails and I need to debug the failure: which test runner allows me to debug a failed test quicker? While I am partial, I have to say, realistic Cypress tests are easier to write and debug.

Finally, when running tests on the continuous integration service, the true test speed up comes from properly configuring dependencies caching and running tests in parallel - something we have extensively documented and consider a solved problem.

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.

Missing code coverage

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.

Gatsby.js projects not supported

Currently, this project cannot find Webpack settings used by Gatsby.js, thus it cannot bundle specs and application code correctly. Keep an eye on #307

Context Provider usage

React context provider usage and API described in ./docs/providers-and-composition.md

Chat

We have a chat workspace at https://component-testing.slack.com/, you are welcome to join us.

Development

See docs/development.md

Debugging

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

Since some objects might be deeply nested, if you see an object that is printed simply { module: { rules: [ [Object] ] } you can increase the max printed depth

DEBUG=cypress-react-unit-test,find-webpack DEBUG_DEPTH=10

Migration guide

From v3 to v4

The old v3 main branch is available as branch v3

  • the cy.mount is now simply import { 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

Keywords

FAQs

Last updated on 11 Dec 2020

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc