Skip to content

Commit b47d137

Browse files
committed
chore(expect): use matcher utils via context instead of direct imports
1 parent 7c48c4c commit b47d137

File tree

7 files changed

+917
-501
lines changed

7 files changed

+917
-501
lines changed

packages/expect/src/extractExpectedAssertionsErrors.ts

Lines changed: 44 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({
@@ -23,10 +25,28 @@ const resetAssertionsLocalState = () => {
2325
});
2426
};
2527

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

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

5782
result.push({
@@ -61,10 +86,12 @@ const extractExpectedAssertionsErrors: Expect['extractExpectedAssertionsErrors']
6186
});
6287
}
6388
if (isExpectingAssertions && assertionCalls === 0) {
64-
const expected = EXPECTED_COLOR('at least one assertion');
65-
const received = RECEIVED_COLOR('received none');
89+
const expected = matcherContext.utils.EXPECTED_COLOR(
90+
'at least one assertion',
91+
);
92+
const received = matcherContext.utils.RECEIVED_COLOR('received none');
6693

67-
isExpectingAssertionsError!.message = `${matcherHint(
94+
isExpectingAssertionsError!.message = `${matcherContext.utils.matcherHint(
6895
'.hasAssertions',
6996
'',
7097
'',

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 {isPromise} from 'jest-util';
@@ -150,33 +149,32 @@ export const expect: Expect = (actual: any, ...rest: Array<any>) => {
150149
return expectation;
151150
};
152151

153-
const getMessage = (message?: () => string) =>
152+
const getMessage = (receivedColor: ChalkFunction, message?: () => string) =>
154153
(message && message()) ||
155-
matcherUtils.RECEIVED_COLOR('No message was specified for this matcher.');
156-
157-
const makeResolveMatcher =
158-
(
159-
matcherName: string,
160-
matcher: RawMatcherFn,
161-
isNot: boolean,
162-
actual: Promise<any>,
163-
outerErr: JestAssertionError,
164-
): PromiseMatcherFn =>
165-
(...args) => {
154+
receivedColor('No message was specified for this matcher.');
155+
156+
const makeResolveMatcher = (
157+
matcherName: string,
158+
matcher: RawMatcherFn,
159+
isNot: boolean,
160+
actual: Promise<any>,
161+
outerErr: JestAssertionError,
162+
): PromiseMatcherFn =>
163+
function (...args) {
166164
const options = {
167165
isNot,
168166
promise: 'resolves',
169167
};
170168

171169
if (!isPromise(actual)) {
172170
throw new JestAssertionError(
173-
matcherUtils.matcherErrorMessage(
174-
matcherUtils.matcherHint(matcherName, undefined, '', options),
175-
`${matcherUtils.RECEIVED_COLOR('received')} value must be a promise`,
176-
matcherUtils.printWithType(
171+
this.utils.matcherErrorMessage(
172+
this.utils.matcherHint(matcherName, undefined, '', options),
173+
`${this.utils.RECEIVED_COLOR('received')} value must be a promise`,
174+
this.utils.printWithType(
177175
'Received',
178176
actual,
179-
matcherUtils.printReceived,
177+
this.utils.printReceived,
180178
),
181179
),
182180
);
@@ -187,33 +185,27 @@ const makeResolveMatcher =
187185
return actual.then(
188186
result =>
189187
makeThrowingMatcher(matcher, isNot, 'resolves', result, innerErr).apply(
190-
null,
188+
this,
191189
args,
192190
),
193191
reason => {
194192
outerErr.message =
195-
`${matcherUtils.matcherHint(
196-
matcherName,
197-
undefined,
198-
'',
199-
options,
200-
)}\n\n` +
193+
`${this.utils.matcherHint(matcherName, undefined, '', options)}\n\n` +
201194
'Received promise rejected instead of resolved\n' +
202-
`Rejected to value: ${matcherUtils.printReceived(reason)}`;
195+
`Rejected to value: ${this.utils.printReceived(reason)}`;
203196
return Promise.reject(outerErr);
204197
},
205198
);
206199
};
207200

208-
const makeRejectMatcher =
209-
(
210-
matcherName: string,
211-
matcher: RawMatcherFn,
212-
isNot: boolean,
213-
actual: Promise<any> | (() => Promise<any>),
214-
outerErr: JestAssertionError,
215-
): PromiseMatcherFn =>
216-
(...args) => {
201+
const makeRejectMatcher = (
202+
matcherName: string,
203+
matcher: RawMatcherFn,
204+
isNot: boolean,
205+
actual: Promise<any> | (() => Promise<any>),
206+
outerErr: JestAssertionError,
207+
): PromiseMatcherFn =>
208+
function (...args) {
217209
const options = {
218210
isNot,
219211
promise: 'rejects',
@@ -224,15 +216,15 @@ const makeRejectMatcher =
224216

225217
if (!isPromise(actualWrapper)) {
226218
throw new JestAssertionError(
227-
matcherUtils.matcherErrorMessage(
228-
matcherUtils.matcherHint(matcherName, undefined, '', options),
229-
`${matcherUtils.RECEIVED_COLOR(
219+
this.utils.matcherErrorMessage(
220+
this.utils.matcherHint(matcherName, undefined, '', options),
221+
`${this.utils.RECEIVED_COLOR(
230222
'received',
231223
)} value must be a promise or a function returning a promise`,
232-
matcherUtils.printWithType(
224+
this.utils.printWithType(
233225
'Received',
234226
actual,
235-
matcherUtils.printReceived,
227+
this.utils.printReceived,
236228
),
237229
),
238230
);
@@ -243,24 +235,25 @@ const makeRejectMatcher =
243235
return actualWrapper.then(
244236
result => {
245237
outerErr.message =
246-
`${matcherUtils.matcherHint(
247-
matcherName,
248-
undefined,
249-
'',
250-
options,
251-
)}\n\n` +
238+
`${this.utils.matcherHint(matcherName, undefined, '', options)}\n\n` +
252239
'Received promise resolved instead of rejected\n' +
253-
`Resolved to value: ${matcherUtils.printReceived(result)}`;
240+
`Resolved to value: ${this.utils.printReceived(result)}`;
254241
return Promise.reject(outerErr);
255242
},
256243
reason =>
257244
makeThrowingMatcher(matcher, isNot, 'rejects', reason, innerErr).apply(
258-
null,
245+
this,
259246
args,
260247
),
261248
);
262249
};
263250

251+
const utils: MatcherUtils['utils'] = Object.freeze({
252+
...matcherUtils,
253+
iterableEquality,
254+
subsetEquality,
255+
});
256+
264257
const makeThrowingMatcher = (
265258
matcher: RawMatcherFn,
266259
isNot: boolean,
@@ -270,11 +263,6 @@ const makeThrowingMatcher = (
270263
): ThrowingMatcherFn =>
271264
function throwingMatcher(...args): any {
272265
let throws = true;
273-
const utils: MatcherUtils['utils'] = {
274-
...matcherUtils,
275-
iterableEquality,
276-
subsetEquality,
277-
};
278266

279267
const matcherUtilsThing: MatcherUtils = {
280268
// When throws is disabled, the matcher will not throw errors during test
@@ -299,7 +287,7 @@ const makeThrowingMatcher = (
299287
result: SyncExpectationResult,
300288
asyncError?: JestAssertionError,
301289
) => {
302-
_validateResult(result);
290+
_validateResult(this.utils.stringify, result);
303291

304292
getState().assertionCalls++;
305293

@@ -400,7 +388,10 @@ expect.objectContaining = objectContaining;
400388
expect.stringContaining = stringContaining;
401389
expect.stringMatching = stringMatching;
402390

403-
const _validateResult = (result: any) => {
391+
const _validateResult = (
392+
stringify: typeof matcherUtils['stringify'],
393+
result: any,
394+
) => {
404395
if (
405396
typeof result !== 'object' ||
406397
typeof result.pass !== 'boolean' ||
@@ -413,7 +404,7 @@ const _validateResult = (result: any) => {
413404
'Matcher functions should ' +
414405
'return an object in the following format:\n' +
415406
' {message?: string | function, pass: boolean}\n' +
416-
`'${matcherUtils.stringify(result)}' was returned`,
407+
`'${stringify(result)}' was returned`,
417408
);
418409
}
419410
};

0 commit comments

Comments
 (0)