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 assertion 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 are value 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 matchers on them. Jest offers several matchers, for a full list visit API doc.

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 -g jest
jest --init

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

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

Summary

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