@vitest/expect 4.1.0-beta.3 → 4.1.0-beta.5
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/dist/index.d.ts +17 -45
- package/dist/index.js +69 -45
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Test } from '@vitest/runner';
|
|
2
2
|
import { MockInstance } from '@vitest/spy';
|
|
3
|
-
import { Constructable } from '@vitest/utils';
|
|
4
3
|
import { Formatter } from 'tinyrainbow';
|
|
5
4
|
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
6
5
|
import { diff, printDiffOrStringify } from '@vitest/utils/diff';
|
|
@@ -459,6 +458,7 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
459
458
|
*
|
|
460
459
|
* @example
|
|
461
460
|
* expect(mockFunc).toBeCalledTimes(2);
|
|
461
|
+
* @deprecated Use `toHaveBeenCalledTimes` instead
|
|
462
462
|
*/
|
|
463
463
|
toBeCalledTimes: (times: number) => void;
|
|
464
464
|
/**
|
|
@@ -477,6 +477,7 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
477
477
|
*
|
|
478
478
|
* @example
|
|
479
479
|
* expect(mockFunc).toBeCalled();
|
|
480
|
+
* @deprecated Use `toHaveBeenCalled` instead
|
|
480
481
|
*/
|
|
481
482
|
toBeCalled: () => void;
|
|
482
483
|
/**
|
|
@@ -495,6 +496,7 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
495
496
|
*
|
|
496
497
|
* @example
|
|
497
498
|
* expect(mockFunc).toBeCalledWith('arg1', 42);
|
|
499
|
+
* @deprecated Use `toHaveBeenCalledWith` instead
|
|
498
500
|
*/
|
|
499
501
|
toBeCalledWith: <E extends any[]>(...args: E) => void;
|
|
500
502
|
/**
|
|
@@ -507,15 +509,6 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
507
509
|
*/
|
|
508
510
|
toHaveBeenNthCalledWith: <E extends any[]>(n: number, ...args: E) => void;
|
|
509
511
|
/**
|
|
510
|
-
* Ensure that a mock function is called with specific arguments on an Nth call.
|
|
511
|
-
*
|
|
512
|
-
* Alias for `expect.toHaveBeenNthCalledWith`.
|
|
513
|
-
*
|
|
514
|
-
* @example
|
|
515
|
-
* expect(mockFunc).nthCalledWith(2, 'secondArg');
|
|
516
|
-
*/
|
|
517
|
-
nthCalledWith: <E extends any[]>(nthCall: number, ...args: E) => void;
|
|
518
|
-
/**
|
|
519
512
|
* If you have a mock function, you can use `.toHaveBeenLastCalledWith`
|
|
520
513
|
* to test what arguments it was last called with.
|
|
521
514
|
*
|
|
@@ -526,16 +519,6 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
526
519
|
*/
|
|
527
520
|
toHaveBeenLastCalledWith: <E extends any[]>(...args: E) => void;
|
|
528
521
|
/**
|
|
529
|
-
* If you have a mock function, you can use `.lastCalledWith`
|
|
530
|
-
* to test what arguments it was last called with.
|
|
531
|
-
*
|
|
532
|
-
* Alias for `expect.toHaveBeenLastCalledWith`.
|
|
533
|
-
*
|
|
534
|
-
* @example
|
|
535
|
-
* expect(mockFunc).lastCalledWith('lastArg');
|
|
536
|
-
*/
|
|
537
|
-
lastCalledWith: <E extends any[]>(...args: E) => void;
|
|
538
|
-
/**
|
|
539
522
|
* Used to test that a function throws when it is called.
|
|
540
523
|
*
|
|
541
524
|
* Also under the alias `expect.toThrowError`.
|
|
@@ -543,8 +526,9 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
543
526
|
* @example
|
|
544
527
|
* expect(() => functionWithError()).toThrow('Error message');
|
|
545
528
|
* expect(() => parseJSON('invalid')).toThrow(SyntaxError);
|
|
529
|
+
* expect(() => { throw 42 }).toThrow(42);
|
|
546
530
|
*/
|
|
547
|
-
toThrow: (expected?:
|
|
531
|
+
toThrow: (expected?: any) => void;
|
|
548
532
|
/**
|
|
549
533
|
* Used to test that a function throws when it is called.
|
|
550
534
|
*
|
|
@@ -553,8 +537,10 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
553
537
|
* @example
|
|
554
538
|
* expect(() => functionWithError()).toThrowError('Error message');
|
|
555
539
|
* expect(() => parseJSON('invalid')).toThrowError(SyntaxError);
|
|
540
|
+
* expect(() => { throw 42 }).toThrowError(42);
|
|
541
|
+
* @deprecated Use `toThrow` instead
|
|
556
542
|
*/
|
|
557
|
-
toThrowError: (expected?:
|
|
543
|
+
toThrowError: (expected?: any) => void;
|
|
558
544
|
/**
|
|
559
545
|
* Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time
|
|
560
546
|
*
|
|
@@ -562,6 +548,7 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
562
548
|
*
|
|
563
549
|
* @example
|
|
564
550
|
* expect(mockFunc).toReturn();
|
|
551
|
+
* @deprecated Use `toHaveReturned` instead
|
|
565
552
|
*/
|
|
566
553
|
toReturn: () => void;
|
|
567
554
|
/**
|
|
@@ -581,6 +568,7 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
581
568
|
*
|
|
582
569
|
* @example
|
|
583
570
|
* expect(mockFunc).toReturnTimes(3);
|
|
571
|
+
* @deprecated Use `toHaveReturnedTimes` instead
|
|
584
572
|
*/
|
|
585
573
|
toReturnTimes: (times: number) => void;
|
|
586
574
|
/**
|
|
@@ -600,6 +588,7 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
600
588
|
*
|
|
601
589
|
* @example
|
|
602
590
|
* expect(mockFunc).toReturnWith('returnValue');
|
|
591
|
+
* @deprecated Use `toHaveReturnedWith` instead
|
|
603
592
|
*/
|
|
604
593
|
toReturnWith: <E>(value: E) => void;
|
|
605
594
|
/**
|
|
@@ -623,17 +612,6 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
623
612
|
*/
|
|
624
613
|
toHaveLastReturnedWith: <E>(value: E) => void;
|
|
625
614
|
/**
|
|
626
|
-
* Use to test the specific value that a mock function last returned.
|
|
627
|
-
* If the last call to the mock function threw an error, then this matcher will fail
|
|
628
|
-
* no matter what value you provided as the expected return value.
|
|
629
|
-
*
|
|
630
|
-
* Alias for `expect.toHaveLastReturnedWith`.
|
|
631
|
-
*
|
|
632
|
-
* @example
|
|
633
|
-
* expect(mockFunc).lastReturnedWith('lastValue');
|
|
634
|
-
*/
|
|
635
|
-
lastReturnedWith: <E>(value: E) => void;
|
|
636
|
-
/**
|
|
637
615
|
* Use to test the specific value that a mock function returned for the nth call.
|
|
638
616
|
* If the nth call to the mock function threw an error, then this matcher will fail
|
|
639
617
|
* no matter what value you provided as the expected return value.
|
|
@@ -644,17 +622,6 @@ interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
|
|
644
622
|
* expect(mockFunc).toHaveNthReturnedWith(2, 'nthValue');
|
|
645
623
|
*/
|
|
646
624
|
toHaveNthReturnedWith: <E>(nthCall: number, value: E) => void;
|
|
647
|
-
/**
|
|
648
|
-
* Use to test the specific value that a mock function returned for the nth call.
|
|
649
|
-
* If the nth call to the mock function threw an error, then this matcher will fail
|
|
650
|
-
* no matter what value you provided as the expected return value.
|
|
651
|
-
*
|
|
652
|
-
* Alias for `expect.toHaveNthReturnedWith`.
|
|
653
|
-
*
|
|
654
|
-
* @example
|
|
655
|
-
* expect(mockFunc).nthReturnedWith(2, 'nthValue');
|
|
656
|
-
*/
|
|
657
|
-
nthReturnedWith: <E>(nthCall: number, value: E) => void;
|
|
658
625
|
}
|
|
659
626
|
type VitestAssertion<
|
|
660
627
|
A,
|
|
@@ -925,6 +892,7 @@ declare const JestExtend: ChaiPlugin;
|
|
|
925
892
|
declare function equals(a: unknown, b: unknown, customTesters?: Array<Tester>, strictCheck?: boolean): boolean;
|
|
926
893
|
declare function isAsymmetric(obj: any): obj is AsymmetricMatcher<any>;
|
|
927
894
|
declare function hasAsymmetric(obj: any, seen?: Set<any>): boolean;
|
|
895
|
+
declare function isError(value: unknown): value is Error;
|
|
928
896
|
declare function isA(typeName: string, value: unknown): boolean;
|
|
929
897
|
declare function fnNameFor(func: Function): string;
|
|
930
898
|
declare function hasProperty(obj: object | null, property: string): boolean;
|
|
@@ -950,5 +918,9 @@ declare function isStandardSchema(obj: any): obj is StandardSchemaV1;
|
|
|
950
918
|
declare function getState<State extends MatcherState = MatcherState>(expect: ExpectStatic): State;
|
|
951
919
|
declare function setState<State extends MatcherState = MatcherState>(state: Partial<State>, expect: ExpectStatic): void;
|
|
952
920
|
|
|
953
|
-
|
|
921
|
+
declare function createAssertionMessage(util: Chai.ChaiUtils, assertion: Assertion, hasArgs: boolean): string;
|
|
922
|
+
declare function recordAsyncExpect(_test: any, promise: Promise<any>, assertion: string, error: Error, isSoft?: boolean): Promise<any>;
|
|
923
|
+
declare function wrapAssertion(utils: Chai.ChaiUtils, name: string, fn: (this: Chai.AssertionStatic & Assertion, ...args: any[]) => void | PromiseLike<void>): (this: Chai.AssertionStatic & Assertion, ...args: any[]) => void | PromiseLike<void>;
|
|
924
|
+
|
|
925
|
+
export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, ChaiStyleAssertions, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, SchemaMatching, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, createAssertionMessage, customMatchers, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isError, isImmutableUnorderedKeyed, isImmutableUnorderedSet, isStandardSchema, iterableEquality, pluralize, recordAsyncExpect, setState, sparseArrayEquality, subsetEquality, typeEquality, wrapAssertion };
|
|
954
926
|
export type { Assertion, AsymmetricMatcherInterface, AsymmetricMatchersContaining, AsyncExpectationResult, ChaiMockAssertion, ChaiPlugin, DeeplyAllowMatchers, ExpectStatic, ExpectationResult, JestAssertion, MatcherHintOptions, MatcherState, Matchers, MatchersObject, PromisifyAssertion, RawMatcherFn, SyncExpectationResult, Tester, TesterContext };
|
package/dist/index.js
CHANGED
|
@@ -244,6 +244,18 @@ function asymmetricMatch(a, b, customTesters) {
|
|
|
244
244
|
return b.asymmetricMatch(a, customTesters);
|
|
245
245
|
}
|
|
246
246
|
}
|
|
247
|
+
// https://github.com/jestjs/jest/blob/905bcbced3d40cdf7aadc4cdf6fb731c4bb3dbe3/packages/expect-utils/src/utils.ts#L509
|
|
248
|
+
function isError(value) {
|
|
249
|
+
if (typeof Error.isError === "function") {
|
|
250
|
+
return Error.isError(value);
|
|
251
|
+
}
|
|
252
|
+
switch (Object.prototype.toString.call(value)) {
|
|
253
|
+
case "[object Error]":
|
|
254
|
+
case "[object Exception]":
|
|
255
|
+
case "[object DOMException]": return true;
|
|
256
|
+
default: return value instanceof Error;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
247
259
|
// Equality function lovingly adapted from isEqual in
|
|
248
260
|
// [Underscore](http://underscorejs.org)
|
|
249
261
|
function eq(a, b, aStack, bStack, customTesters, hasKey) {
|
|
@@ -332,7 +344,7 @@ function eq(a, b, aStack, bStack, customTesters, hasKey) {
|
|
|
332
344
|
if (className === "[object Array]" && a.length !== b.length) {
|
|
333
345
|
return false;
|
|
334
346
|
}
|
|
335
|
-
if (a
|
|
347
|
+
if (isError(a) && isError(b)) {
|
|
336
348
|
try {
|
|
337
349
|
return isErrorEqual(a, b, aStack, bStack, customTesters, hasKey);
|
|
338
350
|
} finally {
|
|
@@ -366,17 +378,17 @@ function isErrorEqual(a, b, aStack, bStack, customTesters, hasKey) {
|
|
|
366
378
|
// - [[Prototype]] of objects are compared using the === operator.
|
|
367
379
|
// - Only enumerable "own" properties are considered.
|
|
368
380
|
// - Error names, messages, causes, and errors are always compared, even if these are not enumerable properties. errors is also compared.
|
|
369
|
-
let result = Object.
|
|
381
|
+
let result = Object.prototype.toString.call(a) === Object.prototype.toString.call(b) && a.name === b.name && a.message === b.message;
|
|
370
382
|
// check Error.cause asymmetrically
|
|
371
383
|
if (typeof b.cause !== "undefined") {
|
|
372
|
-
result
|
|
384
|
+
result &&= eq(a.cause, b.cause, aStack, bStack, customTesters, hasKey);
|
|
373
385
|
}
|
|
374
386
|
// AggregateError.errors
|
|
375
387
|
if (a instanceof AggregateError && b instanceof AggregateError) {
|
|
376
|
-
result
|
|
388
|
+
result &&= eq(a.errors, b.errors, aStack, bStack, customTesters, hasKey);
|
|
377
389
|
}
|
|
378
390
|
// spread to compare enumerable properties
|
|
379
|
-
result
|
|
391
|
+
result &&= eq({ ...a }, { ...b }, aStack, bStack, customTesters, hasKey);
|
|
380
392
|
return result;
|
|
381
393
|
}
|
|
382
394
|
function keys(obj, hasKey) {
|
|
@@ -570,7 +582,7 @@ function hasPropertyInObject(object, key) {
|
|
|
570
582
|
return Object.hasOwn(object, key) || hasPropertyInObject(Object.getPrototypeOf(object), key);
|
|
571
583
|
}
|
|
572
584
|
function isObjectWithKeys(a) {
|
|
573
|
-
return isObject(a) && !(a
|
|
585
|
+
return isObject(a) && !isError(a) && !Array.isArray(a) && !(a instanceof Date) && !(a instanceof Set) && !(a instanceof Map);
|
|
574
586
|
}
|
|
575
587
|
function subsetEquality(object, subset, customTesters = []) {
|
|
576
588
|
const filteredCustomTesters = customTesters.filter((t) => t !== subsetEquality);
|
|
@@ -653,10 +665,7 @@ function pluralize(word, count) {
|
|
|
653
665
|
return `${count} ${word}${count === 1 ? "" : "s"}`;
|
|
654
666
|
}
|
|
655
667
|
function getObjectKeys(object) {
|
|
656
|
-
return [...Object.keys(object), ...Object.getOwnPropertySymbols(object).filter((s) =>
|
|
657
|
-
var _Object$getOwnPropert;
|
|
658
|
-
return (_Object$getOwnPropert = Object.getOwnPropertyDescriptor(object, s)) === null || _Object$getOwnPropert === void 0 ? void 0 : _Object$getOwnPropert.enumerable;
|
|
659
|
-
})];
|
|
668
|
+
return [...Object.keys(object), ...Object.getOwnPropertySymbols(object).filter((s) => Object.getOwnPropertyDescriptor(object, s)?.enumerable)];
|
|
660
669
|
}
|
|
661
670
|
function getObjectSubset(object, subset, customTesters) {
|
|
662
671
|
let stripped = 0;
|
|
@@ -834,10 +843,7 @@ class ObjectContaining extends AsymmetricMatcher {
|
|
|
834
843
|
return this.hasProperty(this.getPrototype(obj), property);
|
|
835
844
|
}
|
|
836
845
|
getProperties(obj) {
|
|
837
|
-
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj).filter((s) =>
|
|
838
|
-
var _Object$getOwnPropert;
|
|
839
|
-
return (_Object$getOwnPropert = Object.getOwnPropertyDescriptor(obj, s)) === null || _Object$getOwnPropert === void 0 ? void 0 : _Object$getOwnPropert.enumerable;
|
|
840
|
-
})];
|
|
846
|
+
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj).filter((s) => Object.getOwnPropertyDescriptor(obj, s)?.enumerable)];
|
|
841
847
|
}
|
|
842
848
|
asymmetricMatch(other, customTesters) {
|
|
843
849
|
if (typeof this.sample !== "object") {
|
|
@@ -1032,9 +1038,8 @@ class SchemaMatching extends AsymmetricMatcher {
|
|
|
1032
1038
|
return "object";
|
|
1033
1039
|
}
|
|
1034
1040
|
toAsymmetricMatcher() {
|
|
1035
|
-
var _this$result;
|
|
1036
1041
|
const { utils } = this.getMatcherContext();
|
|
1037
|
-
const issues =
|
|
1042
|
+
const issues = this.result?.issues || [];
|
|
1038
1043
|
if (issues.length > 0) {
|
|
1039
1044
|
return `${this.toString()} ${utils.stringify(this.result, undefined, { printBasicPrototype: false })}`;
|
|
1040
1045
|
}
|
|
@@ -1062,13 +1067,14 @@ const JestAsymmetricMatchers = (chai, utils) => {
|
|
|
1062
1067
|
};
|
|
1063
1068
|
|
|
1064
1069
|
function createAssertionMessage(util, assertion, hasArgs) {
|
|
1070
|
+
const soft = util.flag(assertion, "soft") ? ".soft" : "";
|
|
1065
1071
|
const not = util.flag(assertion, "negate") ? "not." : "";
|
|
1066
1072
|
const name = `${util.flag(assertion, "_name")}(${hasArgs ? "expected" : ""})`;
|
|
1067
1073
|
const promiseName = util.flag(assertion, "promise");
|
|
1068
1074
|
const promise = promiseName ? `.${promiseName}` : "";
|
|
1069
|
-
return `expect(actual)${promise}.${not}${name}`;
|
|
1075
|
+
return `expect${soft}(actual)${promise}.${not}${name}`;
|
|
1070
1076
|
}
|
|
1071
|
-
function recordAsyncExpect(_test, promise, assertion, error) {
|
|
1077
|
+
function recordAsyncExpect(_test, promise, assertion, error, isSoft) {
|
|
1072
1078
|
const test = _test;
|
|
1073
1079
|
// record promise for test, that resolves before test ends
|
|
1074
1080
|
if (test && promise instanceof Promise) {
|
|
@@ -1086,17 +1092,23 @@ function recordAsyncExpect(_test, promise, assertion, error) {
|
|
|
1086
1092
|
if (!test.promises) {
|
|
1087
1093
|
test.promises = [];
|
|
1088
1094
|
}
|
|
1095
|
+
// setup `expect.soft` handler here instead of `wrapAssertion`
|
|
1096
|
+
// to avoid double error tracking while keeping non-await promise detection.
|
|
1097
|
+
if (isSoft) {
|
|
1098
|
+
promise = promise.then(noop, (err) => {
|
|
1099
|
+
handleTestError(test, err);
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1089
1102
|
test.promises.push(promise);
|
|
1090
1103
|
let resolved = false;
|
|
1091
|
-
test.onFinished
|
|
1104
|
+
test.onFinished ??= [];
|
|
1092
1105
|
test.onFinished.push(() => {
|
|
1093
1106
|
if (!resolved) {
|
|
1094
|
-
|
|
1095
|
-
const processor = ((_vitest_worker__ = globalThis.__vitest_worker__) === null || _vitest_worker__ === void 0 ? void 0 : _vitest_worker__.onFilterStackTrace) || ((s) => s || "");
|
|
1107
|
+
const processor = globalThis.__vitest_worker__?.onFilterStackTrace || ((s) => s || "");
|
|
1096
1108
|
const stack = processor(error.stack);
|
|
1097
1109
|
console.warn([
|
|
1098
1110
|
`Promise returned by \`${assertion}\` was not awaited. `,
|
|
1099
|
-
"Vitest currently auto-awaits hanging assertions at the end of the test, but this will cause the test to fail in Vitest
|
|
1111
|
+
"Vitest currently auto-awaits hanging assertions at the end of the test, but this will cause the test to fail in the next Vitest major. ",
|
|
1100
1112
|
"Please remember to await the assertion.\n",
|
|
1101
1113
|
stack
|
|
1102
1114
|
].join(""));
|
|
@@ -1119,10 +1131,9 @@ function recordAsyncExpect(_test, promise, assertion, error) {
|
|
|
1119
1131
|
return promise;
|
|
1120
1132
|
}
|
|
1121
1133
|
function handleTestError(test, err) {
|
|
1122
|
-
|
|
1123
|
-
test.result || (test.result = { state: "fail" });
|
|
1134
|
+
test.result ||= { state: "fail" };
|
|
1124
1135
|
test.result.state = "fail";
|
|
1125
|
-
|
|
1136
|
+
test.result.errors ||= [];
|
|
1126
1137
|
test.result.errors.push(processError(err));
|
|
1127
1138
|
}
|
|
1128
1139
|
function wrapAssertion(utils, name, fn) {
|
|
@@ -1132,7 +1143,11 @@ function wrapAssertion(utils, name, fn) {
|
|
|
1132
1143
|
utils.flag(this, "_name", name);
|
|
1133
1144
|
}
|
|
1134
1145
|
if (!utils.flag(this, "soft")) {
|
|
1135
|
-
|
|
1146
|
+
// avoid WebKit's proper tail call to preserve stacktrace offset for inline snapshot
|
|
1147
|
+
// https://webkit.org/blog/6240/ecmascript-6-proper-tail-calls-in-webkit
|
|
1148
|
+
try {
|
|
1149
|
+
return fn.apply(this, args);
|
|
1150
|
+
} finally {}
|
|
1136
1151
|
}
|
|
1137
1152
|
const test = utils.flag(this, "vitest-test");
|
|
1138
1153
|
if (!test) {
|
|
@@ -1482,7 +1497,7 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1482
1497
|
throw new AssertionError(formatCalls(spy, msg, args));
|
|
1483
1498
|
}
|
|
1484
1499
|
});
|
|
1485
|
-
def(
|
|
1500
|
+
def("toHaveBeenNthCalledWith", function(times, ...args) {
|
|
1486
1501
|
const spy = getSpy(this);
|
|
1487
1502
|
const spyName = spy.getMockName();
|
|
1488
1503
|
const nthCall = spy.mock.calls[times - 1];
|
|
@@ -1490,7 +1505,7 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1490
1505
|
const isCalled = times <= callCount;
|
|
1491
1506
|
this.assert(nthCall && equalsArgumentArray(nthCall, args), `expected ${ordinalOf(times)} "${spyName}" call to have been called with #{exp}${isCalled ? `` : `, but called only ${callCount} times`}`, `expected ${ordinalOf(times)} "${spyName}" call to not have been called with #{exp}`, args, nthCall, isCalled);
|
|
1492
1507
|
});
|
|
1493
|
-
def(
|
|
1508
|
+
def("toHaveBeenLastCalledWith", function(...args) {
|
|
1494
1509
|
const spy = getSpy(this);
|
|
1495
1510
|
const spyName = spy.getMockName();
|
|
1496
1511
|
const lastCall = spy.mock.calls.at(-1);
|
|
@@ -1561,7 +1576,7 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1561
1576
|
const name = expected.name || expected.prototype.constructor.name;
|
|
1562
1577
|
return this.assert(thrown && thrown instanceof expected, `expected error to be instance of ${name}`, `expected error not to be instance of ${name}`, expected, thrown);
|
|
1563
1578
|
}
|
|
1564
|
-
if (expected
|
|
1579
|
+
if (isError(expected)) {
|
|
1565
1580
|
const equal = equals(thrown, expected, [...customTesters, iterableEquality]);
|
|
1566
1581
|
return this.assert(equal, "expected a thrown error to be #{exp}", "expected a thrown error not to be #{exp}", expected, thrown);
|
|
1567
1582
|
}
|
|
@@ -1569,7 +1584,8 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1569
1584
|
const matcher = expected;
|
|
1570
1585
|
return this.assert(thrown && matcher.asymmetricMatch(thrown), "expected error to match asymmetric matcher", "expected error not to match asymmetric matcher", matcher, thrown);
|
|
1571
1586
|
}
|
|
1572
|
-
|
|
1587
|
+
const equal = equals(thrown, expected, [...customTesters, iterableEquality]);
|
|
1588
|
+
return this.assert(equal, "expected a thrown value to equal #{exp}", "expected a thrown value not to equal #{exp}", expected, thrown);
|
|
1573
1589
|
});
|
|
1574
1590
|
[{
|
|
1575
1591
|
name: "toHaveResolved",
|
|
@@ -1637,7 +1653,7 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1637
1653
|
},
|
|
1638
1654
|
action: "resolve"
|
|
1639
1655
|
}, {
|
|
1640
|
-
name:
|
|
1656
|
+
name: "toHaveLastReturnedWith",
|
|
1641
1657
|
condition: (spy, value) => {
|
|
1642
1658
|
const result = spy.mock.results.at(-1);
|
|
1643
1659
|
return Boolean(result && result.type === "return" && equals(result.value, value));
|
|
@@ -1649,7 +1665,7 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1649
1665
|
const results = action === "return" ? spy.mock.results : spy.mock.settledResults;
|
|
1650
1666
|
const result = results.at(-1);
|
|
1651
1667
|
const spyName = spy.getMockName();
|
|
1652
|
-
this.assert(condition(spy, value), `expected last "${spyName}" call to ${action} #{exp}`, `expected last "${spyName}" call to not ${action} #{exp}`, value, result
|
|
1668
|
+
this.assert(condition(spy, value), `expected last "${spyName}" call to ${action} #{exp}`, `expected last "${spyName}" call to not ${action} #{exp}`, value, result?.value);
|
|
1653
1669
|
});
|
|
1654
1670
|
});
|
|
1655
1671
|
[{
|
|
@@ -1660,7 +1676,7 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1660
1676
|
},
|
|
1661
1677
|
action: "resolve"
|
|
1662
1678
|
}, {
|
|
1663
|
-
name:
|
|
1679
|
+
name: "toHaveNthReturnedWith",
|
|
1664
1680
|
condition: (spy, index, value) => {
|
|
1665
1681
|
const result = spy.mock.results[index - 1];
|
|
1666
1682
|
return result && result.type === "return" && equals(result.value, value);
|
|
@@ -1673,7 +1689,7 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1673
1689
|
const results = action === "return" ? spy.mock.results : spy.mock.settledResults;
|
|
1674
1690
|
const result = results[nthCall - 1];
|
|
1675
1691
|
const ordinalCall = `${ordinalOf(nthCall)} call`;
|
|
1676
|
-
this.assert(condition(spy, nthCall, value), `expected ${ordinalCall} "${spyName}" call to ${action} #{exp}`, `expected ${ordinalCall} "${spyName}" call to not ${action} #{exp}`, value, result
|
|
1692
|
+
this.assert(condition(spy, nthCall, value), `expected ${ordinalCall} "${spyName}" call to ${action} #{exp}`, `expected ${ordinalCall} "${spyName}" call to not ${action} #{exp}`, value, result?.value);
|
|
1677
1693
|
});
|
|
1678
1694
|
});
|
|
1679
1695
|
// @ts-expect-error @internal
|
|
@@ -1692,7 +1708,7 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1692
1708
|
if (utils.flag(this, "poll")) {
|
|
1693
1709
|
throw new SyntaxError(`expect.poll() is not supported in combination with .resolves`);
|
|
1694
1710
|
}
|
|
1695
|
-
if (typeof
|
|
1711
|
+
if (typeof obj?.then !== "function") {
|
|
1696
1712
|
throw new TypeError(`You must provide a Promise to expect() when using .resolves, not '${typeof obj}'.`);
|
|
1697
1713
|
}
|
|
1698
1714
|
const proxy = new Proxy(this, { get: (target, key, receiver) => {
|
|
@@ -1702,14 +1718,18 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1702
1718
|
}
|
|
1703
1719
|
return (...args) => {
|
|
1704
1720
|
utils.flag(this, "_name", key);
|
|
1705
|
-
const promise = obj.then((value) => {
|
|
1721
|
+
const promise = Promise.resolve(obj).then((value) => {
|
|
1706
1722
|
utils.flag(this, "object", value);
|
|
1707
1723
|
return result.call(this, ...args);
|
|
1708
1724
|
}, (err) => {
|
|
1709
1725
|
const _error = new AssertionError(`promise rejected "${utils.inspect(err)}" instead of resolving`, { showDiff: false });
|
|
1710
1726
|
_error.cause = err;
|
|
1711
|
-
_error.stack = error.stack.replace(error.message, _error.message);
|
|
1712
1727
|
throw _error;
|
|
1728
|
+
}).catch((err) => {
|
|
1729
|
+
if (isError(err) && error.stack) {
|
|
1730
|
+
err.stack = error.stack.replace(error.message, err.message);
|
|
1731
|
+
}
|
|
1732
|
+
throw err;
|
|
1713
1733
|
});
|
|
1714
1734
|
return recordAsyncExpect(test, promise, createAssertionMessage(utils, this, !!args.length), error);
|
|
1715
1735
|
};
|
|
@@ -1726,7 +1746,7 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1726
1746
|
if (utils.flag(this, "poll")) {
|
|
1727
1747
|
throw new SyntaxError(`expect.poll() is not supported in combination with .rejects`);
|
|
1728
1748
|
}
|
|
1729
|
-
if (typeof
|
|
1749
|
+
if (typeof wrapper?.then !== "function") {
|
|
1730
1750
|
throw new TypeError(`You must provide a Promise to expect() when using .rejects, not '${typeof wrapper}'.`);
|
|
1731
1751
|
}
|
|
1732
1752
|
const proxy = new Proxy(this, { get: (target, key, receiver) => {
|
|
@@ -1736,17 +1756,21 @@ const JestChaiExpect = (chai, utils) => {
|
|
|
1736
1756
|
}
|
|
1737
1757
|
return (...args) => {
|
|
1738
1758
|
utils.flag(this, "_name", key);
|
|
1739
|
-
const promise = wrapper.then((value) => {
|
|
1759
|
+
const promise = Promise.resolve(wrapper).then((value) => {
|
|
1740
1760
|
const _error = new AssertionError(`promise resolved "${utils.inspect(value)}" instead of rejecting`, {
|
|
1741
1761
|
showDiff: true,
|
|
1742
1762
|
expected: new Error("rejected promise"),
|
|
1743
1763
|
actual: value
|
|
1744
1764
|
});
|
|
1745
|
-
_error.stack = error.stack.replace(error.message, _error.message);
|
|
1746
1765
|
throw _error;
|
|
1747
1766
|
}, (err) => {
|
|
1748
1767
|
utils.flag(this, "object", err);
|
|
1749
1768
|
return result.call(this, ...args);
|
|
1769
|
+
}).catch((err) => {
|
|
1770
|
+
if (isError(err) && error.stack) {
|
|
1771
|
+
err.stack = error.stack.replace(error.message, err.message);
|
|
1772
|
+
}
|
|
1773
|
+
throw err;
|
|
1750
1774
|
});
|
|
1751
1775
|
return recordAsyncExpect(test, promise, createAssertionMessage(utils, this, !!args.length), error);
|
|
1752
1776
|
};
|
|
@@ -1770,7 +1794,7 @@ function ordinalOf(i) {
|
|
|
1770
1794
|
}
|
|
1771
1795
|
function formatCalls(spy, msg, showActualCall) {
|
|
1772
1796
|
if (spy.mock.calls.length) {
|
|
1773
|
-
msg += c.gray(`\n\nReceived
|
|
1797
|
+
msg += c.gray(`\n\nReceived:\n\n${spy.mock.calls.map((callArg, i) => {
|
|
1774
1798
|
let methodCall = c.bold(` ${ordinalOf(i + 1)} ${spy.getMockName()} call:\n\n`);
|
|
1775
1799
|
if (showActualCall) {
|
|
1776
1800
|
methodCall += diff(showActualCall, callArg, { omitAnnotationLines: true });
|
|
@@ -1786,7 +1810,7 @@ function formatCalls(spy, msg, showActualCall) {
|
|
|
1786
1810
|
}
|
|
1787
1811
|
function formatReturns(spy, results, msg, showActualReturn) {
|
|
1788
1812
|
if (results.length) {
|
|
1789
|
-
msg += c.gray(`\n\nReceived
|
|
1813
|
+
msg += c.gray(`\n\nReceived:\n\n${results.map((callReturn, i) => {
|
|
1790
1814
|
let methodCall = c.bold(` ${ordinalOf(i + 1)} ${spy.getMockName()} call return:\n\n`);
|
|
1791
1815
|
if (showActualReturn) {
|
|
1792
1816
|
methodCall += diff(showActualReturn, callReturn.value, { omitAnnotationLines: true });
|
|
@@ -1814,8 +1838,8 @@ function getMatcherState(assertion, expect) {
|
|
|
1814
1838
|
subsetEquality
|
|
1815
1839
|
};
|
|
1816
1840
|
let task = util.flag(assertion, "vitest-test");
|
|
1817
|
-
const currentTestName =
|
|
1818
|
-
if (
|
|
1841
|
+
const currentTestName = task?.fullTestName ?? "";
|
|
1842
|
+
if (task?.type !== "test") {
|
|
1819
1843
|
task = undefined;
|
|
1820
1844
|
}
|
|
1821
1845
|
const matcherState = {
|
|
@@ -1917,4 +1941,4 @@ const JestExtend = (chai, utils) => {
|
|
|
1917
1941
|
});
|
|
1918
1942
|
};
|
|
1919
1943
|
|
|
1920
|
-
export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, ChaiStyleAssertions, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, SchemaMatching, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, customMatchers, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, isStandardSchema, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
|
|
1944
|
+
export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, ChaiStyleAssertions, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, SchemaMatching, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, createAssertionMessage, customMatchers, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isError, isImmutableUnorderedKeyed, isImmutableUnorderedSet, isStandardSchema, iterableEquality, pluralize, recordAsyncExpect, setState, sparseArrayEquality, subsetEquality, typeEquality, wrapAssertion };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitest/expect",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.1.0-beta.
|
|
4
|
+
"version": "4.1.0-beta.5",
|
|
5
5
|
"description": "Jest's expect matchers as a Chai plugin",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://opencollective.com/vitest",
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"@types/chai": "^5.2.2",
|
|
34
34
|
"chai": "^6.2.2",
|
|
35
35
|
"tinyrainbow": "^3.0.3",
|
|
36
|
-
"@vitest/spy": "4.1.0-beta.
|
|
37
|
-
"@vitest/utils": "4.1.0-beta.
|
|
36
|
+
"@vitest/spy": "4.1.0-beta.5",
|
|
37
|
+
"@vitest/utils": "4.1.0-beta.5"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@vitest/runner": "4.1.0-beta.
|
|
40
|
+
"@vitest/runner": "4.1.0-beta.5"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"build": "premove dist && rollup -c",
|