Skip to content

Commit 95c4c8f

Browse files
committed
chore(expect): use matcher utils via context instead of direct imports
1 parent a5f29b4 commit 95c4c8f

File tree

7 files changed

+802
-499
lines changed

7 files changed

+802
-499
lines changed

packages/expect/src/extractExpectedAssertionsErrors.ts

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
*
77
*/
88

9-
import {
10-
EXPECTED_COLOR,
11-
RECEIVED_COLOR,
12-
matcherHint,
13-
pluralize,
14-
} from 'jest-matcher-utils';
9+
import {equals, iterableEquality, subsetEquality} from '@jest/expect-utils';
10+
import * as matcherUtils from 'jest-matcher-utils';
1511
import {getState, setState} from './jestMatchersObject';
16-
import type {Expect, ExpectedAssertionsErrors} from './types';
12+
import type {
13+
Expect,
14+
ExpectedAssertionsErrors,
15+
MatcherContext,
16+
MatcherState,
17+
MatcherUtils,
18+
} from './types';
1719

1820
const resetAssertionsLocalState = () => {
1921
setState({
@@ -24,10 +26,28 @@ const resetAssertionsLocalState = () => {
2426
});
2527
};
2628

29+
const utils: MatcherUtils['utils'] = {
30+
...matcherUtils,
31+
iterableEquality,
32+
subsetEquality,
33+
};
34+
35+
const matcherUtilsThing: MatcherUtils = {
36+
dontThrow: () => {
37+
// nothing
38+
},
39+
equals,
40+
utils,
41+
};
42+
2743
// Create and format all errors related to the mismatched number of `expect`
2844
// calls and reset the matcher's state.
2945
const extractExpectedAssertionsErrors: Expect['extractExpectedAssertionsErrors'] =
3046
() => {
47+
const matcherContext: MatcherContext = {
48+
...getState<MatcherState>(),
49+
...matcherUtilsThing,
50+
};
3151
const result: ExpectedAssertionsErrors = [];
3252
const {
3353
assertionCalls,
@@ -43,16 +63,19 @@ const extractExpectedAssertionsErrors: Expect['extractExpectedAssertionsErrors']
4363
typeof expectedAssertionsNumber === 'number' &&
4464
assertionCalls !== expectedAssertionsNumber
4565
) {
46-
const numOfAssertionsExpected = EXPECTED_COLOR(
47-
pluralize('assertion', expectedAssertionsNumber),
66+
const numOfAssertionsExpected = matcherContext.utils.EXPECTED_COLOR(
67+
matcherContext.utils.pluralize('assertion', expectedAssertionsNumber),
4868
);
4969

5070
expectedAssertionsNumberError!.message =
51-
`${matcherHint('.assertions', '', expectedAssertionsNumber.toString(), {
52-
isDirectExpectCall: true,
53-
})}\n\n` +
54-
`Expected ${numOfAssertionsExpected} to be called but received ${RECEIVED_COLOR(
55-
pluralize('assertion call', assertionCalls || 0),
71+
`${matcherContext.utils.matcherHint(
72+
'.assertions',
73+
'',
74+
expectedAssertionsNumber.toString(),
75+
{isDirectExpectCall: true},
76+
)}\n\n` +
77+
`Expected ${numOfAssertionsExpected} to be called but received ${matcherContext.utils.RECEIVED_COLOR(
78+
matcherContext.utils.pluralize('assertion call', assertionCalls || 0),
5679
)}.`;
5780

5881
result.push({
@@ -62,10 +85,12 @@ const extractExpectedAssertionsErrors: Expect['extractExpectedAssertionsErrors']
6285
});
6386
}
6487
if (isExpectingAssertions && assertionCalls === 0) {
65-
const expected = EXPECTED_COLOR('at least one assertion');
66-
const received = RECEIVED_COLOR('received none');
88+
const expected = matcherContext.utils.EXPECTED_COLOR(
89+
'at least one assertion',
90+
);
91+
const received = matcherContext.utils.RECEIVED_COLOR('received none');
6792

68-
isExpectingAssertionsError!.message = `${matcherHint(
93+
isExpectingAssertionsError!.message = `${matcherContext.utils.matcherHint(
6994
'.hasAssertions',
7095
'',
7196
'',

packages/expect/src/index.ts

Lines changed: 48 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
*
77
*/
88

9-
/* eslint-disable local/prefer-spread-eventually */
10-
9+
import type {ChalkFunction} from 'chalk';
1110
import {equals, iterableEquality, subsetEquality} from '@jest/expect-utils';
1211
import * as matcherUtils from 'jest-matcher-utils';
1312
import {ErrorWithStack, isPromise} from 'jest-util';
@@ -155,33 +154,32 @@ export const expect: Expect = (actual: any, ...rest: Array<any>) => {
155154
return expectation;
156155
};
157156

158-
const getMessage = (message?: () => string) =>
157+
const getMessage = (receivedColor: ChalkFunction, message?: () => string) =>
159158
(message && message()) ||
160-
matcherUtils.RECEIVED_COLOR('No message was specified for this matcher.');
161-
162-
const makeResolveMatcher =
163-
(
164-
matcherName: string,
165-
matcher: RawMatcherFn,
166-
isNot: boolean,
167-
actual: Promise<any>,
168-
outerErr: JestAssertionError,
169-
): PromiseMatcherFn =>
170-
(...args) => {
159+
receivedColor('No message was specified for this matcher.');
160+
161+
const makeResolveMatcher = (
162+
matcherName: string,
163+
matcher: RawMatcherFn,
164+
isNot: boolean,
165+
actual: Promise<any>,
166+
outerErr: JestAssertionError,
167+
): PromiseMatcherFn =>
168+
function (...args) {
171169
const options = {
172170
isNot,
173171
promise: 'resolves',
174172
};
175173

176174
if (!isPromise(actual)) {
177175
throw new JestAssertionError(
178-
matcherUtils.matcherErrorMessage(
179-
matcherUtils.matcherHint(matcherName, undefined, '', options),
180-
`${matcherUtils.RECEIVED_COLOR('received')} value must be a promise`,
181-
matcherUtils.printWithType(
176+
this.utils.matcherErrorMessage(
177+
this.utils.matcherHint(matcherName, undefined, '', options),
178+
`${this.utils.RECEIVED_COLOR('received')} value must be a promise`,
179+
this.utils.printWithType(
182180
'Received',
183181
actual,
184-
matcherUtils.printReceived,
182+
this.utils.printReceived,
185183
),
186184
),
187185
);
@@ -192,33 +190,27 @@ const makeResolveMatcher =
192190
return actual.then(
193191
result =>
194192
makeThrowingMatcher(matcher, isNot, 'resolves', result, innerErr).apply(
195-
null,
193+
this,
196194
args,
197195
),
198196
error => {
199197
outerErr.message =
200-
`${matcherUtils.matcherHint(
201-
matcherName,
202-
undefined,
203-
'',
204-
options,
205-
)}\n\n` +
198+
`${this.utils.matcherHint(matcherName, undefined, '', options)}\n\n` +
206199
'Received promise rejected instead of resolved\n' +
207-
`Rejected to value: ${matcherUtils.printReceived(error)}`;
200+
`Rejected to value: ${this.utils.printReceived(error)}`;
208201
throw outerErr;
209202
},
210203
);
211204
};
212205

213-
const makeRejectMatcher =
214-
(
215-
matcherName: string,
216-
matcher: RawMatcherFn,
217-
isNot: boolean,
218-
actual: Promise<any> | (() => Promise<any>),
219-
outerErr: JestAssertionError,
220-
): PromiseMatcherFn =>
221-
(...args) => {
206+
const makeRejectMatcher = (
207+
matcherName: string,
208+
matcher: RawMatcherFn,
209+
isNot: boolean,
210+
actual: Promise<any> | (() => Promise<any>),
211+
outerErr: JestAssertionError,
212+
): PromiseMatcherFn =>
213+
function (...args) {
222214
const options = {
223215
isNot,
224216
promise: 'rejects',
@@ -229,15 +221,15 @@ const makeRejectMatcher =
229221

230222
if (!isPromise(actualWrapper)) {
231223
throw new JestAssertionError(
232-
matcherUtils.matcherErrorMessage(
233-
matcherUtils.matcherHint(matcherName, undefined, '', options),
234-
`${matcherUtils.RECEIVED_COLOR(
224+
this.utils.matcherErrorMessage(
225+
this.utils.matcherHint(matcherName, undefined, '', options),
226+
`${this.utils.RECEIVED_COLOR(
235227
'received',
236228
)} value must be a promise or a function returning a promise`,
237-
matcherUtils.printWithType(
229+
this.utils.printWithType(
238230
'Received',
239231
actual,
240-
matcherUtils.printReceived,
232+
this.utils.printReceived,
241233
),
242234
),
243235
);
@@ -248,24 +240,25 @@ const makeRejectMatcher =
248240
return actualWrapper.then(
249241
result => {
250242
outerErr.message =
251-
`${matcherUtils.matcherHint(
252-
matcherName,
253-
undefined,
254-
'',
255-
options,
256-
)}\n\n` +
243+
`${this.utils.matcherHint(matcherName, undefined, '', options)}\n\n` +
257244
'Received promise resolved instead of rejected\n' +
258-
`Resolved to value: ${matcherUtils.printReceived(result)}`;
245+
`Resolved to value: ${this.utils.printReceived(result)}`;
259246
throw outerErr;
260247
},
261248
error =>
262249
makeThrowingMatcher(matcher, isNot, 'rejects', error, innerErr).apply(
263-
null,
250+
this,
264251
args,
265252
),
266253
);
267254
};
268255

256+
const utils: MatcherUtils['utils'] = Object.freeze({
257+
...matcherUtils,
258+
iterableEquality,
259+
subsetEquality,
260+
});
261+
269262
const makeThrowingMatcher = (
270263
matcher: RawMatcherFn,
271264
isNot: boolean,
@@ -275,11 +268,6 @@ const makeThrowingMatcher = (
275268
): ThrowingMatcherFn =>
276269
function throwingMatcher(...args): any {
277270
let throws = true;
278-
const utils: MatcherUtils['utils'] = {
279-
...matcherUtils,
280-
iterableEquality,
281-
subsetEquality,
282-
};
283271

284272
const matcherUtilsThing: MatcherUtils = {
285273
customTesters: getCustomEqualityTesters(),
@@ -305,7 +293,7 @@ const makeThrowingMatcher = (
305293
result: SyncExpectationResult,
306294
asyncError?: JestAssertionError,
307295
) => {
308-
_validateResult(result);
296+
_validateResult(this.utils.stringify, result);
309297

310298
getState().assertionCalls++;
311299

@@ -413,7 +401,10 @@ expect.objectContaining = objectContaining;
413401
expect.stringContaining = stringContaining;
414402
expect.stringMatching = stringMatching;
415403

416-
const _validateResult = (result: any) => {
404+
const _validateResult = (
405+
stringify: (typeof matcherUtils)['stringify'],
406+
result: any,
407+
) => {
417408
if (
418409
typeof result !== 'object' ||
419410
typeof result.pass !== 'boolean' ||
@@ -426,7 +417,7 @@ const _validateResult = (result: any) => {
426417
'Matcher functions should ' +
427418
'return an object in the following format:\n' +
428419
' {message?: string | function, pass: boolean}\n' +
429-
`'${matcherUtils.stringify(result)}' was returned`,
420+
`'${stringify(result)}' was returned`,
430421
);
431422
}
432423
};

0 commit comments

Comments
 (0)