Skip to content

A Jest matcher to verify the shape of an object. Makes integration testing simple.

License

Notifications You must be signed in to change notification settings

Dean177/jest-to-match-shape-of

Repository files navigation

toMatchShapeOf

CircleCI codecov Npm

A Jest matcher to verify the structure of an object, particularly useful for API integration tests.

example-gif

Installation

First install the package via npm, pnpm or yarn:

npm install --save-dev jest-to-match-shape-of
pnpm add --dev jest-to-match-shape-of
yarn add --dev jest-to-match-shape-of

Then create a file to setup your tests. This guide uses test/setup.js (for Javascript projects) or test/setup.ts (for Typescript projects), but it should still work if you place it somewhere else.

Add the following to test/setup.js file (if you are using CommonJS):

// /test/setup.js
// Setup your test environment

const { toMatchOneOf, toMatchShapeOf } = require('jest-to-match-shape-of')

expect.extend({
  toMatchOneOf,
  toMatchShapeOf,
})

If you are using ESM or Typescript, use the following instead:

// /test/setup.ts
// Setup your test environment

import { toMatchOneOf, toMatchShapeOf } from 'jest-to-match-shape-of'

expect.extend({
  toMatchOneOf,
  toMatchShapeOf,
})

Then add the following to your Jest configuration:

// CommonJS/ESM
"setupFilesAfterEnv": ["./test/setup.js"]

// Typescript
"setupFilesAfterEnv": ["./test/setup.ts"]

For usage in a project created using CRA (create-react-app) you simply need to add the above setup code to the test setup file (usually src/setupTests.js or src/setupTests.ts), there is no need to modify your Jest configuration.

import '@testing-library/jest-dom'

import { toMatchOneOf, toMatchShapeOf } from 'jest-to-match-shape-of'

expect.extend({
  toMatchOneOf,
  toMatchShapeOf,
})

Usage

expect(someThing).toMatchOneOf([
  someOtherThingA,
  someOtherThingB,
  someOtherThingC,
])
expect(someThing).toMatchShapeOf(someOtherThing)

Works particularly well when being used with Typescript to write integration tests e.g.

type Resource = {
  maybeNumber: number | null
  someString: string
}

const testResource: Resource = {
  maybeNumber: 6,
  someString: 'some real looking data',
}

const testResourceAlt: Resource = {
  maybeNumber: null,
  someString: 'some real looking data',
}

describe('an api', () => {
  it('returns what I was expecting', () => {
    return fetch('/resources/1')
      .then((response) => response.json())
      .then((data) => {
        expect(data).toMatchShapeOf(testResource)
      })
  })

  it('could return a couple of different things', () => {
    return fetch('/resources/1')
      .then((response) => response.json())
      .then((data) => {
        expect(data).toMatchOneOf([testResource, testResourceAlt])
      })
  })
})

Matching Optional Fields

Sometimes, the expected shape may vary during integration tests (for example, a field may be missing).

If you want to make a shape allow optional fields, the simplest way is to remove those fields from the expected shape, as follow:

toMatchShapeOf({ ant: 17 }) // `bat` is optional here

A more robust alternative is to define all possible shapes, this way you still test the types of the properties:

toMatchOneOf([{ ant: 17, bat: 176 }, { ant: 17 }]) // `bat` is still optional, but must be numeric

Motivation

I wanted to write integration test for my frontend code but found it was tedious, brittle and hard to debug when I encountered a legitimate failure.

I realised that

  • Almost all of the errors were due to bad data from the API, most often missing data
  • I did not care about exactly what data came back, but more about the shape of the data.
  • Since I was using React and Typescript I could be confident my app would work as intended if the types were correct
  • Thanks to Enzyme, I already had a great way to test my component interactions

toMatchShapeOf hopefully achieves a lot of the value of full blown integration test written with something like Nightwatch whilst being simpler to write, understand and debug.

I also found out that the test data I created for use with this matcher was useful for other unit tests in my application.

About

A Jest matcher to verify the shape of an object. Makes integration testing simple.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published