React Testing Recipes
You want to setup jest
A minimal config
jest.config.js
module.exports = {
transform: {
"^.+\\.jsx?$": `<rootDir>/jest-preprocess.js`,
},
moduleNameMapper: {
'^.+\\.(css|style|less|sass|scss)$': 'identity-obj-proxy',
},
transformIgnorePatterns: [ '!node_modules/',],
testEnvironmentOptions: {
url: `http://localhost`,
},
}Further Reading
- Jest configuration docs
identity-obj-proxydocs
jest.preprocess.js
const babelOptions = {
// your babel config goes here
};
module.exports = require('babel-jest').default.createTransformer(babelOptions);Further Reading
You want coverage reports
jest.config.js
module.exports = {
...
collectCoverage: true,
coverageDirectory: 'coverage',
reporters: ['default', ['jest-junit', { outputDirectory: 'reports' }]],
...
}Further reading
You want to enable/add path alias support
jest.config.js
const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./jsconfig.json'); // or tsconfig.json
const paths = pathsToModuleNameMapper(compilerOptions.paths, {
prefix: '<rootDir>/',
});
module.exports = {
...
moduleNameMapper: {
...paths,
// other path aliases you want to add manually
}
...
}Your project uses other file extensions ie svg/gql/…
You need transformers
Here’s how you would add transformers for .gql & .svg files. You will need to add them as dev dependencies.
jest.config.js
module.exports = {
...
transform: {
'\\.(gql|graphql)$': '@graphql-tools/jest-transform',
'^.+\\.svg$': 'jest-transformer-svg',
...
},
...}Further Reading
- Transformers
Setup file
- Why you need this?
- When you have Provider wrappers in your app ie
SnackbarProvider,ThemeProviders, you might need to setup a custom render function which automatically wraps your Component to be tested with the necessary wrappers.
- When you have Provider wrappers in your app ie
jest.setup.js
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/extend-expect'; // needed for assertions
import React from 'react';
import { render } from '@testing-library/react';
// import all your Providers here
const AllTheProviders = ({ children }) => {
return <Provider>{children}</Provider>;
};
const customRender = (ui, options) =>
render(ui, { wrapper: AllTheProviders, ...options });
export * from '@testing-library/react';
export { customRender as render };You want to run jest
npx jestAdd it as a script to package.json
package.json
{
"scripts": {
"test": "jest"
}
}Further Reading
- Jest CLI options
You want to see how tests are written?
While testing
You want to test Apollo graphql
- Here’s how to set it up
- Here’s a really neat way to set it up along with preliminary debugging
- Is there any way to make this easier?
- I pass my
mocksas second argument to therenderfunction - I have a utility to create the mock request-response entity
- Here’s how it looks like
const {...} = render(<Component {...props}/>, MakeResponses({ 'query-name': { params: // query params go here, data: // response goes here }, ... }))
- I pass my
You want to simulate browser events - Click/Change/…
You are facing SOME_ENV_VAR not defined
You can define global variables by jest.config.js
module.exports = {
...,
globals: {
ENV_VAR_NAME: VALUE
},
...
}Further Reading
- Globals Object
You want to mock
You want to mock a npm dependency
If the dependency is a commonjs module, you can do
jest.mock('dependency', () => ({
default: jest.fn(),
}));Assuming the dependency is exported as default
- For named exports, you can do
jest.mock('dependency', () => ({
namedExportedFunction: jest.fn(),
}));- If the dependency is es6 module, you can do
jest.mock('dependency', () => ({
__esModule: true,
default: jest.fn(),
namedExportedFunction: jest.fn(),
}));Further Reading
- Jest Mocks
You want to mock a Component
For example, You want to mock Route to bypass authentication. Assuming you have the following folder structure and Route is the default export
...
|-Route
|- index.jsYou can add the Route mock at Route/__mocks__/index.js
Route/mocks/index.js
function MockRoute({children}) {
return (
<>{children}</>
);
};Route can be automatically mocked by placing the following snippet in your test file
jest.mock('path/to/Route');You want to mock a Context
AuthProvider has the following state
const AuthContext = React.createContext({
user: null,
login: () => {},
logout: () => {},
});You can mock AuthProvider by AuthProvider/mocks/index.js
const AuthContext = React.createContext();
const AuthState = {
user: null,
login: jest.fn(),
logout: jest.fn(),
};
export default function AuthProvider(){
return (<AuthContext.Provider value={{
user: null,
login: () => {},
logout: () => {},
}}>
{children}
</AuthContext.Provider>);
}