@vitest/expect 2.0.0-beta.10 → 2.0.0-beta.12
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.js +680 -454
- package/package.json +4 -4
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__@@";
|
@@ -309,12 +346,14 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
309
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
|
}
|
312
|
-
if (a.constructor !== b.constructor)
|
349
|
+
if (a.constructor !== b.constructor) {
|
313
350
|
return false;
|
351
|
+
}
|
314
352
|
let length = aStack.length;
|
315
353
|
while (length--) {
|
316
|
-
if (aStack[length] === a)
|
354
|
+
if (aStack[length] === a) {
|
317
355
|
return bStack[length] === b;
|
356
|
+
}
|
318
357
|
}
|
319
358
|
aStack.push(a);
|
320
359
|
bStack.push(b);
|
@@ -323,13 +362,7 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
323
362
|
iterableEqualityWithStack
|
324
363
|
];
|
325
364
|
function iterableEqualityWithStack(a2, b2) {
|
326
|
-
return iterableEquality(
|
327
|
-
a2,
|
328
|
-
b2,
|
329
|
-
[...customTesters],
|
330
|
-
[...aStack],
|
331
|
-
[...bStack]
|
332
|
-
);
|
365
|
+
return iterableEquality(a2, b2, [...customTesters], [...aStack], [...bStack]);
|
333
366
|
}
|
334
367
|
if (a.size !== void 0) {
|
335
368
|
if (a.size !== b.size) {
|
@@ -341,8 +374,9 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
341
374
|
let has = false;
|
342
375
|
for (const bValue of b) {
|
343
376
|
const isEqual = equals(aValue, bValue, filteredCustomTesters);
|
344
|
-
if (isEqual === true)
|
377
|
+
if (isEqual === true) {
|
345
378
|
has = true;
|
379
|
+
}
|
346
380
|
}
|
347
381
|
if (has === false) {
|
348
382
|
allFound = false;
|
@@ -359,12 +393,22 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
359
393
|
if (!b.has(aEntry[0]) || !equals(aEntry[1], b.get(aEntry[0]), filteredCustomTesters)) {
|
360
394
|
let has = false;
|
361
395
|
for (const bEntry of b) {
|
362
|
-
const matchedKey = equals(
|
396
|
+
const matchedKey = equals(
|
397
|
+
aEntry[0],
|
398
|
+
bEntry[0],
|
399
|
+
filteredCustomTesters
|
400
|
+
);
|
363
401
|
let matchedValue = false;
|
364
|
-
if (matchedKey === true)
|
365
|
-
matchedValue = equals(
|
366
|
-
|
402
|
+
if (matchedKey === true) {
|
403
|
+
matchedValue = equals(
|
404
|
+
aEntry[1],
|
405
|
+
bEntry[1],
|
406
|
+
filteredCustomTesters
|
407
|
+
);
|
408
|
+
}
|
409
|
+
if (matchedValue === true) {
|
367
410
|
has = true;
|
411
|
+
}
|
368
412
|
}
|
369
413
|
if (has === false) {
|
370
414
|
allFound = false;
|
@@ -384,13 +428,15 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
384
428
|
return false;
|
385
429
|
}
|
386
430
|
}
|
387
|
-
if (!bIterator.next().done)
|
431
|
+
if (!bIterator.next().done) {
|
388
432
|
return false;
|
433
|
+
}
|
389
434
|
if (!isImmutableList(a) && !isImmutableOrderedKeyed(a) && !isImmutableOrderedSet(a) && !isImmutableRecord(a)) {
|
390
435
|
const aEntries = Object.entries(a);
|
391
436
|
const bEntries = Object.entries(b);
|
392
|
-
if (!equals(aEntries, bEntries))
|
437
|
+
if (!equals(aEntries, bEntries)) {
|
393
438
|
return false;
|
439
|
+
}
|
394
440
|
}
|
395
441
|
aStack.pop();
|
396
442
|
bStack.pop();
|
@@ -398,22 +444,27 @@ function iterableEquality(a, b, customTesters = [], aStack = [], bStack = []) {
|
|
398
444
|
}
|
399
445
|
function hasPropertyInObject(object, key) {
|
400
446
|
const shouldTerminate = !object || typeof object !== "object" || object === Object.prototype;
|
401
|
-
if (shouldTerminate)
|
447
|
+
if (shouldTerminate) {
|
402
448
|
return false;
|
449
|
+
}
|
403
450
|
return Object.prototype.hasOwnProperty.call(object, key) || hasPropertyInObject(Object.getPrototypeOf(object), key);
|
404
451
|
}
|
405
452
|
function isObjectWithKeys(a) {
|
406
453
|
return isObject(a) && !(a instanceof Error) && !Array.isArray(a) && !(a instanceof Date);
|
407
454
|
}
|
408
455
|
function subsetEquality(object, subset, customTesters = []) {
|
409
|
-
const filteredCustomTesters = customTesters.filter(
|
456
|
+
const filteredCustomTesters = customTesters.filter(
|
457
|
+
(t) => t !== subsetEquality
|
458
|
+
);
|
410
459
|
const subsetEqualityWithContext = (seenReferences = /* @__PURE__ */ new WeakMap()) => (object2, subset2) => {
|
411
|
-
if (!isObjectWithKeys(subset2))
|
460
|
+
if (!isObjectWithKeys(subset2)) {
|
412
461
|
return void 0;
|
462
|
+
}
|
413
463
|
return Object.keys(subset2).every((key) => {
|
414
464
|
if (subset2[key] != null && typeof subset2[key] === "object") {
|
415
|
-
if (seenReferences.has(subset2[key]))
|
465
|
+
if (seenReferences.has(subset2[key])) {
|
416
466
|
return equals(object2[key], subset2[key], filteredCustomTesters);
|
467
|
+
}
|
417
468
|
seenReferences.set(subset2[key], true);
|
418
469
|
}
|
419
470
|
const result = object2 != null && hasPropertyInObject(object2, key) && equals(object2[key], subset2[key], [
|
@@ -427,16 +478,18 @@ function subsetEquality(object, subset, customTesters = []) {
|
|
427
478
|
return subsetEqualityWithContext()(object, subset);
|
428
479
|
}
|
429
480
|
function typeEquality(a, b) {
|
430
|
-
if (a == null || b == null || a.constructor === b.constructor)
|
481
|
+
if (a == null || b == null || a.constructor === b.constructor) {
|
431
482
|
return void 0;
|
483
|
+
}
|
432
484
|
return false;
|
433
485
|
}
|
434
486
|
function arrayBufferEquality(a, b) {
|
435
487
|
let dataViewA = a;
|
436
488
|
let dataViewB = b;
|
437
489
|
if (!(a instanceof DataView && b instanceof DataView)) {
|
438
|
-
if (!(a instanceof ArrayBuffer) || !(b instanceof ArrayBuffer))
|
490
|
+
if (!(a instanceof ArrayBuffer) || !(b instanceof ArrayBuffer)) {
|
439
491
|
return void 0;
|
492
|
+
}
|
440
493
|
try {
|
441
494
|
dataViewA = new DataView(a);
|
442
495
|
dataViewB = new DataView(b);
|
@@ -444,25 +497,30 @@ function arrayBufferEquality(a, b) {
|
|
444
497
|
return void 0;
|
445
498
|
}
|
446
499
|
}
|
447
|
-
if (dataViewA.byteLength !== dataViewB.byteLength)
|
500
|
+
if (dataViewA.byteLength !== dataViewB.byteLength) {
|
448
501
|
return false;
|
502
|
+
}
|
449
503
|
for (let i = 0; i < dataViewA.byteLength; i++) {
|
450
|
-
if (dataViewA.getUint8(i) !== dataViewB.getUint8(i))
|
504
|
+
if (dataViewA.getUint8(i) !== dataViewB.getUint8(i)) {
|
451
505
|
return false;
|
506
|
+
}
|
452
507
|
}
|
453
508
|
return true;
|
454
509
|
}
|
455
510
|
function sparseArrayEquality(a, b, customTesters = []) {
|
456
|
-
if (!Array.isArray(a) || !Array.isArray(b))
|
511
|
+
if (!Array.isArray(a) || !Array.isArray(b)) {
|
457
512
|
return void 0;
|
513
|
+
}
|
458
514
|
const aKeys = Object.keys(a);
|
459
515
|
const bKeys = Object.keys(b);
|
460
|
-
const filteredCustomTesters = customTesters.filter(
|
516
|
+
const filteredCustomTesters = customTesters.filter(
|
517
|
+
(t) => t !== sparseArrayEquality
|
518
|
+
);
|
461
519
|
return equals(a, b, filteredCustomTesters, true) && equals(aKeys, bKeys);
|
462
520
|
}
|
463
521
|
function generateToBeMessage(deepEqualityName, expected = "#{this}", actual = "#{exp}") {
|
464
522
|
const toBeMessage = `expected ${expected} to be ${actual} // Object.is equality`;
|
465
|
-
if (["toStrictEqual", "toEqual"].includes(deepEqualityName))
|
523
|
+
if (["toStrictEqual", "toEqual"].includes(deepEqualityName)) {
|
466
524
|
return `${toBeMessage}
|
467
525
|
|
468
526
|
If it should pass with deep equality, replace "toBe" with "${deepEqualityName}"
|
@@ -470,6 +528,7 @@ If it should pass with deep equality, replace "toBe" with "${deepEqualityName}"
|
|
470
528
|
Expected: ${expected}
|
471
529
|
Received: serializes to the same string
|
472
530
|
`;
|
531
|
+
}
|
473
532
|
return toBeMessage;
|
474
533
|
}
|
475
534
|
function pluralize(word, count) {
|
@@ -509,18 +568,26 @@ function getObjectSubset(object, subset, customTesters = []) {
|
|
509
568
|
seenReferences.set(object2, trimmed);
|
510
569
|
for (const key of getObjectKeys(object2)) {
|
511
570
|
if (hasPropertyInObject(subset2, key)) {
|
512
|
-
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
|
+
);
|
513
575
|
} else {
|
514
576
|
if (!seenReferences.has(object2[key])) {
|
515
577
|
stripped += 1;
|
516
|
-
if (isObject(object2[key]))
|
578
|
+
if (isObject(object2[key])) {
|
517
579
|
stripped += getObjectKeys(object2[key]).length;
|
518
|
-
|
580
|
+
}
|
581
|
+
getObjectSubsetWithContext(seenReferences)(
|
582
|
+
object2[key],
|
583
|
+
subset2[key]
|
584
|
+
);
|
519
585
|
}
|
520
586
|
}
|
521
587
|
}
|
522
|
-
if (getObjectKeys(trimmed).length > 0)
|
588
|
+
if (getObjectKeys(trimmed).length > 0) {
|
523
589
|
return trimmed;
|
590
|
+
}
|
524
591
|
}
|
525
592
|
return object2;
|
526
593
|
};
|
@@ -553,15 +620,17 @@ class AsymmetricMatcher {
|
|
553
620
|
// https://github.com/chaijs/loupe/blob/9b8a6deabcd50adc056a64fb705896194710c5c6/src/index.ts#L29
|
554
621
|
[Symbol.for("chai/inspect")](options) {
|
555
622
|
const result = stringify(this, options.depth, { min: true });
|
556
|
-
if (result.length <= options.truncate)
|
623
|
+
if (result.length <= options.truncate) {
|
557
624
|
return result;
|
625
|
+
}
|
558
626
|
return `${this.toString()}{\u2026}`;
|
559
627
|
}
|
560
628
|
}
|
561
629
|
class StringContaining extends AsymmetricMatcher {
|
562
630
|
constructor(sample, inverse = false) {
|
563
|
-
if (!isA("String", sample))
|
631
|
+
if (!isA("String", sample)) {
|
564
632
|
throw new Error("Expected is not a string");
|
633
|
+
}
|
565
634
|
super(sample, inverse);
|
566
635
|
}
|
567
636
|
asymmetricMatch(other) {
|
@@ -591,17 +660,21 @@ class ObjectContaining extends AsymmetricMatcher {
|
|
591
660
|
super(sample, inverse);
|
592
661
|
}
|
593
662
|
getPrototype(obj) {
|
594
|
-
if (Object.getPrototypeOf)
|
663
|
+
if (Object.getPrototypeOf) {
|
595
664
|
return Object.getPrototypeOf(obj);
|
596
|
-
|
665
|
+
}
|
666
|
+
if (obj.constructor.prototype === obj) {
|
597
667
|
return null;
|
668
|
+
}
|
598
669
|
return obj.constructor.prototype;
|
599
670
|
}
|
600
671
|
hasProperty(obj, property) {
|
601
|
-
if (!obj)
|
672
|
+
if (!obj) {
|
602
673
|
return false;
|
603
|
-
|
674
|
+
}
|
675
|
+
if (Object.prototype.hasOwnProperty.call(obj, property)) {
|
604
676
|
return true;
|
677
|
+
}
|
605
678
|
return this.hasProperty(this.getPrototype(obj), property);
|
606
679
|
}
|
607
680
|
asymmetricMatch(other) {
|
@@ -613,7 +686,11 @@ class ObjectContaining extends AsymmetricMatcher {
|
|
613
686
|
let result = true;
|
614
687
|
const matcherContext = this.getMatcherContext();
|
615
688
|
for (const property in this.sample) {
|
616
|
-
if (!this.hasProperty(other, property) || !equals(
|
689
|
+
if (!this.hasProperty(other, property) || !equals(
|
690
|
+
this.sample[property],
|
691
|
+
other[property],
|
692
|
+
matcherContext.customTesters
|
693
|
+
)) {
|
617
694
|
result = false;
|
618
695
|
break;
|
619
696
|
}
|
@@ -639,7 +716,9 @@ class ArrayContaining extends AsymmetricMatcher {
|
|
639
716
|
}
|
640
717
|
const matcherContext = this.getMatcherContext();
|
641
718
|
const result = this.sample.length === 0 || Array.isArray(other) && this.sample.every(
|
642
|
-
(item) => other.some(
|
719
|
+
(item) => other.some(
|
720
|
+
(another) => equals(item, another, matcherContext.customTesters)
|
721
|
+
)
|
643
722
|
);
|
644
723
|
return this.inverse ? !result : result;
|
645
724
|
}
|
@@ -660,43 +739,56 @@ class Any extends AsymmetricMatcher {
|
|
660
739
|
super(sample);
|
661
740
|
}
|
662
741
|
fnNameFor(func) {
|
663
|
-
if (func.name)
|
742
|
+
if (func.name) {
|
664
743
|
return func.name;
|
744
|
+
}
|
665
745
|
const functionToString = Function.prototype.toString;
|
666
746
|
const matches = functionToString.call(func).match(/^(?:async)?\s*function\s*(?:\*\s*)?([\w$]+)\s*\(/);
|
667
747
|
return matches ? matches[1] : "<anonymous>";
|
668
748
|
}
|
669
749
|
asymmetricMatch(other) {
|
670
|
-
if (this.sample === String)
|
750
|
+
if (this.sample === String) {
|
671
751
|
return typeof other == "string" || other instanceof String;
|
672
|
-
|
752
|
+
}
|
753
|
+
if (this.sample === Number) {
|
673
754
|
return typeof other == "number" || other instanceof Number;
|
674
|
-
|
755
|
+
}
|
756
|
+
if (this.sample === Function) {
|
675
757
|
return typeof other == "function" || other instanceof Function;
|
676
|
-
|
758
|
+
}
|
759
|
+
if (this.sample === Boolean) {
|
677
760
|
return typeof other == "boolean" || other instanceof Boolean;
|
678
|
-
|
761
|
+
}
|
762
|
+
if (this.sample === BigInt) {
|
679
763
|
return typeof other == "bigint" || other instanceof BigInt;
|
680
|
-
|
764
|
+
}
|
765
|
+
if (this.sample === Symbol) {
|
681
766
|
return typeof other == "symbol" || other instanceof Symbol;
|
682
|
-
|
767
|
+
}
|
768
|
+
if (this.sample === Object) {
|
683
769
|
return typeof other == "object";
|
770
|
+
}
|
684
771
|
return other instanceof this.sample;
|
685
772
|
}
|
686
773
|
toString() {
|
687
774
|
return "Any";
|
688
775
|
}
|
689
776
|
getExpectedType() {
|
690
|
-
if (this.sample === String)
|
777
|
+
if (this.sample === String) {
|
691
778
|
return "string";
|
692
|
-
|
779
|
+
}
|
780
|
+
if (this.sample === Number) {
|
693
781
|
return "number";
|
694
|
-
|
782
|
+
}
|
783
|
+
if (this.sample === Function) {
|
695
784
|
return "function";
|
696
|
-
|
785
|
+
}
|
786
|
+
if (this.sample === Object) {
|
697
787
|
return "object";
|
698
|
-
|
788
|
+
}
|
789
|
+
if (this.sample === Boolean) {
|
699
790
|
return "boolean";
|
791
|
+
}
|
700
792
|
return this.fnNameFor(this.sample);
|
701
793
|
}
|
702
794
|
toAsymmetricMatcher() {
|
@@ -705,8 +797,9 @@ class Any extends AsymmetricMatcher {
|
|
705
797
|
}
|
706
798
|
class StringMatching extends AsymmetricMatcher {
|
707
799
|
constructor(sample, inverse = false) {
|
708
|
-
if (!isA("String", sample) && !isA("RegExp", sample))
|
800
|
+
if (!isA("String", sample) && !isA("RegExp", sample)) {
|
709
801
|
throw new Error("Expected is not a String or a RegExp");
|
802
|
+
}
|
710
803
|
super(new RegExp(sample), inverse);
|
711
804
|
}
|
712
805
|
asymmetricMatch(other) {
|
@@ -723,17 +816,20 @@ class StringMatching extends AsymmetricMatcher {
|
|
723
816
|
class CloseTo extends AsymmetricMatcher {
|
724
817
|
precision;
|
725
818
|
constructor(sample, precision = 2, inverse = false) {
|
726
|
-
if (!isA("Number", sample))
|
819
|
+
if (!isA("Number", sample)) {
|
727
820
|
throw new Error("Expected is not a Number");
|
728
|
-
|
821
|
+
}
|
822
|
+
if (!isA("Number", precision)) {
|
729
823
|
throw new Error("Precision is not a Number");
|
824
|
+
}
|
730
825
|
super(sample);
|
731
826
|
this.inverse = inverse;
|
732
827
|
this.precision = precision;
|
733
828
|
}
|
734
829
|
asymmetricMatch(other) {
|
735
|
-
if (!isA("Number", other))
|
830
|
+
if (!isA("Number", other)) {
|
736
831
|
return false;
|
832
|
+
}
|
737
833
|
let result = false;
|
738
834
|
if (other === Number.POSITIVE_INFINITY && this.sample === Number.POSITIVE_INFINITY) {
|
739
835
|
result = true;
|
@@ -759,16 +855,8 @@ class CloseTo extends AsymmetricMatcher {
|
|
759
855
|
}
|
760
856
|
}
|
761
857
|
const JestAsymmetricMatchers = (chai, utils) => {
|
762
|
-
utils.addMethod(
|
763
|
-
|
764
|
-
"anything",
|
765
|
-
() => new Anything()
|
766
|
-
);
|
767
|
-
utils.addMethod(
|
768
|
-
chai.expect,
|
769
|
-
"any",
|
770
|
-
(expected) => new Any(expected)
|
771
|
-
);
|
858
|
+
utils.addMethod(chai.expect, "anything", () => new Anything());
|
859
|
+
utils.addMethod(chai.expect, "any", (expected) => new Any(expected));
|
772
860
|
utils.addMethod(
|
773
861
|
chai.expect,
|
774
862
|
"stringContaining",
|
@@ -807,11 +895,13 @@ function recordAsyncExpect(test, promise) {
|
|
807
895
|
if (test && promise instanceof Promise) {
|
808
896
|
promise = promise.finally(() => {
|
809
897
|
const index = test.promises.indexOf(promise);
|
810
|
-
if (index !== -1)
|
898
|
+
if (index !== -1) {
|
811
899
|
test.promises.splice(index, 1);
|
900
|
+
}
|
812
901
|
});
|
813
|
-
if (!test.promises)
|
902
|
+
if (!test.promises) {
|
814
903
|
test.promises = [];
|
904
|
+
}
|
815
905
|
test.promises.push(promise);
|
816
906
|
}
|
817
907
|
return promise;
|
@@ -819,11 +909,13 @@ function recordAsyncExpect(test, promise) {
|
|
819
909
|
function wrapSoft(utils, fn) {
|
820
910
|
return function(...args) {
|
821
911
|
var _a;
|
822
|
-
if (!utils.flag(this, "soft"))
|
912
|
+
if (!utils.flag(this, "soft")) {
|
823
913
|
return fn.apply(this, args);
|
914
|
+
}
|
824
915
|
const test = utils.flag(this, "vitest-test");
|
825
|
-
if (!test)
|
916
|
+
if (!test) {
|
826
917
|
throw new Error("expect.soft() can only be used inside a test");
|
918
|
+
}
|
827
919
|
try {
|
828
920
|
return fn.apply(this, args);
|
829
921
|
} catch (err) {
|
@@ -843,12 +935,17 @@ const JestChaiExpect = (chai, utils) => {
|
|
843
935
|
const addMethod = (n) => {
|
844
936
|
const softWrapper = wrapSoft(utils, fn);
|
845
937
|
utils.addMethod(chai.Assertion.prototype, n, softWrapper);
|
846
|
-
utils.addMethod(
|
938
|
+
utils.addMethod(
|
939
|
+
globalThis[JEST_MATCHERS_OBJECT].matchers,
|
940
|
+
n,
|
941
|
+
softWrapper
|
942
|
+
);
|
847
943
|
};
|
848
|
-
if (Array.isArray(name))
|
944
|
+
if (Array.isArray(name)) {
|
849
945
|
name.forEach((n) => addMethod(n));
|
850
|
-
else
|
946
|
+
} else {
|
851
947
|
addMethod(name);
|
948
|
+
}
|
852
949
|
}
|
853
950
|
["throw", "throws", "Throw"].forEach((m) => {
|
854
951
|
utils.overwriteMethod(chai.Assertion.prototype, m, (_super) => {
|
@@ -881,11 +978,10 @@ const JestChaiExpect = (chai, utils) => {
|
|
881
978
|
});
|
882
979
|
def("toEqual", function(expected) {
|
883
980
|
const actual = utils.flag(this, "object");
|
884
|
-
const equal = equals(
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
);
|
981
|
+
const equal = equals(actual, expected, [
|
982
|
+
...customTesters,
|
983
|
+
iterableEquality
|
984
|
+
]);
|
889
985
|
return this.assert(
|
890
986
|
equal,
|
891
987
|
"expected #{this} to deeply equal #{exp}",
|
@@ -936,13 +1032,13 @@ const JestChaiExpect = (chai, utils) => {
|
|
936
1032
|
if (toStrictEqualPass) {
|
937
1033
|
deepEqualityName = "toStrictEqual";
|
938
1034
|
} else {
|
939
|
-
const toEqualPass = equals(
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
)
|
944
|
-
if (toEqualPass)
|
1035
|
+
const toEqualPass = equals(actual, expected, [
|
1036
|
+
...customTesters,
|
1037
|
+
iterableEquality
|
1038
|
+
]);
|
1039
|
+
if (toEqualPass) {
|
945
1040
|
deepEqualityName = "toEqual";
|
1041
|
+
}
|
946
1042
|
}
|
947
1043
|
}
|
948
1044
|
return this.assert(
|
@@ -955,30 +1051,41 @@ const JestChaiExpect = (chai, utils) => {
|
|
955
1051
|
});
|
956
1052
|
def("toMatchObject", function(expected) {
|
957
1053
|
const actual = this._obj;
|
958
|
-
const pass = equals(actual, expected, [
|
1054
|
+
const pass = equals(actual, expected, [
|
1055
|
+
...customTesters,
|
1056
|
+
iterableEquality,
|
1057
|
+
subsetEquality
|
1058
|
+
]);
|
959
1059
|
const isNot = utils.flag(this, "negate");
|
960
|
-
const { subset: actualSubset, stripped } = getObjectSubset(
|
1060
|
+
const { subset: actualSubset, stripped } = getObjectSubset(
|
1061
|
+
actual,
|
1062
|
+
expected
|
1063
|
+
);
|
961
1064
|
if (pass && isNot || !pass && !isNot) {
|
962
|
-
const msg = utils.getMessage(
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
false
|
971
|
-
]
|
972
|
-
);
|
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
|
+
]);
|
973
1073
|
const message = stripped === 0 ? msg : `${msg}
|
974
1074
|
(${stripped} matching ${stripped === 1 ? "property" : "properties"} omitted from actual)`;
|
975
|
-
throw new AssertionError(message, {
|
1075
|
+
throw new AssertionError(message, {
|
1076
|
+
showDiff: true,
|
1077
|
+
expected,
|
1078
|
+
actual: actualSubset
|
1079
|
+
});
|
976
1080
|
}
|
977
1081
|
});
|
978
1082
|
def("toMatch", function(expected) {
|
979
1083
|
const actual = this._obj;
|
980
|
-
if (typeof actual !== "string")
|
981
|
-
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
|
+
}
|
982
1089
|
return this.assert(
|
983
1090
|
typeof expected === "string" ? actual.includes(expected) : actual.match(expected),
|
984
1091
|
`expected #{this} to match #{exp}`,
|
@@ -990,8 +1097,11 @@ const JestChaiExpect = (chai, utils) => {
|
|
990
1097
|
def("toContain", function(item) {
|
991
1098
|
const actual = this._obj;
|
992
1099
|
if (typeof Node !== "undefined" && actual instanceof Node) {
|
993
|
-
if (!(item instanceof Node))
|
994
|
-
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
|
+
}
|
995
1105
|
return this.assert(
|
996
1106
|
actual.contains(item),
|
997
1107
|
"expected #{this} to contain element #{exp}",
|
@@ -1021,8 +1131,9 @@ const JestChaiExpect = (chai, utils) => {
|
|
1021
1131
|
actual
|
1022
1132
|
);
|
1023
1133
|
}
|
1024
|
-
if (actual != null && typeof actual !== "string")
|
1134
|
+
if (actual != null && typeof actual !== "string") {
|
1025
1135
|
utils.flag(this, "object", Array.from(actual));
|
1136
|
+
}
|
1026
1137
|
return this.contain(item);
|
1027
1138
|
});
|
1028
1139
|
def("toContainEqual", function(expected) {
|
@@ -1121,49 +1232,61 @@ const JestChaiExpect = (chai, utils) => {
|
|
1121
1232
|
def("toBeDefined", function() {
|
1122
1233
|
const negate = utils.flag(this, "negate");
|
1123
1234
|
utils.flag(this, "negate", false);
|
1124
|
-
if (negate)
|
1235
|
+
if (negate) {
|
1125
1236
|
return this.be.undefined;
|
1237
|
+
}
|
1126
1238
|
return this.not.be.undefined;
|
1127
1239
|
});
|
1128
|
-
def(
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
equal
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
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
|
+
);
|
1139
1254
|
def("toBeInstanceOf", function(obj) {
|
1140
1255
|
return this.instanceOf(obj);
|
1141
1256
|
});
|
1142
1257
|
def("toHaveLength", function(length) {
|
1143
1258
|
return this.have.length(length);
|
1144
1259
|
});
|
1145
|
-
def(
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
const
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
exists
|
1165
|
-
|
1166
|
-
|
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
|
+
);
|
1167
1290
|
def("toBeCloseTo", function(received, precision = 2) {
|
1168
1291
|
const expected = this._obj;
|
1169
1292
|
let pass = false;
|
@@ -1188,8 +1311,11 @@ const JestChaiExpect = (chai, utils) => {
|
|
1188
1311
|
);
|
1189
1312
|
});
|
1190
1313
|
const assertIsMock = (assertion) => {
|
1191
|
-
if (!isMockFunction(assertion._obj))
|
1192
|
-
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
|
+
}
|
1193
1319
|
};
|
1194
1320
|
const getSpy = (assertion) => {
|
1195
1321
|
assertIsMock(assertion);
|
@@ -1198,58 +1324,79 @@ const JestChaiExpect = (chai, utils) => {
|
|
1198
1324
|
const ordinalOf = (i) => {
|
1199
1325
|
const j = i % 10;
|
1200
1326
|
const k = i % 100;
|
1201
|
-
if (j === 1 && k !== 11)
|
1327
|
+
if (j === 1 && k !== 11) {
|
1202
1328
|
return `${i}st`;
|
1203
|
-
|
1329
|
+
}
|
1330
|
+
if (j === 2 && k !== 12) {
|
1204
1331
|
return `${i}nd`;
|
1205
|
-
|
1332
|
+
}
|
1333
|
+
if (j === 3 && k !== 13) {
|
1206
1334
|
return `${i}rd`;
|
1335
|
+
}
|
1207
1336
|
return `${i}th`;
|
1208
1337
|
};
|
1209
1338
|
const formatCalls = (spy, msg, showActualCall) => {
|
1210
1339
|
if (spy.mock.calls) {
|
1211
|
-
msg += c().gray(
|
1340
|
+
msg += c().gray(
|
1341
|
+
`
|
1212
1342
|
|
1213
1343
|
Received:
|
1214
1344
|
|
1215
1345
|
${spy.mock.calls.map((callArg, i) => {
|
1216
|
-
|
1346
|
+
let methodCall = c().bold(
|
1347
|
+
` ${ordinalOf(i + 1)} ${spy.getMockName()} call:
|
1217
1348
|
|
1218
|
-
`
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
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
|
+
);
|
1226
1362
|
}
|
1227
|
-
msg += c().gray(
|
1363
|
+
msg += c().gray(
|
1364
|
+
`
|
1228
1365
|
|
1229
1366
|
Number of calls: ${c().bold(spy.mock.calls.length)}
|
1230
|
-
`
|
1367
|
+
`
|
1368
|
+
);
|
1231
1369
|
return msg;
|
1232
1370
|
};
|
1233
1371
|
const formatReturns = (spy, results, msg, showActualReturn) => {
|
1234
|
-
msg += c().gray(
|
1372
|
+
msg += c().gray(
|
1373
|
+
`
|
1235
1374
|
|
1236
1375
|
Received:
|
1237
1376
|
|
1238
1377
|
${results.map((callReturn, i) => {
|
1239
|
-
|
1378
|
+
let methodCall = c().bold(
|
1379
|
+
` ${ordinalOf(i + 1)} ${spy.getMockName()} call return:
|
1240
1380
|
|
1241
|
-
`
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
}).join("\n")
|
1249
|
-
|
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
|
+
`
|
1250
1396
|
|
1251
1397
|
Number of calls: ${c().bold(spy.mock.calls.length)}
|
1252
|
-
`
|
1398
|
+
`
|
1399
|
+
);
|
1253
1400
|
return msg;
|
1254
1401
|
};
|
1255
1402
|
def(["toHaveBeenCalledTimes", "toBeCalledTimes"], function(number) {
|
@@ -1284,131 +1431,146 @@ Number of calls: ${c().bold(spy.mock.calls.length)}
|
|
1284
1431
|
const callCount = spy.mock.calls.length;
|
1285
1432
|
const called = callCount > 0;
|
1286
1433
|
const isNot = utils.flag(this, "negate");
|
1287
|
-
let msg = utils.getMessage(
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
]
|
1296
|
-
);
|
1297
|
-
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) {
|
1298
1442
|
msg = formatCalls(spy, msg);
|
1299
|
-
|
1443
|
+
}
|
1444
|
+
if (called && isNot || !called && !isNot) {
|
1300
1445
|
throw new AssertionError(msg);
|
1446
|
+
}
|
1301
1447
|
});
|
1302
1448
|
def(["toHaveBeenCalledWith", "toBeCalledWith"], function(...args) {
|
1303
1449
|
const spy = getSpy(this);
|
1304
1450
|
const spyName = spy.getMockName();
|
1305
|
-
const pass = spy.mock.calls.some(
|
1306
|
-
|
1307
|
-
const msg = utils.getMessage(
|
1308
|
-
this,
|
1309
|
-
[
|
1310
|
-
pass,
|
1311
|
-
`expected "${spyName}" to be called with arguments: #{exp}`,
|
1312
|
-
`expected "${spyName}" to not be called with arguments: #{exp}`,
|
1313
|
-
args
|
1314
|
-
]
|
1315
|
-
);
|
1316
|
-
if (pass && isNot || !pass && !isNot)
|
1317
|
-
throw new AssertionError(formatCalls(spy, msg, args));
|
1318
|
-
});
|
1319
|
-
def(["toHaveBeenNthCalledWith", "nthCalledWith"], function(times, ...args) {
|
1320
|
-
const spy = getSpy(this);
|
1321
|
-
const spyName = spy.getMockName();
|
1322
|
-
const nthCall = spy.mock.calls[times - 1];
|
1323
|
-
const callCount = spy.mock.calls.length;
|
1324
|
-
const isCalled = times <= callCount;
|
1325
|
-
this.assert(
|
1326
|
-
equals(nthCall, args, [...customTesters, iterableEquality]),
|
1327
|
-
`expected ${ordinalOf(times)} "${spyName}" call to have been called with #{exp}${isCalled ? `` : `, but called only ${callCount} times`}`,
|
1328
|
-
`expected ${ordinalOf(times)} "${spyName}" call to not have been called with #{exp}`,
|
1329
|
-
args,
|
1330
|
-
nthCall,
|
1331
|
-
isCalled
|
1451
|
+
const pass = spy.mock.calls.some(
|
1452
|
+
(callArg) => equals(callArg, args, [...customTesters, iterableEquality])
|
1332
1453
|
);
|
1333
|
-
});
|
1334
|
-
def(["toHaveBeenLastCalledWith", "lastCalledWith"], function(...args) {
|
1335
|
-
const spy = getSpy(this);
|
1336
|
-
const spyName = spy.getMockName();
|
1337
|
-
const lastCall = spy.mock.calls[spy.mock.calls.length - 1];
|
1338
|
-
this.assert(
|
1339
|
-
equals(lastCall, args, [...customTesters, iterableEquality]),
|
1340
|
-
`expected last "${spyName}" call to have been called with #{exp}`,
|
1341
|
-
`expected last "${spyName}" call to not have been called with #{exp}`,
|
1342
|
-
args,
|
1343
|
-
lastCall
|
1344
|
-
);
|
1345
|
-
});
|
1346
|
-
def(["toThrow", "toThrowError"], function(expected) {
|
1347
|
-
if (typeof expected === "string" || typeof expected === "undefined" || expected instanceof RegExp)
|
1348
|
-
return this.throws(expected);
|
1349
|
-
const obj = this._obj;
|
1350
|
-
const promise = utils.flag(this, "promise");
|
1351
1454
|
const isNot = utils.flag(this, "negate");
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
};
|
1361
|
-
throw new AssertionError(message, error, utils.flag(this, "ssfi"));
|
1362
|
-
} else {
|
1363
|
-
return;
|
1364
|
-
}
|
1365
|
-
} else {
|
1366
|
-
let isThrow = false;
|
1367
|
-
try {
|
1368
|
-
obj();
|
1369
|
-
} catch (err) {
|
1370
|
-
isThrow = true;
|
1371
|
-
thrown = err;
|
1372
|
-
}
|
1373
|
-
if (!isThrow && !isNot) {
|
1374
|
-
const message = utils.flag(this, "message") || "expected function to throw an error, but it didn't";
|
1375
|
-
const error = {
|
1376
|
-
showDiff: false
|
1377
|
-
};
|
1378
|
-
throw new AssertionError(message, error, utils.flag(this, "ssfi"));
|
1379
|
-
}
|
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));
|
1380
1463
|
}
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
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
|
1389
1484
|
);
|
1390
1485
|
}
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
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
|
1398
1499
|
);
|
1399
1500
|
}
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
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}"`
|
1408
1571
|
);
|
1409
1572
|
}
|
1410
|
-
|
1411
|
-
});
|
1573
|
+
);
|
1412
1574
|
[
|
1413
1575
|
{
|
1414
1576
|
name: "toHaveResolved",
|
@@ -1438,12 +1600,18 @@ Number of calls: ${c().bold(spy.mock.calls.length)}
|
|
1438
1600
|
[
|
1439
1601
|
{
|
1440
1602
|
name: "toHaveResolvedTimes",
|
1441
|
-
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,
|
1442
1607
|
action: "resolved"
|
1443
1608
|
},
|
1444
1609
|
{
|
1445
1610
|
name: ["toHaveReturnedTimes", "toReturnTimes"],
|
1446
|
-
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,
|
1447
1615
|
action: "called"
|
1448
1616
|
}
|
1449
1617
|
].forEach(({ name, condition, action }) => {
|
@@ -1464,12 +1632,16 @@ Number of calls: ${c().bold(spy.mock.calls.length)}
|
|
1464
1632
|
[
|
1465
1633
|
{
|
1466
1634
|
name: "toHaveResolvedWith",
|
1467
|
-
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
|
+
),
|
1468
1638
|
action: "resolve"
|
1469
1639
|
},
|
1470
1640
|
{
|
1471
1641
|
name: ["toHaveReturnedWith", "toReturnWith"],
|
1472
|
-
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
|
+
),
|
1473
1645
|
action: "return"
|
1474
1646
|
}
|
1475
1647
|
].forEach(({ name, condition, action }) => {
|
@@ -1479,15 +1651,12 @@ Number of calls: ${c().bold(spy.mock.calls.length)}
|
|
1479
1651
|
const isNot = utils.flag(this, "negate");
|
1480
1652
|
if (pass && isNot || !pass && !isNot) {
|
1481
1653
|
const spyName = spy.getMockName();
|
1482
|
-
const msg = utils.getMessage(
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
value
|
1489
|
-
]
|
1490
|
-
);
|
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
|
+
]);
|
1491
1660
|
const results = action === "return" ? spy.mock.results : spy.mock.settledResults;
|
1492
1661
|
throw new AssertionError(formatReturns(spy, results, msg, value));
|
1493
1662
|
}
|
@@ -1562,84 +1731,121 @@ Number of calls: ${c().bold(spy.mock.calls.length)}
|
|
1562
1731
|
return this.be.satisfy(matcher, message);
|
1563
1732
|
});
|
1564
1733
|
def("withContext", function(context) {
|
1565
|
-
for (const key in context)
|
1734
|
+
for (const key in context) {
|
1566
1735
|
utils.flag(this, key, context[key]);
|
1736
|
+
}
|
1567
1737
|
return this;
|
1568
1738
|
});
|
1569
|
-
utils.addProperty(
|
1570
|
-
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
if (typeof result !== "function")
|
1583
|
-
return result instanceof chai.Assertion ? proxy : result;
|
1584
|
-
return async (...args) => {
|
1585
|
-
const promise = obj.then(
|
1586
|
-
(value) => {
|
1587
|
-
utils.flag(this, "object", value);
|
1588
|
-
return result.call(this, ...args);
|
1589
|
-
},
|
1590
|
-
(err) => {
|
1591
|
-
const _error = new AssertionError(
|
1592
|
-
`promise rejected "${utils.inspect(err)}" instead of resolving`,
|
1593
|
-
{ showDiff: false }
|
1594
|
-
);
|
1595
|
-
_error.cause = err;
|
1596
|
-
_error.stack = error.stack.replace(error.message, _error.message);
|
1597
|
-
throw _error;
|
1598
|
-
}
|
1599
|
-
);
|
1600
|
-
return recordAsyncExpect(test, promise);
|
1601
|
-
};
|
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
|
+
);
|
1602
1752
|
}
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
const error = new Error("rejects");
|
1608
|
-
utils.flag(this, "promise", "rejects");
|
1609
|
-
utils.flag(this, "error", error);
|
1610
|
-
const test = utils.flag(this, "vitest-test");
|
1611
|
-
const obj = utils.flag(this, "object");
|
1612
|
-
const wrapper = typeof obj === "function" ? obj() : obj;
|
1613
|
-
if (utils.flag(this, "poll"))
|
1614
|
-
throw new SyntaxError(`expect.poll() is not supported in combination with .rejects`);
|
1615
|
-
if (typeof (wrapper == null ? void 0 : wrapper.then) !== "function")
|
1616
|
-
throw new TypeError(`You must provide a Promise to expect() when using .rejects, not '${typeof wrapper}'.`);
|
1617
|
-
const proxy = new Proxy(this, {
|
1618
|
-
get: (target, key, receiver) => {
|
1619
|
-
const result = Reflect.get(target, key, receiver);
|
1620
|
-
if (typeof result !== "function")
|
1621
|
-
return result instanceof chai.Assertion ? proxy : result;
|
1622
|
-
return async (...args) => {
|
1623
|
-
const promise = wrapper.then(
|
1624
|
-
(value) => {
|
1625
|
-
const _error = new AssertionError(
|
1626
|
-
`promise resolved "${utils.inspect(value)}" instead of rejecting`,
|
1627
|
-
{ showDiff: true, expected: new Error("rejected promise"), actual: value }
|
1628
|
-
);
|
1629
|
-
_error.stack = error.stack.replace(error.message, _error.message);
|
1630
|
-
throw _error;
|
1631
|
-
},
|
1632
|
-
(err) => {
|
1633
|
-
utils.flag(this, "object", err);
|
1634
|
-
return result.call(this, ...args);
|
1635
|
-
}
|
1636
|
-
);
|
1637
|
-
return recordAsyncExpect(test, promise);
|
1638
|
-
};
|
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
|
+
);
|
1639
1757
|
}
|
1640
|
-
|
1641
|
-
|
1642
|
-
|
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
|
+
);
|
1643
1849
|
};
|
1644
1850
|
|
1645
1851
|
function getMatcherState(assertion, expect) {
|
@@ -1680,71 +1886,91 @@ class JestExtendError extends Error {
|
|
1680
1886
|
}
|
1681
1887
|
function JestExtendPlugin(c, expect, matchers) {
|
1682
1888
|
return (_, utils) => {
|
1683
|
-
Object.entries(matchers).forEach(
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
utils.addMethod(c.Assertion.prototype, expectAssertionName, softWrapper);
|
1700
|
-
class CustomMatcher extends AsymmetricMatcher {
|
1701
|
-
constructor(inverse = false, ...sample) {
|
1702
|
-
super(sample, inverse);
|
1703
|
-
}
|
1704
|
-
asymmetricMatch(other) {
|
1705
|
-
const { pass } = expectAssertion.call(
|
1706
|
-
this.getMatcherContext(expect),
|
1707
|
-
other,
|
1708
|
-
...this.sample
|
1709
|
-
);
|
1710
|
-
return this.inverse ? !pass : pass;
|
1711
|
-
}
|
1712
|
-
toString() {
|
1713
|
-
return `${this.inverse ? "not." : ""}${expectAssertionName}`;
|
1714
|
-
}
|
1715
|
-
getExpectedType() {
|
1716
|
-
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
|
+
}
|
1717
1905
|
}
|
1718
|
-
|
1719
|
-
|
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
|
+
}
|
1720
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
|
+
);
|
1721
1962
|
}
|
1722
|
-
|
1723
|
-
Object.defineProperty(expect, expectAssertionName, {
|
1724
|
-
configurable: true,
|
1725
|
-
enumerable: true,
|
1726
|
-
value: customMatcher,
|
1727
|
-
writable: true
|
1728
|
-
});
|
1729
|
-
Object.defineProperty(expect.not, expectAssertionName, {
|
1730
|
-
configurable: true,
|
1731
|
-
enumerable: true,
|
1732
|
-
value: (...sample) => new CustomMatcher(true, ...sample),
|
1733
|
-
writable: true
|
1734
|
-
});
|
1735
|
-
Object.defineProperty(globalThis[ASYMMETRIC_MATCHERS_OBJECT], expectAssertionName, {
|
1736
|
-
configurable: true,
|
1737
|
-
enumerable: true,
|
1738
|
-
value: customMatcher,
|
1739
|
-
writable: true
|
1740
|
-
});
|
1741
|
-
});
|
1963
|
+
);
|
1742
1964
|
};
|
1743
1965
|
}
|
1744
1966
|
const JestExtend = (chai, utils) => {
|
1745
|
-
utils.addMethod(
|
1746
|
-
|
1747
|
-
|
1967
|
+
utils.addMethod(
|
1968
|
+
chai.expect,
|
1969
|
+
"extend",
|
1970
|
+
(expect, expects) => {
|
1971
|
+
use(JestExtendPlugin(chai, expect, expects));
|
1972
|
+
}
|
1973
|
+
);
|
1748
1974
|
};
|
1749
1975
|
|
1750
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 };
|