@vitest/expect 2.0.0-beta.9 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +684 -456
- package/package.json +5 -5
package/dist/index.js
CHANGED
@@ -8,7 +8,9 @@ import { use, util } from 'chai';
|
|
8
8
|
const MATCHERS_OBJECT = Symbol.for("matchers-object");
|
9
9
|
const JEST_MATCHERS_OBJECT = Symbol.for("$$jest-matchers-object");
|
10
10
|
const GLOBAL_EXPECT = Symbol.for("expect-global");
|
11
|
-
const ASYMMETRIC_MATCHERS_OBJECT = Symbol.for(
|
11
|
+
const ASYMMETRIC_MATCHERS_OBJECT = Symbol.for(
|
12
|
+
"asymmetric-matchers-object"
|
13
|
+
);
|
12
14
|
|
13
15
|
if (!Object.prototype.hasOwnProperty.call(globalThis, MATCHERS_OBJECT)) {
|
14
16
|
const globalState = /* @__PURE__ */ new WeakMap();
|
@@ -83,14 +85,17 @@ function getMatcherUtils() {
|
|
83
85
|
dimString += "()";
|
84
86
|
} else {
|
85
87
|
hint += DIM_COLOR(`${dimString}(`) + expectedColor(expected);
|
86
|
-
if (secondArgument)
|
88
|
+
if (secondArgument) {
|
87
89
|
hint += DIM_COLOR(", ") + secondArgumentColor(secondArgument);
|
90
|
+
}
|
88
91
|
dimString = ")";
|
89
92
|
}
|
90
|
-
if (comment !== "")
|
93
|
+
if (comment !== "") {
|
91
94
|
dimString += ` // ${comment}`;
|
92
|
-
|
95
|
+
}
|
96
|
+
if (dimString !== "") {
|
93
97
|
hint += DIM_COLOR(dimString);
|
98
|
+
}
|
94
99
|
return hint;
|
95
100
|
}
|
96
101
|
const SPACE_SYMBOL = "\xB7";
|
@@ -133,51 +138,71 @@ function isAsymmetric(obj) {
|
|
133
138
|
return !!obj && typeof obj === "object" && "asymmetricMatch" in obj && isA("Function", obj.asymmetricMatch);
|
134
139
|
}
|
135
140
|
function hasAsymmetric(obj, seen = /* @__PURE__ */ new Set()) {
|
136
|
-
if (seen.has(obj))
|
141
|
+
if (seen.has(obj)) {
|
137
142
|
return false;
|
143
|
+
}
|
138
144
|
seen.add(obj);
|
139
|
-
if (isAsymmetric(obj))
|
145
|
+
if (isAsymmetric(obj)) {
|
140
146
|
return true;
|
141
|
-
|
147
|
+
}
|
148
|
+
if (Array.isArray(obj)) {
|
142
149
|
return obj.some((i) => hasAsymmetric(i, seen));
|
143
|
-
|
150
|
+
}
|
151
|
+
if (obj instanceof Set) {
|
144
152
|
return Array.from(obj).some((i) => hasAsymmetric(i, seen));
|
145
|
-
|
153
|
+
}
|
154
|
+
if (isObject(obj)) {
|
146
155
|
return Object.values(obj).some((v) => hasAsymmetric(v, seen));
|
156
|
+
}
|
147
157
|
return false;
|
148
158
|
}
|
149
159
|
function asymmetricMatch(a, b) {
|
150
160
|
const asymmetricA = isAsymmetric(a);
|
151
161
|
const asymmetricB = isAsymmetric(b);
|
152
|
-
if (asymmetricA && asymmetricB)
|
162
|
+
if (asymmetricA && asymmetricB) {
|
153
163
|
return void 0;
|
154
|
-
|
164
|
+
}
|
165
|
+
if (asymmetricA) {
|
155
166
|
return a.asymmetricMatch(b);
|
156
|
-
|
167
|
+
}
|
168
|
+
if (asymmetricB) {
|
157
169
|
return b.asymmetricMatch(a);
|
170
|
+
}
|
158
171
|
}
|
159
172
|
function eq(a, b, aStack, bStack, customTesters, hasKey2) {
|
160
173
|
let result = true;
|
161
174
|
const asymmetricResult = asymmetricMatch(a, b);
|
162
|
-
if (asymmetricResult !== void 0)
|
175
|
+
if (asymmetricResult !== void 0) {
|
163
176
|
return asymmetricResult;
|
177
|
+
}
|
164
178
|
const testerContext = { equals };
|
165
179
|
for (let i = 0; i < customTesters.length; i++) {
|
166
|
-
const customTesterResult = customTesters[i].call(
|
167
|
-
|
180
|
+
const customTesterResult = customTesters[i].call(
|
181
|
+
testerContext,
|
182
|
+
a,
|
183
|
+
b,
|
184
|
+
customTesters
|
185
|
+
);
|
186
|
+
if (customTesterResult !== void 0) {
|
168
187
|
return customTesterResult;
|
188
|
+
}
|
169
189
|
}
|
170
|
-
if (a instanceof Error && b instanceof Error)
|
190
|
+
if (a instanceof Error && b instanceof Error) {
|
171
191
|
return a.message === b.message;
|
172
|
-
|
192
|
+
}
|
193
|
+
if (typeof URL === "function" && a instanceof URL && b instanceof URL) {
|
173
194
|
return a.href === b.href;
|
174
|
-
|
195
|
+
}
|
196
|
+
if (Object.is(a, b)) {
|
175
197
|
return true;
|
176
|
-
|
198
|
+
}
|
199
|
+
if (a === null || b === null) {
|
177
200
|
return a === b;
|
201
|
+
}
|
178
202
|
const className = Object.prototype.toString.call(a);
|
179
|
-
if (className !== Object.prototype.toString.call(b))
|
203
|
+
if (className !== Object.prototype.toString.call(b)) {
|
180
204
|
return false;
|
205
|
+
}
|
181
206
|
switch (className) {
|
182
207
|
case "[object Boolean]":
|
183
208
|
case "[object String]":
|
@@ -197,31 +222,37 @@ function eq(a, b, aStack, bStack, customTesters, hasKey2) {
|
|
197
222
|
case "[object RegExp]":
|
198
223
|
return a.source === b.source && a.flags === b.flags;
|
199
224
|
}
|
200
|
-
if (typeof a !== "object" || typeof b !== "object")
|
225
|
+
if (typeof a !== "object" || typeof b !== "object") {
|
201
226
|
return false;
|
202
|
-
|
227
|
+
}
|
228
|
+
if (isDomNode(a) && isDomNode(b)) {
|
203
229
|
return a.isEqualNode(b);
|
230
|
+
}
|
204
231
|
let length = aStack.length;
|
205
232
|
while (length--) {
|
206
|
-
if (aStack[length] === a)
|
233
|
+
if (aStack[length] === a) {
|
207
234
|
return bStack[length] === b;
|
208
|
-
else if (bStack[length] === b)
|
235
|
+
} else if (bStack[length] === b) {
|
209
236
|
return false;
|
237
|
+
}
|
210
238
|
}
|
211
239
|
aStack.push(a);
|
212
240
|
bStack.push(b);
|
213
|
-
if (className === "[object Array]" && a.length !== b.length)
|
241
|
+
if (className === "[object Array]" && a.length !== b.length) {
|
214
242
|
return false;
|
243
|
+
}
|
215
244
|
const aKeys = keys(a, hasKey2);
|
216
245
|
let key;
|
217
246
|
let size = aKeys.length;
|
218
|
-
if (keys(b, hasKey2).length !== size)
|
247
|
+
if (keys(b, hasKey2).length !== size) {
|
219
248
|
return false;
|
249
|
+
}
|
220
250
|
while (size--) {
|
221
251
|
key = aKeys[size];
|
222
252
|
result = hasKey2(b, key) && eq(a[key], b[key], aStack, bStack, customTesters, hasKey2);
|
223
|
-
if (!result)
|
253
|
+
if (!result) {
|
224
254
|
return false;
|
255
|
+
}
|
225
256
|
}
|
226
257
|
aStack.pop();
|
227
258
|
bStack.pop();
|
@@ -230,8 +261,9 @@ function eq(a, b, aStack, bStack, customTesters, hasKey2) {
|
|
230
261
|
function keys(obj, hasKey2) {
|
231
262
|
const keys2 = [];
|
232
263
|
for (const key in obj) {
|
233
|
-
if (hasKey2(obj, key))
|
264
|
+
if (hasKey2(obj, key)) {
|
234
265
|
keys2.push(key);
|
266
|
+
}
|
235
267
|
}
|
236
268
|
return keys2.concat(
|
237
269
|
Object.getOwnPropertySymbols(obj).filter(
|
@@ -252,23 +284,28 @@ function isDomNode(obj) {
|
|
252
284
|
return obj !== null && typeof obj === "object" && "nodeType" in obj && typeof obj.nodeType === "number" && "nodeName" in obj && typeof obj.nodeName === "string" && "isEqualNode" in obj && typeof obj.isEqualNode === "function";
|
253
285
|
}
|
254
286
|
function fnNameFor(func) {
|
255
|
-
if (func.name)
|
287
|
+
if (func.name) {
|
256
288
|
return func.name;
|
289
|
+
}
|
257
290
|
const matches = functionToString.call(func).match(/^(?:async)?\s*function\s*(?:\*\s*)?([\w$]+)\s*\(/);
|
258
291
|
return matches ? matches[1] : "<anonymous>";
|
259
292
|
}
|
260
293
|
function getPrototype(obj) {
|
261
|
-
if (Object.getPrototypeOf)
|
294
|
+
if (Object.getPrototypeOf) {
|
262
295
|
return Object.getPrototypeOf(obj);
|
263
|
-
|
296
|
+
}
|
297
|
+
if (obj.constructor.prototype === obj) {
|
264
298
|
return null;
|
299
|
+
}
|
265
300
|
return obj.constructor.prototype;
|
266
301
|
}
|
267
302
|
function hasProperty(obj, property) {
|
268
|
-
if (!obj)
|
303
|
+
if (!obj) {
|
269
304
|
return false;
|
270
|
-
|
305
|
+
}
|
306
|
+
if (Object.prototype.hasOwnProperty.call(obj, property)) {
|
271
307
|
return true;
|
308
|
+
}
|
272
309
|
return hasProperty(getPrototype(obj), property);
|
273
310
|
}
|
274
311
|
const IS_KEYED_SENTINEL = "@@__IMMUTABLE_KEYED__@@";
|
@@ -306,14 +343,17 @@ function hasIterator(object) {
|
|
306
343
|
return !!(object != null && object[IteratorSymbol]);
|
307
344
|
}
|
308
345
|
function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
309
|
-
if (typeof a !== "object" || typeof b !== "object" || Array.isArray(a) || Array.isArray(b) || !hasIterator(a) || !hasIterator(b))
|
346
|
+
if (typeof a !== "object" || typeof b !== "object" || Array.isArray(a) || Array.isArray(b) || !hasIterator(a) || !hasIterator(b)) {
|
310
347
|
return void 0;
|
311
|
-
|
348
|
+
}
|
349
|
+
if (a.constructor !== b.constructor) {
|
312
350
|
return false;
|
351
|
+
}
|
313
352
|
let length = aStack.length;
|
314
353
|
while (length--) {
|
315
|
-
if (aStack[length] === a)
|
354
|
+
if (aStack[length] === a) {
|
316
355
|
return bStack[length] === b;
|
356
|
+
}
|
317
357
|
}
|
318
358
|
aStack.push(a);
|
319
359
|
bStack.push(b);
|
@@ -322,13 +362,7 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
322
362
|
iterableEqualityWithStack
|
323
363
|
];
|
324
364
|
function iterableEqualityWithStack(a2, b2) {
|
325
|
-
return iterableEquality(
|
326
|
-
a2,
|
327
|
-
b2,
|
328
|
-
[...customTesters],
|
329
|
-
[...aStack],
|
330
|
-
[...bStack]
|
331
|
-
);
|
365
|
+
return iterableEquality(a2, b2, [...customTesters], [...aStack], [...bStack]);
|
332
366
|
}
|
333
367
|
if (a.size !== void 0) {
|
334
368
|
if (a.size !== b.size) {
|
@@ -340,8 +374,9 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
340
374
|
let has = false;
|
341
375
|
for (const bValue of b) {
|
342
376
|
const isEqual = equals(aValue, bValue, filteredCustomTesters);
|
343
|
-
if (isEqual === true)
|
377
|
+
if (isEqual === true) {
|
344
378
|
has = true;
|
379
|
+
}
|
345
380
|
}
|
346
381
|
if (has === false) {
|
347
382
|
allFound = false;
|
@@ -358,12 +393,22 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
358
393
|
if (!b.has(aEntry[0]) || !equals(aEntry[1], b.get(aEntry[0]), filteredCustomTesters)) {
|
359
394
|
let has = false;
|
360
395
|
for (const bEntry of b) {
|
361
|
-
const matchedKey = equals(
|
396
|
+
const matchedKey = equals(
|
397
|
+
aEntry[0],
|
398
|
+
bEntry[0],
|
399
|
+
filteredCustomTesters
|
400
|
+
);
|
362
401
|
let matchedValue = false;
|
363
|
-
if (matchedKey === true)
|
364
|
-
matchedValue = equals(
|
365
|
-
|
402
|
+
if (matchedKey === true) {
|
403
|
+
matchedValue = equals(
|
404
|
+
aEntry[1],
|
405
|
+
bEntry[1],
|
406
|
+
filteredCustomTesters
|
407
|
+
);
|
408
|
+
}
|
409
|
+
if (matchedValue === true) {
|
366
410
|
has = true;
|
411
|
+
}
|
367
412
|
}
|
368
413
|
if (has === false) {
|
369
414
|
allFound = false;
|
@@ -379,16 +424,19 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
379
424
|
const bIterator = b[IteratorSymbol]();
|
380
425
|
for (const aValue of a) {
|
381
426
|
const nextB = bIterator.next();
|
382
|
-
if (nextB.done || !equals(aValue, nextB.value, filteredCustomTesters))
|
427
|
+
if (nextB.done || !equals(aValue, nextB.value, filteredCustomTesters)) {
|
383
428
|
return false;
|
429
|
+
}
|
384
430
|
}
|
385
|
-
if (!bIterator.next().done)
|
431
|
+
if (!bIterator.next().done) {
|
386
432
|
return false;
|
433
|
+
}
|
387
434
|
if (!isImmutableList(a) && !isImmutableOrderedKeyed(a) && !isImmutableOrderedSet(a) && !isImmutableRecord(a)) {
|
388
435
|
const aEntries = Object.entries(a);
|
389
436
|
const bEntries = Object.entries(b);
|
390
|
-
if (!equals(aEntries, bEntries))
|
437
|
+
if (!equals(aEntries, bEntries)) {
|
391
438
|
return false;
|
439
|
+
}
|
392
440
|
}
|
393
441
|
aStack.pop();
|
394
442
|
bStack.pop();
|
@@ -396,22 +444,27 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
396
444
|
}
|
397
445
|
function hasPropertyInObject(object, key) {
|
398
446
|
const shouldTerminate = !object || typeof object !== "object" || object === Object.prototype;
|
399
|
-
if (shouldTerminate)
|
447
|
+
if (shouldTerminate) {
|
400
448
|
return false;
|
449
|
+
}
|
401
450
|
return Object.prototype.hasOwnProperty.call(object, key) || hasPropertyInObject(Object.getPrototypeOf(object), key);
|
402
451
|
}
|
403
452
|
function isObjectWithKeys(a) {
|
404
453
|
return isObject(a) && !(a instanceof Error) && !Array.isArray(a) && !(a instanceof Date);
|
405
454
|
}
|
406
455
|
function subsetEquality(object, subset, customTesters = []) {
|
407
|
-
const filteredCustomTesters = customTesters.filter(
|
456
|
+
const filteredCustomTesters = customTesters.filter(
|
457
|
+
(t) => t !== subsetEquality
|
458
|
+
);
|
408
459
|
const subsetEqualityWithContext = (seenReferences = /* @__PURE__ */ new WeakMap()) => (object2, subset2) => {
|
409
|
-
if (!isObjectWithKeys(subset2))
|
460
|
+
if (!isObjectWithKeys(subset2)) {
|
410
461
|
return void 0;
|
462
|
+
}
|
411
463
|
return Object.keys(subset2).every((key) => {
|
412
464
|
if (subset2[key] != null && typeof subset2[key] === "object") {
|
413
|
-
if (seenReferences.has(subset2[key]))
|
465
|
+
if (seenReferences.has(subset2[key])) {
|
414
466
|
return equals(object2[key], subset2[key], filteredCustomTesters);
|
467
|
+
}
|
415
468
|
seenReferences.set(subset2[key], true);
|
416
469
|
}
|
417
470
|
const result = object2 != null && hasPropertyInObject(object2, key) && equals(object2[key], subset2[key], [
|
@@ -425,16 +478,18 @@ function subsetEquality(object, subset, customTesters = []) {
|
|
425
478
|
return subsetEqualityWithContext()(object, subset);
|
426
479
|
}
|
427
480
|
function typeEquality(a, b) {
|
428
|
-
if (a == null || b == null || a.constructor === b.constructor)
|
481
|
+
if (a == null || b == null || a.constructor === b.constructor) {
|
429
482
|
return void 0;
|
483
|
+
}
|
430
484
|
return false;
|
431
485
|
}
|
432
486
|
function arrayBufferEquality(a, b) {
|
433
487
|
let dataViewA = a;
|
434
488
|
let dataViewB = b;
|
435
489
|
if (!(a instanceof DataView && b instanceof DataView)) {
|
436
|
-
if (!(a instanceof ArrayBuffer) || !(b instanceof ArrayBuffer))
|
490
|
+
if (!(a instanceof ArrayBuffer) || !(b instanceof ArrayBuffer)) {
|
437
491
|
return void 0;
|
492
|
+
}
|
438
493
|
try {
|
439
494
|
dataViewA = new DataView(a);
|
440
495
|
dataViewB = new DataView(b);
|
@@ -442,25 +497,30 @@ function arrayBufferEquality(a, b) {
|
|
442
497
|
return void 0;
|
443
498
|
}
|
444
499
|
}
|
445
|
-
if (dataViewA.byteLength !== dataViewB.byteLength)
|
500
|
+
if (dataViewA.byteLength !== dataViewB.byteLength) {
|
446
501
|
return false;
|
502
|
+
}
|
447
503
|
for (let i = 0; i < dataViewA.byteLength; i++) {
|
448
|
-
if (dataViewA.getUint8(i) !== dataViewB.getUint8(i))
|
504
|
+
if (dataViewA.getUint8(i) !== dataViewB.getUint8(i)) {
|
449
505
|
return false;
|
506
|
+
}
|
450
507
|
}
|
451
508
|
return true;
|
452
509
|
}
|
453
510
|
function sparseArrayEquality(a, b, customTesters = []) {
|
454
|
-
if (!Array.isArray(a) || !Array.isArray(b))
|
511
|
+
if (!Array.isArray(a) || !Array.isArray(b)) {
|
455
512
|
return void 0;
|
513
|
+
}
|
456
514
|
const aKeys = Object.keys(a);
|
457
515
|
const bKeys = Object.keys(b);
|
458
|
-
const filteredCustomTesters = customTesters.filter(
|
516
|
+
const filteredCustomTesters = customTesters.filter(
|
517
|
+
(t) => t !== sparseArrayEquality
|
518
|
+
);
|
459
519
|
return equals(a, b, filteredCustomTesters, true) && equals(aKeys, bKeys);
|
460
520
|
}
|
461
521
|
function generateToBeMessage(deepEqualityName, expected = "#{this}", actual = "#{exp}") {
|
462
522
|
const toBeMessage = `expected ${expected} to be ${actual} // Object.is equality`;
|
463
|
-
if (["toStrictEqual", "toEqual"].includes(deepEqualityName))
|
523
|
+
if (["toStrictEqual", "toEqual"].includes(deepEqualityName)) {
|
464
524
|
return `${toBeMessage}
|
465
525
|
|
466
526
|
If it should pass with deep equality, replace "toBe" with "${deepEqualityName}"
|
@@ -468,6 +528,7 @@ If it should pass with deep equality, replace "toBe" with "${deepEqualityName}"
|
|
468
528
|
Expected: ${expected}
|
469
529
|
Received: serializes to the same string
|
470
530
|
`;
|
531
|
+
}
|
471
532
|
return toBeMessage;
|
472
533
|
}
|
473
534
|
function pluralize(word, count) {
|
@@ -507,18 +568,26 @@ function getObjectSubset(object, subset, customTesters = []) {
|
|
507
568
|
seenReferences.set(object2, trimmed);
|
508
569
|
for (const key of getObjectKeys(object2)) {
|
509
570
|
if (hasPropertyInObject(subset2, key)) {
|
510
|
-
trimmed[key] = seenReferences.has(object2[key]) ? seenReferences.get(object2[key]) : getObjectSubsetWithContext(seenReferences)(
|
571
|
+
trimmed[key] = seenReferences.has(object2[key]) ? seenReferences.get(object2[key]) : getObjectSubsetWithContext(seenReferences)(
|
572
|
+
object2[key],
|
573
|
+
subset2[key]
|
574
|
+
);
|
511
575
|
} else {
|
512
576
|
if (!seenReferences.has(object2[key])) {
|
513
577
|
stripped += 1;
|
514
|
-
if (isObject(object2[key]))
|
578
|
+
if (isObject(object2[key])) {
|
515
579
|
stripped += getObjectKeys(object2[key]).length;
|
516
|
-
|
580
|
+
}
|
581
|
+
getObjectSubsetWithContext(seenReferences)(
|
582
|
+
object2[key],
|
583
|
+
subset2[key]
|
584
|
+
);
|
517
585
|
}
|
518
586
|
}
|
519
587
|
}
|
520
|
-
if (getObjectKeys(trimmed).length > 0)
|
588
|
+
if (getObjectKeys(trimmed).length > 0) {
|
521
589
|
return trimmed;
|
590
|
+
}
|
522
591
|
}
|
523
592
|
return object2;
|
524
593
|
};
|
@@ -551,15 +620,17 @@ class AsymmetricMatcher {
|
|
551
620
|
// https://github.com/chaijs/loupe/blob/9b8a6deabcd50adc056a64fb705896194710c5c6/src/index.ts#L29
|
552
621
|
[Symbol.for("chai/inspect")](options) {
|
553
622
|
const result = stringify(this, options.depth, { min: true });
|
554
|
-
if (result.length <= options.truncate)
|
623
|
+
if (result.length <= options.truncate) {
|
555
624
|
return result;
|
625
|
+
}
|
556
626
|
return `${this.toString()}{\u2026}`;
|
557
627
|
}
|
558
628
|
}
|
559
629
|
class StringContaining extends AsymmetricMatcher {
|
560
630
|
constructor(sample, inverse = false) {
|
561
|
-
if (!isA("String", sample))
|
631
|
+
if (!isA("String", sample)) {
|
562
632
|
throw new Error("Expected is not a string");
|
633
|
+
}
|
563
634
|
super(sample, inverse);
|
564
635
|
}
|
565
636
|
asymmetricMatch(other) {
|
@@ -589,17 +660,21 @@ class ObjectContaining extends AsymmetricMatcher {
|
|
589
660
|
super(sample, inverse);
|
590
661
|
}
|
591
662
|
getPrototype(obj) {
|
592
|
-
if (Object.getPrototypeOf)
|
663
|
+
if (Object.getPrototypeOf) {
|
593
664
|
return Object.getPrototypeOf(obj);
|
594
|
-
|
665
|
+
}
|
666
|
+
if (obj.constructor.prototype === obj) {
|
595
667
|
return null;
|
668
|
+
}
|
596
669
|
return obj.constructor.prototype;
|
597
670
|
}
|
598
671
|
hasProperty(obj, property) {
|
599
|
-
if (!obj)
|
672
|
+
if (!obj) {
|
600
673
|
return false;
|
601
|
-
|
674
|
+
}
|
675
|
+
if (Object.prototype.hasOwnProperty.call(obj, property)) {
|
602
676
|
return true;
|
677
|
+
}
|
603
678
|
return this.hasProperty(this.getPrototype(obj), property);
|
604
679
|
}
|
605
680
|
asymmetricMatch(other) {
|
@@ -611,7 +686,11 @@ class ObjectContaining extends AsymmetricMatcher {
|
|
611
686
|
let result = true;
|
612
687
|
const matcherContext = this.getMatcherContext();
|
613
688
|
for (const property in this.sample) {
|
614
|
-
if (!this.hasProperty(other, property) || !equals(
|
689
|
+
if (!this.hasProperty(other, property) || !equals(
|
690
|
+
this.sample[property],
|
691
|
+
other[property],
|
692
|
+
matcherContext.customTesters
|
693
|
+
)) {
|
615
694
|
result = false;
|
616
695
|
break;
|
617
696
|
}
|
@@ -637,7 +716,9 @@ class ArrayContaining extends AsymmetricMatcher {
|
|
637
716
|
}
|
638
717
|
const matcherContext = this.getMatcherContext();
|
639
718
|
const result = this.sample.length === 0 || Array.isArray(other) && this.sample.every(
|
640
|
-
(item) => other.some(
|
719
|
+
(item) => other.some(
|
720
|
+
(another) => equals(item, another, matcherContext.customTesters)
|
721
|
+
)
|
641
722
|
);
|
642
723
|
return this.inverse ? !result : result;
|
643
724
|
}
|
@@ -658,43 +739,56 @@ class Any extends AsymmetricMatcher {
|
|
658
739
|
super(sample);
|
659
740
|
}
|
660
741
|
fnNameFor(func) {
|
661
|
-
if (func.name)
|
742
|
+
if (func.name) {
|
662
743
|
return func.name;
|
744
|
+
}
|
663
745
|
const functionToString = Function.prototype.toString;
|
664
746
|
const matches = functionToString.call(func).match(/^(?:async)?\s*function\s*(?:\*\s*)?([\w$]+)\s*\(/);
|
665
747
|
return matches ? matches[1] : "<anonymous>";
|
666
748
|
}
|
667
749
|
asymmetricMatch(other) {
|
668
|
-
if (this.sample === String)
|
750
|
+
if (this.sample === String) {
|
669
751
|
return typeof other == "string" || other instanceof String;
|
670
|
-
|
752
|
+
}
|
753
|
+
if (this.sample === Number) {
|
671
754
|
return typeof other == "number" || other instanceof Number;
|
672
|
-
|
755
|
+
}
|
756
|
+
if (this.sample === Function) {
|
673
757
|
return typeof other == "function" || other instanceof Function;
|
674
|
-
|
758
|
+
}
|
759
|
+
if (this.sample === Boolean) {
|
675
760
|
return typeof other == "boolean" || other instanceof Boolean;
|
676
|
-
|
761
|
+
}
|
762
|
+
if (this.sample === BigInt) {
|
677
763
|
return typeof other == "bigint" || other instanceof BigInt;
|
678
|
-
|
764
|
+
}
|
765
|
+
if (this.sample === Symbol) {
|
679
766
|
return typeof other == "symbol" || other instanceof Symbol;
|
680
|
-
|
767
|
+
}
|
768
|
+
if (this.sample === Object) {
|
681
769
|
return typeof other == "object";
|
770
|
+
}
|
682
771
|
return other instanceof this.sample;
|
683
772
|
}
|
684
773
|
toString() {
|
685
774
|
return "Any";
|
686
775
|
}
|
687
776
|
getExpectedType() {
|
688
|
-
if (this.sample === String)
|
777
|
+
if (this.sample === String) {
|
689
778
|
return "string";
|
690
|
-
|
779
|
+
}
|
780
|
+
if (this.sample === Number) {
|
691
781
|
return "number";
|
692
|
-
|
782
|
+
}
|
783
|
+
if (this.sample === Function) {
|
693
784
|
return "function";
|
694
|
-
|
785
|
+
}
|
786
|
+
if (this.sample === Object) {
|
695
787
|
return "object";
|
696
|
-
|
788
|
+
}
|
789
|
+
if (this.sample === Boolean) {
|
697
790
|
return "boolean";
|
791
|
+
}
|
698
792
|
return this.fnNameFor(this.sample);
|
699
793
|
}
|
700
794
|
toAsymmetricMatcher() {
|
@@ -703,8 +797,9 @@ class Any extends AsymmetricMatcher {
|
|
703
797
|
}
|
704
798
|
class StringMatching extends AsymmetricMatcher {
|
705
799
|
constructor(sample, inverse = false) {
|
706
|
-
if (!isA("String", sample) && !isA("RegExp", sample))
|
800
|
+
if (!isA("String", sample) && !isA("RegExp", sample)) {
|
707
801
|
throw new Error("Expected is not a String or a RegExp");
|
802
|
+
}
|
708
803
|
super(new RegExp(sample), inverse);
|
709
804
|
}
|
710
805
|
asymmetricMatch(other) {
|
@@ -721,17 +816,20 @@ class StringMatching extends AsymmetricMatcher {
|
|
721
816
|
class CloseTo extends AsymmetricMatcher {
|
722
817
|
precision;
|
723
818
|
constructor(sample, precision = 2, inverse = false) {
|
724
|
-
if (!isA("Number", sample))
|
819
|
+
if (!isA("Number", sample)) {
|
725
820
|
throw new Error("Expected is not a Number");
|
726
|
-
|
821
|
+
}
|
822
|
+
if (!isA("Number", precision)) {
|
727
823
|
throw new Error("Precision is not a Number");
|
824
|
+
}
|
728
825
|
super(sample);
|
729
826
|
this.inverse = inverse;
|
730
827
|
this.precision = precision;
|
731
828
|
}
|
732
829
|
asymmetricMatch(other) {
|
733
|
-
if (!isA("Number", other))
|
830
|
+
if (!isA("Number", other)) {
|
734
831
|
return false;
|
832
|
+
}
|
735
833
|
let result = false;
|
736
834
|
if (other === Number.POSITIVE_INFINITY && this.sample === Number.POSITIVE_INFINITY) {
|
737
835
|
result = true;
|
@@ -757,16 +855,8 @@ class CloseTo extends AsymmetricMatcher {
|
|
757
855
|
}
|
758
856
|
}
|
759
857
|
const JestAsymmetricMatchers = (chai, utils) => {
|
760
|
-
utils.addMethod(
|
761
|
-
|
762
|
-
"anything",
|
763
|
-
() => new Anything()
|
764
|
-
);
|
765
|
-
utils.addMethod(
|
766
|
-
chai.expect,
|
767
|
-
"any",
|
768
|
-
(expected) => new Any(expected)
|
769
|
-
);
|
858
|
+
utils.addMethod(chai.expect, "anything", () => new Anything());
|
859
|
+
utils.addMethod(chai.expect, "any", (expected) => new Any(expected));
|
770
860
|
utils.addMethod(
|
771
861
|
chai.expect,
|
772
862
|
"stringContaining",
|
@@ -805,11 +895,13 @@ function recordAsyncExpect(test, promise) {
|
|
805
895
|
if (test && promise instanceof Promise) {
|
806
896
|
promise = promise.finally(() => {
|
807
897
|
const index = test.promises.indexOf(promise);
|
808
|
-
if (index !== -1)
|
898
|
+
if (index !== -1) {
|
809
899
|
test.promises.splice(index, 1);
|
900
|
+
}
|
810
901
|
});
|
811
|
-
if (!test.promises)
|
902
|
+
if (!test.promises) {
|
812
903
|
test.promises = [];
|
904
|
+
}
|
813
905
|
test.promises.push(promise);
|
814
906
|
}
|
815
907
|
return promise;
|
@@ -817,11 +909,13 @@ function recordAsyncExpect(test, promise) {
|
|
817
909
|
function wrapSoft(utils, fn) {
|
818
910
|
return function(...args) {
|
819
911
|
var _a;
|
820
|
-
if (!utils.flag(this, "soft"))
|
912
|
+
if (!utils.flag(this, "soft")) {
|
821
913
|
return fn.apply(this, args);
|
914
|
+
}
|
822
915
|
const test = utils.flag(this, "vitest-test");
|
823
|
-
if (!test)
|
916
|
+
if (!test) {
|
824
917
|
throw new Error("expect.soft() can only be used inside a test");
|
918
|
+
}
|
825
919
|
try {
|
826
920
|
return fn.apply(this, args);
|
827
921
|
} catch (err) {
|
@@ -841,12 +935,17 @@ const JestChaiExpect = (chai, utils) => {
|
|
841
935
|
const addMethod = (n) => {
|
842
936
|
const softWrapper = wrapSoft(utils, fn);
|
843
937
|
utils.addMethod(chai.Assertion.prototype, n, softWrapper);
|
844
|
-
utils.addMethod(
|
938
|
+
utils.addMethod(
|
939
|
+
globalThis[JEST_MATCHERS_OBJECT].matchers,
|
940
|
+
n,
|
941
|
+
softWrapper
|
942
|
+
);
|
845
943
|
};
|
846
|
-
if (Array.isArray(name))
|
944
|
+
if (Array.isArray(name)) {
|
847
945
|
name.forEach((n) => addMethod(n));
|
848
|
-
else
|
946
|
+
} else {
|
849
947
|
addMethod(name);
|
948
|
+
}
|
850
949
|
}
|
851
950
|
["throw", "throws", "Throw"].forEach((m) => {
|
852
951
|
utils.overwriteMethod(chai.Assertion.prototype, m, (_super) => {
|
@@ -879,11 +978,10 @@ const JestChaiExpect = (chai, utils) => {
|
|
879
978
|
});
|
880
979
|
def("toEqual", function(expected) {
|
881
980
|
const actual = utils.flag(this, "object");
|
882
|
-
const equal = equals(
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
);
|
981
|
+
const equal = equals(actual, expected, [
|
982
|
+
...customTesters,
|
983
|
+
iterableEquality
|
984
|
+
]);
|
887
985
|
return this.assert(
|
888
986
|
equal,
|
889
987
|
"expected #{this} to deeply equal #{exp}",
|
@@ -934,13 +1032,13 @@ const JestChaiExpect = (chai, utils) => {
|
|
934
1032
|
if (toStrictEqualPass) {
|
935
1033
|
deepEqualityName = "toStrictEqual";
|
936
1034
|
} else {
|
937
|
-
const toEqualPass = equals(
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
)
|
942
|
-
if (toEqualPass)
|
1035
|
+
const toEqualPass = equals(actual, expected, [
|
1036
|
+
...customTesters,
|
1037
|
+
iterableEquality
|
1038
|
+
]);
|
1039
|
+
if (toEqualPass) {
|
943
1040
|
deepEqualityName = "toEqual";
|
1041
|
+
}
|
944
1042
|
}
|
945
1043
|
}
|
946
1044
|
return this.assert(
|
@@ -953,30 +1051,41 @@ const JestChaiExpect = (chai, utils) => {
|
|
953
1051
|
});
|
954
1052
|
def("toMatchObject", function(expected) {
|
955
1053
|
const actual = this._obj;
|
956
|
-
const pass = equals(actual, expected, [
|
1054
|
+
const pass = equals(actual, expected, [
|
1055
|
+
...customTesters,
|
1056
|
+
iterableEquality,
|
1057
|
+
subsetEquality
|
1058
|
+
]);
|
957
1059
|
const isNot = utils.flag(this, "negate");
|
958
|
-
const { subset: actualSubset, stripped } = getObjectSubset(
|
1060
|
+
const { subset: actualSubset, stripped } = getObjectSubset(
|
1061
|
+
actual,
|
1062
|
+
expected
|
1063
|
+
);
|
959
1064
|
if (pass && isNot || !pass && !isNot) {
|
960
|
-
const msg = utils.getMessage(
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
false
|
969
|
-
]
|
970
|
-
);
|
1065
|
+
const msg = utils.getMessage(this, [
|
1066
|
+
pass,
|
1067
|
+
"expected #{this} to match object #{exp}",
|
1068
|
+
"expected #{this} to not match object #{exp}",
|
1069
|
+
expected,
|
1070
|
+
actualSubset,
|
1071
|
+
false
|
1072
|
+
]);
|
971
1073
|
const message = stripped === 0 ? msg : `${msg}
|
972
1074
|
(${stripped} matching ${stripped === 1 ? "property" : "properties"} omitted from actual)`;
|
973
|
-
throw new AssertionError(message, {
|
1075
|
+
throw new AssertionError(message, {
|
1076
|
+
showDiff: true,
|
1077
|
+
expected,
|
1078
|
+
actual: actualSubset
|
1079
|
+
});
|
974
1080
|
}
|
975
1081
|
});
|
976
1082
|
def("toMatch", function(expected) {
|
977
1083
|
const actual = this._obj;
|
978
|
-
if (typeof actual !== "string")
|
979
|
-
throw new TypeError(
|
1084
|
+
if (typeof actual !== "string") {
|
1085
|
+
throw new TypeError(
|
1086
|
+
`.toMatch() expects to receive a string, but got ${typeof actual}`
|
1087
|
+
);
|
1088
|
+
}
|
980
1089
|
return this.assert(
|
981
1090
|
typeof expected === "string" ? actual.includes(expected) : actual.match(expected),
|
982
1091
|
`expected #{this} to match #{exp}`,
|
@@ -988,8 +1097,11 @@ const JestChaiExpect = (chai, utils) => {
|
|
988
1097
|
def("toContain", function(item) {
|
989
1098
|
const actual = this._obj;
|
990
1099
|
if (typeof Node !== "undefined" && actual instanceof Node) {
|
991
|
-
if (!(item instanceof Node))
|
992
|
-
throw new TypeError(
|
1100
|
+
if (!(item instanceof Node)) {
|
1101
|
+
throw new TypeError(
|
1102
|
+
`toContain() expected a DOM node as the argument, but got ${typeof item}`
|
1103
|
+
);
|
1104
|
+
}
|
993
1105
|
return this.assert(
|
994
1106
|
actual.contains(item),
|
995
1107
|
"expected #{this} to contain element #{exp}",
|
@@ -1019,8 +1131,9 @@ const JestChaiExpect = (chai, utils) => {
|
|
1019
1131
|
actual
|
1020
1132
|
);
|
1021
1133
|
}
|
1022
|
-
if (actual != null && typeof actual !== "string")
|
1134
|
+
if (actual != null && typeof actual !== "string") {
|
1023
1135
|
utils.flag(this, "object", Array.from(actual));
|
1136
|
+
}
|
1024
1137
|
return this.contain(item);
|
1025
1138
|
});
|
1026
1139
|
def("toContainEqual", function(expected) {
|
@@ -1119,49 +1232,61 @@ const JestChaiExpect = (chai, utils) => {
|
|
1119
1232
|
def("toBeDefined", function() {
|
1120
1233
|
const negate = utils.flag(this, "negate");
|
1121
1234
|
utils.flag(this, "negate", false);
|
1122
|
-
if (negate)
|
1235
|
+
if (negate) {
|
1123
1236
|
return this.be.undefined;
|
1237
|
+
}
|
1124
1238
|
return this.not.be.undefined;
|
1125
1239
|
});
|
1126
|
-
def(
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
equal
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1240
|
+
def(
|
1241
|
+
"toBeTypeOf",
|
1242
|
+
function(expected) {
|
1243
|
+
const actual = typeof this._obj;
|
1244
|
+
const equal = expected === actual;
|
1245
|
+
return this.assert(
|
1246
|
+
equal,
|
1247
|
+
"expected #{this} to be type of #{exp}",
|
1248
|
+
"expected #{this} not to be type of #{exp}",
|
1249
|
+
expected,
|
1250
|
+
actual
|
1251
|
+
);
|
1252
|
+
}
|
1253
|
+
);
|
1137
1254
|
def("toBeInstanceOf", function(obj) {
|
1138
1255
|
return this.instanceOf(obj);
|
1139
1256
|
});
|
1140
1257
|
def("toHaveLength", function(length) {
|
1141
1258
|
return this.have.length(length);
|
1142
1259
|
});
|
1143
|
-
def(
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
const
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
exists
|
1163
|
-
|
1164
|
-
|
1260
|
+
def(
|
1261
|
+
"toHaveProperty",
|
1262
|
+
function(...args) {
|
1263
|
+
if (Array.isArray(args[0])) {
|
1264
|
+
args[0] = args[0].map((key) => String(key).replace(/([.[\]])/g, "\\$1")).join(".");
|
1265
|
+
}
|
1266
|
+
const actual = this._obj;
|
1267
|
+
const [propertyName, expected] = args;
|
1268
|
+
const getValue = () => {
|
1269
|
+
const hasOwn = Object.prototype.hasOwnProperty.call(
|
1270
|
+
actual,
|
1271
|
+
propertyName
|
1272
|
+
);
|
1273
|
+
if (hasOwn) {
|
1274
|
+
return { value: actual[propertyName], exists: true };
|
1275
|
+
}
|
1276
|
+
return utils.getPathInfo(actual, propertyName);
|
1277
|
+
};
|
1278
|
+
const { value, exists } = getValue();
|
1279
|
+
const pass = exists && (args.length === 1 || equals(expected, value, customTesters));
|
1280
|
+
const valueString = args.length === 1 ? "" : ` with value ${utils.objDisplay(expected)}`;
|
1281
|
+
return this.assert(
|
1282
|
+
pass,
|
1283
|
+
`expected #{this} to have property "${propertyName}"${valueString}`,
|
1284
|
+
`expected #{this} to not have property "${propertyName}"${valueString}`,
|
1285
|
+
expected,
|
1286
|
+
exists ? value : void 0
|
1287
|
+
);
|
1288
|
+
}
|
1289
|
+
);
|
1165
1290
|
def("toBeCloseTo", function(received, precision = 2) {
|
1166
1291
|
const expected = this._obj;
|
1167
1292
|
let pass = false;
|
@@ -1186,8 +1311,11 @@ const JestChaiExpect = (chai, utils) => {
|
|
1186
1311
|
);
|
1187
1312
|
});
|
1188
1313
|
const assertIsMock = (assertion) => {
|
1189
|
-
if (!isMockFunction(assertion._obj))
|
1190
|
-
throw new TypeError(
|
1314
|
+
if (!isMockFunction(assertion._obj)) {
|
1315
|
+
throw new TypeError(
|
1316
|
+
`${utils.inspect(assertion._obj)} is not a spy or a call to a spy!`
|
1317
|
+
);
|
1318
|
+
}
|
1191
1319
|
};
|
1192
1320
|
const getSpy = (assertion) => {
|
1193
1321
|
assertIsMock(assertion);
|
@@ -1196,58 +1324,79 @@ const JestChaiExpect = (chai, utils) => {
|
|
1196
1324
|
const ordinalOf = (i) => {
|
1197
1325
|
const j = i % 10;
|
1198
1326
|
const k = i % 100;
|
1199
|
-
if (j === 1 && k !== 11)
|
1327
|
+
if (j === 1 && k !== 11) {
|
1200
1328
|
return `${i}st`;
|
1201
|
-
|
1329
|
+
}
|
1330
|
+
if (j === 2 && k !== 12) {
|
1202
1331
|
return `${i}nd`;
|
1203
|
-
|
1332
|
+
}
|
1333
|
+
if (j === 3 && k !== 13) {
|
1204
1334
|
return `${i}rd`;
|
1335
|
+
}
|
1205
1336
|
return `${i}th`;
|
1206
1337
|
};
|
1207
1338
|
const formatCalls = (spy, msg, showActualCall) => {
|
1208
1339
|
if (spy.mock.calls) {
|
1209
|
-
msg += c().gray(
|
1340
|
+
msg += c().gray(
|
1341
|
+
`
|
1210
1342
|
|
1211
1343
|
Received:
|
1212
1344
|
|
1213
1345
|
${spy.mock.calls.map((callArg, i) => {
|
1214
|
-
|
1346
|
+
let methodCall = c().bold(
|
1347
|
+
` ${ordinalOf(i + 1)} ${spy.getMockName()} call:
|
1215
1348
|
|
1216
|
-
`
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1349
|
+
`
|
1350
|
+
);
|
1351
|
+
if (showActualCall) {
|
1352
|
+
methodCall += diff(showActualCall, callArg, {
|
1353
|
+
omitAnnotationLines: true
|
1354
|
+
});
|
1355
|
+
} else {
|
1356
|
+
methodCall += stringify(callArg).split("\n").map((line) => ` ${line}`).join("\n");
|
1357
|
+
}
|
1358
|
+
methodCall += "\n";
|
1359
|
+
return methodCall;
|
1360
|
+
}).join("\n")}`
|
1361
|
+
);
|
1224
1362
|
}
|
1225
|
-
msg += c().gray(
|
1363
|
+
msg += c().gray(
|
1364
|
+
`
|
1226
1365
|
|
1227
1366
|
Number of calls: ${c().bold(spy.mock.calls.length)}
|
1228
|
-
`
|
1367
|
+
`
|
1368
|
+
);
|
1229
1369
|
return msg;
|
1230
1370
|
};
|
1231
1371
|
const formatReturns = (spy, results, msg, showActualReturn) => {
|
1232
|
-
msg += c().gray(
|
1372
|
+
msg += c().gray(
|
1373
|
+
`
|
1233
1374
|
|
1234
1375
|
Received:
|
1235
1376
|
|
1236
1377
|
${results.map((callReturn, i) => {
|
1237
|
-
|
1378
|
+
let methodCall = c().bold(
|
1379
|
+
` ${ordinalOf(i + 1)} ${spy.getMockName()} call return:
|
1238
1380
|
|
1239
|
-
`
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
}).join("\n")
|
1247
|
-
|
1381
|
+
`
|
1382
|
+
);
|
1383
|
+
if (showActualReturn) {
|
1384
|
+
methodCall += diff(showActualReturn, callReturn.value, {
|
1385
|
+
omitAnnotationLines: true
|
1386
|
+
});
|
1387
|
+
} else {
|
1388
|
+
methodCall += stringify(callReturn).split("\n").map((line) => ` ${line}`).join("\n");
|
1389
|
+
}
|
1390
|
+
methodCall += "\n";
|
1391
|
+
return methodCall;
|
1392
|
+
}).join("\n")}`
|
1393
|
+
);
|
1394
|
+
msg += c().gray(
|
1395
|
+
`
|
1248
1396
|
|
1249
1397
|
Number of calls: ${c().bold(spy.mock.calls.length)}
|
1250
|
-
`
|
1398
|
+
`
|
1399
|
+
);
|
1251
1400
|
return msg;
|
1252
1401
|
};
|
1253
1402
|
def(["toHaveBeenCalledTimes", "toBeCalledTimes"], function(number) {
|
@@ -1282,131 +1431,146 @@ Number of calls: ${c().bold(spy.mock.calls.length)}
|
|
1282
1431
|
const callCount = spy.mock.calls.length;
|
1283
1432
|
const called = callCount > 0;
|
1284
1433
|
const isNot = utils.flag(this, "negate");
|
1285
|
-
let msg = utils.getMessage(
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
]
|
1294
|
-
);
|
1295
|
-
if (called && isNot)
|
1434
|
+
let msg = utils.getMessage(this, [
|
1435
|
+
called,
|
1436
|
+
`expected "${spyName}" to be called at least once`,
|
1437
|
+
`expected "${spyName}" to not be called at all, but actually been called ${callCount} times`,
|
1438
|
+
true,
|
1439
|
+
called
|
1440
|
+
]);
|
1441
|
+
if (called && isNot) {
|
1296
1442
|
msg = formatCalls(spy, msg);
|
1297
|
-
|
1443
|
+
}
|
1444
|
+
if (called && isNot || !called && !isNot) {
|
1298
1445
|
throw new AssertionError(msg);
|
1446
|
+
}
|
1299
1447
|
});
|
1300
1448
|
def(["toHaveBeenCalledWith", "toBeCalledWith"], function(...args) {
|
1301
1449
|
const spy = getSpy(this);
|
1302
1450
|
const spyName = spy.getMockName();
|
1303
|
-
const pass = spy.mock.calls.some(
|
1304
|
-
|
1305
|
-
const msg = utils.getMessage(
|
1306
|
-
this,
|
1307
|
-
[
|
1308
|
-
pass,
|
1309
|
-
`expected "${spyName}" to be called with arguments: #{exp}`,
|
1310
|
-
`expected "${spyName}" to not be called with arguments: #{exp}`,
|
1311
|
-
args
|
1312
|
-
]
|
1451
|
+
const pass = spy.mock.calls.some(
|
1452
|
+
(callArg) => equals(callArg, args, [...customTesters, iterableEquality])
|
1313
1453
|
);
|
1314
|
-
if (pass && isNot || !pass && !isNot)
|
1315
|
-
throw new AssertionError(formatCalls(spy, msg, args));
|
1316
|
-
});
|
1317
|
-
def(["toHaveBeenNthCalledWith", "nthCalledWith"], function(times, ...args) {
|
1318
|
-
const spy = getSpy(this);
|
1319
|
-
const spyName = spy.getMockName();
|
1320
|
-
const nthCall = spy.mock.calls[times - 1];
|
1321
|
-
const callCount = spy.mock.calls.length;
|
1322
|
-
const isCalled = times <= callCount;
|
1323
|
-
this.assert(
|
1324
|
-
equals(nthCall, args, [...customTesters, iterableEquality]),
|
1325
|
-
`expected ${ordinalOf(times)} "${spyName}" call to have been called with #{exp}${isCalled ? `` : `, but called only ${callCount} times`}`,
|
1326
|
-
`expected ${ordinalOf(times)} "${spyName}" call to not have been called with #{exp}`,
|
1327
|
-
args,
|
1328
|
-
nthCall,
|
1329
|
-
isCalled
|
1330
|
-
);
|
1331
|
-
});
|
1332
|
-
def(["toHaveBeenLastCalledWith", "lastCalledWith"], function(...args) {
|
1333
|
-
const spy = getSpy(this);
|
1334
|
-
const spyName = spy.getMockName();
|
1335
|
-
const lastCall = spy.mock.calls[spy.mock.calls.length - 1];
|
1336
|
-
this.assert(
|
1337
|
-
equals(lastCall, args, [...customTesters, iterableEquality]),
|
1338
|
-
`expected last "${spyName}" call to have been called with #{exp}`,
|
1339
|
-
`expected last "${spyName}" call to not have been called with #{exp}`,
|
1340
|
-
args,
|
1341
|
-
lastCall
|
1342
|
-
);
|
1343
|
-
});
|
1344
|
-
def(["toThrow", "toThrowError"], function(expected) {
|
1345
|
-
if (typeof expected === "string" || typeof expected === "undefined" || expected instanceof RegExp)
|
1346
|
-
return this.throws(expected);
|
1347
|
-
const obj = this._obj;
|
1348
|
-
const promise = utils.flag(this, "promise");
|
1349
1454
|
const isNot = utils.flag(this, "negate");
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
};
|
1359
|
-
throw new AssertionError(message, error, utils.flag(this, "ssfi"));
|
1360
|
-
} else {
|
1361
|
-
return;
|
1362
|
-
}
|
1363
|
-
} else {
|
1364
|
-
let isThrow = false;
|
1365
|
-
try {
|
1366
|
-
obj();
|
1367
|
-
} catch (err) {
|
1368
|
-
isThrow = true;
|
1369
|
-
thrown = err;
|
1370
|
-
}
|
1371
|
-
if (!isThrow && !isNot) {
|
1372
|
-
const message = utils.flag(this, "message") || "expected function to throw an error, but it didn't";
|
1373
|
-
const error = {
|
1374
|
-
showDiff: false
|
1375
|
-
};
|
1376
|
-
throw new AssertionError(message, error, utils.flag(this, "ssfi"));
|
1377
|
-
}
|
1455
|
+
const msg = utils.getMessage(this, [
|
1456
|
+
pass,
|
1457
|
+
`expected "${spyName}" to be called with arguments: #{exp}`,
|
1458
|
+
`expected "${spyName}" to not be called with arguments: #{exp}`,
|
1459
|
+
args
|
1460
|
+
]);
|
1461
|
+
if (pass && isNot || !pass && !isNot) {
|
1462
|
+
throw new AssertionError(formatCalls(spy, msg, args));
|
1378
1463
|
}
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1464
|
+
});
|
1465
|
+
def(
|
1466
|
+
["toHaveBeenNthCalledWith", "nthCalledWith"],
|
1467
|
+
function(times, ...args) {
|
1468
|
+
const spy = getSpy(this);
|
1469
|
+
const spyName = spy.getMockName();
|
1470
|
+
const nthCall = spy.mock.calls[times - 1];
|
1471
|
+
const callCount = spy.mock.calls.length;
|
1472
|
+
const isCalled = times <= callCount;
|
1473
|
+
this.assert(
|
1474
|
+
equals(nthCall, args, [...customTesters, iterableEquality]),
|
1475
|
+
`expected ${ordinalOf(
|
1476
|
+
times
|
1477
|
+
)} "${spyName}" call to have been called with #{exp}${isCalled ? `` : `, but called only ${callCount} times`}`,
|
1478
|
+
`expected ${ordinalOf(
|
1479
|
+
times
|
1480
|
+
)} "${spyName}" call to not have been called with #{exp}`,
|
1481
|
+
args,
|
1482
|
+
nthCall,
|
1483
|
+
isCalled
|
1387
1484
|
);
|
1388
1485
|
}
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1486
|
+
);
|
1487
|
+
def(
|
1488
|
+
["toHaveBeenLastCalledWith", "lastCalledWith"],
|
1489
|
+
function(...args) {
|
1490
|
+
const spy = getSpy(this);
|
1491
|
+
const spyName = spy.getMockName();
|
1492
|
+
const lastCall = spy.mock.calls[spy.mock.calls.length - 1];
|
1493
|
+
this.assert(
|
1494
|
+
equals(lastCall, args, [...customTesters, iterableEquality]),
|
1495
|
+
`expected last "${spyName}" call to have been called with #{exp}`,
|
1496
|
+
`expected last "${spyName}" call to not have been called with #{exp}`,
|
1497
|
+
args,
|
1498
|
+
lastCall
|
1396
1499
|
);
|
1397
1500
|
}
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1501
|
+
);
|
1502
|
+
def(
|
1503
|
+
["toThrow", "toThrowError"],
|
1504
|
+
function(expected) {
|
1505
|
+
if (typeof expected === "string" || typeof expected === "undefined" || expected instanceof RegExp) {
|
1506
|
+
return this.throws(expected);
|
1507
|
+
}
|
1508
|
+
const obj = this._obj;
|
1509
|
+
const promise = utils.flag(this, "promise");
|
1510
|
+
const isNot = utils.flag(this, "negate");
|
1511
|
+
let thrown = null;
|
1512
|
+
if (promise === "rejects") {
|
1513
|
+
thrown = obj;
|
1514
|
+
} else if (promise === "resolves" && typeof obj !== "function") {
|
1515
|
+
if (!isNot) {
|
1516
|
+
const message = utils.flag(this, "message") || "expected promise to throw an error, but it didn't";
|
1517
|
+
const error = {
|
1518
|
+
showDiff: false
|
1519
|
+
};
|
1520
|
+
throw new AssertionError(message, error, utils.flag(this, "ssfi"));
|
1521
|
+
} else {
|
1522
|
+
return;
|
1523
|
+
}
|
1524
|
+
} else {
|
1525
|
+
let isThrow = false;
|
1526
|
+
try {
|
1527
|
+
obj();
|
1528
|
+
} catch (err) {
|
1529
|
+
isThrow = true;
|
1530
|
+
thrown = err;
|
1531
|
+
}
|
1532
|
+
if (!isThrow && !isNot) {
|
1533
|
+
const message = utils.flag(this, "message") || "expected function to throw an error, but it didn't";
|
1534
|
+
const error = {
|
1535
|
+
showDiff: false
|
1536
|
+
};
|
1537
|
+
throw new AssertionError(message, error, utils.flag(this, "ssfi"));
|
1538
|
+
}
|
1539
|
+
}
|
1540
|
+
if (typeof expected === "function") {
|
1541
|
+
const name = expected.name || expected.prototype.constructor.name;
|
1542
|
+
return this.assert(
|
1543
|
+
thrown && thrown instanceof expected,
|
1544
|
+
`expected error to be instance of ${name}`,
|
1545
|
+
`expected error not to be instance of ${name}`,
|
1546
|
+
expected,
|
1547
|
+
thrown
|
1548
|
+
);
|
1549
|
+
}
|
1550
|
+
if (expected instanceof Error) {
|
1551
|
+
return this.assert(
|
1552
|
+
thrown && expected.message === thrown.message,
|
1553
|
+
`expected error to have message: ${expected.message}`,
|
1554
|
+
`expected error not to have message: ${expected.message}`,
|
1555
|
+
expected.message,
|
1556
|
+
thrown && thrown.message
|
1557
|
+
);
|
1558
|
+
}
|
1559
|
+
if (typeof expected === "object" && "asymmetricMatch" in expected && typeof expected.asymmetricMatch === "function") {
|
1560
|
+
const matcher = expected;
|
1561
|
+
return this.assert(
|
1562
|
+
thrown && matcher.asymmetricMatch(thrown),
|
1563
|
+
"expected error to match asymmetric matcher",
|
1564
|
+
"expected error not to match asymmetric matcher",
|
1565
|
+
matcher,
|
1566
|
+
thrown
|
1567
|
+
);
|
1568
|
+
}
|
1569
|
+
throw new Error(
|
1570
|
+
`"toThrow" expects string, RegExp, function, Error instance or asymmetric matcher, got "${typeof expected}"`
|
1406
1571
|
);
|
1407
1572
|
}
|
1408
|
-
|
1409
|
-
});
|
1573
|
+
);
|
1410
1574
|
[
|
1411
1575
|
{
|
1412
1576
|
name: "toHaveResolved",
|
@@ -1436,12 +1600,18 @@ Number of calls: ${c().bold(spy.mock.calls.length)}
|
|
1436
1600
|
[
|
1437
1601
|
{
|
1438
1602
|
name: "toHaveResolvedTimes",
|
1439
|
-
condition: (spy, times) => spy.mock.settledResults.reduce(
|
1603
|
+
condition: (spy, times) => spy.mock.settledResults.reduce(
|
1604
|
+
(s, { type }) => type === "fulfilled" ? ++s : s,
|
1605
|
+
0
|
1606
|
+
) === times,
|
1440
1607
|
action: "resolved"
|
1441
1608
|
},
|
1442
1609
|
{
|
1443
1610
|
name: ["toHaveReturnedTimes", "toReturnTimes"],
|
1444
|
-
condition: (spy, times) => spy.mock.results.reduce(
|
1611
|
+
condition: (spy, times) => spy.mock.results.reduce(
|
1612
|
+
(s, { type }) => type === "throw" ? s : ++s,
|
1613
|
+
0
|
1614
|
+
) === times,
|
1445
1615
|
action: "called"
|
1446
1616
|
}
|
1447
1617
|
].forEach(({ name, condition, action }) => {
|
@@ -1462,12 +1632,16 @@ Number of calls: ${c().bold(spy.mock.calls.length)}
|
|
1462
1632
|
[
|
1463
1633
|
{
|
1464
1634
|
name: "toHaveResolvedWith",
|
1465
|
-
condition: (spy, value) => spy.mock.settledResults.some(
|
1635
|
+
condition: (spy, value) => spy.mock.settledResults.some(
|
1636
|
+
({ type, value: result }) => type === "fulfilled" && equals(value, result)
|
1637
|
+
),
|
1466
1638
|
action: "resolve"
|
1467
1639
|
},
|
1468
1640
|
{
|
1469
1641
|
name: ["toHaveReturnedWith", "toReturnWith"],
|
1470
|
-
condition: (spy, value) => spy.mock.results.some(
|
1642
|
+
condition: (spy, value) => spy.mock.results.some(
|
1643
|
+
({ type, value: result }) => type === "return" && equals(value, result)
|
1644
|
+
),
|
1471
1645
|
action: "return"
|
1472
1646
|
}
|
1473
1647
|
].forEach(({ name, condition, action }) => {
|
@@ -1477,15 +1651,12 @@ Number of calls: ${c().bold(spy.mock.calls.length)}
|
|
1477
1651
|
const isNot = utils.flag(this, "negate");
|
1478
1652
|
if (pass && isNot || !pass && !isNot) {
|
1479
1653
|
const spyName = spy.getMockName();
|
1480
|
-
const msg = utils.getMessage(
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
value
|
1487
|
-
]
|
1488
|
-
);
|
1654
|
+
const msg = utils.getMessage(this, [
|
1655
|
+
pass,
|
1656
|
+
`expected "${spyName}" to ${action} with: #{exp} at least once`,
|
1657
|
+
`expected "${spyName}" to not ${action} with: #{exp}`,
|
1658
|
+
value
|
1659
|
+
]);
|
1489
1660
|
const results = action === "return" ? spy.mock.results : spy.mock.settledResults;
|
1490
1661
|
throw new AssertionError(formatReturns(spy, results, msg, value));
|
1491
1662
|
}
|
@@ -1560,84 +1731,121 @@ Number of calls: ${c().bold(spy.mock.calls.length)}
|
|
1560
1731
|
return this.be.satisfy(matcher, message);
|
1561
1732
|
});
|
1562
1733
|
def("withContext", function(context) {
|
1563
|
-
for (const key in context)
|
1734
|
+
for (const key in context) {
|
1564
1735
|
utils.flag(this, key, context[key]);
|
1736
|
+
}
|
1565
1737
|
return this;
|
1566
1738
|
});
|
1567
|
-
utils.addProperty(
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
if (typeof result !== "function")
|
1581
|
-
return result instanceof chai.Assertion ? proxy : result;
|
1582
|
-
return async (...args) => {
|
1583
|
-
const promise = obj.then(
|
1584
|
-
(value) => {
|
1585
|
-
utils.flag(this, "object", value);
|
1586
|
-
return result.call(this, ...args);
|
1587
|
-
},
|
1588
|
-
(err) => {
|
1589
|
-
const _error = new AssertionError(
|
1590
|
-
`promise rejected "${utils.inspect(err)}" instead of resolving`,
|
1591
|
-
{ showDiff: false }
|
1592
|
-
);
|
1593
|
-
_error.cause = err;
|
1594
|
-
_error.stack = error.stack.replace(error.message, _error.message);
|
1595
|
-
throw _error;
|
1596
|
-
}
|
1597
|
-
);
|
1598
|
-
return recordAsyncExpect(test, promise);
|
1599
|
-
};
|
1739
|
+
utils.addProperty(
|
1740
|
+
chai.Assertion.prototype,
|
1741
|
+
"resolves",
|
1742
|
+
function __VITEST_RESOLVES__() {
|
1743
|
+
const error = new Error("resolves");
|
1744
|
+
utils.flag(this, "promise", "resolves");
|
1745
|
+
utils.flag(this, "error", error);
|
1746
|
+
const test = utils.flag(this, "vitest-test");
|
1747
|
+
const obj = utils.flag(this, "object");
|
1748
|
+
if (utils.flag(this, "poll")) {
|
1749
|
+
throw new SyntaxError(
|
1750
|
+
`expect.poll() is not supported in combination with .resolves`
|
1751
|
+
);
|
1600
1752
|
}
|
1601
|
-
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
const error = new Error("rejects");
|
1606
|
-
utils.flag(this, "promise", "rejects");
|
1607
|
-
utils.flag(this, "error", error);
|
1608
|
-
const test = utils.flag(this, "vitest-test");
|
1609
|
-
const obj = utils.flag(this, "object");
|
1610
|
-
const wrapper = typeof obj === "function" ? obj() : obj;
|
1611
|
-
if (utils.flag(this, "poll"))
|
1612
|
-
throw new SyntaxError(`expect.poll() is not supported in combination with .rejects`);
|
1613
|
-
if (typeof (wrapper == null ? void 0 : wrapper.then) !== "function")
|
1614
|
-
throw new TypeError(`You must provide a Promise to expect() when using .rejects, not '${typeof wrapper}'.`);
|
1615
|
-
const proxy = new Proxy(this, {
|
1616
|
-
get: (target, key, receiver) => {
|
1617
|
-
const result = Reflect.get(target, key, receiver);
|
1618
|
-
if (typeof result !== "function")
|
1619
|
-
return result instanceof chai.Assertion ? proxy : result;
|
1620
|
-
return async (...args) => {
|
1621
|
-
const promise = wrapper.then(
|
1622
|
-
(value) => {
|
1623
|
-
const _error = new AssertionError(
|
1624
|
-
`promise resolved "${utils.inspect(value)}" instead of rejecting`,
|
1625
|
-
{ showDiff: true, expected: new Error("rejected promise"), actual: value }
|
1626
|
-
);
|
1627
|
-
_error.stack = error.stack.replace(error.message, _error.message);
|
1628
|
-
throw _error;
|
1629
|
-
},
|
1630
|
-
(err) => {
|
1631
|
-
utils.flag(this, "object", err);
|
1632
|
-
return result.call(this, ...args);
|
1633
|
-
}
|
1634
|
-
);
|
1635
|
-
return recordAsyncExpect(test, promise);
|
1636
|
-
};
|
1753
|
+
if (typeof (obj == null ? void 0 : obj.then) !== "function") {
|
1754
|
+
throw new TypeError(
|
1755
|
+
`You must provide a Promise to expect() when using .resolves, not '${typeof obj}'.`
|
1756
|
+
);
|
1637
1757
|
}
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1758
|
+
const proxy = new Proxy(this, {
|
1759
|
+
get: (target, key, receiver) => {
|
1760
|
+
const result = Reflect.get(target, key, receiver);
|
1761
|
+
if (typeof result !== "function") {
|
1762
|
+
return result instanceof chai.Assertion ? proxy : result;
|
1763
|
+
}
|
1764
|
+
return async (...args) => {
|
1765
|
+
const promise = obj.then(
|
1766
|
+
(value) => {
|
1767
|
+
utils.flag(this, "object", value);
|
1768
|
+
return result.call(this, ...args);
|
1769
|
+
},
|
1770
|
+
(err) => {
|
1771
|
+
const _error = new AssertionError(
|
1772
|
+
`promise rejected "${utils.inspect(
|
1773
|
+
err
|
1774
|
+
)}" instead of resolving`,
|
1775
|
+
{ showDiff: false }
|
1776
|
+
);
|
1777
|
+
_error.cause = err;
|
1778
|
+
_error.stack = error.stack.replace(
|
1779
|
+
error.message,
|
1780
|
+
_error.message
|
1781
|
+
);
|
1782
|
+
throw _error;
|
1783
|
+
}
|
1784
|
+
);
|
1785
|
+
return recordAsyncExpect(test, promise);
|
1786
|
+
};
|
1787
|
+
}
|
1788
|
+
});
|
1789
|
+
return proxy;
|
1790
|
+
}
|
1791
|
+
);
|
1792
|
+
utils.addProperty(
|
1793
|
+
chai.Assertion.prototype,
|
1794
|
+
"rejects",
|
1795
|
+
function __VITEST_REJECTS__() {
|
1796
|
+
const error = new Error("rejects");
|
1797
|
+
utils.flag(this, "promise", "rejects");
|
1798
|
+
utils.flag(this, "error", error);
|
1799
|
+
const test = utils.flag(this, "vitest-test");
|
1800
|
+
const obj = utils.flag(this, "object");
|
1801
|
+
const wrapper = typeof obj === "function" ? obj() : obj;
|
1802
|
+
if (utils.flag(this, "poll")) {
|
1803
|
+
throw new SyntaxError(
|
1804
|
+
`expect.poll() is not supported in combination with .rejects`
|
1805
|
+
);
|
1806
|
+
}
|
1807
|
+
if (typeof (wrapper == null ? void 0 : wrapper.then) !== "function") {
|
1808
|
+
throw new TypeError(
|
1809
|
+
`You must provide a Promise to expect() when using .rejects, not '${typeof wrapper}'.`
|
1810
|
+
);
|
1811
|
+
}
|
1812
|
+
const proxy = new Proxy(this, {
|
1813
|
+
get: (target, key, receiver) => {
|
1814
|
+
const result = Reflect.get(target, key, receiver);
|
1815
|
+
if (typeof result !== "function") {
|
1816
|
+
return result instanceof chai.Assertion ? proxy : result;
|
1817
|
+
}
|
1818
|
+
return async (...args) => {
|
1819
|
+
const promise = wrapper.then(
|
1820
|
+
(value) => {
|
1821
|
+
const _error = new AssertionError(
|
1822
|
+
`promise resolved "${utils.inspect(
|
1823
|
+
value
|
1824
|
+
)}" instead of rejecting`,
|
1825
|
+
{
|
1826
|
+
showDiff: true,
|
1827
|
+
expected: new Error("rejected promise"),
|
1828
|
+
actual: value
|
1829
|
+
}
|
1830
|
+
);
|
1831
|
+
_error.stack = error.stack.replace(
|
1832
|
+
error.message,
|
1833
|
+
_error.message
|
1834
|
+
);
|
1835
|
+
throw _error;
|
1836
|
+
},
|
1837
|
+
(err) => {
|
1838
|
+
utils.flag(this, "object", err);
|
1839
|
+
return result.call(this, ...args);
|
1840
|
+
}
|
1841
|
+
);
|
1842
|
+
return recordAsyncExpect(test, promise);
|
1843
|
+
};
|
1844
|
+
}
|
1845
|
+
});
|
1846
|
+
return proxy;
|
1847
|
+
}
|
1848
|
+
);
|
1641
1849
|
};
|
1642
1850
|
|
1643
1851
|
function getMatcherState(assertion, expect) {
|
@@ -1678,71 +1886,91 @@ class JestExtendError extends Error {
|
|
1678
1886
|
}
|
1679
1887
|
function JestExtendPlugin(c, expect, matchers) {
|
1680
1888
|
return (_, utils) => {
|
1681
|
-
Object.entries(matchers).forEach(
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
utils.addMethod(c.Assertion.prototype, expectAssertionName, softWrapper);
|
1698
|
-
class CustomMatcher extends AsymmetricMatcher {
|
1699
|
-
constructor(inverse = false, ...sample) {
|
1700
|
-
super(sample, inverse);
|
1701
|
-
}
|
1702
|
-
asymmetricMatch(other) {
|
1703
|
-
const { pass } = expectAssertion.call(
|
1704
|
-
this.getMatcherContext(expect),
|
1705
|
-
other,
|
1706
|
-
...this.sample
|
1707
|
-
);
|
1708
|
-
return this.inverse ? !pass : pass;
|
1709
|
-
}
|
1710
|
-
toString() {
|
1711
|
-
return `${this.inverse ? "not." : ""}${expectAssertionName}`;
|
1712
|
-
}
|
1713
|
-
getExpectedType() {
|
1714
|
-
return "any";
|
1889
|
+
Object.entries(matchers).forEach(
|
1890
|
+
([expectAssertionName, expectAssertion]) => {
|
1891
|
+
function expectWrapper(...args) {
|
1892
|
+
const { state, isNot, obj } = getMatcherState(this, expect);
|
1893
|
+
const result = expectAssertion.call(state, obj, ...args);
|
1894
|
+
if (result && typeof result === "object" && result instanceof Promise) {
|
1895
|
+
return result.then(({ pass: pass2, message: message2, actual: actual2, expected: expected2 }) => {
|
1896
|
+
if (pass2 && isNot || !pass2 && !isNot) {
|
1897
|
+
throw new JestExtendError(message2(), actual2, expected2);
|
1898
|
+
}
|
1899
|
+
});
|
1900
|
+
}
|
1901
|
+
const { pass, message, actual, expected } = result;
|
1902
|
+
if (pass && isNot || !pass && !isNot) {
|
1903
|
+
throw new JestExtendError(message(), actual, expected);
|
1904
|
+
}
|
1715
1905
|
}
|
1716
|
-
|
1717
|
-
|
1906
|
+
const softWrapper = wrapSoft(utils, expectWrapper);
|
1907
|
+
utils.addMethod(
|
1908
|
+
globalThis[JEST_MATCHERS_OBJECT].matchers,
|
1909
|
+
expectAssertionName,
|
1910
|
+
softWrapper
|
1911
|
+
);
|
1912
|
+
utils.addMethod(
|
1913
|
+
c.Assertion.prototype,
|
1914
|
+
expectAssertionName,
|
1915
|
+
softWrapper
|
1916
|
+
);
|
1917
|
+
class CustomMatcher extends AsymmetricMatcher {
|
1918
|
+
constructor(inverse = false, ...sample) {
|
1919
|
+
super(sample, inverse);
|
1920
|
+
}
|
1921
|
+
asymmetricMatch(other) {
|
1922
|
+
const { pass } = expectAssertion.call(
|
1923
|
+
this.getMatcherContext(expect),
|
1924
|
+
other,
|
1925
|
+
...this.sample
|
1926
|
+
);
|
1927
|
+
return this.inverse ? !pass : pass;
|
1928
|
+
}
|
1929
|
+
toString() {
|
1930
|
+
return `${this.inverse ? "not." : ""}${expectAssertionName}`;
|
1931
|
+
}
|
1932
|
+
getExpectedType() {
|
1933
|
+
return "any";
|
1934
|
+
}
|
1935
|
+
toAsymmetricMatcher() {
|
1936
|
+
return `${this.toString()}<${this.sample.map(String).join(", ")}>`;
|
1937
|
+
}
|
1718
1938
|
}
|
1939
|
+
const customMatcher = (...sample) => new CustomMatcher(false, ...sample);
|
1940
|
+
Object.defineProperty(expect, expectAssertionName, {
|
1941
|
+
configurable: true,
|
1942
|
+
enumerable: true,
|
1943
|
+
value: customMatcher,
|
1944
|
+
writable: true
|
1945
|
+
});
|
1946
|
+
Object.defineProperty(expect.not, expectAssertionName, {
|
1947
|
+
configurable: true,
|
1948
|
+
enumerable: true,
|
1949
|
+
value: (...sample) => new CustomMatcher(true, ...sample),
|
1950
|
+
writable: true
|
1951
|
+
});
|
1952
|
+
Object.defineProperty(
|
1953
|
+
globalThis[ASYMMETRIC_MATCHERS_OBJECT],
|
1954
|
+
expectAssertionName,
|
1955
|
+
{
|
1956
|
+
configurable: true,
|
1957
|
+
enumerable: true,
|
1958
|
+
value: customMatcher,
|
1959
|
+
writable: true
|
1960
|
+
}
|
1961
|
+
);
|
1719
1962
|
}
|
1720
|
-
|
1721
|
-
Object.defineProperty(expect, expectAssertionName, {
|
1722
|
-
configurable: true,
|
1723
|
-
enumerable: true,
|
1724
|
-
value: customMatcher,
|
1725
|
-
writable: true
|
1726
|
-
});
|
1727
|
-
Object.defineProperty(expect.not, expectAssertionName, {
|
1728
|
-
configurable: true,
|
1729
|
-
enumerable: true,
|
1730
|
-
value: (...sample) => new CustomMatcher(true, ...sample),
|
1731
|
-
writable: true
|
1732
|
-
});
|
1733
|
-
Object.defineProperty(globalThis[ASYMMETRIC_MATCHERS_OBJECT], expectAssertionName, {
|
1734
|
-
configurable: true,
|
1735
|
-
enumerable: true,
|
1736
|
-
value: customMatcher,
|
1737
|
-
writable: true
|
1738
|
-
});
|
1739
|
-
});
|
1963
|
+
);
|
1740
1964
|
};
|
1741
1965
|
}
|
1742
1966
|
const JestExtend = (chai, utils) => {
|
1743
|
-
utils.addMethod(
|
1744
|
-
|
1745
|
-
|
1967
|
+
utils.addMethod(
|
1968
|
+
chai.expect,
|
1969
|
+
"extend",
|
1970
|
+
(expect, expects) => {
|
1971
|
+
use(JestExtendPlugin(chai, expect, expects));
|
1972
|
+
}
|
1973
|
+
);
|
1746
1974
|
};
|
1747
1975
|
|
1748
1976
|
export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
|