3 tips for setting up Jest and rtl for Next.js
Tags: nextjs, jest
Published: 2022-10-10 16:15:48

Since version 12, `Next.js` has build in configuration for `Jest`. The [documentation](https://nextjs.org/docs/testing#jest-and-react-testing-library) 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:

```javascript
// 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`](https://github.com/testing-library/jest-dom#table-of-contents) 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.

```javascript
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`):

```javascript
// jest.config.js
setupFilesAfterEnv: ['<rootDir>/jest.setup.js']
```
And then making a new file: `jest.setup.js`

```javascript
// 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`:

```javascript
// 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](https://github.com/testing-library/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` 

```json
{
  "extends": "next/core-web-vitals"
}
```
Add the following lines:

```json
{
  "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.