Add Jest testing framework to an existing Next.js app

Author: David Fekke

Published: 5/11/2022

I have been using Next.js for a new project I am currently working. Most of my Node.js experience working with web apps has been using the Express.js framework. One of the tools I like using for my testing is Jest.

If you have not had a chance to use Jest, it is definitely worth checking out. It is very popular with the React community and it has test coverage built into the framework.

The easy way to add Jest to Next.js

The easiest way to add Jest to Next.js is to do so when scaffolding out a new app using the create-next-app command line tool. Here is an example of how you can create a Next app using that tool:

npx create-next-app --example with-jest with-jest-app
# or
yarn create next-app --example with-jest with-jest-app
# or
pnpm create next-app -- --example with-jest with-jest-app

This will create an example Next.js app with Jest already configured and ready to go.

The not so hard way to add Jest to Next.js

If you have a pre-existing Next.js app, jest can be added fairly easily. We are going to add Jest to a Next.js 12 app by using the following steps;

Add Testing Modules

Add the @testing-library/react, @testing-library/jest-dom, jest-environment-jsdom modules using your package manger of choice. I am going to use yarn for my examples:

yarn add jest @testing-library/react @testing-library/jest-dom jest-environment-jsdom --dev

Add Jest Config

The next thing we need to do is add a jest.config.js file to the root directory of our project, and code the following configuration:

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',
};

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);

Add Unit Test

Now we will add out first unit test for the landing page. We will create a folder in the root directory for all of our tests. Jest uses the following convention of a __tests__ directory for storing all of your Jest tests. We will create this directory and add a test file called index.test.js for our test. Add the following code to this file:

// __tests__/index.test.js

import { render, screen } from '@testing-library/react';
import Home from '../pages/index';
import '@testing-library/jest-dom';

describe('Home', () => {
  it('renders a heading', () => {
    render(<Home />)

    const heading = screen.getByRole('heading', {
      name: /welcome to next\.js!/i,
    })

    expect(heading).toBeInTheDocument()
  })
});

Add a Test Runner to package.json

Our last step will be to modify our package.json file to add a test runner script to the scripts section. My scripts section look like the following example:

...
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "test": "jest"
  },
...

Running our unit test

Now that we have made these four changes we can run our first test:

> yarn test
yarn run v1.22.18
$ jest
 PASS  __tests__/index.test.js
  Home
 renders a heading (94 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.419 s
Ran all test suites.
  Done in 3.29s.

Now if we want to add a test coverage report, we can add the --coverage flag in the test command in the scripts section of our package.json file.

"test": "jest --coverage"

If you run the test runner again, your output should look like the following:

 yarn test
yarn run v1.22.18
$ jest --coverage
 PASS  __tests__/index.test.js
  Home
 renders a heading (90 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files |     100 |      100 |     100 |     100 |
 index.js |     100 |      100 |     100 |     100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.382 s
Ran all test suites.
  Done in 3.13s.

Conclusion

Next.js offers a lot of options when it comes to testing and mocking. Along with Jest, you can also test using Cypress, Playwright or Vitest.

The example of using Jest in this post is using the Rust compiler, but you can also set up Jest to run using Babel if you prefer. Have fun testing!