My workplace has largish single page application, it was built in 2020 and uses Create React App for the build tool. Unfortunately, nearly every component takes an excessive amount of time to test. Sometimes it is longer than 300seconds, sometimes 100seconds, the fastest I've ever seen a test complete is 30seconds. Is this normal behaviour, if not, why are these tests taking such a long time?
While this code example is not reproducable, I am hoping that somebody may be able to take a read through it and highlight some possible problem areas:
// required imports from React & 3rd party libraries
import React from 'react';
import { render, screen, within } from '@testing-library/react';
import { API } from 'aws-amplify';
// react component to be tested, plus context and helper functions
import { MyComponent } from './MyComponent';
import { Store, UserContext, FurtherDetailContext } from 'store/store';
import * as helpers from 'helpers';
// mock data
import userContextMock from '../../../tests/fixtures/userContext/userContext.json';
import furtherDetailContextMock from '../../../tests/fixtures/furtherDetailContext/furtherDetailContext.json';
import gqlQueryResponse1 from '../../../tests/fixtures/gql/gqlQueryResponse1.json';
import gqlQueryResponse2 from '../../../tests/fixtures/gql/gqlQueryResponse2.json';
const mockJson = {
this: 'is',
an: 'example',
response: true
};
const arrange = async () => {
const mockToggleOpen = jest.fn();
render(
<Store>
<UserContext.Provider
value={{
userContext: userContextMock,
setUserContext: () => {
// do nothing
}
}}>
<FurtherDetailContext.Provider
value={{
furtherDetailContext: furtherDetailContextMock,
setFurtherDetailContext: () => {
/*do nothing */
}
}}>
<MyComponent myProps={mockJson} toggleOpen={mockToggleOpen} />
</FurtherDetailContext.Provider>
</UserContext.Provider>
</Store>
);
// this component performs a network request before rendering
await screen.findByText('text on the screen');
const testid1 = screen.getByTestId('test-id-example');
const testid2 = screen.getByTestId('test-id-example-2');
return { testid1, testid2 };
};
describe('MyComponent', () => {
beforeEach(() => {
// get auth token
jest.spyOn(helpers, 'getAuthtoken').mockResolvedValue('validAuthToken');
});
describe('all calls mocked', () => {
beforeEach(() => {
// mock graphql requests
API.graphql = jest.fn().mockImplementation((url) => {
const gqlQuery = url.query;
if (RegExp('.*.mockGqlQuery*').test(gqlQuery)) {
return gqlQueryResponse1;
}
if (RegExp('.*.mockGql2*').test(gqlQuery)) {
return gqlQueryResponse2;
}
return;
});
});
it('shows the original text on component mount', async () => {
const { testid1 } = await arrange();
expect(within(testid1).getByText('this text should be here')).toBeInTheDocument();
});
});
});
Here are the relevant dependencies:
"dependencies": {
"@types/node": "^12.12.50",
"@types/react": "^17.0.52",
"@types/react-dom": "^17.0.18",
"@types/react-router-dom": "^5.1.7",
"@types/react-leaflet": "^2.8.1",
"aws-amplify": "^4.3.26",
"leaflet": "^1.7.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-leaflet": ">=3.1.0 <3.2.0 || ^3.2.1",
"@react-leaflet/core": ">=1.0.0 <1.1.0 || ^1.1.1",
"react-router-dom": "^6.4.3",
"typescript": "^3.7.5",
}
"devDependencies": {
"react-scripts": "^5.0.1",
"@testing-library/dom": "^7.28.1",
"@testing-library/jest-dom": "^5.11.6",
"@testing-library/react": "^12.1.5",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^26.0.4",
"jest": "^26.6.3",
"node-sass": "^6.0.1",
}
local development node version: v16.15.1
It's a well known issue that create-react-app
is quite slow; and this issue is also extended to the tests.
The problem is probably webpack
, your bundler program, sadly you can't easily decouple an app built with create-react-app
from it.
My recommendation is to switch over to vite
, and then to use vite's testing library: vitest in particular.
(I believe you might keep your normal create-react-scripts
and only use vitetest for testing.)
I understand that this is not the type of answer you might like to receive - it's not only Yet Another Dependency it also means changing a lot of the plumbing; but overall I found it incredibly useful to switch from create-react-app
to vite
; the speed difference is night and day.
Here's a migration guide for vitest that you might find useful.