vitest 5.0.0-beta.4 → 5.0.0-beta.6

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.
Files changed (58) hide show
  1. package/LICENSE.md +0 -17
  2. package/dist/browser.d.ts +8 -6
  3. package/dist/browser.js +5 -3
  4. package/dist/chunks/artifact.BNnEI1sJ.js +2770 -0
  5. package/dist/chunks/{base.BEGVMQrS.js → base.BKfXyFN7.js} +12 -12
  6. package/dist/chunks/browser.d.DoM6vBOs.d.ts +64 -0
  7. package/dist/chunks/{cac.CyXAEMkE.js → cac.DKrA6qEB.js} +15 -7
  8. package/dist/chunks/{cli-api.DJMXq34b.js → cli-api.cZcvaUFI.js} +491 -852
  9. package/dist/chunks/config.d.CKWK3nld.d.ts +2920 -0
  10. package/dist/chunks/{console.B3IRP8fX.js → console.DjVIMaXT.js} +4 -4
  11. package/dist/chunks/{coverage.d.g2xbl2sP.d.ts → coverage.d.CCNrKR65.d.ts} +2 -0
  12. package/dist/chunks/{creator.D66cVXYh.js → creator.C4nK7Krt.js} +19 -4
  13. package/dist/chunks/{defaults.CUUnbOrq.js → defaults.B_pFOTYy.js} +1 -1
  14. package/dist/chunks/{globals.BuY-yD0m.js → globals.CzUA1xn8.js} +12 -12
  15. package/dist/chunks/{index.CcluKS59.js → index.B4UTDegh.js} +6 -6
  16. package/dist/chunks/{nativeModuleRunner.BOeMnHl4.js → index.CesbTg1C.js} +3 -34
  17. package/dist/chunks/{index.CE58PZNH.js → index.D6NDM5O1.js} +515 -121
  18. package/dist/chunks/{index.nQFVd50u.js → index.DNRmy2jU.js} +32 -10
  19. package/dist/chunks/{index.og1WyBLx.js → index.Djaij2xr.js} +660 -58
  20. package/dist/chunks/{init-forks.Ce3vGWgL.js → init-forks.BG4bCDny.js} +1 -1
  21. package/dist/chunks/{init-threads.8e1OLv5v.js → init-threads.DLtIP5Qq.js} +1 -1
  22. package/dist/chunks/{init.6qx-LaHs.js → init.DTAQFCjl.js} +10 -6
  23. package/dist/chunks/{nativeModuleMocker.DDZfQXLs.js → nativeModuleMocker.BKtCThoO.js} +2 -3
  24. package/dist/chunks/nativeModuleRunner.WlMdOB52.js +36 -0
  25. package/dist/chunks/{node.CwFbQqI1.js → node.C9I1sbE9.js} +1 -2
  26. package/dist/chunks/{plugin.d.B7MTG_Fe.d.ts → plugin.d.Bpge8Jye.d.ts} +94 -37
  27. package/dist/chunks/{rpc.DFRWVnRh.js → rpc.DZEh5xnQ.js} +1 -1
  28. package/dist/chunks/{rpc.d.OQ_EZi1Z.d.ts → rpc.d.C6-dGZ2f.d.ts} +1 -2
  29. package/dist/chunks/{setup-common.DdEF_hkE.js → setup-common.ZNdeu5wa.js} +2 -2
  30. package/dist/chunks/{global.d.BtKPuz2X.d.ts → task-utils.d.mMDXJF_I.d.ts} +30 -89
  31. package/dist/chunks/{utils.BX5Fg8C4.js → utils.DYj33du9.js} +1 -17
  32. package/dist/chunks/{vm.Bu7mmcZq.js → vm.CeHWcIrU.js} +4 -4
  33. package/dist/chunks/{worker.d.yR22cs6X.d.ts → worker.d.JES7ffPK.d.ts} +3 -3
  34. package/dist/cli.js +1 -1
  35. package/dist/config.cjs +1 -1
  36. package/dist/config.d.ts +12 -13
  37. package/dist/config.js +1 -1
  38. package/dist/index.d.ts +416 -21
  39. package/dist/index.js +9 -9
  40. package/dist/module-evaluator.d.ts +7 -4
  41. package/dist/module-evaluator.js +7 -0
  42. package/dist/node.d.ts +31 -18
  43. package/dist/node.js +22 -16
  44. package/dist/runtime.d.ts +9 -3
  45. package/dist/runtime.js +4 -5
  46. package/dist/task-utils.js +296 -0
  47. package/dist/worker.d.ts +7 -6
  48. package/dist/worker.js +15 -14
  49. package/dist/workers/forks.js +16 -15
  50. package/dist/workers/runVmTests.js +10 -10
  51. package/dist/workers/threads.js +16 -15
  52. package/dist/workers/vmForks.js +8 -8
  53. package/dist/workers/vmThreads.js +8 -8
  54. package/package.json +18 -19
  55. package/dist/chunks/browser.d.BGxB4Xum.d.ts +0 -878
  56. package/dist/chunks/config.d.DXq1aBpy.d.ts +0 -244
  57. package/dist/chunks/environment.d-DOJxxZV9.d.DOJxxZV9.d.ts +0 -17
  58. package/dist/chunks/general.d.DFAHgpC2.d.ts +0 -247
@@ -1,21 +1,21 @@
1
- import { TestSyntaxError, getCurrentTest, createTaskCollector, getCurrentSuite, getHooks, getFn, afterAll, afterEach, aroundAll, aroundEach, beforeAll, beforeEach, describe, it, onTestFailed, onTestFinished, recordArtifact, suite, test } from '@vitest/runner';
2
- import { i as isChildProcess, w as waitForImportsToResolve, r as resetModules, g as getWorkerState } from './utils.BX5Fg8C4.js';
1
+ import { T as TestSyntaxError, g as getCurrentTest, c as createTaskCollector, a as getCurrentSuite, b as createChainable, d as getHooks, e as getFn, m as matchesTags, f as afterAll, h as afterEach, i as aroundAll, j as aroundEach, k as beforeAll, l as beforeEach, n as describe, o as it, q as onTestFailed, r as onTestFinished, t as recordArtifact, u as suite, v as test } from './artifact.BNnEI1sJ.js';
2
+ import { i as isChildProcess, r as resetModules, g as getWorkerState } from './utils.DYj33du9.js';
3
3
  import { getSafeTimers, delay } from '@vitest/utils/timers';
4
4
  import { isMockFunction, fn, spyOn, restoreAllMocks, resetAllMocks, clearAllMocks } from '@vitest/spy';
5
5
  import { getType, isObject, noop, assertTypes, ordinal, createSimpleStackTrace, getCallLastIndex } from '@vitest/utils/helpers';
6
6
  import { positionToOffset, offsetToLineNumber, lineSplitRE } from '@vitest/utils/offset';
7
7
  import { parseSingleStack, parseErrorStacktrace } from '@vitest/utils/source-map';
8
8
  import { c as commonjsGlobal, g as getDefaultExportFromCjs } from './_commonjsHelpers.D26ty3Ew.js';
9
- import { R as RealDate, b as resetDate, m as mockDate, r as rpc, V as VitestEvaluatedModules } from './rpc.DFRWVnRh.js';
9
+ import { R as RealDate, b as resetDate, m as mockDate, r as rpc, V as VitestEvaluatedModules } from './rpc.DZEh5xnQ.js';
10
+ import { stringify, inspect } from '@vitest/utils/display';
11
+ import { printDiffOrStringify, diff } from '@vitest/utils/diff';
12
+ import c from 'tinyrainbow';
10
13
  import * as chai from 'chai';
11
14
  import { use, util } from 'chai';
12
- import { getNames, getTests, getTestName, createChainable, matchesTags } from '@vitest/runner/utils';
13
15
  import { processError } from '@vitest/utils/error';
16
+ import { getNames, getTests, getTestName, createFileTask } from '../task-utils.js';
14
17
  import { g as getSerializers, a as addSerializer } from './plugins.DrsmdUE2.js';
15
18
  import { format } from '@vitest/pretty-format';
16
- import { printDiffOrStringify, diff } from '@vitest/utils/diff';
17
- import { stringify, inspect } from '@vitest/utils/display';
18
- import c from 'tinyrainbow';
19
19
  import { isAbsolute, relative, normalize } from 'pathe';
20
20
  import { Bench } from 'tinybench';
21
21
  import { expectTypeOf } from 'expect-type';
@@ -342,7 +342,7 @@ function isA(typeName, value) {
342
342
  function isDomNode(obj) {
343
343
  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";
344
344
  }
345
- // SENTINEL constants are from https://github.com/facebook/immutable-js
345
+ // SENTINEL constants are from https://github.com/immutable-js/immutable-js
346
346
  const IS_KEYED_SENTINEL = "@@__IMMUTABLE_KEYED__@@";
347
347
  const IS_SET_SENTINEL = "@@__IMMUTABLE_SET__@@";
348
348
  const IS_LIST_SENTINEL = "@@__IMMUTABLE_LIST__@@";
@@ -2729,15 +2729,35 @@ function requireFakeTimersSrc () {
2729
2729
  * @returns {void}
2730
2730
  */
2731
2731
 
2732
+ /**
2733
+ * @typedef {object} TemporalDuration
2734
+ * @property {number} years - years component
2735
+ * @property {number} months - months component
2736
+ * @property {number} weeks - weeks component
2737
+ * @property {number} days - days component
2738
+ * @property {number} hours - hours component
2739
+ * @property {number} minutes - minutes component
2740
+ * @property {number} seconds - seconds component
2741
+ * @property {number} milliseconds - milliseconds component
2742
+ * @property {number} microseconds - microseconds component
2743
+ * @property {number} nanoseconds - nanoseconds component
2744
+ * @property {(options: {unit: string, relativeTo?: unknown}) => number} total - converts to a single unit
2745
+ */
2746
+
2747
+ /**
2748
+ * @typedef {object} TemporalTimelike
2749
+ * @property {number} epochMilliseconds - milliseconds since the Unix epoch (present on Temporal.Instant and Temporal.ZonedDateTime)
2750
+ */
2751
+
2732
2752
  /**
2733
2753
  * @callback Tick
2734
- * @param {number|string} tickValue milliseconds or a string parseable by parseTime
2754
+ * @param {number|string|TemporalDuration} tickValue milliseconds, a string parseable by parseTime, or a Temporal.Duration
2735
2755
  * @returns {number} will return the new `now` value
2736
2756
  */
2737
2757
 
2738
2758
  /**
2739
2759
  * @callback TickAsync
2740
- * @param {number|string} tickValue milliseconds or a string parseable by parseTime
2760
+ * @param {number|string|TemporalDuration} tickValue milliseconds, a string parseable by parseTime, or a Temporal.Duration
2741
2761
  * @returns {Promise<number>}
2742
2762
  */
2743
2763
 
@@ -2783,13 +2803,13 @@ function requireFakeTimersSrc () {
2783
2803
 
2784
2804
  /**
2785
2805
  * @callback SetSystemTime
2786
- * @param {number|Date} [now] initial mocked time, as milliseconds since epoch or a Date
2806
+ * @param {number|Date|TemporalTimelike} [now] initial mocked time, as milliseconds since epoch, a Date, a Temporal.Instant, or a Temporal.ZonedDateTime
2787
2807
  * @returns {void}
2788
2808
  */
2789
2809
 
2790
2810
  /**
2791
2811
  * @callback Jump
2792
- * @param {number|string} tickValue milliseconds or a human-readable value like "01:11:15"
2812
+ * @param {number|string|TemporalDuration} tickValue milliseconds, a human-readable value like "01:11:15", or a Temporal.Duration
2793
2813
  * @returns {number}
2794
2814
  */
2795
2815
 
@@ -2817,7 +2837,7 @@ function requireFakeTimersSrc () {
2817
2837
  */
2818
2838
 
2819
2839
  /**
2820
- * @typedef {"setTimeout" | "clearTimeout" | "setImmediate" | "clearImmediate" | "setInterval" | "clearInterval" | "Date" | "nextTick" | "hrtime" | "requestAnimationFrame" | "cancelAnimationFrame" | "requestIdleCallback" | "cancelIdleCallback" | "performance" | "queueMicrotask"} FakeMethod
2840
+ * @typedef {"setTimeout" | "clearTimeout" | "setImmediate" | "clearImmediate" | "setInterval" | "clearInterval" | "Date" | "nextTick" | "hrtime" | "requestAnimationFrame" | "cancelAnimationFrame" | "requestIdleCallback" | "cancelIdleCallback" | "performance" | "queueMicrotask" | "Intl" | "Temporal"} FakeMethod
2821
2841
  */
2822
2842
 
2823
2843
  /**
@@ -2842,6 +2862,7 @@ function requireFakeTimersSrc () {
2842
2862
  * performance?: any,
2843
2863
  * Performance?: any,
2844
2864
  * Intl?: any,
2865
+ * Temporal?: any,
2845
2866
  * Promise?: typeof Promise,
2846
2867
  * Date: typeof Date & { isFake?: boolean, toSource?: () => string, clock?: any }
2847
2868
  * }} GlobalObject
@@ -2873,6 +2894,10 @@ function requireFakeTimersSrc () {
2873
2894
  * @typedef {Record<string, any> & { clock: Clock }} IntlWithClock
2874
2895
  */
2875
2896
 
2897
+ /**
2898
+ * @typedef {Record<string, any> & { now: () => number }} PerformanceLike
2899
+ */
2900
+
2876
2901
  /**
2877
2902
  * @typedef {object} Timers
2878
2903
  * @property {SetTimeout} setTimeout - native `setTimeout`
@@ -2881,11 +2906,12 @@ function requireFakeTimersSrc () {
2881
2906
  * @property {ClearInterval} clearInterval - native `clearInterval`
2882
2907
  * @property {typeof Date} Date - native `Date`
2883
2908
  * @property {typeof Intl} [Intl] - native `Intl`
2909
+ * @property {any} [Temporal] - native `Temporal`
2884
2910
  * @property {SetImmediate} [setImmediate] - native `setImmediate`, if available
2885
2911
  * @property {ClearImmediate} [clearImmediate] - native `clearImmediate`, if available
2886
2912
  * @property {Hrtime} [hrtime] - native `process.hrtime`, if available
2887
2913
  * @property {NextTick} [nextTick] - native `process.nextTick`, if available
2888
- * @property {Performance} [performance] - native `performance`, if available
2914
+ * @property {PerformanceLike} [performance] - native `performance`, if available
2889
2915
  * @property {RequestAnimationFrame} [requestAnimationFrame] - native `requestAnimationFrame`, if available
2890
2916
  * @property {QueueMicrotask} [queueMicrotask] - whether `queueMicrotask` exists
2891
2917
  * @property {CancelAnimationFrame} [cancelAnimationFrame] - native `cancelAnimationFrame`, if available
@@ -2926,7 +2952,7 @@ function requireFakeTimersSrc () {
2926
2952
 
2927
2953
  /**
2928
2954
  * @callback CreateClockCallback
2929
- * @param {number|Date} [start] initial mocked time, as milliseconds since epoch or a Date
2955
+ * @param {number|Date|TemporalTimelike} [start] initial mocked time, as milliseconds since epoch, a Date, a Temporal.Instant, or a Temporal.ZonedDateTime
2930
2956
  * @param {number} [loopLimit] maximum number of timers run before aborting with an infinite-loop error
2931
2957
  * @returns {Clock}
2932
2958
  */
@@ -2993,13 +3019,14 @@ function requireFakeTimersSrc () {
2993
3019
  * @property {ClockTickMode} [tickMode] - internal flag
2994
3020
  * @property {Timer[]} [jobs] - internal flag
2995
3021
  * @property {IntlWithClock} [Intl] - fake Intl object
3022
+ * @property {any} [Temporal] - fake Temporal object
2996
3023
  */
2997
3024
  /* eslint-enable jsdoc/reject-any-type */
2998
3025
 
2999
3026
  /**
3000
3027
  * Configuration object for the `install` method.
3001
3028
  * @typedef {object} Config
3002
- * @property {number|Date} [now] initial mocked time, as milliseconds since epoch or a Date
3029
+ * @property {number|Date|TemporalTimelike} [now] initial mocked time, as milliseconds since epoch, a Date, a Temporal.Instant, or a Temporal.ZonedDateTime
3003
3030
  * @property {FakeMethod[]} [toFake] method names that should be faked
3004
3031
  * @property {FakeMethod[]} [toNotFake] method names that should remain native
3005
3032
  * @property {number} [loopLimit] maximum number of timers run before aborting with an infinite-loop error
@@ -3108,6 +3135,11 @@ function requireFakeTimersSrc () {
3108
3135
  isPresent.clearImmediate =
3109
3136
  _global.clearImmediate && typeof _global.clearImmediate === "function";
3110
3137
  isPresent.Intl = _global.Intl && typeof _global.Intl === "object";
3138
+ isPresent.Temporal =
3139
+ _global.Temporal !== null &&
3140
+ typeof _global.Temporal === "object" &&
3141
+ typeof _global.Temporal.Now !== "undefined" &&
3142
+ typeof _global.Temporal.Instant !== "undefined";
3111
3143
 
3112
3144
  if (_global.clearTimeout) {
3113
3145
  _global.clearTimeout(timeoutResult);
@@ -3120,6 +3152,7 @@ function requireFakeTimersSrc () {
3120
3152
  Object.getOwnPropertyDescriptors(_global.Intl),
3121
3153
  )
3122
3154
  : undefined;
3155
+ const NativeTemporal = isPresent.Temporal ? _global.Temporal : undefined;
3123
3156
  let uniqueTimerId = idCounterStart;
3124
3157
  /** @type {number} */
3125
3158
  let uniqueTimerOrder = 0;
@@ -3237,7 +3270,7 @@ function requireFakeTimersSrc () {
3237
3270
 
3238
3271
  /**
3239
3272
  * Used to grok the `now` parameter to createClock.
3240
- * @param {Date|number} epoch the system time
3273
+ * @param {Date|number|TemporalTimelike} epoch the system time
3241
3274
  * @returns {number}
3242
3275
  */
3243
3276
  function getEpoch(epoch) {
@@ -3247,8 +3280,16 @@ function requireFakeTimersSrc () {
3247
3280
  if (typeof epoch === "number") {
3248
3281
  return epoch;
3249
3282
  }
3250
- if (typeof epoch.getTime === "function") {
3251
- return epoch.getTime();
3283
+ if (typeof (/** @type {Date} */ (epoch).getTime) === "function") {
3284
+ return /** @type {Date} */ (epoch).getTime();
3285
+ }
3286
+ if (
3287
+ typeof (
3288
+ /** @type {TemporalTimelike} */ (epoch).epochMilliseconds
3289
+ ) === "number"
3290
+ ) {
3291
+ // Temporal.Instant and Temporal.ZonedDateTime both have epochMilliseconds
3292
+ return /** @type {TemporalTimelike} */ (epoch).epochMilliseconds;
3252
3293
  }
3253
3294
  throw new TypeError("now should be milliseconds since UNIX epoch");
3254
3295
  }
@@ -3465,6 +3506,56 @@ function requireFakeTimersSrc () {
3465
3506
  return IntlWithClock;
3466
3507
  }
3467
3508
 
3509
+ //eslint-disable-next-line jsdoc/require-jsdoc
3510
+ function createTemporal(clock, getNanos) {
3511
+ const fakeNow = {
3512
+ instant() {
3513
+ return NativeTemporal.Instant.fromEpochNanoseconds(
3514
+ BigInt(clock.now) * 1_000_000n + BigInt(getNanos()),
3515
+ );
3516
+ },
3517
+ timeZoneId() {
3518
+ return NativeTemporal.Now.timeZoneId();
3519
+ },
3520
+ zonedDateTimeISO(timeZone) {
3521
+ const tz = timeZone ?? NativeTemporal.Now.timeZoneId();
3522
+ return fakeNow.instant().toZonedDateTimeISO(tz);
3523
+ },
3524
+ plainDateTimeISO(timeZone) {
3525
+ return fakeNow.zonedDateTimeISO(timeZone).toPlainDateTime();
3526
+ },
3527
+ plainDateISO(timeZone) {
3528
+ return fakeNow.zonedDateTimeISO(timeZone).toPlainDate();
3529
+ },
3530
+ plainTimeISO(timeZone) {
3531
+ return fakeNow.zonedDateTimeISO(timeZone).toPlainTime();
3532
+ },
3533
+ };
3534
+
3535
+ const TemporalWithClock = Object.create(
3536
+ Object.getPrototypeOf(NativeTemporal),
3537
+ );
3538
+ [
3539
+ ...Object.getOwnPropertyNames(NativeTemporal),
3540
+ ...Object.getOwnPropertySymbols(NativeTemporal),
3541
+ ].forEach((prop) => {
3542
+ Object.defineProperty(
3543
+ TemporalWithClock,
3544
+ prop,
3545
+ Object.getOwnPropertyDescriptor(NativeTemporal, prop),
3546
+ );
3547
+ });
3548
+ // Temporal.Now is writable:false in the spec so we must use defineProperty
3549
+ Object.defineProperty(TemporalWithClock, "Now", {
3550
+ value: fakeNow,
3551
+ writable: true,
3552
+ enumerable: false,
3553
+ configurable: true,
3554
+ });
3555
+
3556
+ return TemporalWithClock;
3557
+ }
3558
+
3468
3559
  //eslint-disable-next-line jsdoc/require-jsdoc
3469
3560
  function enqueueJob(clock, job) {
3470
3561
  // enqueues a microtick-deferred task - ecma262/#sec-enqueuejob
@@ -4099,85 +4190,6 @@ function requireFakeTimersSrc () {
4099
4190
  }
4100
4191
  }
4101
4192
 
4102
- /**
4103
- * @param {Clock} clock
4104
- * @returns {Timer[]}
4105
- */
4106
- function uninstall(clock) {
4107
- let method, i, l;
4108
- const installedHrTime = "_hrtime";
4109
- const installedNextTick = "_nextTick";
4110
-
4111
- for (i = 0, l = clock.methods.length; i < l; i++) {
4112
- method = clock.methods[i];
4113
- if (method === "hrtime" && _global.process) {
4114
- _global.process.hrtime = clock[installedHrTime];
4115
- } else if (method === "nextTick" && _global.process) {
4116
- _global.process.nextTick = clock[installedNextTick];
4117
- } else if (method === "performance") {
4118
- const originalPerfDescriptor = Object.getOwnPropertyDescriptor(
4119
- clock,
4120
- `_${method}`,
4121
- );
4122
- if (
4123
- originalPerfDescriptor &&
4124
- originalPerfDescriptor.get &&
4125
- !originalPerfDescriptor.set
4126
- ) {
4127
- Object.defineProperty(
4128
- _global,
4129
- method,
4130
- originalPerfDescriptor,
4131
- );
4132
- } else if (originalPerfDescriptor.configurable) {
4133
- _global[method] = clock[`_${method}`];
4134
- }
4135
- } else {
4136
- if (clock[method] && clock[method].hasOwnProperty) {
4137
- _global[method] = clock[`_${method}`];
4138
- } else {
4139
- try {
4140
- delete _global[method];
4141
- } catch {
4142
- /* eslint no-empty: "off" */
4143
- }
4144
- }
4145
- }
4146
- if (clock.timersModuleMethods !== undefined) {
4147
- for (let j = 0; j < clock.timersModuleMethods.length; j++) {
4148
- const entry = clock.timersModuleMethods[j];
4149
- timersModule[entry.methodName] = entry.original;
4150
- }
4151
- }
4152
- if (clock.timersPromisesModuleMethods !== undefined) {
4153
- for (
4154
- let j = 0;
4155
- j < clock.timersPromisesModuleMethods.length;
4156
- j++
4157
- ) {
4158
- const entry = clock.timersPromisesModuleMethods[j];
4159
- timersPromisesModule[entry.methodName] = entry.original;
4160
- }
4161
- }
4162
- }
4163
-
4164
- clock.setTickMode({ mode: "manual" });
4165
-
4166
- // Prevent multiple executions which will completely remove these props
4167
- clock.methods = [];
4168
-
4169
- for (const [listener, signal] of clock.abortListenerMap.entries()) {
4170
- signal.removeEventListener("abort", listener);
4171
- clock.abortListenerMap.delete(listener);
4172
- }
4173
-
4174
- // return pending timers, to enable checking what timers remained on uninstall
4175
- if (!clock.timerHeap) {
4176
- return [];
4177
- }
4178
- return clock.timerHeap.timers.slice();
4179
- }
4180
-
4181
4193
  /**
4182
4194
  * @param {object} target the target containing the method to replace
4183
4195
  * @param {string} method the keyname of the method on the target
@@ -4194,6 +4206,8 @@ function requireFakeTimersSrc () {
4194
4206
  target[method] = clock[method];
4195
4207
  } else if (method === "Intl") {
4196
4208
  target[method] = clock[method];
4209
+ } else if (method === "Temporal") {
4210
+ target[method] = clock[method];
4197
4211
  } else if (method === "performance") {
4198
4212
  const originalPerfDescriptor = Object.getOwnPropertyDescriptor(
4199
4213
  target,
@@ -4294,12 +4308,16 @@ function requireFakeTimersSrc () {
4294
4308
  timers.Intl = NativeIntl;
4295
4309
  }
4296
4310
 
4311
+ if (isPresent.Temporal) {
4312
+ timers.Temporal = NativeTemporal;
4313
+ }
4314
+
4297
4315
  const originalSetTimeout = _global.setImmediate || _global.setTimeout;
4298
4316
  const originalClearInterval = _global.clearInterval;
4299
4317
  const originalSetInterval = _global.setInterval;
4300
4318
 
4301
4319
  /**
4302
- * @param {Date|number} [start] the system time - non-integer values are floored
4320
+ * @param {Date|number|TemporalTimelike} [start] the system time - non-integer values are floored
4303
4321
  * @param {number} [loopLimit] maximum number of timers that will be run when calling runAll()
4304
4322
  * @returns {Clock}
4305
4323
  */
@@ -4312,6 +4330,7 @@ function requireFakeTimersSrc () {
4312
4330
  loopLimit = loopLimit || 1000;
4313
4331
  /** @type {number} */
4314
4332
  let nanos = 0;
4333
+ let uninstalled = false;
4315
4334
  /** @type {number[]} */
4316
4335
  const adjustedSystemTime = [0, 0]; // [millis, nanoremainder]
4317
4336
 
@@ -4389,6 +4408,10 @@ function requireFakeTimersSrc () {
4389
4408
  clock.Intl.clock = clock;
4390
4409
  }
4391
4410
 
4411
+ if (isPresent.Temporal) {
4412
+ clock.Temporal = createTemporal(clock, () => nanos);
4413
+ }
4414
+
4392
4415
  /**
4393
4416
  * @param {SetTickModeConfig} tickModeConfig - The new configuration for how the clock should tick.
4394
4417
  */
@@ -4467,7 +4490,9 @@ function requireFakeTimersSrc () {
4467
4490
  }
4468
4491
  clock.setTickMode({ mode: "manual" });
4469
4492
  return promise.finally(() => {
4470
- clock.setTickMode({ mode: "nextAsync" });
4493
+ if (!uninstalled) {
4494
+ clock.setTickMode({ mode: "nextAsync" });
4495
+ }
4471
4496
  });
4472
4497
  }
4473
4498
 
@@ -4623,15 +4648,44 @@ function requireFakeTimersSrc () {
4623
4648
  runJobs(clock);
4624
4649
  };
4625
4650
 
4651
+ //eslint-disable-next-line jsdoc/require-jsdoc
4652
+ function durationToMs(duration) {
4653
+ // relativeTo uses the real system timezone — fake-timers fakes time, not place.
4654
+ // Calendar-unit durations (months, years) will resolve DST/length using the host tz.
4655
+ const relativeTo = NativeTemporal.Instant.fromEpochMilliseconds(
4656
+ clock.now,
4657
+ ).toZonedDateTimeISO(NativeTemporal.Now.timeZoneId());
4658
+ return duration.total({ unit: "millisecond", relativeTo });
4659
+ }
4660
+
4626
4661
  /**
4627
- * @param {number|string} tickValue milliseconds or a string parseable by parseTime
4662
+ * @param {number|string|TemporalDuration} tickValue
4663
+ * @returns {number} milliseconds as a float
4664
+ */
4665
+ function tickValueToMs(tickValue) {
4666
+ if (typeof tickValue === "number") {
4667
+ return tickValue;
4668
+ }
4669
+ if (
4670
+ isPresent.Temporal &&
4671
+ tickValue !== null &&
4672
+ typeof tickValue === "object" &&
4673
+ typeof (/** @type {TemporalDuration} */ (tickValue).total) ===
4674
+ "function"
4675
+ ) {
4676
+ return durationToMs(
4677
+ /** @type {TemporalDuration} */ (tickValue),
4678
+ );
4679
+ }
4680
+ return parseTime(/** @type {string} */ (tickValue));
4681
+ }
4682
+
4683
+ /**
4684
+ * @param {number|string|TemporalDuration} tickValue milliseconds, a string parseable by parseTime, or a Temporal.Duration
4628
4685
  * @returns {ClockState} a mutable state object for the tick execution
4629
4686
  */
4630
4687
  function createTickState(tickValue) {
4631
- const msFloat =
4632
- typeof tickValue === "number"
4633
- ? tickValue
4634
- : parseTime(tickValue);
4688
+ const msFloat = tickValueToMs(tickValue);
4635
4689
  const ms = Math.floor(msFloat);
4636
4690
  const remainder = nanoRemainder(msFloat);
4637
4691
  let nanosTotal = nanos + remainder;
@@ -4792,7 +4846,7 @@ function requireFakeTimersSrc () {
4792
4846
  }
4793
4847
 
4794
4848
  /**
4795
- * @param {number|string} tickValue milliseconds or a string parseable by parseTime
4849
+ * @param {number|string|TemporalDuration} tickValue milliseconds or a string parseable by parseTime
4796
4850
  * @param {boolean} isAsync whether this is an async tick
4797
4851
  * @param {FakeTimersFunction} [resolve] promise resolve function
4798
4852
  * @param {FakeTimersFunction} [reject] promise reject function
@@ -4848,7 +4902,7 @@ function requireFakeTimersSrc () {
4848
4902
  }
4849
4903
 
4850
4904
  /**
4851
- * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15"
4905
+ * @param {string|number|TemporalDuration} tickValue number of milliseconds, a human-readable value like "01:11:15", or a Temporal.Duration
4852
4906
  * @returns {number} will return the new `now` value
4853
4907
  */
4854
4908
  clock.tick = function tick(tickValue) {
@@ -4929,7 +4983,7 @@ function requireFakeTimersSrc () {
4929
4983
 
4930
4984
  if (typeof _global.Promise !== "undefined") {
4931
4985
  /**
4932
- * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15"
4986
+ * @param {string|number|TemporalDuration} tickValue number of milliseconds, a human-readable value like "01:11:15", or a Temporal.Duration
4933
4987
  * @returns {Promise}
4934
4988
  */
4935
4989
  clock.tickAsync = function tickAsync(tickValue) {
@@ -5055,14 +5109,11 @@ function requireFakeTimersSrc () {
5055
5109
  };
5056
5110
 
5057
5111
  /**
5058
- * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15"
5112
+ * @param {string|number|TemporalDuration} tickValue number of milliseconds, a human-readable value like "01:11:15", or a Temporal.Duration
5059
5113
  * @returns {number} the new `now` value
5060
5114
  */
5061
5115
  clock.jump = function jump(tickValue) {
5062
- const msFloat =
5063
- typeof tickValue === "number"
5064
- ? tickValue
5065
- : parseTime(tickValue);
5116
+ const msFloat = tickValueToMs(tickValue);
5066
5117
  const ms = Math.floor(msFloat);
5067
5118
 
5068
5119
  forEachActiveTimer(clock, (timer) => {
@@ -5087,6 +5138,97 @@ function requireFakeTimersSrc () {
5087
5138
  clock.hrtime = hrtime;
5088
5139
  }
5089
5140
 
5141
+ /**
5142
+ * @returns {Timer[]}
5143
+ */
5144
+ clock.uninstall = function () {
5145
+ uninstalled = true;
5146
+ clock.setTickMode({ mode: "manual" });
5147
+
5148
+ if (clock.methods) {
5149
+ const installedHrTime = "_hrtime";
5150
+ const installedNextTick = "_nextTick";
5151
+ let method, i, l;
5152
+ for (i = 0, l = clock.methods.length; i < l; i++) {
5153
+ method = clock.methods[i];
5154
+ if (method === "hrtime" && _global.process) {
5155
+ _global.process.hrtime = clock[installedHrTime];
5156
+ } else if (method === "nextTick" && _global.process) {
5157
+ _global.process.nextTick = clock[installedNextTick];
5158
+ } else if (method === "performance") {
5159
+ const originalPerfDescriptor =
5160
+ Object.getOwnPropertyDescriptor(
5161
+ clock,
5162
+ `_${method}`,
5163
+ );
5164
+ if (
5165
+ originalPerfDescriptor &&
5166
+ originalPerfDescriptor.get &&
5167
+ !originalPerfDescriptor.set
5168
+ ) {
5169
+ Object.defineProperty(
5170
+ _global,
5171
+ method,
5172
+ originalPerfDescriptor,
5173
+ );
5174
+ } else if (originalPerfDescriptor.configurable) {
5175
+ _global[method] = clock[`_${method}`];
5176
+ }
5177
+ } else {
5178
+ if (clock[method] && clock[method].hasOwnProperty) {
5179
+ _global[method] = clock[`_${method}`];
5180
+ } else {
5181
+ try {
5182
+ delete _global[method];
5183
+ } catch {
5184
+ /* eslint no-empty: "off" */
5185
+ }
5186
+ }
5187
+ }
5188
+ if (clock.timersModuleMethods !== undefined) {
5189
+ for (
5190
+ let j = 0;
5191
+ j < clock.timersModuleMethods.length;
5192
+ j++
5193
+ ) {
5194
+ const entry = clock.timersModuleMethods[j];
5195
+ timersModule[entry.methodName] = entry.original;
5196
+ }
5197
+ }
5198
+ if (clock.timersPromisesModuleMethods !== undefined) {
5199
+ for (
5200
+ let j = 0;
5201
+ j < clock.timersPromisesModuleMethods.length;
5202
+ j++
5203
+ ) {
5204
+ const entry = clock.timersPromisesModuleMethods[j];
5205
+ timersPromisesModule[entry.methodName] =
5206
+ entry.original;
5207
+ }
5208
+ }
5209
+ }
5210
+
5211
+ // Prevent multiple executions which will completely remove these props
5212
+ clock.methods = [];
5213
+ }
5214
+
5215
+ if (clock.abortListenerMap) {
5216
+ for (const [
5217
+ listener,
5218
+ signal,
5219
+ ] of clock.abortListenerMap.entries()) {
5220
+ signal.removeEventListener("abort", listener);
5221
+ clock.abortListenerMap.delete(listener);
5222
+ }
5223
+ }
5224
+
5225
+ // return pending timers, to enable checking what timers remained on uninstall
5226
+ if (!clock.timerHeap) {
5227
+ return [];
5228
+ }
5229
+ return clock.timerHeap.timers.slice();
5230
+ };
5231
+
5090
5232
  return clock;
5091
5233
  }
5092
5234
 
@@ -5175,10 +5317,6 @@ function requireFakeTimersSrc () {
5175
5317
  const clock = createClock(config.now, config.loopLimit);
5176
5318
  clock.shouldClearNativeTimers = config.shouldClearNativeTimers;
5177
5319
 
5178
- clock.uninstall = function () {
5179
- return uninstall(clock);
5180
- };
5181
-
5182
5320
  clock.abortListenerMap = new Map();
5183
5321
 
5184
5322
  if (hasToFake) {
@@ -5692,6 +5830,235 @@ class FakeTimers {
5692
5830
  }
5693
5831
  }
5694
5832
 
5833
+ const whenSymbol = Symbol.for("$$vitest:when");
5834
+ /**
5835
+ * Returns `true` if the given value is a {@linkcode When} chain created by {@linkcode when|vi.when}.
5836
+ *
5837
+ * @param input - The value to check.
5838
+ * @returns `true` if `input` is a {@linkcode When} instance, `false` otherwise.
5839
+ *
5840
+ * @example
5841
+ * const spy = vi.fn()
5842
+ * const w = vi.when(spy).calledWith(1).thenReturn(0)
5843
+ *
5844
+ * expect(isWhenChain(w)).toBe(true)
5845
+ * expect(isWhenChain(spy)).toBe(false)
5846
+ */
5847
+ function isWhenChain(input) {
5848
+ try {
5849
+ return Reflect.has(input, whenSymbol);
5850
+ } catch {
5851
+ return false;
5852
+ }
5853
+ }
5854
+ /**
5855
+ * Defines conditional behaviors on a Vitest spy based on the arguments it is called with.
5856
+ *
5857
+ * Behaviors are matched using deep equality, last-registered first within each argument set.
5858
+ *
5859
+ * It automatically restores the spy's original implementation when the enclosing block exits if used with the `using` keyword.
5860
+ *
5861
+ * @param spy - A Vitest mock function to attach behaviors to.
5862
+ * @param options - Optional configuration.
5863
+ * @returns A {@linkcode When} instance for registering behaviors.
5864
+ *
5865
+ * @throws {TypeError} If `spy` is not a Vitest mock function.
5866
+ * @throws {Error} If chaining a non-existent method after `calledWith`.
5867
+ * @throws {RangeError} If setting the `times` option on a `then*` method as a negative value or `0`.
5868
+ *
5869
+ * @since 5.0.0
5870
+ * @see {@link https://vitest.dev/api/vi#vi-when}
5871
+ * @see {@link https://vitest.dev/guide/recipes/conditional-mocking}
5872
+ *
5873
+ * @example
5874
+ * // Basic usage
5875
+ * const spy = vi.fn(() => Number.NEGATIVE_INFINITY)
5876
+ * vi.when(spy).calledWith(1).thenReturn(0)
5877
+ *
5878
+ * expect(spy(1)).toBe(0)
5879
+ * expect(spy(2)).toBe(Number.NEGATIVE_INFINITY) // falls through to original implementation
5880
+ *
5881
+ * @example
5882
+ * // Async
5883
+ * const spy = vi.fn()
5884
+ * vi.when(spy).calledWith('user').thenResolve({ id: 1 })
5885
+ *
5886
+ * await expect(spy('user')).resolves.toEqual({ id: 1 })
5887
+ *
5888
+ * @example
5889
+ * // Scoped with `using`
5890
+ * const spy = vi.fn()
5891
+ *
5892
+ * {
5893
+ * using w = vi.when(spy)
5894
+ * .calledWith('darkMode')
5895
+ * .thenReturn(true)
5896
+ *
5897
+ * expect(spy('darkMode')).toBe(true)
5898
+ * }
5899
+ *
5900
+ * // spy's original implementation is restored here
5901
+ * expect(spy('darkMode')).toBe(undefined)
5902
+ *
5903
+ * @example
5904
+ * // Throw on unmatched calls
5905
+ * vi.when(spy, { onUnmatched: 'throw' })
5906
+ * .calledWith(1)
5907
+ * .thenReturn({ id: 1, name: 'Alice' })
5908
+ *
5909
+ * expect(spy(1)).toEqual({ id: 1, name: 'Alice' })
5910
+ * expect(() => spy(2)).toThrow()
5911
+ */
5912
+ function when(spy, options) {
5913
+ if (!isMockFunction(spy)) throw new TypeError("vi.when: the argument must be a mock function created with `vi.fn()` or `vi.spyOn()`");
5914
+ const behaviors = [];
5915
+ const originalImplementation = spy.getMockImplementation();
5916
+ function findAction(args) {
5917
+ const testers = [...getCustomEqualityTesters(), iterableEquality];
5918
+ for (const behavior of behaviors) if (equals(args, behavior.arguments, testers)) return behavior.actions.findLast((action) => !(action.remaining === 0 && action.called)) ?? null;
5919
+ return null;
5920
+ }
5921
+ spy.mockImplementation(
5922
+ // @ts-expect-error cannot resolve generic args
5923
+ (...args) => {
5924
+ const action = findAction(args);
5925
+ if (action === null) return (typeof options?.onUnmatched === "function" ? options.onUnmatched : options?.onUnmatched === "throw" ? () => {
5926
+ throw new Error(`vi.when: no behavior defined when called with [${args.map((arg) => stringify(arg)).join(", ")}]`);
5927
+ } : originalImplementation)?.(...args);
5928
+ action.remaining -= 1;
5929
+ action.called = true;
5930
+ switch (action.type) {
5931
+ case "return": return action.value;
5932
+ case "throw": throw action.value;
5933
+ case "resolve": return Promise.resolve(action.value);
5934
+ case "reject": return Promise.reject(action.value);
5935
+ }
5936
+ }
5937
+ );
5938
+ function getOrCreateBehavior(args) {
5939
+ const testers = [...getCustomEqualityTesters(), iterableEquality];
5940
+ let behavior = behaviors.find((behavior) => equals(args, behavior.arguments, testers));
5941
+ if (behavior === void 0) {
5942
+ behavior = {
5943
+ arguments: args,
5944
+ actions: []
5945
+ };
5946
+ behaviors.push(behavior);
5947
+ }
5948
+ return behavior;
5949
+ }
5950
+ // @ts-expect-error `Symbol.dispose` has to be assigned conditionally since it's only supported in Node >= 24
5951
+ const output = markWhenChain({
5952
+ calledWith: (...args) => {
5953
+ const behavior = getOrCreateBehavior(args);
5954
+ function appendAction(behavior, type, value, times) {
5955
+ behavior.actions.push({
5956
+ type,
5957
+ value,
5958
+ times,
5959
+ remaining: times,
5960
+ called: false
5961
+ });
5962
+ }
5963
+ const calledWithInstance = markWhenChain({
5964
+ ...output,
5965
+ thenThrow: (value, options) => {
5966
+ validateOptions(options);
5967
+ appendAction(behavior, "throw", value, options?.times ?? Number.POSITIVE_INFINITY);
5968
+ return calledWithInstance;
5969
+ },
5970
+ thenThrowOnce: (value) => {
5971
+ appendAction(behavior, "throw", value, 1);
5972
+ return calledWithInstance;
5973
+ },
5974
+ thenReturn: (value, options) => {
5975
+ validateOptions(options);
5976
+ appendAction(behavior, "return", value, options?.times ?? Number.POSITIVE_INFINITY);
5977
+ return calledWithInstance;
5978
+ },
5979
+ thenReturnOnce: (value) => {
5980
+ appendAction(behavior, "return", value, 1);
5981
+ return calledWithInstance;
5982
+ },
5983
+ thenResolve: (value, options) => {
5984
+ validateOptions(options);
5985
+ appendAction(behavior, "resolve", value, options?.times ?? Number.POSITIVE_INFINITY);
5986
+ return calledWithInstance;
5987
+ },
5988
+ thenResolveOnce: (value) => {
5989
+ appendAction(behavior, "resolve", value, 1);
5990
+ return calledWithInstance;
5991
+ },
5992
+ thenReject: (value, options) => {
5993
+ validateOptions(options);
5994
+ appendAction(behavior, "reject", value, options?.times ?? Number.POSITIVE_INFINITY);
5995
+ return calledWithInstance;
5996
+ },
5997
+ thenRejectOnce: (value) => {
5998
+ appendAction(behavior, "reject", value, 1);
5999
+ return calledWithInstance;
6000
+ }
6001
+ });
6002
+ return calledWithInstance;
6003
+ },
6004
+ _getDiagnostics: () => {
6005
+ const pendingBehaviors = behaviors.filter((behavior) => behavior.actions.length === 0 || behavior.actions.some((action) => !hasBeenConsumed(action)));
6006
+ return {
6007
+ isExhausted: behaviors.length !== 0 && pendingBehaviors.length === 0,
6008
+ pendingBehaviors: pendingBehaviors.map((behavior) => `calledWith(${behavior.arguments.map((argument) => stringify(argument)).join(", ")})${behavior.actions.length === 0 ? " → no actions" : `\n${formatActions(behavior.actions)}`}`).join("\n\n")
6009
+ };
6010
+ }
6011
+ });
6012
+ if (Symbol.dispose) output[Symbol.dispose] = () => {
6013
+ spy.mockImplementation(
6014
+ // @ts-expect-error without an original implementation we should fall back to an undefined-returning function as that's what the mocking functions do
6015
+ originalImplementation ?? noop
6016
+ );
6017
+ };
6018
+ return output;
6019
+ }
6020
+ const whenChainMarkerOptions = {};
6021
+ function markWhenChain(input) {
6022
+ Reflect.defineProperty(input, whenSymbol, whenChainMarkerOptions);
6023
+ return input;
6024
+ }
6025
+ function formatActions(actions) {
6026
+ const lines = actions.map((action, index) => {
6027
+ const method = getMethodName(action.type);
6028
+ const left = ` ${getSymbol(action)} ${method}(${stringify(action.value)}${action.times === Number.POSITIVE_INFINITY ? "" : `, { times: ${action.times} }`})`;
6029
+ const unreachable = !hasBeenConsumed(action) && actions.slice(index + 1).some((later) => later.times === Number.POSITIVE_INFINITY);
6030
+ return {
6031
+ left,
6032
+ remaining: getRemainingLabel(action) + (unreachable ? " → unreachable action" : "")
6033
+ };
6034
+ });
6035
+ const maxLeft = Math.max(...lines.map((line) => line.left.length));
6036
+ return lines.map(({ left, remaining }) => `${left.padEnd(maxLeft + 2)}${remaining}`).join("\n");
6037
+ }
6038
+ function getMethodName(type) {
6039
+ switch (type) {
6040
+ case "return": return "thenReturn";
6041
+ case "resolve": return "thenResolve";
6042
+ case "throw": return "thenThrow";
6043
+ case "reject": return "thenReject";
6044
+ default: throw new Error(`vi.when: "${type}" is not a known method`);
6045
+ }
6046
+ }
6047
+ function hasBeenConsumed(action) {
6048
+ return action.remaining === 0 || action.remaining === Number.POSITIVE_INFINITY && action.called;
6049
+ }
6050
+ function getRemainingLabel(action) {
6051
+ if (hasBeenConsumed(action)) return action.remaining === Number.POSITIVE_INFINITY ? "exhausted" : `exhausted (${action.times} of ${action.times})`;
6052
+ return action.remaining === Number.POSITIVE_INFINITY ? "never called" : `${action.remaining} remaining (out of ${action.times})`;
6053
+ }
6054
+ function getSymbol(action) {
6055
+ if (hasBeenConsumed(action)) return "✓";
6056
+ return "✗";
6057
+ }
6058
+ function validateOptions(options) {
6059
+ if (typeof options?.times === "number" && options.times <= 0) throw new RangeError("vi.when: `times` option must be greater than 0");
6060
+ }
6061
+
5695
6062
  function copyStackTrace$2(target, source) {
5696
6063
  if (source.stack !== void 0) target.stack = source.stack.replace(source.message, target.message);
5697
6064
  return target;
@@ -5888,6 +6255,8 @@ function createVitest() {
5888
6255
  },
5889
6256
  spyOn,
5890
6257
  fn,
6258
+ when,
6259
+ isWhenChain,
5891
6260
  waitFor,
5892
6261
  waitUntil,
5893
6262
  defineHelper: (fn) => {
@@ -6034,6 +6403,20 @@ function copyStackTrace$1(target, source) {
6034
6403
  if (source.stack !== void 0) target.stack = source.stack.replace(source.message, target.message);
6035
6404
  return target;
6036
6405
  }
6406
+ function waitNextTick() {
6407
+ const { setTimeout } = getSafeTimers();
6408
+ return new Promise((resolve) => setTimeout(resolve, 0));
6409
+ }
6410
+ async function waitForImportsToResolve() {
6411
+ await waitNextTick();
6412
+ const state = getWorkerState();
6413
+ const promises = [];
6414
+ const resolvingCount = state.resolvingModules.size;
6415
+ for (const [_, mod] of state.evaluatedModules.idToModuleMap) if (mod.promise && !mod.evaluated) promises.push(mod.promise);
6416
+ if (!promises.length && !resolvingCount) return;
6417
+ await Promise.allSettled(promises);
6418
+ await waitForImportsToResolve();
6419
+ }
6037
6420
 
6038
6421
  // these matchers are not supported because they don't make sense with poll
6039
6422
  const unsupported = [
@@ -6057,7 +6440,7 @@ const unsupported = [
6057
6440
  * @throws Always throws the provided error with an amended stack trace
6058
6441
  */
6059
6442
  function throwWithCause(error, source) {
6060
- if (error.cause == null) error.cause = /* @__PURE__ */ new Error("Matcher did not succeed in time.");
6443
+ error.cause ??= /* @__PURE__ */ new Error("Matcher did not succeed in time.");
6061
6444
  throw copyStackTrace(error, source);
6062
6445
  }
6063
6446
  function createExpectPoll(expect) {
@@ -6215,6 +6598,15 @@ function raceWith$1(promise, other) {
6215
6598
  }))]);
6216
6599
  }
6217
6600
 
6601
+ const MockPlugin = (chai, utils) => {
6602
+ utils.addMethod(chai.Assertion.prototype, "toHaveBeenExhausted", wrapAssertion(utils, "toHaveBeenExhausted", function() {
6603
+ const chain = utils.flag(this, "object");
6604
+ if (!isWhenChain(chain)) throw new TypeError(`${utils.inspect(chain)} is not a \`vi.when\` instance`);
6605
+ const diagnostics = chain._getDiagnostics();
6606
+ this.assert(diagnostics.isExhausted, `expected all behaviors to have been exhausted, but some remain:\n\n ${diagnostics.pendingBehaviors.replaceAll(/\n(?!\n)/g, "\n ")}`, "expected at least one behavior to remain un-exhausted, but all were");
6607
+ }));
6608
+ };
6609
+
6218
6610
  var naturalCompare$1 = {exports: {}};
6219
6611
 
6220
6612
  var hasRequiredNaturalCompare;
@@ -6874,7 +7266,7 @@ class SnapshotState {
6874
7266
  if (!rawSnapshot) receivedSerialized = addExtraLineBreaks(receivedSerialized);
6875
7267
  if (rawSnapshot) {
6876
7268
  // normalize EOL when snapshot contains CRLF but received is LF
6877
- if (rawSnapshot.content && rawSnapshot.content.match(/\r\n/) && !receivedSerialized.match(/\r\n/)) rawSnapshot.content = normalizeNewlines(rawSnapshot.content);
7269
+ if (rawSnapshot.content && /\r\n/.test(rawSnapshot.content) && !/\r\n/.test(receivedSerialized)) rawSnapshot.content = normalizeNewlines(rawSnapshot.content);
6878
7270
  }
6879
7271
  const expected = isInline ? inlineSnapshot : rawSnapshot ? rawSnapshot.content : this._snapshotData[key];
6880
7272
  const expectedTrimmed = rawSnapshot ? expected : expected?.trim();
@@ -7467,6 +7859,7 @@ chai.use(JestChaiExpect);
7467
7859
  chai.use(ChaiStyleAssertions);
7468
7860
  chai.use(SnapshotPlugin);
7469
7861
  chai.use(JestAsymmetricMatchers);
7862
+ chai.use(MockPlugin);
7470
7863
 
7471
7864
  function createExpect(test) {
7472
7865
  const expect = ((value, message) => {
@@ -7724,7 +8117,7 @@ function createBench(test, config) {
7724
8117
  bench.compare = async (...args) => {
7725
8118
  validateBenchmarkProject(config);
7726
8119
  // extract optional trailing BenchCompareOptions argument
7727
- const lastArg = args[args.length - 1];
8120
+ const lastArg = args.at(-1);
7728
8121
  const benchOptions = lastArg != null && typeof lastArg === "object" && !(kRegistration in lastArg) ? args.pop() : void 0;
7729
8122
  const registrations = args;
7730
8123
  // Mark every passed-in registration as consumed before validation so a
@@ -7775,7 +8168,7 @@ function createBench(test, config) {
7775
8168
  };
7776
8169
  bench[kFinalize] = () => {
7777
8170
  if (pending.size === 0) return;
7778
- const names = [...pending].map((reg) => `"${reg.name}"`).join(", ");
8171
+ const names = Array.from(pending, (reg) => `"${reg.name}"`).join(", ");
7779
8172
  pending.clear();
7780
8173
  console.warn([
7781
8174
  c.yellow(c.bold("Benchmark Warning")),
@@ -7981,6 +8374,7 @@ class TestRunner {
7981
8374
  static setSuiteHooks = getHooks;
7982
8375
  static setTestFn = getFn;
7983
8376
  static matchesTags = matchesTags;
8377
+ static createFileTask = createFileTask;
7984
8378
  /**
7985
8379
  * @experimental
7986
8380
  * A function that runs tinybench tasks.