Since version 12, Next.js
has build in configuration for Jest
. The documentation is pretty clear how to get started. Install the npm packages (jest
, jest-environment-jsdom
, @testing-library/react
, @testing-library/jest-dom
) and add a jest.config.js
file:
// jest.config.js
const nextJest = require('next/jest')
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})
// Add any custom config to be passed to Jest
/** @type {import('jest').Config} */
const customJestConfig = {
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig)
But this default configuration isn't optimal. You can make your workflow more easy with the following tips.
1. Auto include jest-dom
in every test
jest-dom
is a library with a whole series of usefull matcher functions. To use these matchers, you need to import jest-dom
in every test file.
import '@testing-library/jest-dom/extend-expect'
You can automate this import by adding following line in jest.config.js (This line is commented out in the above example provided by Next.js
):
// jest.config.js
setupFilesAfterEnv: ['<rootDir>/jest.setup.js']
And then making a new file: jest.setup.js
// jest.setup.js
import '@testing-library/jest-dom/extend-expect'
And that's all, no more manually writing an import line for jest-dom
in every test file.
2. Auto clear all mocks
To prevent different tests from polluting each other, you can call jest.clearAllMocks()
. You can call this manually in each test or inside a lifecycle hook like beforeEach
.
But, when you have a lot of tests, this can grow tiresome. So, let's automate it. This is really easy. We add clearMocks: true
to Jest.config.js
:
// jest.config.js
const nextJest = require('next/jest')
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})
// Add any custom config to be passed to Jest
const customJestConfig = {
// Add more setup options before each test is run
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
// automate clear mocks
clearMocks: true,
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig)
And we're done.
3. Use eslint-plugin-testing-library
It's a good habit to let eslint help you out when you're coding. There is a specific eslint library for testing: eslint-plugin-testing-library Here is how you configure it.
First, install the package:
npm install --save-dev eslint-plugin-testing-library
Then go to the file .eslintrc.json
{
"extends": "next/core-web-vitals"
}
Add the following lines:
{
"extends": ["next/core-web-vitals", "plugin:testing-library/react"],
"plugins": ["testing-library"]
}
And we are done. Eslint will now happily yell at you whenever you make a mistake.