Unit testing React components in Cypress without CRA and react-scripts

So you have an app or component library that you have created without and you want to unit test it using Cypress. I had to go through some hassle to get that working with a custom webpack configuration, but it’s finally working, and here is my solution.

1. Install Cypress

npm install --save-dev cypress @cypress/react

Additional installation instructions can be found here.

2. Add cypress.json

{
"testFiles": "**/*.spec.js",
"experimentalComponentTesting": true,
"componentFolder": "./src",
"nodeVersion": "system",
"env": {
"webpackFilename": "./webpack.tests.config.js"
}
}
  • specifies a pattern for files that contain your tests
  • enables unit testing support. Though it says experimental, it’s quite stable now
  • is akin and specifies where your unit and integration tests reside. You could keep your unit tests inside your folder and have one to one mapping to your components, i.e. and
  • tells Cypress to use the node version of the system it runs on, and not use the bundled version. This might be necessary if you are using and other binaries that are platform specific.
  • specifies the localtion of the webpack config you want to use for your tests. Cypress will transpile your components on the fly, hence you may need to have a different configuration that what you use to build your project. Think Storybook.

All the configuration options are defined here.

3. Update support bindings

Update and import directives needed for Cypress to mount your unit tests into the Cypress DOM.

// ./cypress/support/index.jsimport '@cypress/react/support';

4. Configure the plugins

Update and tell Cypress how to process your test files.

// ./cypress/plugins/index.jsmodule.exports = (on, config) => {
require('@cypress/react/plugins/load-webpack')(on, config);
return config;
};

plugin will transpile your components files during testing using webpack config you have specified in .

5. Write your tests

// ./src/Button.spec.jsimport React from 'react';
import Button from './Button';
import { mount } from '@cypress/react';
describe('Button', () => {
it('should handle onClick', () => {
const onClick = cy.stub().as('onClick');

mount(
<Button onClick={onClick}>Click me</Button>,
);

cy.findByRole('button', { name: 'Click me' }).click();

cy.get('@onClick').should('have.been.calledOnce');
});
});

6. Run your tests

You can now run your tests with or .

7. Rejoice

Running components tests in an actual DOM boosts confidence in the reliability of your tests. You can run them in multiple browsers. You can create functional tests combining multiple components together to see how they interact with each other, how user interacts with them using the mouse and the keyboard, and you can stub your dependencies to avoid complex definitions.

And added bonus, is that Cypress automatically generates test coverage reports, so you don’t have to instrument anything.

Full-stack developer, passionate about front-end frameworks, design systems and UX.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store