@vitest/expect 3.0.0-beta.1 → 3.0.0-beta.3
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 +27 -13
- package/dist/index.js +79 -13
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
@@ -97,7 +97,29 @@ interface ExpectStatic extends Chai.ExpectStatic, AsymmetricMatchersContaining {
|
|
97
97
|
setState: (state: Partial<MatcherState>) => void;
|
98
98
|
not: AsymmetricMatchersContaining;
|
99
99
|
}
|
100
|
-
interface
|
100
|
+
interface CustomMatcher {
|
101
|
+
/**
|
102
|
+
* Checks that a value satisfies a custom matcher function.
|
103
|
+
*
|
104
|
+
* @param matcher - A function returning a boolean based on the custom condition
|
105
|
+
* @param message - Optional custom error message on failure
|
106
|
+
*
|
107
|
+
* @example
|
108
|
+
* expect(age).toSatisfy(val => val >= 18, 'Age must be at least 18');
|
109
|
+
* expect(age).toEqual(expect.toSatisfy(val => val >= 18, 'Age must be at least 18'));
|
110
|
+
*/
|
111
|
+
toSatisfy: (matcher: (value: any) => boolean, message?: string) => any;
|
112
|
+
/**
|
113
|
+
* Matches if the received value is one of the values in the expected array.
|
114
|
+
*
|
115
|
+
* @example
|
116
|
+
* expect(1).toBeOneOf([1, 2, 3])
|
117
|
+
* expect('foo').toBeOneOf([expect.any(String)])
|
118
|
+
* expect({ a: 1 }).toEqual({ a: expect.toBeOneOf(['1', '2', '3']) })
|
119
|
+
*/
|
120
|
+
toBeOneOf: <T>(sample: Array<T>) => any;
|
121
|
+
}
|
122
|
+
interface AsymmetricMatchersContaining extends CustomMatcher {
|
101
123
|
/**
|
102
124
|
* Matches if the received string contains the expected substring.
|
103
125
|
*
|
@@ -139,7 +161,7 @@ interface AsymmetricMatchersContaining {
|
|
139
161
|
*/
|
140
162
|
closeTo: (expected: number, precision?: number) => any;
|
141
163
|
}
|
142
|
-
interface JestAssertion<T = any> extends jest.Matchers<void, T
|
164
|
+
interface JestAssertion<T = any> extends jest.Matchers<void, T>, CustomMatcher {
|
143
165
|
/**
|
144
166
|
* Used when you want to check that two objects have the same value.
|
145
167
|
* This matcher recursively checks the equality of all fields, rather than checking for object identity.
|
@@ -558,16 +580,6 @@ interface Assertion<T = any> extends VitestAssertion<Chai.Assertion, T>, JestAss
|
|
558
580
|
* expect(mockFunc).toHaveBeenCalledExactlyOnceWith('arg1', 42);
|
559
581
|
*/
|
560
582
|
toHaveBeenCalledExactlyOnceWith: <E extends any[]>(...args: E) => void;
|
561
|
-
/**
|
562
|
-
* Checks that a value satisfies a custom matcher function.
|
563
|
-
*
|
564
|
-
* @param matcher - A function returning a boolean based on the custom condition
|
565
|
-
* @param message - Optional custom error message on failure
|
566
|
-
*
|
567
|
-
* @example
|
568
|
-
* expect(age).toSatisfy(val => val >= 18, 'Age must be at least 18');
|
569
|
-
*/
|
570
|
-
toSatisfy: <E>(matcher: (value: E) => boolean, message?: string) => void;
|
571
583
|
/**
|
572
584
|
* This assertion checks if a `Mock` was called before another `Mock`.
|
573
585
|
* @param mock - A mock function created by `vi.spyOn` or `vi.fn`
|
@@ -655,6 +667,8 @@ declare global {
|
|
655
667
|
}
|
656
668
|
}
|
657
669
|
|
670
|
+
declare const customMatchers: MatchersObject;
|
671
|
+
|
658
672
|
interface AsymmetricMatcherInterface {
|
659
673
|
asymmetricMatch: (other: unknown) => boolean;
|
660
674
|
toString: () => string;
|
@@ -741,4 +755,4 @@ declare function getObjectSubset(object: any, subset: any, customTesters: Array<
|
|
741
755
|
declare function getState<State extends MatcherState = MatcherState>(expect: ExpectStatic): State;
|
742
756
|
declare function setState<State extends MatcherState = MatcherState>(state: Partial<State>, expect: ExpectStatic): void;
|
743
757
|
|
744
|
-
export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, type Assertion, AsymmetricMatcher, type AsymmetricMatcherInterface, type AsymmetricMatchersContaining, type AsyncExpectationResult, type ChaiPlugin, type ExpectStatic, type ExpectationResult, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, type JestAssertion, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, type MatcherHintOptions, type MatcherState, type MatchersObject, ObjectContaining, type PromisifyAssertion, type RawMatcherFn, StringContaining, StringMatching, type SyncExpectationResult, type Tester, type TesterContext, addCustomEqualityTesters, arrayBufferEquality, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
|
758
|
+
export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, type Assertion, AsymmetricMatcher, type AsymmetricMatcherInterface, type AsymmetricMatchersContaining, type AsyncExpectationResult, type ChaiPlugin, type ExpectStatic, type ExpectationResult, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, type JestAssertion, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, type MatcherHintOptions, type MatcherState, type MatchersObject, ObjectContaining, type PromisifyAssertion, type RawMatcherFn, StringContaining, StringMatching, type SyncExpectationResult, type Tester, type TesterContext, addCustomEqualityTesters, arrayBufferEquality, customMatchers, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
|
package/dist/index.js
CHANGED
@@ -12,6 +12,55 @@ const ASYMMETRIC_MATCHERS_OBJECT = Symbol.for(
|
|
12
12
|
"asymmetric-matchers-object"
|
13
13
|
);
|
14
14
|
|
15
|
+
const customMatchers = {
|
16
|
+
toSatisfy(actual, expected, message) {
|
17
|
+
const { printReceived, printExpected, matcherHint } = this.utils;
|
18
|
+
const pass = expected(actual);
|
19
|
+
return {
|
20
|
+
pass,
|
21
|
+
message: () => pass ? `${matcherHint(".not.toSatisfy", "received", "")}
|
22
|
+
|
23
|
+
Expected value to not satisfy:
|
24
|
+
${message || printExpected(expected)}
|
25
|
+
Received:
|
26
|
+
${printReceived(actual)}` : `${matcherHint(".toSatisfy", "received", "")}
|
27
|
+
|
28
|
+
Expected value to satisfy:
|
29
|
+
${message || printExpected(expected)}
|
30
|
+
|
31
|
+
Received:
|
32
|
+
${printReceived(actual)}`
|
33
|
+
};
|
34
|
+
},
|
35
|
+
toBeOneOf(actual, expected) {
|
36
|
+
const { equals, customTesters } = this;
|
37
|
+
const { printReceived, printExpected, matcherHint } = this.utils;
|
38
|
+
if (!Array.isArray(expected)) {
|
39
|
+
throw new TypeError(
|
40
|
+
`You must provide an array to ${matcherHint(".toBeOneOf")}, not '${typeof expected}'.`
|
41
|
+
);
|
42
|
+
}
|
43
|
+
const pass = expected.length === 0 || expected.some(
|
44
|
+
(item) => equals(item, actual, customTesters)
|
45
|
+
);
|
46
|
+
return {
|
47
|
+
pass,
|
48
|
+
message: () => pass ? `${matcherHint(".not.toBeOneOf", "received", "")}
|
49
|
+
|
50
|
+
Expected value to not be one of:
|
51
|
+
${printExpected(expected)}
|
52
|
+
Received:
|
53
|
+
${printReceived(actual)}` : `${matcherHint(".toBeOneOf", "received", "")}
|
54
|
+
|
55
|
+
Expected value to be one of:
|
56
|
+
${printExpected(expected)}
|
57
|
+
|
58
|
+
Received:
|
59
|
+
${printReceived(actual)}`
|
60
|
+
};
|
61
|
+
}
|
62
|
+
};
|
63
|
+
|
15
64
|
const EXPECTED_COLOR = c.green;
|
16
65
|
const RECEIVED_COLOR = c.red;
|
17
66
|
const INVERTED_COLOR = c.inverse;
|
@@ -164,9 +213,6 @@ function eq(a, b, aStack, bStack, customTesters, hasKey2) {
|
|
164
213
|
return customTesterResult;
|
165
214
|
}
|
166
215
|
}
|
167
|
-
if (a instanceof Error && b instanceof Error) {
|
168
|
-
return a.message === b.message;
|
169
|
-
}
|
170
216
|
if (typeof URL === "function" && a instanceof URL && b instanceof URL) {
|
171
217
|
return a.href === b.href;
|
172
218
|
}
|
@@ -219,6 +265,14 @@ function eq(a, b, aStack, bStack, customTesters, hasKey2) {
|
|
219
265
|
if (className === "[object Array]" && a.length !== b.length) {
|
220
266
|
return false;
|
221
267
|
}
|
268
|
+
if (a instanceof Error && b instanceof Error) {
|
269
|
+
try {
|
270
|
+
return isErrorEqual(a, b, aStack, bStack, customTesters, hasKey2);
|
271
|
+
} finally {
|
272
|
+
aStack.pop();
|
273
|
+
bStack.pop();
|
274
|
+
}
|
275
|
+
}
|
222
276
|
const aKeys = keys(a, hasKey2);
|
223
277
|
let key;
|
224
278
|
let size = aKeys.length;
|
@@ -236,6 +290,17 @@ function eq(a, b, aStack, bStack, customTesters, hasKey2) {
|
|
236
290
|
bStack.pop();
|
237
291
|
return result;
|
238
292
|
}
|
293
|
+
function isErrorEqual(a, b, aStack, bStack, customTesters, hasKey2) {
|
294
|
+
let result = Object.getPrototypeOf(a) === Object.getPrototypeOf(b) && a.name === b.name && a.message === b.message;
|
295
|
+
if (typeof b.cause !== "undefined") {
|
296
|
+
result && (result = eq(a.cause, b.cause, aStack, bStack, customTesters, hasKey2));
|
297
|
+
}
|
298
|
+
if (a instanceof AggregateError && b instanceof AggregateError) {
|
299
|
+
result && (result = eq(a.errors, b.errors, aStack, bStack, customTesters, hasKey2));
|
300
|
+
}
|
301
|
+
result && (result = eq({ ...a }, { ...b }, aStack, bStack, customTesters, hasKey2));
|
302
|
+
return result;
|
303
|
+
}
|
239
304
|
function keys(obj, hasKey2) {
|
240
305
|
const keys2 = [];
|
241
306
|
for (const key in obj) {
|
@@ -1625,12 +1690,16 @@ const JestChaiExpect = (chai, utils) => {
|
|
1625
1690
|
);
|
1626
1691
|
}
|
1627
1692
|
if (expected instanceof Error) {
|
1693
|
+
const equal = equals(thrown, expected, [
|
1694
|
+
...customTesters,
|
1695
|
+
iterableEquality
|
1696
|
+
]);
|
1628
1697
|
return this.assert(
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
expected
|
1633
|
-
thrown
|
1698
|
+
equal,
|
1699
|
+
"expected a thrown error to be #{exp}",
|
1700
|
+
"expected a thrown error not to be #{exp}",
|
1701
|
+
expected,
|
1702
|
+
thrown
|
1634
1703
|
);
|
1635
1704
|
}
|
1636
1705
|
if (typeof expected === "object" && "asymmetricMatch" in expected && typeof expected.asymmetricMatch === "function") {
|
@@ -1804,9 +1873,6 @@ const JestChaiExpect = (chai, utils) => {
|
|
1804
1873
|
);
|
1805
1874
|
});
|
1806
1875
|
});
|
1807
|
-
def("toSatisfy", function(matcher, message) {
|
1808
|
-
return this.be.satisfy(matcher, message);
|
1809
|
-
});
|
1810
1876
|
def("withContext", function(context) {
|
1811
1877
|
for (const key in context) {
|
1812
1878
|
utils.flag(this, key, context[key]);
|
@@ -2100,7 +2166,7 @@ function JestExtendPlugin(c, expect, matchers) {
|
|
2100
2166
|
return "any";
|
2101
2167
|
}
|
2102
2168
|
toAsymmetricMatcher() {
|
2103
|
-
return `${this.toString()}<${this.sample.map(
|
2169
|
+
return `${this.toString()}<${this.sample.map((item) => stringify(item)).join(", ")}>`;
|
2104
2170
|
}
|
2105
2171
|
}
|
2106
2172
|
const customMatcher = (...sample) => new CustomMatcher(false, ...sample);
|
@@ -2140,4 +2206,4 @@ const JestExtend = (chai, utils) => {
|
|
2140
2206
|
);
|
2141
2207
|
};
|
2142
2208
|
|
2143
|
-
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 };
|
2209
|
+
export { ASYMMETRIC_MATCHERS_OBJECT, Any, Anything, ArrayContaining, AsymmetricMatcher, GLOBAL_EXPECT, JEST_MATCHERS_OBJECT, JestAsymmetricMatchers, JestChaiExpect, JestExtend, MATCHERS_OBJECT, ObjectContaining, StringContaining, StringMatching, addCustomEqualityTesters, arrayBufferEquality, customMatchers, equals, fnNameFor, generateToBeMessage, getObjectKeys, getObjectSubset, getState, hasAsymmetric, hasProperty, isA, isAsymmetric, isImmutableUnorderedKeyed, isImmutableUnorderedSet, iterableEquality, pluralize, setState, sparseArrayEquality, subsetEquality, typeEquality };
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vitest/expect",
|
3
3
|
"type": "module",
|
4
|
-
"version": "3.0.0-beta.
|
4
|
+
"version": "3.0.0-beta.3",
|
5
5
|
"description": "Jest's expect matchers as a Chai plugin",
|
6
6
|
"license": "MIT",
|
7
7
|
"funding": "https://opencollective.com/vitest",
|
@@ -32,13 +32,13 @@
|
|
32
32
|
"dependencies": {
|
33
33
|
"chai": "^5.1.2",
|
34
34
|
"tinyrainbow": "^1.2.0",
|
35
|
-
"@vitest/
|
36
|
-
"@vitest/
|
35
|
+
"@vitest/spy": "3.0.0-beta.3",
|
36
|
+
"@vitest/utils": "3.0.0-beta.3"
|
37
37
|
},
|
38
38
|
"devDependencies": {
|
39
39
|
"@types/chai": "4.3.6",
|
40
40
|
"rollup-plugin-copy": "^3.5.0",
|
41
|
-
"@vitest/runner": "3.0.0-beta.
|
41
|
+
"@vitest/runner": "3.0.0-beta.3"
|
42
42
|
},
|
43
43
|
"scripts": {
|
44
44
|
"build": "rimraf dist && rollup -c",
|