@vitest/expect 2.1.4 → 2.2.0-beta.1
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 +482 -1
- package/dist/index.js +131 -4
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import { MockInstance } from '@vitest/spy';
|
1
2
|
import { stringify, Constructable } from '@vitest/utils';
|
2
3
|
import * as tinyrainbow from 'tinyrainbow';
|
3
4
|
import { Formatter } from 'tinyrainbow';
|
@@ -97,55 +98,433 @@ interface ExpectStatic extends Chai.ExpectStatic, AsymmetricMatchersContaining {
|
|
97
98
|
not: AsymmetricMatchersContaining;
|
98
99
|
}
|
99
100
|
interface AsymmetricMatchersContaining {
|
101
|
+
/**
|
102
|
+
* Matches if the received string contains the expected substring.
|
103
|
+
*
|
104
|
+
* @example
|
105
|
+
* expect('I have an apple').toEqual(expect.stringContaining('apple'));
|
106
|
+
* expect({ a: 'test string' }).toEqual({ a: expect.stringContaining('test') });
|
107
|
+
*/
|
100
108
|
stringContaining: (expected: string) => any;
|
109
|
+
/**
|
110
|
+
* Matches if the received object contains all properties of the expected object.
|
111
|
+
*
|
112
|
+
* @example
|
113
|
+
* expect({ a: '1', b: 2 }).toEqual(expect.objectContaining({ a: '1' }))
|
114
|
+
*/
|
101
115
|
objectContaining: <T = any>(expected: T) => any;
|
116
|
+
/**
|
117
|
+
* Matches if the received array contains all elements in the expected array.
|
118
|
+
*
|
119
|
+
* @example
|
120
|
+
* expect(['a', 'b', 'c']).toEqual(expect.arrayContaining(['b', 'a']));
|
121
|
+
*/
|
102
122
|
arrayContaining: <T = unknown>(expected: Array<T>) => any;
|
123
|
+
/**
|
124
|
+
* Matches if the received string or regex matches the expected pattern.
|
125
|
+
*
|
126
|
+
* @example
|
127
|
+
* expect('hello world').toEqual(expect.stringMatching(/^hello/));
|
128
|
+
* expect('hello world').toEqual(expect.stringMatching('hello'));
|
129
|
+
*/
|
103
130
|
stringMatching: (expected: string | RegExp) => any;
|
131
|
+
/**
|
132
|
+
* Matches if the received number is within a certain precision of the expected number.
|
133
|
+
*
|
134
|
+
* @param precision - Optional decimal precision for comparison. Default is 2.
|
135
|
+
*
|
136
|
+
* @example
|
137
|
+
* expect(10.45).toEqual(expect.closeTo(10.5, 1));
|
138
|
+
* expect(5.11).toEqual(expect.closeTo(5.12)); // with default precision
|
139
|
+
*/
|
104
140
|
closeTo: (expected: number, precision?: number) => any;
|
105
141
|
}
|
106
142
|
interface JestAssertion<T = any> extends jest.Matchers<void, T> {
|
143
|
+
/**
|
144
|
+
* Used when you want to check that two objects have the same value.
|
145
|
+
* This matcher recursively checks the equality of all fields, rather than checking for object identity.
|
146
|
+
*
|
147
|
+
* @example
|
148
|
+
* expect(user).toEqual({ name: 'Alice', age: 30 });
|
149
|
+
*/
|
107
150
|
toEqual: <E>(expected: E) => void;
|
151
|
+
/**
|
152
|
+
* Use to test that objects have the same types as well as structure.
|
153
|
+
*
|
154
|
+
* @example
|
155
|
+
* expect(user).toStrictEqual({ name: 'Alice', age: 30 });
|
156
|
+
*/
|
108
157
|
toStrictEqual: <E>(expected: E) => void;
|
158
|
+
/**
|
159
|
+
* Checks that a value is what you expect. It calls `Object.is` to compare values.
|
160
|
+
* Don't use `toBe` with floating-point numbers.
|
161
|
+
*
|
162
|
+
* @example
|
163
|
+
* expect(result).toBe(42);
|
164
|
+
* expect(status).toBe(true);
|
165
|
+
*/
|
109
166
|
toBe: <E>(expected: E) => void;
|
167
|
+
/**
|
168
|
+
* Check that a string matches a regular expression.
|
169
|
+
*
|
170
|
+
* @example
|
171
|
+
* expect(message).toMatch(/hello/);
|
172
|
+
* expect(greeting).toMatch('world');
|
173
|
+
*/
|
110
174
|
toMatch: (expected: string | RegExp) => void;
|
175
|
+
/**
|
176
|
+
* Used to check that a JavaScript object matches a subset of the properties of an object
|
177
|
+
*
|
178
|
+
* @example
|
179
|
+
* expect(user).toMatchObject({
|
180
|
+
* name: 'Alice',
|
181
|
+
* address: { city: 'Wonderland' }
|
182
|
+
* });
|
183
|
+
*/
|
111
184
|
toMatchObject: <E extends object | any[]>(expected: E) => void;
|
185
|
+
/**
|
186
|
+
* Used when you want to check that an item is in a list.
|
187
|
+
* For testing the items in the list, this uses `===`, a strict equality check.
|
188
|
+
*
|
189
|
+
* @example
|
190
|
+
* expect(items).toContain('apple');
|
191
|
+
* expect(numbers).toContain(5);
|
192
|
+
*/
|
112
193
|
toContain: <E>(item: E) => void;
|
194
|
+
/**
|
195
|
+
* Used when you want to check that an item is in a list.
|
196
|
+
* For testing the items in the list, this matcher recursively checks the
|
197
|
+
* equality of all fields, rather than checking for object identity.
|
198
|
+
*
|
199
|
+
* @example
|
200
|
+
* expect(items).toContainEqual({ name: 'apple', quantity: 1 });
|
201
|
+
*/
|
113
202
|
toContainEqual: <E>(item: E) => void;
|
203
|
+
/**
|
204
|
+
* Use when you don't care what a value is, you just want to ensure a value
|
205
|
+
* is true in a boolean context. In JavaScript, there are six falsy values:
|
206
|
+
* `false`, `0`, `''`, `null`, `undefined`, and `NaN`. Everything else is truthy.
|
207
|
+
*
|
208
|
+
* @example
|
209
|
+
* expect(user.isActive).toBeTruthy();
|
210
|
+
*/
|
114
211
|
toBeTruthy: () => void;
|
212
|
+
/**
|
213
|
+
* When you don't care what a value is, you just want to
|
214
|
+
* ensure a value is false in a boolean context.
|
215
|
+
*
|
216
|
+
* @example
|
217
|
+
* expect(user.isActive).toBeFalsy();
|
218
|
+
*/
|
115
219
|
toBeFalsy: () => void;
|
220
|
+
/**
|
221
|
+
* For comparing floating point numbers.
|
222
|
+
*
|
223
|
+
* @example
|
224
|
+
* expect(score).toBeGreaterThan(10);
|
225
|
+
*/
|
116
226
|
toBeGreaterThan: (num: number | bigint) => void;
|
227
|
+
/**
|
228
|
+
* For comparing floating point numbers.
|
229
|
+
*
|
230
|
+
* @example
|
231
|
+
* expect(score).toBeGreaterThanOrEqual(10);
|
232
|
+
*/
|
117
233
|
toBeGreaterThanOrEqual: (num: number | bigint) => void;
|
234
|
+
/**
|
235
|
+
* For comparing floating point numbers.
|
236
|
+
*
|
237
|
+
* @example
|
238
|
+
* expect(score).toBeLessThan(10);
|
239
|
+
*/
|
118
240
|
toBeLessThan: (num: number | bigint) => void;
|
241
|
+
/**
|
242
|
+
* For comparing floating point numbers.
|
243
|
+
*
|
244
|
+
* @example
|
245
|
+
* expect(score).toBeLessThanOrEqual(10);
|
246
|
+
*/
|
119
247
|
toBeLessThanOrEqual: (num: number | bigint) => void;
|
248
|
+
/**
|
249
|
+
* Used to check that a variable is NaN.
|
250
|
+
*
|
251
|
+
* @example
|
252
|
+
* expect(value).toBeNaN();
|
253
|
+
*/
|
120
254
|
toBeNaN: () => void;
|
255
|
+
/**
|
256
|
+
* Used to check that a variable is undefined.
|
257
|
+
*
|
258
|
+
* @example
|
259
|
+
* expect(value).toBeUndefined();
|
260
|
+
*/
|
121
261
|
toBeUndefined: () => void;
|
262
|
+
/**
|
263
|
+
* This is the same as `.toBe(null)` but the error messages are a bit nicer.
|
264
|
+
* So use `.toBeNull()` when you want to check that something is null.
|
265
|
+
*
|
266
|
+
* @example
|
267
|
+
* expect(value).toBeNull();
|
268
|
+
*/
|
122
269
|
toBeNull: () => void;
|
270
|
+
/**
|
271
|
+
* Ensure that a variable is not undefined.
|
272
|
+
*
|
273
|
+
* @example
|
274
|
+
* expect(value).toBeDefined();
|
275
|
+
*/
|
123
276
|
toBeDefined: () => void;
|
277
|
+
/**
|
278
|
+
* Ensure that an object is an instance of a class.
|
279
|
+
* This matcher uses `instanceof` underneath.
|
280
|
+
*
|
281
|
+
* @example
|
282
|
+
* expect(new Date()).toBeInstanceOf(Date);
|
283
|
+
*/
|
124
284
|
toBeInstanceOf: <E>(expected: E) => void;
|
125
|
-
|
285
|
+
/**
|
286
|
+
* Used to check that an object has a `.length` property
|
287
|
+
* and it is set to a certain numeric value.
|
288
|
+
*
|
289
|
+
* @example
|
290
|
+
* expect([1, 2, 3]).toHaveLength(3);
|
291
|
+
* expect('hello').toHaveLength(5);
|
292
|
+
*/
|
126
293
|
toHaveLength: (length: number) => void;
|
294
|
+
/**
|
295
|
+
* Use to check if a property at the specified path exists on an object.
|
296
|
+
* For checking deeply nested properties, you may use dot notation or an array containing
|
297
|
+
* the path segments for deep references.
|
298
|
+
*
|
299
|
+
* Optionally, you can provide a value to check if it matches the value present at the path
|
300
|
+
* on the target object. This matcher uses 'deep equality' (like `toEqual()`) and recursively checks
|
301
|
+
* the equality of all fields.
|
302
|
+
*
|
303
|
+
* @example
|
304
|
+
* expect(user).toHaveProperty('address.city', 'New York');
|
305
|
+
* expect(config).toHaveProperty(['settings', 'theme'], 'dark');
|
306
|
+
*/
|
127
307
|
toHaveProperty: <E>(property: string | (string | number)[], value?: E) => void;
|
308
|
+
/**
|
309
|
+
* Using exact equality with floating point numbers is a bad idea.
|
310
|
+
* Rounding means that intuitive things fail.
|
311
|
+
* The default for `precision` is 2.
|
312
|
+
*
|
313
|
+
* @example
|
314
|
+
* expect(price).toBeCloseTo(9.99, 2);
|
315
|
+
*/
|
128
316
|
toBeCloseTo: (number: number, numDigits?: number) => void;
|
317
|
+
/**
|
318
|
+
* Ensures that a mock function is called an exact number of times.
|
319
|
+
*
|
320
|
+
* Also under the alias `expect.toBeCalledTimes`.
|
321
|
+
*
|
322
|
+
* @example
|
323
|
+
* expect(mockFunc).toHaveBeenCalledTimes(2);
|
324
|
+
*/
|
129
325
|
toHaveBeenCalledTimes: (times: number) => void;
|
326
|
+
/**
|
327
|
+
* Ensures that a mock function is called an exact number of times.
|
328
|
+
*
|
329
|
+
* Alias for `expect.toHaveBeenCalledTimes`.
|
330
|
+
*
|
331
|
+
* @example
|
332
|
+
* expect(mockFunc).toBeCalledTimes(2);
|
333
|
+
*/
|
334
|
+
toBeCalledTimes: (times: number) => void;
|
335
|
+
/**
|
336
|
+
* Ensures that a mock function is called.
|
337
|
+
*
|
338
|
+
* Also under the alias `expect.toBeCalled`.
|
339
|
+
*
|
340
|
+
* @example
|
341
|
+
* expect(mockFunc).toHaveBeenCalled();
|
342
|
+
*/
|
130
343
|
toHaveBeenCalled: () => void;
|
344
|
+
/**
|
345
|
+
* Ensures that a mock function is called.
|
346
|
+
*
|
347
|
+
* Alias for `expect.toHaveBeenCalled`.
|
348
|
+
*
|
349
|
+
* @example
|
350
|
+
* expect(mockFunc).toBeCalled();
|
351
|
+
*/
|
131
352
|
toBeCalled: () => void;
|
353
|
+
/**
|
354
|
+
* Ensure that a mock function is called with specific arguments.
|
355
|
+
*
|
356
|
+
* Also under the alias `expect.toBeCalledWith`.
|
357
|
+
*
|
358
|
+
* @example
|
359
|
+
* expect(mockFunc).toHaveBeenCalledWith('arg1', 42);
|
360
|
+
*/
|
132
361
|
toHaveBeenCalledWith: <E extends any[]>(...args: E) => void;
|
362
|
+
/**
|
363
|
+
* Ensure that a mock function is called with specific arguments.
|
364
|
+
*
|
365
|
+
* Alias for `expect.toHaveBeenCalledWith`.
|
366
|
+
*
|
367
|
+
* @example
|
368
|
+
* expect(mockFunc).toBeCalledWith('arg1', 42);
|
369
|
+
*/
|
133
370
|
toBeCalledWith: <E extends any[]>(...args: E) => void;
|
371
|
+
/**
|
372
|
+
* Ensure that a mock function is called with specific arguments on an Nth call.
|
373
|
+
*
|
374
|
+
* Also under the alias `expect.nthCalledWith`.
|
375
|
+
*
|
376
|
+
* @example
|
377
|
+
* expect(mockFunc).toHaveBeenNthCalledWith(2, 'secondArg');
|
378
|
+
*/
|
134
379
|
toHaveBeenNthCalledWith: <E extends any[]>(n: number, ...args: E) => void;
|
380
|
+
/**
|
381
|
+
* Ensure that a mock function is called with specific arguments on an Nth call.
|
382
|
+
*
|
383
|
+
* Alias for `expect.toHaveBeenNthCalledWith`.
|
384
|
+
*
|
385
|
+
* @example
|
386
|
+
* expect(mockFunc).nthCalledWith(2, 'secondArg');
|
387
|
+
*/
|
135
388
|
nthCalledWith: <E extends any[]>(nthCall: number, ...args: E) => void;
|
389
|
+
/**
|
390
|
+
* If you have a mock function, you can use `.toHaveBeenLastCalledWith`
|
391
|
+
* to test what arguments it was last called with.
|
392
|
+
*
|
393
|
+
* Also under the alias `expect.lastCalledWith`.
|
394
|
+
*
|
395
|
+
* @example
|
396
|
+
* expect(mockFunc).toHaveBeenLastCalledWith('lastArg');
|
397
|
+
*/
|
136
398
|
toHaveBeenLastCalledWith: <E extends any[]>(...args: E) => void;
|
399
|
+
/**
|
400
|
+
* If you have a mock function, you can use `.lastCalledWith`
|
401
|
+
* to test what arguments it was last called with.
|
402
|
+
*
|
403
|
+
* Alias for `expect.toHaveBeenLastCalledWith`.
|
404
|
+
*
|
405
|
+
* @example
|
406
|
+
* expect(mockFunc).lastCalledWith('lastArg');
|
407
|
+
*/
|
137
408
|
lastCalledWith: <E extends any[]>(...args: E) => void;
|
409
|
+
/**
|
410
|
+
* Used to test that a function throws when it is called.
|
411
|
+
*
|
412
|
+
* Also under the alias `expect.toThrowError`.
|
413
|
+
*
|
414
|
+
* @example
|
415
|
+
* expect(() => functionWithError()).toThrow('Error message');
|
416
|
+
* expect(() => parseJSON('invalid')).toThrow(SyntaxError);
|
417
|
+
*/
|
138
418
|
toThrow: (expected?: string | Constructable | RegExp | Error) => void;
|
419
|
+
/**
|
420
|
+
* Used to test that a function throws when it is called.
|
421
|
+
*
|
422
|
+
* Alias for `expect.toThrow`.
|
423
|
+
*
|
424
|
+
* @example
|
425
|
+
* expect(() => functionWithError()).toThrowError('Error message');
|
426
|
+
* expect(() => parseJSON('invalid')).toThrowError(SyntaxError);
|
427
|
+
*/
|
139
428
|
toThrowError: (expected?: string | Constructable | RegExp | Error) => void;
|
429
|
+
/**
|
430
|
+
* Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time
|
431
|
+
*
|
432
|
+
* Alias for `expect.toHaveReturned`.
|
433
|
+
*
|
434
|
+
* @example
|
435
|
+
* expect(mockFunc).toReturn();
|
436
|
+
*/
|
140
437
|
toReturn: () => void;
|
438
|
+
/**
|
439
|
+
* Use to test that the mock function successfully returned (i.e., did not throw an error) at least one time
|
440
|
+
*
|
441
|
+
* Also under the alias `expect.toReturn`.
|
442
|
+
*
|
443
|
+
* @example
|
444
|
+
* expect(mockFunc).toHaveReturned();
|
445
|
+
*/
|
141
446
|
toHaveReturned: () => void;
|
447
|
+
/**
|
448
|
+
* Use to ensure that a mock function returned successfully (i.e., did not throw an error) an exact number of times.
|
449
|
+
* Any calls to the mock function that throw an error are not counted toward the number of times the function returned.
|
450
|
+
*
|
451
|
+
* Alias for `expect.toHaveReturnedTimes`.
|
452
|
+
*
|
453
|
+
* @example
|
454
|
+
* expect(mockFunc).toReturnTimes(3);
|
455
|
+
*/
|
142
456
|
toReturnTimes: (times: number) => void;
|
457
|
+
/**
|
458
|
+
* Use to ensure that a mock function returned successfully (i.e., did not throw an error) an exact number of times.
|
459
|
+
* Any calls to the mock function that throw an error are not counted toward the number of times the function returned.
|
460
|
+
*
|
461
|
+
* Also under the alias `expect.toReturnTimes`.
|
462
|
+
*
|
463
|
+
* @example
|
464
|
+
* expect(mockFunc).toHaveReturnedTimes(3);
|
465
|
+
*/
|
143
466
|
toHaveReturnedTimes: (times: number) => void;
|
467
|
+
/**
|
468
|
+
* Use to ensure that a mock function returned a specific value.
|
469
|
+
*
|
470
|
+
* Alias for `expect.toHaveReturnedWith`.
|
471
|
+
*
|
472
|
+
* @example
|
473
|
+
* expect(mockFunc).toReturnWith('returnValue');
|
474
|
+
*/
|
144
475
|
toReturnWith: <E>(value: E) => void;
|
476
|
+
/**
|
477
|
+
* Use to ensure that a mock function returned a specific value.
|
478
|
+
*
|
479
|
+
* Also under the alias `expect.toReturnWith`.
|
480
|
+
*
|
481
|
+
* @example
|
482
|
+
* expect(mockFunc).toHaveReturnedWith('returnValue');
|
483
|
+
*/
|
145
484
|
toHaveReturnedWith: <E>(value: E) => void;
|
485
|
+
/**
|
486
|
+
* Use to test the specific value that a mock function last returned.
|
487
|
+
* If the last call to the mock function threw an error, then this matcher will fail
|
488
|
+
* no matter what value you provided as the expected return value.
|
489
|
+
*
|
490
|
+
* Also under the alias `expect.lastReturnedWith`.
|
491
|
+
*
|
492
|
+
* @example
|
493
|
+
* expect(mockFunc).toHaveLastReturnedWith('lastValue');
|
494
|
+
*/
|
146
495
|
toHaveLastReturnedWith: <E>(value: E) => void;
|
496
|
+
/**
|
497
|
+
* Use to test the specific value that a mock function last returned.
|
498
|
+
* If the last call to the mock function threw an error, then this matcher will fail
|
499
|
+
* no matter what value you provided as the expected return value.
|
500
|
+
*
|
501
|
+
* Alias for `expect.toHaveLastReturnedWith`.
|
502
|
+
*
|
503
|
+
* @example
|
504
|
+
* expect(mockFunc).lastReturnedWith('lastValue');
|
505
|
+
*/
|
147
506
|
lastReturnedWith: <E>(value: E) => void;
|
507
|
+
/**
|
508
|
+
* Use to test the specific value that a mock function returned for the nth call.
|
509
|
+
* If the nth call to the mock function threw an error, then this matcher will fail
|
510
|
+
* no matter what value you provided as the expected return value.
|
511
|
+
*
|
512
|
+
* Also under the alias `expect.nthReturnedWith`.
|
513
|
+
*
|
514
|
+
* @example
|
515
|
+
* expect(mockFunc).toHaveNthReturnedWith(2, 'nthValue');
|
516
|
+
*/
|
148
517
|
toHaveNthReturnedWith: <E>(nthCall: number, value: E) => void;
|
518
|
+
/**
|
519
|
+
* Use to test the specific value that a mock function returned for the nth call.
|
520
|
+
* If the nth call to the mock function threw an error, then this matcher will fail
|
521
|
+
* no matter what value you provided as the expected return value.
|
522
|
+
*
|
523
|
+
* Alias for `expect.toHaveNthReturnedWith`.
|
524
|
+
*
|
525
|
+
* @example
|
526
|
+
* expect(mockFunc).nthReturnedWith(2, 'nthValue');
|
527
|
+
*/
|
149
528
|
nthReturnedWith: <E>(nthCall: number, value: E) => void;
|
150
529
|
}
|
151
530
|
type VitestAssertion<A, T> = {
|
@@ -156,15 +535,117 @@ type Promisify<O> = {
|
|
156
535
|
};
|
157
536
|
type PromisifyAssertion<T> = Promisify<Assertion<T>>;
|
158
537
|
interface Assertion<T = any> extends VitestAssertion<Chai.Assertion, T>, JestAssertion<T> {
|
538
|
+
/**
|
539
|
+
* Ensures a value is of a specific type.
|
540
|
+
*
|
541
|
+
* @example
|
542
|
+
* expect(value).toBeTypeOf('string');
|
543
|
+
* expect(number).toBeTypeOf('number');
|
544
|
+
*/
|
159
545
|
toBeTypeOf: (expected: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined') => void;
|
546
|
+
/**
|
547
|
+
* Asserts that a mock function was called exactly once.
|
548
|
+
*
|
549
|
+
* @example
|
550
|
+
* expect(mockFunc).toHaveBeenCalledOnce();
|
551
|
+
*/
|
160
552
|
toHaveBeenCalledOnce: () => void;
|
553
|
+
/**
|
554
|
+
* Ensure that a mock function is called with specific arguments and called
|
555
|
+
* exactly once.
|
556
|
+
*
|
557
|
+
* @example
|
558
|
+
* expect(mockFunc).toHaveBeenCalledExactlyOnceWith('arg1', 42);
|
559
|
+
*/
|
560
|
+
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
|
+
*/
|
161
570
|
toSatisfy: <E>(matcher: (value: E) => boolean, message?: string) => void;
|
571
|
+
/**
|
572
|
+
* This assertion checks if a `Mock` was called before another `Mock`.
|
573
|
+
* @param mock - A mock function created by `vi.spyOn` or `vi.fn`
|
574
|
+
* @param failIfNoFirstInvocation - Fail if the first mock was never called
|
575
|
+
* @example
|
576
|
+
* const mock1 = vi.fn()
|
577
|
+
* const mock2 = vi.fn()
|
578
|
+
*
|
579
|
+
* mock1()
|
580
|
+
* mock2()
|
581
|
+
* mock1()
|
582
|
+
*
|
583
|
+
* expect(mock1).toHaveBeenCalledBefore(mock2)
|
584
|
+
*/
|
585
|
+
toHaveBeenCalledBefore: (mock: MockInstance, failIfNoFirstInvocation?: boolean) => void;
|
586
|
+
/**
|
587
|
+
* This assertion checks if a `Mock` was called after another `Mock`.
|
588
|
+
* @param mock - A mock function created by `vi.spyOn` or `vi.fn`
|
589
|
+
* @param failIfNoFirstInvocation - Fail if the first mock was never called
|
590
|
+
* @example
|
591
|
+
* const mock1 = vi.fn()
|
592
|
+
* const mock2 = vi.fn()
|
593
|
+
*
|
594
|
+
* mock2()
|
595
|
+
* mock1()
|
596
|
+
* mock2()
|
597
|
+
*
|
598
|
+
* expect(mock1).toHaveBeenCalledAfter(mock2)
|
599
|
+
*/
|
600
|
+
toHaveBeenCalledAfter: (mock: MockInstance, failIfNoFirstInvocation?: boolean) => void;
|
601
|
+
/**
|
602
|
+
* Checks that a promise resolves successfully at least once.
|
603
|
+
*
|
604
|
+
* @example
|
605
|
+
* await expect(promise).toHaveResolved();
|
606
|
+
*/
|
162
607
|
toHaveResolved: () => void;
|
608
|
+
/**
|
609
|
+
* Checks that a promise resolves to a specific value.
|
610
|
+
*
|
611
|
+
* @example
|
612
|
+
* await expect(promise).toHaveResolvedWith('success');
|
613
|
+
*/
|
163
614
|
toHaveResolvedWith: <E>(value: E) => void;
|
615
|
+
/**
|
616
|
+
* Ensures a promise resolves a specific number of times.
|
617
|
+
*
|
618
|
+
* @example
|
619
|
+
* expect(mockAsyncFunc).toHaveResolvedTimes(3);
|
620
|
+
*/
|
164
621
|
toHaveResolvedTimes: (times: number) => void;
|
622
|
+
/**
|
623
|
+
* Asserts that the last resolved value of a promise matches an expected value.
|
624
|
+
*
|
625
|
+
* @example
|
626
|
+
* await expect(mockAsyncFunc).toHaveLastResolvedWith('finalResult');
|
627
|
+
*/
|
165
628
|
toHaveLastResolvedWith: <E>(value: E) => void;
|
629
|
+
/**
|
630
|
+
* Ensures a specific value was returned by a promise on the nth resolution.
|
631
|
+
*
|
632
|
+
* @example
|
633
|
+
* await expect(mockAsyncFunc).toHaveNthResolvedWith(2, 'secondResult');
|
634
|
+
*/
|
166
635
|
toHaveNthResolvedWith: <E>(nthCall: number, value: E) => void;
|
636
|
+
/**
|
637
|
+
* Verifies that a promise resolves.
|
638
|
+
*
|
639
|
+
* @example
|
640
|
+
* await expect(someAsyncFunc).resolves.toBe(42);
|
641
|
+
*/
|
167
642
|
resolves: PromisifyAssertion<T>;
|
643
|
+
/**
|
644
|
+
* Verifies that a promise rejects.
|
645
|
+
*
|
646
|
+
* @example
|
647
|
+
* await expect(someAsyncFunc).rejects.toThrow('error');
|
648
|
+
*/
|
168
649
|
rejects: PromisifyAssertion<T>;
|
169
650
|
}
|
170
651
|
declare global {
|
package/dist/index.js
CHANGED
@@ -908,9 +908,20 @@ const JestAsymmetricMatchers = (chai, utils) => {
|
|
908
908
|
};
|
909
909
|
};
|
910
910
|
|
911
|
-
function
|
911
|
+
function createAssertionMessage(util, assertion, hasArgs) {
|
912
|
+
const not = util.flag(assertion, "negate") ? "not." : "";
|
913
|
+
const name = `${util.flag(assertion, "_name")}(${hasArgs ? "expected" : ""})`;
|
914
|
+
const promiseName = util.flag(assertion, "promise");
|
915
|
+
const promise = promiseName ? `.${promiseName}` : "";
|
916
|
+
return `expect(actual)${promise}.${not}${name}`;
|
917
|
+
}
|
918
|
+
function recordAsyncExpect(_test, promise, assertion, error) {
|
919
|
+
const test = _test;
|
912
920
|
if (test && promise instanceof Promise) {
|
913
921
|
promise = promise.finally(() => {
|
922
|
+
if (!test.promises) {
|
923
|
+
return;
|
924
|
+
}
|
914
925
|
const index = test.promises.indexOf(promise);
|
915
926
|
if (index !== -1) {
|
916
927
|
test.promises.splice(index, 1);
|
@@ -920,13 +931,43 @@ function recordAsyncExpect(test, promise) {
|
|
920
931
|
test.promises = [];
|
921
932
|
}
|
922
933
|
test.promises.push(promise);
|
934
|
+
let resolved = false;
|
935
|
+
test.onFinished ?? (test.onFinished = []);
|
936
|
+
test.onFinished.push(() => {
|
937
|
+
var _a;
|
938
|
+
if (!resolved) {
|
939
|
+
const processor = ((_a = globalThis.__vitest_worker__) == null ? void 0 : _a.onFilterStackTrace) || ((s) => s || "");
|
940
|
+
const stack = processor(error.stack);
|
941
|
+
console.warn([
|
942
|
+
`Promise returned by \`${assertion}\` was not awaited. `,
|
943
|
+
"Vitest currently auto-awaits hanging assertions at the end of the test, but this will cause the test to fail in Vitest 3. ",
|
944
|
+
"Please remember to await the assertion.\n",
|
945
|
+
stack
|
946
|
+
].join(""));
|
947
|
+
}
|
948
|
+
});
|
949
|
+
return {
|
950
|
+
then(onFullfilled, onRejected) {
|
951
|
+
resolved = true;
|
952
|
+
return promise.then(onFullfilled, onRejected);
|
953
|
+
},
|
954
|
+
catch(onRejected) {
|
955
|
+
return promise.catch(onRejected);
|
956
|
+
},
|
957
|
+
finally(onFinally) {
|
958
|
+
return promise.finally(onFinally);
|
959
|
+
},
|
960
|
+
[Symbol.toStringTag]: "Promise"
|
961
|
+
};
|
923
962
|
}
|
924
963
|
return promise;
|
925
964
|
}
|
926
965
|
function wrapAssertion(utils, name, fn) {
|
927
966
|
return function(...args) {
|
928
967
|
var _a;
|
929
|
-
|
968
|
+
if (name !== "withTest") {
|
969
|
+
utils.flag(this, "_name", name);
|
970
|
+
}
|
930
971
|
if (!utils.flag(this, "soft")) {
|
931
972
|
return fn.apply(this, args);
|
932
973
|
}
|
@@ -1424,6 +1465,25 @@ const JestChaiExpect = (chai, utils) => {
|
|
1424
1465
|
throw new AssertionError(formatCalls(spy, msg, args));
|
1425
1466
|
}
|
1426
1467
|
});
|
1468
|
+
def("toHaveBeenCalledExactlyOnceWith", function(...args) {
|
1469
|
+
const spy = getSpy(this);
|
1470
|
+
const spyName = spy.getMockName();
|
1471
|
+
const callCount = spy.mock.calls.length;
|
1472
|
+
const hasCallWithArgs = spy.mock.calls.some(
|
1473
|
+
(callArg) => equals(callArg, args, [...customTesters, iterableEquality])
|
1474
|
+
);
|
1475
|
+
const pass = hasCallWithArgs && callCount === 1;
|
1476
|
+
const isNot = utils.flag(this, "negate");
|
1477
|
+
const msg = utils.getMessage(this, [
|
1478
|
+
pass,
|
1479
|
+
`expected "${spyName}" to be called once with arguments: #{exp}`,
|
1480
|
+
`expected "${spyName}" to not be called once with arguments: #{exp}`,
|
1481
|
+
args
|
1482
|
+
]);
|
1483
|
+
if (pass && isNot || !pass && !isNot) {
|
1484
|
+
throw new AssertionError(formatCalls(spy, msg, args));
|
1485
|
+
}
|
1486
|
+
});
|
1427
1487
|
def(
|
1428
1488
|
["toHaveBeenNthCalledWith", "nthCalledWith"],
|
1429
1489
|
function(times, ...args) {
|
@@ -1461,6 +1521,61 @@ const JestChaiExpect = (chai, utils) => {
|
|
1461
1521
|
);
|
1462
1522
|
}
|
1463
1523
|
);
|
1524
|
+
function isSpyCalledBeforeAnotherSpy(beforeSpy, afterSpy, failIfNoFirstInvocation) {
|
1525
|
+
const beforeInvocationCallOrder = beforeSpy.mock.invocationCallOrder;
|
1526
|
+
const afterInvocationCallOrder = afterSpy.mock.invocationCallOrder;
|
1527
|
+
if (beforeInvocationCallOrder.length === 0) {
|
1528
|
+
return !failIfNoFirstInvocation;
|
1529
|
+
}
|
1530
|
+
if (afterInvocationCallOrder.length === 0) {
|
1531
|
+
return false;
|
1532
|
+
}
|
1533
|
+
return beforeInvocationCallOrder[0] < afterInvocationCallOrder[0];
|
1534
|
+
}
|
1535
|
+
def(
|
1536
|
+
["toHaveBeenCalledBefore"],
|
1537
|
+
function(resultSpy, failIfNoFirstInvocation = true) {
|
1538
|
+
const expectSpy = getSpy(this);
|
1539
|
+
if (!isMockFunction(resultSpy)) {
|
1540
|
+
throw new TypeError(
|
1541
|
+
`${utils.inspect(resultSpy)} is not a spy or a call to a spy`
|
1542
|
+
);
|
1543
|
+
}
|
1544
|
+
this.assert(
|
1545
|
+
isSpyCalledBeforeAnotherSpy(
|
1546
|
+
expectSpy,
|
1547
|
+
resultSpy,
|
1548
|
+
failIfNoFirstInvocation
|
1549
|
+
),
|
1550
|
+
`expected "${expectSpy.getMockName()}" to have been called before "${resultSpy.getMockName()}"`,
|
1551
|
+
`expected "${expectSpy.getMockName()}" to not have been called before "${resultSpy.getMockName()}"`,
|
1552
|
+
resultSpy,
|
1553
|
+
expectSpy
|
1554
|
+
);
|
1555
|
+
}
|
1556
|
+
);
|
1557
|
+
def(
|
1558
|
+
["toHaveBeenCalledAfter"],
|
1559
|
+
function(resultSpy, failIfNoFirstInvocation = true) {
|
1560
|
+
const expectSpy = getSpy(this);
|
1561
|
+
if (!isMockFunction(resultSpy)) {
|
1562
|
+
throw new TypeError(
|
1563
|
+
`${utils.inspect(resultSpy)} is not a spy or a call to a spy`
|
1564
|
+
);
|
1565
|
+
}
|
1566
|
+
this.assert(
|
1567
|
+
isSpyCalledBeforeAnotherSpy(
|
1568
|
+
resultSpy,
|
1569
|
+
expectSpy,
|
1570
|
+
failIfNoFirstInvocation
|
1571
|
+
),
|
1572
|
+
`expected "${expectSpy.getMockName()}" to have been called after "${resultSpy.getMockName()}"`,
|
1573
|
+
`expected "${expectSpy.getMockName()}" to not have been called after "${resultSpy.getMockName()}"`,
|
1574
|
+
resultSpy,
|
1575
|
+
expectSpy
|
1576
|
+
);
|
1577
|
+
}
|
1578
|
+
);
|
1464
1579
|
def(
|
1465
1580
|
["toThrow", "toThrowError"],
|
1466
1581
|
function(expected) {
|
@@ -1724,6 +1839,7 @@ const JestChaiExpect = (chai, utils) => {
|
|
1724
1839
|
return result instanceof chai.Assertion ? proxy : result;
|
1725
1840
|
}
|
1726
1841
|
return (...args) => {
|
1842
|
+
utils.flag(this, "_name", key);
|
1727
1843
|
const promise = obj.then(
|
1728
1844
|
(value) => {
|
1729
1845
|
utils.flag(this, "object", value);
|
@@ -1744,7 +1860,12 @@ const JestChaiExpect = (chai, utils) => {
|
|
1744
1860
|
throw _error;
|
1745
1861
|
}
|
1746
1862
|
);
|
1747
|
-
return recordAsyncExpect(
|
1863
|
+
return recordAsyncExpect(
|
1864
|
+
test,
|
1865
|
+
promise,
|
1866
|
+
createAssertionMessage(utils, this, !!args.length),
|
1867
|
+
error
|
1868
|
+
);
|
1748
1869
|
};
|
1749
1870
|
}
|
1750
1871
|
});
|
@@ -1778,6 +1899,7 @@ const JestChaiExpect = (chai, utils) => {
|
|
1778
1899
|
return result instanceof chai.Assertion ? proxy : result;
|
1779
1900
|
}
|
1780
1901
|
return (...args) => {
|
1902
|
+
utils.flag(this, "_name", key);
|
1781
1903
|
const promise = wrapper.then(
|
1782
1904
|
(value) => {
|
1783
1905
|
const _error = new AssertionError(
|
@@ -1801,7 +1923,12 @@ const JestChaiExpect = (chai, utils) => {
|
|
1801
1923
|
return result.call(this, ...args);
|
1802
1924
|
}
|
1803
1925
|
);
|
1804
|
-
return recordAsyncExpect(
|
1926
|
+
return recordAsyncExpect(
|
1927
|
+
test,
|
1928
|
+
promise,
|
1929
|
+
createAssertionMessage(utils, this, !!args.length),
|
1930
|
+
error
|
1931
|
+
);
|
1805
1932
|
};
|
1806
1933
|
}
|
1807
1934
|
});
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vitest/expect",
|
3
3
|
"type": "module",
|
4
|
-
"version": "2.1
|
4
|
+
"version": "2.2.0-beta.1",
|
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/spy": "2.1
|
36
|
-
"@vitest/utils": "2.1
|
35
|
+
"@vitest/spy": "2.2.0-beta.1",
|
36
|
+
"@vitest/utils": "2.2.0-beta.1"
|
37
37
|
},
|
38
38
|
"devDependencies": {
|
39
39
|
"@types/chai": "4.3.6",
|
40
40
|
"rollup-plugin-copy": "^3.5.0",
|
41
|
-
"@vitest/runner": "2.1
|
41
|
+
"@vitest/runner": "2.2.0-beta.1"
|
42
42
|
},
|
43
43
|
"scripts": {
|
44
44
|
"build": "rimraf dist && rollup -c",
|