Component Testing with Cypress and Reactjs
Tags: cypress, react, testing, component
Published: 2023-09-03 11:26:38

Cypress has a feature called [Component Testing](https://docs.cypress.io/guides/component-testing/overview), and I found the experience using it quite interesting, and familiar for those coming from non-UI testing suites. I assume that you have basic knowledge of Reactjs and Cypress and perhaps [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/) and [Jest](https://jestjs.io/) so I will skip the details and focus on the core concept.

Let us assume we have created a `Parent` component that renders a `Child` component. `Parent` makes an API request to a backend, stores it in state, and renders it to `Child` via props. We are adding some tests to make sure that the `Child` properly renders the data, and nothing crashes if some part of the data is missing. Simple stuff, typical example.

For our testing purposes we don't need a proper backend API to make our request since we're going to stub it. We can write something like:

```js
export async function getData() {
  const {data} = await axios.get('/api/users/');
  return data
}
```

...and then we call `getData` in our useEffect, store the user object in state, pass the user as a prop to our child component, blah blah, you know the part. Now let's get down to business!

We start writing our mock data:

```ts
const MOCK_DATA = {
    user: {
      address: '33265 Kirlin Center',
      name: 'Enoch',
      lastName: 'Graham',
      city: 'Port Neha',
      country: 'Berkshire',
    },
};
```

Since Parent is making the request, we need to use the [intercept](https://docs.cypress.io/api/commands/intercept#Intercepted-requests) command to stub the response.

```js
describe('<Parent/>', () => {
  it('renders', () => {
    cy.intercept('GET', '/api/users/', (req) => {
      req.reply({
        statusCode: 200,
        body: MOCK_DATA, // <---
      });
    });

    cy.mount(<Parent />);
  });
});
```

We are now ready to add more assertions by modifying the `MOCK_DATA` object, for example to test what happens when `address` is undefined.

With the React Testing Library and Jest, we would do pretty much the same thing: We would use something like [jest.spyOn](https://jestjs.io/docs/jest-object#jestspyonobject-methodname) in combination with [mockResolvedValue](https://jestjs.io/docs/mock-function-api/#mockfnmockresolvedvaluevalue) to intercept the request and mock the response. 


> What is great about Cypress Component Testing is that we have a visual representation of our test with simple methods, which is a big enhacement in terms of the development experience.



### Some notes on configuring Cypress, and improving your testing strategy:

- When Cypress creates a component test, you will notice that the styles are not applied. Simply follow the relevant [documentation](https://docs.cypress.io/guides/component-testing/styling-components) to solve this.
- If you are using Typescript, you will probably need to configure `tsconfig.json` so that Cypress types are recognized.
- Use [faker.js](https://fakerjs.dev/) and factories to generate random values for your mock data. 

Cheers!