Skip to content

Instantly share code, notes, and snippets.

@julien-f
Last active March 4, 2021 10:14
Show Gist options
  • Save julien-f/ef8a268a8190c79ef8b8b52e03de7376 to your computer and use it in GitHub Desktop.
Save julien-f/ef8a268a8190c79ef8b8b52e03de7376 to your computer and use it in GitHub Desktop.
Proposal for better Jest matcher

Goals

  • minimalist: only one way to test something
  • composable: test negation, behavior and value testing composition

Value testing

Existing matchers

  • toBe(value)
  • toBeCloseTo(number, precision)
  • toBeGreaterThan(number)
  • toBeGreaterThanOrEqual(number)
  • toBeLessThan(number)
  • toBeLessThanOrEqual(number)
  • toBeInstanceOf(Class)
  • toContain(item)
  • toContainEqual(item)
  • toEqual(value)
  • toMatch(regexpOrString)
  • toMatchObject(object)
  • toMatchSnapshot(optionalString)

Deprecated matchers

  • toBeFalsy(): expect(Boolean(value)).toBe(false)
  • toBeNull(): toBe(null)
  • toBeTruthy(): expect(Boolean(value)).toBe(true)
  • toBeUndefined(): toBe(undefined) or not.toBeDefined()
  • toHaveLength(): expect(typeof value.length).toBe('number')
  • toThrowErrorMatchingSnapshot(): toThrow().toMatchSnapshot()

Behaviour testing

Behaviour matchers changes the tested value and accept an optional function which is also passed the new tested value. This is necessary to allows multiple tests on them.

New matchers

  • toFulfill([ fn ]): assert the passed value is a promise which fulfills and makes the fulfillment value the current tested value, following matchers are called asynchronously
  • toReject([ fn ]): assert the passed value is a promise which rejects and makes the rejection reason the current tested value, following matchers are called asynchronously

Updated matchers

  • toThrow([ fn ]): assert the passed value is a function which throws and makes the thrown value the current tested value

Examples

expect(fn).toThrow().toBeInstanceOf(MyError)
expect(fn).toThrow(error => {
  expect(error).toBeInstanceOf(MyError)
  expect(error.message).toMatch(/yuck/)
})

// when `toFulfill() or toReject() are used, expect returns a promise which must be awaited for
await expect(promise).toFulfill().toEqual([ 'foo', 'bar' ])
await expect(promise).toReject().toBeInstanceOf(MyError)

// behaviour matchers could be chained (also it usually does not make a lot of sense)
await expect(fn).toThrow().toFulfill().toBe(3)

Negation modifier

  • not: reverse the following (singular) matcher result
@julien-f
Copy link
Author

The meaning of resolve is a bit complicated, fulfill should be used instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment