Skip to main content

What is Jest?

What is Jest?

Jest is a JavaScript testing framework originally created at Facebook (now Meta) alongside React, and today maintained by the community under the OpenJS Foundation. Despite its React roots, it is not limited to React — I use it just as happily for plain Node.js services, Express APIs, TypeScript libraries, Angular, and Vue projects.

What makes Jest the default choice is that it ships everything in one package: a test runner, an assertion library, mocking, code coverage, and snapshot testing. With Mocha you assemble those pieces yourself (Chai for assertions, Sinon for mocks, nyc for coverage); with Jest you install one dev dependency and start writing tests.

Getting Started

Installation

Jest is a Node-based runner. This means that the tests always run in a Node environment and not in a real browser. This lets us enable fast iteration speed and prevent flakiness.

First of all, create a new project in React, Express, or any other Node.js framework. I am going to use simple node js for this doc.

First of all, create directory and initialize npm:

mkdir jest-demo
cd jest-demo
npm init -y

Now, install Jest:

npm install --save-dev jest

For TypeScript, you'll need to install ts-jest and @types/jest types, and set the ts-jest preset in your Jest config:

npm install --save-dev ts-jest @types/jest
jest.config.js
module.exports = {
preset: "ts-jest",
};

Test File Setup

Jest will look for test files with any of the following popular naming conventions:

  • Files with .js, .jsx, .ts or .tsx suffix in __tests__ folders.
  • Files with .test.js, .test.jsx, .test.ts or .test.tsx suffix.
  • Files with .spec.js, .spec.jsx, .spec.ts or .spec.tsx suffix.

The __tests__ folder name is special. Jest will consider files in __tests__ folders as tests, so you can store test files anywhere you want.

Writing Tests

To create a test case, call the test function inside a test file. Let's say we have a function that adds two numbers. We could test it like this:

math.test.js
// sum function
function sum(a, b) {
return a + b;
}

// test case for sum function
test("addition should return 4", () => {
const a = 2;
const b = 2;

expect(sum(a, b)).toBe(4);
});

This is your standard test call (it is an alias — it("adds two numbers", ...) behaves identically, pick one style and stay consistent). It receives two arguments:

  • a string describing the behavior under test
  • a callback that runs the test — the expect call checks whether the function produced the correct result

Running Tests

To run the test, we can use the npx jest command. This will run all the tests in the project.

npx jest

By default, Jest will look for files matching the above mentioned naming convention. To run a specific file, pass its name (or any part of the path — Jest treats it as a pattern):

npx jest math.test.js

To run a single test by name, use -t with part of the test description:

npx jest -t "addition"

In a real project, wire Jest into package.json so npm test works for everyone:

package.json
{
"scripts": {
"test": "jest"
}
}

Watch Mode

Jest can be run in watch mode. In this mode, Jest re-runs the tests affected by your changes every time you save a file — this is the mode I keep running while developing.

npx jest --watch

--watch requires a git repository, because it uses git to detect which files changed. Outside a repo, use --watchAll to re-run everything on every change.

Coverage

Coverage is a measure of how much of our code is executed by tests. Jest generates coverage reports out of the box:

npx jest --coverage

This prints a summary table and writes a detailed HTML report to the coverage folder. Treat the number as a guide, not a target — more on that in Testing Best Practices.

Assertions

Jest uses the expect function to make assertions. An assertion is a way to test the result of a function.

math.test.js
// sum function
function sum(a, b) {
return a + b;
}

// test case for sum function
test("addition should return 4", () => {
const a = 2;
const b = 2;

expect(sum(a, b)).toBe(4);
});

In the above example, we are using the toBe matcher to check whether the result of the sum function is 4.

Common Matchers

Jest has a lot of matchers that can be used to make assertions. Here are some of the most common matchers:

  1. toBe()
  2. toEqual()
  3. not.toBe()
  4. toContain()
  5. toBeNull()
  6. toBeUndefined()
  7. toHaveLength()
  8. toThrow()
  9. toMatch()

toBe()

Checks if the result of a function is equal to the expected value using strict equality (===).

test("add function should correctly add two numbers", () => {
const result = add(2, 3);
expect(result).toBe(5);
});

toEqual()

Verifies deep equality between the result of a function and the expected value.

test("calculateTotal should return correct object", () => {
const cart = [10, 20, 30];
const result = calculateTotal(cart);
expect(result).toEqual({ total: 60 });
});

not.toBe()

Ensures that the result of a function is not strictly equal to the expected value.

test("subtract function should not return incorrect value", () => {
const result = subtract(10, 5);
expect(result).not.toBe(10);
});

toContain()

Verifies if an array, string, or iterable object contains the specified element or substring.

test("shopping cart should contain the added item", () => {
const cart = ["apple", "banana", "orange"];
const newItem = "pear";
cart.push(newItem);
expect(cart).toContain(newItem);
});

toBeNull()

Checks if the result of a function is null.

test("should return null", () => {
const result = null;
expect(result).toBeNull();
});

toBeUndefined()

Checks if the result of a function is undefined.

test("should return undefined", () => {
const result = undefined;
expect(result).toBeUndefined();
});

toHaveLength()

Checks if a string, array, or object has the specified length property.

test("string length should be equal to the specified length", () => {
const str = "Hello, World!";
expect(str).toHaveLength(13);
});

toThrow()

Ensures that a function throws an error when it is invoked.

test("divide function should throw an error when dividing by zero", () => {
const divideByZero = () => divide(10, 0);
expect(divideByZero).toThrow();
});

toMatch()

Verifies if a string matches the specified regular expression pattern.

test("email should match the regular expression pattern", () => {
const email = "test@example.com";
expect(email).toMatch(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}$/);
});

These are the matchers I reach for daily. The full list lives in the Jest expect API reference, but a good rule of thumb: pick the most specific matcher available. expect(cart).toContain("pear") produces a far better failure message than expect(cart.includes("pear")).toBe(true) — the first tells you what the array actually contained, the second just says false is not true.

Next steps: Unit Testing covers test structure and setup/teardown, Mocking covers isolating dependencies, and Async Testing covers promises and timers.

Code

You can find the code for this doc from here