Introduction

In this article, we shall learn how to extend ‘matchers’ provided by Jest. Jest is a testing library designed to be simple to use and can be used as a full testing suite(both Test Runner and Test suite(providing assertions called ‘matchers’)). Let’s get started!

What are Matchers?

Matchers are functions that are used to do assertions at the end of a test case. Matchers are used to test values in different ways.

All code samples for this example can be found here

Common Matchers

One of the simplest ways to test a condition is to check exact equality. Note: it(args) is an alias for test(args)

test('five plus five is ten', () => {
  expect(5 + 5).toBe(10)
})

In the above snippet expect(5 + 5) returns an “expectation” object which we can call a matcher on them. Jest offers several matchers, for a full list visit using matchers.

Extending Jest with Custom Matchers

Matchers test values and are called on an “expectation” object. A typical matcher would look like:

expect(['Anita', 'Alice', 'Jane']).toContain('Anita') // .toContain is the matcher checking for value in array
  1. Let’s set up a fresh Nodejs project:
mkdir extending-jest
cd extending-jest
yarn init -y
  1. Add Jest and jest-extended DevDependencies
yarn add --dev jest jest-extended
  1. Initialize a Jest config file for customizing jest behavior and options across the project.
npm i --save-dev jest
jest --init
npm i --save-dev jest-extended

jest --init creates a jest.config.js file that holds options for configuring jest. Check out more here

  1. Update jest.config.js:
module.exports = {
  // Indicates whether the coverage information should be collected while executing the test
  collectCoverage: true,

  // The directory where Jest should output its coverage files
  coverageDirectory: "coverage",


  // A list of paths to directories that Jest should use to search for files in
  roots: [
    "<rootDir>"
  ],

  // The glob patterns Jest uses to detect test files
  testMatch: [
    "**/__tests__/**/*.[jt]s?(x)",
    "**/?(*.)+(spec|test).[tj]s?(x)"
  ],

  // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
  testPathIgnorePatterns: [
    "/node_modules/"
  ],

  // The regexp pattern or array of patterns that Jest uses to detect test files
  testRegex: [],
  // https://github.com/jest-community/jest-extended: Extended matchers
  setupFilesAfterEnv: ['jest-extended/all'],
};

Add setupFilesAfterEnv: ['jest-extended/all'], option to extend jest with all custom matchers provided by the jest-extended package.

expect

When writing tests, you often need to check that values meet certain condition, the same applies to behavior. expect gives you number of “matchers” that make it possible to validate certain things:

expect(sum(2,8)).toBe(10)

Read more about expect. Often times, expect will be commonly used together with a matcher. expect takes the behavior, condition to be tested and the matcher to test the condition.

Use a Custom matcher

create a __test__ directory inside a src directory inside the project and add a test file, index.test.js: Add a dummy testcase like below:

const matchers = require('jest-extended')
expect.extend(matchers)

describe('', () => {
  test('existence of object property using a custom matcher', () => {
    expect({ token: '8cb41e94-825c-315a-a668-612b2f5fa1b9' }).toContainKey('token')
  })
})

jest-extended provides a handful of useful custom matchers:

/* Custom matchers provided by jest-extended */
// .pass(message)
// .fail(message)
// .toBeEmpty()
// .toBeOneOf([members])
// .toBeNil()
// .toSatisfy(predicate)
// Array
// .toBeArray()
// .toBeArrayOfSize()
// .toIncludeAllMembers([members])
// .toIncludeAllPartialMembers([members])
// .toIncludeAnyMembers([members])
// .toIncludeSameMembers([members])
// .toPartiallyContain(member)
// .toSatisfyAll(predicate)
// .toSatisfyAny(predicate)
// Boolean
// .toBeBoolean()
// .toBeTrue()
// .toBeFalse()
// Date
// .toBeDate()
// .toBeValidDate()
// .toBeAfter(date)
// .toBeBefore(date)
// .toBeAfterOrEqualTo(date)
// .toBeBeforeOrEqualTo(date)
// .toBeBetween(startDate, endDate)
// Further proposals in #117 PRs welcome
// Function
// .toBeFunction()
// .toThrowWithMessage()
// Mock
// .toHaveBeenCalledBefore()
// .toHaveBeenCalledAfter()
// .toHaveBeenCalledOnce()
// Number
// .toBeNumber()
// .toBeNaN()
// .toBeFinite()
// .toBePositive()
// .toBeNegative()
// .toBeEven()
// .toBeOdd()
// .toBeWithin(start, end)
// .toBeInteger()
// Object
// .toBeObject()
// .toBeEmptyObject()
// .toContainKey(key)
// .toContainKeys([keys])
// .toContainAllKeys([keys])
// .toContainAnyKeys([keys])
// .toContainValue(value)
// .toContainValues([values])
// .toContainAllValues([values])
// .toContainAnyValues([values])
// .toContainEntry([key, value])
// .toContainEntries([[key, value]])
// .toContainAllEntries([[key, value]])
// .toContainAnyEntries([[key, value]])
// .toBeExtensible()
// .toBeFrozen()
// .toBeSealed()
// Promise
// .toResolve()
// .toReject()
// String
// .toBeString()
// .toBeHexadecimal(string)
// .toBeDateString(string)
// .toEqualCaseInsensitive(string)
// .toStartWith(prefix)
// .toEndWith(suffix)
// .toInclude(substring)
// .toIncludeRepeated(substring, times)
// .toIncludeMultiple([substring])
// .toEqualIgnoringWhitespace(string)

For more, check out the official jest-extended Github repository jest-extended

If new to matchers, learn more about matchers read more on official jest docs

Summary

Jest provides a simple way to carry out Test Driven development. Extending jest with custom matchers makes it a lot more powerful and versatile to cover more conditions.