Skip to content

Commit 2183087

Browse files
authored
Expose this.equals to custom matchers. (jestjs#3469)
1 parent 59c6d8a commit 2183087

File tree

4 files changed

+26
-6
lines changed

4 files changed

+26
-6
lines changed

docs/en/ExpectAPI.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ These helper functions can be found on `this` inside a custom matcher:
7373

7474
A boolean to let you know this matcher was called with the negated `.not` modifier allowing you to flip your assertion.
7575

76+
#### `this.equals(a, b)`
77+
78+
This is a deep-equality function that will return `true` if two objects have the same values (recursively).
79+
7680
#### `this.utils`
7781

7882
There are a number of helpful tools exposed on `this.utils` primarily consisting of the exports from [`jest-matcher-utils`](https://github.com/facebook/jest/tree/master/packages/jest-matcher-utils).

packages/jest-matchers/src/__tests__/extend-test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
'use strict';
1212

13+
const {equals} = require('../jasmine-utils');
1314
const jestExpect = require('../');
1415
const matcherUtils = require('jest-matcher-utils');
1516

@@ -60,3 +61,16 @@ it('is ok if there is no message specified', () => {
6061
jestExpect(true).toFailWithoutMessage(),
6162
).toThrowErrorMatchingSnapshot();
6263
});
64+
65+
it('exposes an equality function to custom matchers', () => {
66+
// jestExpect and expect share the same global state
67+
expect.assertions(3);
68+
jestExpect.extend({
69+
toBeOne() {
70+
expect(this.equals).toBe(equals);
71+
return {pass: !!this.equals(1, 1)};
72+
},
73+
});
74+
75+
expect(() => jestExpect().toBeOne()).not.toThrow();
76+
});

packages/jest-matchers/src/index.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import type {
1414
Expect,
1515
ExpectationObject,
1616
ExpectationResult,
17-
MatcherContext,
17+
MatcherState,
1818
MatchersObject,
1919
RawMatcherFn,
2020
ThrowingMatcherFn,
@@ -24,7 +24,7 @@ import type {
2424
const matchers = require('./matchers');
2525
const spyMatchers = require('./spyMatchers');
2626
const toThrowMatchers = require('./toThrowMatchers');
27-
27+
const {equals} = require('./jasmine-utils');
2828
const utils = require('jest-matcher-utils');
2929
const {
3030
any,
@@ -194,7 +194,7 @@ const makeThrowingMatcher = (
194194
): ThrowingMatcherFn => {
195195
return function throwingMatcher(...args) {
196196
let throws = true;
197-
const matcherContext: MatcherContext = Object.assign(
197+
const matcherContext: MatcherState = Object.assign(
198198
// When throws is disabled, the matcher will not throw errors during test
199199
// execution but instead add them to the global matcher state. If a
200200
// matcher throws, test execution is normally stopped immediately. The
@@ -203,6 +203,7 @@ const makeThrowingMatcher = (
203203
{dontThrow: () => (throws = false)},
204204
global[GLOBAL_STATE].state,
205205
{
206+
equals,
206207
isNot,
207208
utils,
208209
},
@@ -241,8 +242,8 @@ const makeThrowingMatcher = (
241242
};
242243
};
243244

244-
expect.extend = (matchersObj: MatchersObject): void => {
245-
Object.assign(global[GLOBAL_STATE].matchers, matchersObj);
245+
expect.extend = (matchers: MatchersObject): void => {
246+
Object.assign(global[GLOBAL_STATE].matchers, matchers);
246247
};
247248

248249
expect.anything = anything;

types/Matchers.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,18 @@ export type RawMatcherFn = (
2525

2626
export type ThrowingMatcherFn = (actual: any) => void;
2727
export type PromiseMatcherFn = (actual: any) => Promise<void>;
28-
export type MatcherContext = {isNot: boolean};
2928
export type MatcherState = {
3029
assertionCalls: number,
3130
currentTestName?: string,
31+
equals: (any, any) => boolean,
3232
expand?: boolean,
3333
expectedAssertionsNumber: ?number,
3434
isExpectingAssertions: ?boolean,
3535
isNot: boolean,
3636
snapshotState: SnapshotState,
3737
suppressedErrors: Array<Error>,
3838
testPath?: Path,
39+
utils: Object,
3940
};
4041

4142
export type AsymmetricMatcher = Object;

0 commit comments

Comments
 (0)