Testing Next.js with Jest and Enzyme

Thu Dec 2020

Over the last few months, Next.js has become my default framework for pet projects. I love that it integrates painlessly with TypeScript, and I found that setting up a testing framework was just as effortless.

Getting started

Let's first create a Next.js app.

yarn create next-app next-typescript-enzyme-jest-example
yarn create next-app next-typescript-enzyme-jest-example

Add development dependencies for the TypeScript conversion. With ts-node we can also write our config files in TypeScript.

yarn add --dev typescript ts-node @types/react @types/node
yarn add --dev typescript ts-node @types/react @types/node

Finally, we add a tsconfig.json file, which automatically gets populated when we start the Next.js server.

touch tsconfig.json
touch tsconfig.json

Okay! The project is ready to go, and all that's left is to convert any lingering JavaScript files by following these instructions.

Adding Jest & Enzyme

I chose Jest as my front-end testing framework because of familiarity (prior experience with RSpec), and Enzyme for no particular reason whatsoever.

yarn add --dev jest ts-jest enzyme @wojtekmaj/enzyme-adapter-react-17 @types/jest @types/enzyme
yarn add --dev jest ts-jest enzyme @wojtekmaj/enzyme-adapter-react-17 @types/jest @types/enzyme

I chose ts-jest over @babel/preset-typescript because I was told it has better type-checking. Also, @wojtekmaj's fork of enzyme adapter is only a temporary stopgap until the official adapter supports React 17.

Now that we have installed the testing dependencies, we'll create a couple of config files for Jest:

// jest.config.ts
import type { Config } from "@jest/types"
 
const config: Config.InitialOptions = {
  verbose: true,
  preset: "ts-jest",
  testEnvironment: "node",
}
 
export default config
// jest.config.ts
import type { Config } from "@jest/types"
 
const config: Config.InitialOptions = {
  verbose: true,
  preset: "ts-jest",
  testEnvironment: "node",
}
 
export default config

and Enzyme:

// enzyme.config.ts
import { configure } from "enzyme"
import Adapter from "@wojtekmaj/enzyme-adapter-react-17"
 
configure({ adapter: new Adapter() })
// enzyme.config.ts
import { configure } from "enzyme"
import Adapter from "@wojtekmaj/enzyme-adapter-react-17"
 
configure({ adapter: new Adapter() })

That's it! We are now ready to write unit and integration tests. Below is how I have my scripts set up:

  "scripts": {
    ...
    "test": "jest",
    "test:watch": "jest --watchAll",
    "test:coverage": "jest --coverage"
  },
  "scripts": {
    ...
    "test": "jest",
    "test:watch": "jest --watchAll",
    "test:coverage": "jest --coverage"
  },