Skip to the content.
22 December 2022

Writing automated tests helps ensure your code behaves exactly as expected and remains reliable over time. Jest is a popular JavaScript testing framework that provides a complete testing solution with a built-in test runner, assertion library, and mocking utilities. This guide walk you through setting up Jest and testing both plain JavaScript and React components.

To install Jest along with the Enzyme utility library, run:

# npm
npm install --save-dev jest enzyme

# yarn
yarn add --dev jest enzyme

Configure Jest to use a browser environment by adding a jest block to your package.json file:

{
  "jest": {
    "testEnvironment": "jsdom"
  }
}

This configuration tells Jest to run your tests inside a simulated browser environment called jsdom, which allows you to interact with DOM elements directly in your test suites.

Next, add a test script to your package.json:

"scripts": {
  "test": "jest"
}

Now you can start your tests from the command line:

yarn test

Testing plain JavaScript

With Jest installed and configured, you can start writing your first test suite. Jest uses a readable, descriptive syntax. Here is a simple example:

describe("basic calculations", () => {
  it("adds numbers correctly", () => {
    expect(1 + 1).toBe(2);
  });

  it("identifies math errors", () => {
    expect(1 + 1).toBe(3);
  });
});

The describe function groups related tests into a single suite, while it defines an individual test block. The expect function allows you to write assertions.

You can use beforeEach and afterEach hooks to set up common test states and keep your suites clean:

describe("user configuration", () => {
  let role;

  beforeEach(() => {
    role = "admin";
  });

  it("reads the default role", () => {
    expect(role).toBe("admin");
  });

  it("allows updating the role", () => {
    role = "editor";
    expect(role).toBe("editor");
  });
});

Using beforeEach resets the role variable before every test, preventing state from leaking between tests.

Jest includes many matching functions like toBe for strict equality and toEqual for deep object comparisons:

it("verifies strict and soft equality", () => {
  expect(1).toBe(1);
  expect(1).not.toBe("1");
});

Testing React components

Testing React components involves rendering them in a test environment and making assertions about their visual output or behavior.

Import your component and render it to a DOM container in your test:

import React from "react";
import ReactDOM from "react-dom";
import MyComponent from "./MyComponent";

it("renders without crashing", () => {
  const div = document.createElement("div");
  ReactDOM.render(<MyComponent />, div);
});

Snapshot testing

Snapshot tests prevent unexpected changes to your component’s rendered output by saving a text representation of the HTML and comparing it to subsequent test runs.

import React from "react";
import MyComponent from "./MyComponent";
import renderer from "react-test-renderer";

it("renders correctly", () => {
  const tree = renderer.create(<MyComponent />).toJSON();
  expect(tree).toMatchSnapshot();
});

If you make deliberate changes to the component’s UI, Jest will flag the diff, and you can update the stored snapshot from your terminal.

Testing mock functions

You can mock modules or functions to isolate the component you are testing. This is ideal when your component fetches data from a database or relies on external APIs.

import React from "react";
import MyComponent from "./MyComponent";
import * as api from "./api";

jest.mock("./api");

it("calls the API when mounted", () => {
  const spy = jest.spyOn(api, "getData");
  const wrapper = mount(<MyComponent />);
  expect(spy).toHaveBeenCalled();
});

Testing interactive events

You can simulate user interactions like button clicks or form submissions, then assert that the component reacted correctly.

import React from "react";
import { shallow } from "enzyme";
import MyComponent from "./MyComponent";

it("triggers the click handler", () => {
  const mockClickHandler = jest.fn();
  const wrapper = shallow(<MyComponent onClick={mockClickHandler} />);
  wrapper.find("button").simulate("click");
  expect(mockClickHandler).toHaveBeenCalled();
});

This shallow-renders your component, finds the button element, simulates a click event, and asserts that the mock click handler was called.

You can simulate other DOM events in exactly the same way:

import React from "react";
import { shallow } from "enzyme";
import MyComponent from "./MyComponent";

it("triggers the submit handler", () => {
  const mockSubmitHandler = jest.fn();
  const wrapper = shallow(<MyComponent onSubmit={mockSubmitHandler} />);
  wrapper.find("form").simulate("submit");
  expect(mockSubmitHandler).toHaveBeenCalled();
});

Helpful resources