vitest 4.0.17 → 4.1.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.
Files changed (58) hide show
  1. package/dist/browser.d.ts +1 -1
  2. package/dist/browser.js +1 -1
  3. package/dist/chunks/{base.XJJQZiKB.js → base.CBRNZa3k.js} +8 -7
  4. package/dist/chunks/{browser.d.ChKACdzH.d.ts → browser.d.8hOapKZr.d.ts} +3 -1
  5. package/dist/chunks/{cac.jRCLJDDc.js → cac.B1v3xxoC.js} +26 -8
  6. package/dist/chunks/{cli-api.Cx2DW4Bc.js → cli-api.B4CqEpI6.js} +102 -54
  7. package/dist/chunks/{config.d.Cy95HiCx.d.ts → config.d.idH22YSr.d.ts} +8 -11
  8. package/dist/chunks/{console.Cf-YriPC.js → console.uGgdMhyZ.js} +2 -1
  9. package/dist/chunks/{coverage.AVPTjMgw.js → coverage.BMlOMIWl.js} +14 -4
  10. package/dist/chunks/{creator.DAmOKTvJ.js → creator.C7WwjkuR.js} +32 -1
  11. package/dist/chunks/{globals.DOayXfHP.js → globals.DjuGMoMc.js} +10 -9
  12. package/dist/chunks/{index.Z5E_ObnR.js → index.BEFi2-_3.js} +3 -1
  13. package/dist/chunks/{index.6Qv1eEA6.js → index.BiOAd_ki.js} +16 -4
  14. package/dist/chunks/{index.M8mOzt4Y.js → index.Dm4xqZ0s.js} +2 -2
  15. package/dist/chunks/{index.C5r1PdPD.js → index.DyBZXrH3.js} +1 -1
  16. package/dist/chunks/{init-forks.BC6ZwHQN.js → init-forks.CHeQ9Moq.js} +1 -1
  17. package/dist/chunks/{init-threads.CxSxLC0N.js → init-threads.uZiNAuPk.js} +1 -1
  18. package/dist/chunks/{init.C9kljSTm.js → init.DVtKdFty.js} +21 -6
  19. package/dist/chunks/{plugin.d.CtqpEehP.d.ts → plugin.d.D8KU2PY_.d.ts} +1 -1
  20. package/dist/chunks/{reporters.d.CWXNI2jG.d.ts → reporters.d.Db3MiIWX.d.ts} +48 -20
  21. package/dist/chunks/rpc.HLmECnw_.js +148 -0
  22. package/dist/chunks/{setup-common.Cm-kSBVi.js → setup-common.BcqLPsn5.js} +1 -1
  23. package/dist/chunks/{startModuleRunner.DEj0jb3e.js → startModuleRunner.C5CcWyXW.js} +22 -22
  24. package/dist/chunks/{vi.2VT5v0um.js → test.prxIahgM.js} +500 -119
  25. package/dist/chunks/{vm.CMjifoPa.js → vm.CrifS09m.js} +5 -8
  26. package/dist/chunks/{worker.d.Dyxm8DEL.d.ts → worker.d.Bji1eq5g.d.ts} +1 -1
  27. package/dist/cli.js +2 -2
  28. package/dist/config.d.ts +9 -9
  29. package/dist/coverage.d.ts +7 -7
  30. package/dist/coverage.js +3 -1
  31. package/dist/environments.js +2 -0
  32. package/dist/index.d.ts +21 -9
  33. package/dist/index.js +8 -7
  34. package/dist/module-evaluator.js +1 -5
  35. package/dist/node.d.ts +11 -10
  36. package/dist/node.js +19 -19
  37. package/dist/reporters.d.ts +7 -7
  38. package/dist/reporters.js +4 -2
  39. package/dist/runners.d.ts +23 -4
  40. package/dist/runners.js +4 -4
  41. package/dist/runtime.d.ts +6 -0
  42. package/dist/runtime.js +36 -0
  43. package/dist/snapshot.js +2 -0
  44. package/dist/suite.js +2 -0
  45. package/dist/worker.d.ts +4 -3
  46. package/dist/worker.js +8 -10
  47. package/dist/workers/forks.js +9 -11
  48. package/dist/workers/runVmTests.js +10 -12
  49. package/dist/workers/threads.js +9 -11
  50. package/dist/workers/vmForks.js +6 -7
  51. package/dist/workers/vmThreads.js +6 -7
  52. package/package.json +23 -27
  53. package/dist/chunks/date.Bq6ZW5rf.js +0 -73
  54. package/dist/chunks/rpc.BoxB0q7B.js +0 -76
  55. package/dist/chunks/test.B8ej_ZHS.js +0 -254
  56. package/dist/mocker.d.ts +0 -1
  57. package/dist/mocker.js +0 -1
  58. package/dist/module-runner.js +0 -17
@@ -1,16 +1,18 @@
1
- import { chai, equals, iterableEquality, subsetEquality, JestExtend, JestChaiExpect, JestAsymmetricMatchers, GLOBAL_EXPECT, ASYMMETRIC_MATCHERS_OBJECT, getState, setState, addCustomEqualityTesters, customMatchers } from '@vitest/expect';
2
- import { getCurrentTest } from '@vitest/runner';
3
- import { g as getWorkerState, i as isChildProcess, w as waitForImportsToResolve, r as resetModules } from './utils.DvEY5TfP.js';
1
+ import { getCurrentTest, updateTask, createTaskCollector, getCurrentSuite, getHooks, getFn } from '@vitest/runner';
2
+ import { assertTypes, createSimpleStackTrace, createDefer } from '@vitest/utils/helpers';
4
3
  import { getSafeTimers, delay } from '@vitest/utils/timers';
5
- import { getNames } from '@vitest/runner/utils';
4
+ import { a as getBenchOptions, g as getBenchFn } from './benchmark.B3N2zMcH.js';
5
+ import { g as getWorkerState, i as isChildProcess, w as waitForImportsToResolve, r as resetModules } from './utils.DvEY5TfP.js';
6
+ import { chai, equals, iterableEquality, subsetEquality, JestExtend, JestChaiExpect, ChaiStyleAssertions, JestAsymmetricMatchers, GLOBAL_EXPECT, ASYMMETRIC_MATCHERS_OBJECT, getState, setState, addCustomEqualityTesters, customMatchers } from '@vitest/expect';
7
+ import { getNames, getTests, getTestName, createChainable } from '@vitest/runner/utils';
8
+ import { processError } from '@vitest/utils/error';
9
+ import { normalize } from 'pathe';
6
10
  import { stripSnapshotIndentation, addSerializer, SnapshotClient } from '@vitest/snapshot';
7
- import '@vitest/utils/error';
8
- import { assertTypes, createSimpleStackTrace } from '@vitest/utils/helpers';
9
11
  import { fn, spyOn, restoreAllMocks, resetAllMocks, clearAllMocks, isMockFunction } from '@vitest/spy';
10
12
  import '@vitest/utils/offset';
11
13
  import { parseSingleStack } from '@vitest/utils/source-map';
12
14
  import { c as commonjsGlobal } from './_commonjsHelpers.D26ty3Ew.js';
13
- import { R as RealDate, r as resetDate, m as mockDate } from './date.Bq6ZW5rf.js';
15
+ import { R as RealDate, b as resetDate, m as mockDate, r as rpc } from './rpc.HLmECnw_.js';
14
16
 
15
17
  // these matchers are not supported because they don't make sense with poll
16
18
  const unsupported = [
@@ -295,6 +297,7 @@ const SnapshotPlugin = (chai, utils) => {
295
297
 
296
298
  chai.use(JestExtend);
297
299
  chai.use(JestChaiExpect);
300
+ chai.use(ChaiStyleAssertions);
298
301
  chai.use(SnapshotPlugin);
299
302
  chai.use(JestAsymmetricMatchers);
300
303
 
@@ -1326,6 +1329,30 @@ function requireFakeTimersSrc () {
1326
1329
  }
1327
1330
  }
1328
1331
 
1332
+ /**
1333
+ * @typedef {"nextAsync" | "manual" | "interval"} TickMode
1334
+ */
1335
+
1336
+ /**
1337
+ * @typedef {object} NextAsyncTickMode
1338
+ * @property {"nextAsync"} mode
1339
+ */
1340
+
1341
+ /**
1342
+ * @typedef {object} ManualTickMode
1343
+ * @property {"manual"} mode
1344
+ */
1345
+
1346
+ /**
1347
+ * @typedef {object} IntervalTickMode
1348
+ * @property {"interval"} mode
1349
+ * @property {number} [delta]
1350
+ */
1351
+
1352
+ /**
1353
+ * @typedef {IntervalTickMode | NextAsyncTickMode | ManualTickMode} TimerTickMode
1354
+ */
1355
+
1329
1356
  /**
1330
1357
  * @typedef {object} IdleDeadline
1331
1358
  * @property {boolean} didTimeout - whether or not the callback was called before reaching the optional timeout
@@ -1411,6 +1438,7 @@ function requireFakeTimersSrc () {
1411
1438
  * @property {{methodName:string, original:any}[] | undefined} timersModuleMethods
1412
1439
  * @property {{methodName:string, original:any}[] | undefined} timersPromisesModuleMethods
1413
1440
  * @property {Map<function(): void, AbortSignal>} abortListenerMap
1441
+ * @property {function(TimerTickMode): void} setTickMode
1414
1442
  */
1415
1443
  /* eslint-enable jsdoc/require-property-description */
1416
1444
 
@@ -2208,10 +2236,9 @@ function requireFakeTimersSrc () {
2208
2236
 
2209
2237
  /**
2210
2238
  * @param {Clock} clock
2211
- * @param {Config} config
2212
2239
  * @returns {Timer[]}
2213
2240
  */
2214
- function uninstall(clock, config) {
2241
+ function uninstall(clock) {
2215
2242
  let method, i, l;
2216
2243
  const installedHrTime = "_hrtime";
2217
2244
  const installedNextTick = "_nextTick";
@@ -2269,9 +2296,7 @@ function requireFakeTimersSrc () {
2269
2296
  }
2270
2297
  }
2271
2298
 
2272
- if (config.shouldAdvanceTime === true) {
2273
- _global.clearInterval(clock.attachedInterval);
2274
- }
2299
+ clock.setTickMode("manual");
2275
2300
 
2276
2301
  // Prevent multiple executions which will completely remove these props
2277
2302
  clock.methods = [];
@@ -2427,6 +2452,8 @@ function requireFakeTimersSrc () {
2427
2452
  }
2428
2453
 
2429
2454
  const originalSetTimeout = _global.setImmediate || _global.setTimeout;
2455
+ const originalClearInterval = _global.clearInterval;
2456
+ const originalSetInterval = _global.setInterval;
2430
2457
 
2431
2458
  /**
2432
2459
  * @param {Date|number} [start] the system time - non-integer values are floored
@@ -2445,6 +2472,7 @@ function requireFakeTimersSrc () {
2445
2472
  now: start,
2446
2473
  Date: createDate(),
2447
2474
  loopLimit: loopLimit,
2475
+ tickMode: { mode: "manual", counter: 0, delta: undefined },
2448
2476
  };
2449
2477
 
2450
2478
  clock.Date.clock = clock;
@@ -2511,6 +2539,74 @@ function requireFakeTimersSrc () {
2511
2539
  clock.Intl.clock = clock;
2512
2540
  }
2513
2541
 
2542
+ /**
2543
+ * @param {TimerTickMode} tickModeConfig - The new configuration for how the clock should tick.
2544
+ */
2545
+ clock.setTickMode = function (tickModeConfig) {
2546
+ const { mode: newMode, delta: newDelta } = tickModeConfig;
2547
+ const { mode: oldMode, delta: oldDelta } = clock.tickMode;
2548
+ if (newMode === oldMode && newDelta === oldDelta) {
2549
+ return;
2550
+ }
2551
+
2552
+ if (oldMode === "interval") {
2553
+ originalClearInterval(clock.attachedInterval);
2554
+ }
2555
+
2556
+ clock.tickMode = {
2557
+ counter: clock.tickMode.counter + 1,
2558
+ mode: newMode,
2559
+ delta: newDelta,
2560
+ };
2561
+
2562
+ if (newMode === "nextAsync") {
2563
+ advanceUntilModeChanges();
2564
+ } else if (newMode === "interval") {
2565
+ createIntervalTick(clock, newDelta || 20);
2566
+ }
2567
+ };
2568
+
2569
+ async function advanceUntilModeChanges() {
2570
+ async function newMacrotask() {
2571
+ // MessageChannel ensures that setTimeout is not throttled to 4ms.
2572
+ // https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#reasons_for_delays_longer_than_specified
2573
+ // https://stackblitz.com/edit/stackblitz-starters-qtlpcc
2574
+ const channel = new MessageChannel();
2575
+ await new Promise((resolve) => {
2576
+ channel.port1.onmessage = () => {
2577
+ resolve();
2578
+ channel.port1.close();
2579
+ };
2580
+ channel.port2.postMessage(undefined);
2581
+ });
2582
+ channel.port1.close();
2583
+ channel.port2.close();
2584
+ // setTimeout ensures microtask queue is emptied
2585
+ await new Promise((resolve) => {
2586
+ originalSetTimeout(resolve);
2587
+ });
2588
+ }
2589
+
2590
+ const { counter } = clock.tickMode;
2591
+ while (clock.tickMode.counter === counter) {
2592
+ await newMacrotask();
2593
+ if (clock.tickMode.counter !== counter) {
2594
+ return;
2595
+ }
2596
+ clock.next();
2597
+ }
2598
+ }
2599
+
2600
+ function pauseAutoTickUntilFinished(promise) {
2601
+ if (clock.tickMode.mode !== "nextAsync") {
2602
+ return promise;
2603
+ }
2604
+ clock.setTickMode({ mode: "manual" });
2605
+ return promise.finally(() => {
2606
+ clock.setTickMode({ mode: "nextAsync" });
2607
+ });
2608
+ }
2609
+
2514
2610
  clock.requestIdleCallback = function requestIdleCallback(
2515
2611
  func,
2516
2612
  timeout,
@@ -2809,15 +2905,17 @@ function requireFakeTimersSrc () {
2809
2905
  * @returns {Promise}
2810
2906
  */
2811
2907
  clock.tickAsync = function tickAsync(tickValue) {
2812
- return new _global.Promise(function (resolve, reject) {
2813
- originalSetTimeout(function () {
2814
- try {
2815
- doTick(tickValue, true, resolve, reject);
2816
- } catch (e) {
2817
- reject(e);
2818
- }
2819
- });
2820
- });
2908
+ return pauseAutoTickUntilFinished(
2909
+ new _global.Promise(function (resolve, reject) {
2910
+ originalSetTimeout(function () {
2911
+ try {
2912
+ doTick(tickValue, true, resolve, reject);
2913
+ } catch (e) {
2914
+ reject(e);
2915
+ }
2916
+ });
2917
+ }),
2918
+ );
2821
2919
  };
2822
2920
  }
2823
2921
 
@@ -2841,37 +2939,39 @@ function requireFakeTimersSrc () {
2841
2939
 
2842
2940
  if (typeof _global.Promise !== "undefined") {
2843
2941
  clock.nextAsync = function nextAsync() {
2844
- return new _global.Promise(function (resolve, reject) {
2845
- originalSetTimeout(function () {
2846
- try {
2847
- const timer = firstTimer(clock);
2848
- if (!timer) {
2849
- resolve(clock.now);
2850
- return;
2851
- }
2852
-
2853
- let err;
2854
- clock.duringTick = true;
2855
- clock.now = timer.callAt;
2942
+ return pauseAutoTickUntilFinished(
2943
+ new _global.Promise(function (resolve, reject) {
2944
+ originalSetTimeout(function () {
2856
2945
  try {
2857
- callTimer(clock, timer);
2858
- } catch (e) {
2859
- err = e;
2860
- }
2861
- clock.duringTick = false;
2862
-
2863
- originalSetTimeout(function () {
2864
- if (err) {
2865
- reject(err);
2866
- } else {
2946
+ const timer = firstTimer(clock);
2947
+ if (!timer) {
2867
2948
  resolve(clock.now);
2949
+ return;
2868
2950
  }
2869
- });
2870
- } catch (e) {
2871
- reject(e);
2872
- }
2873
- });
2874
- });
2951
+
2952
+ let err;
2953
+ clock.duringTick = true;
2954
+ clock.now = timer.callAt;
2955
+ try {
2956
+ callTimer(clock, timer);
2957
+ } catch (e) {
2958
+ err = e;
2959
+ }
2960
+ clock.duringTick = false;
2961
+
2962
+ originalSetTimeout(function () {
2963
+ if (err) {
2964
+ reject(err);
2965
+ } else {
2966
+ resolve(clock.now);
2967
+ }
2968
+ });
2969
+ } catch (e) {
2970
+ reject(e);
2971
+ }
2972
+ });
2973
+ }),
2974
+ );
2875
2975
  };
2876
2976
  }
2877
2977
 
@@ -2904,51 +3004,55 @@ function requireFakeTimersSrc () {
2904
3004
 
2905
3005
  if (typeof _global.Promise !== "undefined") {
2906
3006
  clock.runAllAsync = function runAllAsync() {
2907
- return new _global.Promise(function (resolve, reject) {
2908
- let i = 0;
2909
- /**
2910
- *
2911
- */
2912
- function doRun() {
2913
- originalSetTimeout(function () {
2914
- try {
2915
- runJobs(clock);
2916
-
2917
- let numTimers;
2918
- if (i < clock.loopLimit) {
2919
- if (!clock.timers) {
2920
- resetIsNearInfiniteLimit();
2921
- resolve(clock.now);
2922
- return;
2923
- }
2924
-
2925
- numTimers = Object.keys(
2926
- clock.timers,
2927
- ).length;
2928
- if (numTimers === 0) {
2929
- resetIsNearInfiniteLimit();
2930
- resolve(clock.now);
3007
+ return pauseAutoTickUntilFinished(
3008
+ new _global.Promise(function (resolve, reject) {
3009
+ let i = 0;
3010
+ /**
3011
+ *
3012
+ */
3013
+ function doRun() {
3014
+ originalSetTimeout(function () {
3015
+ try {
3016
+ runJobs(clock);
3017
+
3018
+ let numTimers;
3019
+ if (i < clock.loopLimit) {
3020
+ if (!clock.timers) {
3021
+ resetIsNearInfiniteLimit();
3022
+ resolve(clock.now);
3023
+ return;
3024
+ }
3025
+
3026
+ numTimers = Object.keys(
3027
+ clock.timers,
3028
+ ).length;
3029
+ if (numTimers === 0) {
3030
+ resetIsNearInfiniteLimit();
3031
+ resolve(clock.now);
3032
+ return;
3033
+ }
3034
+
3035
+ clock.next();
3036
+
3037
+ i++;
3038
+
3039
+ doRun();
3040
+ checkIsNearInfiniteLimit(clock, i);
2931
3041
  return;
2932
3042
  }
2933
3043
 
2934
- clock.next();
2935
-
2936
- i++;
2937
-
2938
- doRun();
2939
- checkIsNearInfiniteLimit(clock, i);
2940
- return;
3044
+ const excessJob = firstTimer(clock);
3045
+ reject(
3046
+ getInfiniteLoopError(clock, excessJob),
3047
+ );
3048
+ } catch (e) {
3049
+ reject(e);
2941
3050
  }
2942
-
2943
- const excessJob = firstTimer(clock);
2944
- reject(getInfiniteLoopError(clock, excessJob));
2945
- } catch (e) {
2946
- reject(e);
2947
- }
2948
- });
2949
- }
2950
- doRun();
2951
- });
3051
+ });
3052
+ }
3053
+ doRun();
3054
+ }),
3055
+ );
2952
3056
  };
2953
3057
  }
2954
3058
 
@@ -2964,21 +3068,25 @@ function requireFakeTimersSrc () {
2964
3068
 
2965
3069
  if (typeof _global.Promise !== "undefined") {
2966
3070
  clock.runToLastAsync = function runToLastAsync() {
2967
- return new _global.Promise(function (resolve, reject) {
2968
- originalSetTimeout(function () {
2969
- try {
2970
- const timer = lastTimer(clock);
2971
- if (!timer) {
2972
- runJobs(clock);
2973
- resolve(clock.now);
2974
- }
3071
+ return pauseAutoTickUntilFinished(
3072
+ new _global.Promise(function (resolve, reject) {
3073
+ originalSetTimeout(function () {
3074
+ try {
3075
+ const timer = lastTimer(clock);
3076
+ if (!timer) {
3077
+ runJobs(clock);
3078
+ resolve(clock.now);
3079
+ }
2975
3080
 
2976
- resolve(clock.tickAsync(timer.callAt - clock.now));
2977
- } catch (e) {
2978
- reject(e);
2979
- }
2980
- });
2981
- });
3081
+ resolve(
3082
+ clock.tickAsync(timer.callAt - clock.now),
3083
+ );
3084
+ } catch (e) {
3085
+ reject(e);
3086
+ }
3087
+ });
3088
+ }),
3089
+ );
2982
3090
  };
2983
3091
  }
2984
3092
 
@@ -3042,6 +3150,12 @@ function requireFakeTimersSrc () {
3042
3150
  return clock;
3043
3151
  }
3044
3152
 
3153
+ function createIntervalTick(clock, delta) {
3154
+ const intervalTick = doIntervalTick.bind(null, clock, delta);
3155
+ const intervalId = originalSetInterval(intervalTick, delta);
3156
+ clock.attachedInterval = intervalId;
3157
+ }
3158
+
3045
3159
  /* eslint-disable complexity */
3046
3160
 
3047
3161
  /**
@@ -3102,7 +3216,7 @@ function requireFakeTimersSrc () {
3102
3216
  clock.shouldClearNativeTimers = config.shouldClearNativeTimers;
3103
3217
 
3104
3218
  clock.uninstall = function () {
3105
- return uninstall(clock, config);
3219
+ return uninstall(clock);
3106
3220
  };
3107
3221
 
3108
3222
  clock.abortListenerMap = new Map();
@@ -3114,16 +3228,10 @@ function requireFakeTimersSrc () {
3114
3228
  }
3115
3229
 
3116
3230
  if (config.shouldAdvanceTime === true) {
3117
- const intervalTick = doIntervalTick.bind(
3118
- null,
3119
- clock,
3120
- config.advanceTimeDelta,
3121
- );
3122
- const intervalId = _global.setInterval(
3123
- intervalTick,
3124
- config.advanceTimeDelta,
3125
- );
3126
- clock.attachedInterval = intervalId;
3231
+ clock.setTickMode({
3232
+ mode: "interval",
3233
+ delta: config.advanceTimeDelta,
3234
+ });
3127
3235
  }
3128
3236
 
3129
3237
  if (clock.methods.includes("performance")) {
@@ -3535,9 +3643,7 @@ class FakeTimers {
3535
3643
  if (this._checkFakeTimers()) this._clock.runToFrame();
3536
3644
  }
3537
3645
  runAllTicks() {
3538
- if (this._checkFakeTimers())
3539
- // @ts-expect-error method not exposed
3540
- this._clock.runMicrotasks();
3646
+ if (this._checkFakeTimers()) this._clock.runMicrotasks();
3541
3647
  }
3542
3648
  useRealTimers() {
3543
3649
  if (this._fakingDate) {
@@ -3591,6 +3697,15 @@ class FakeTimers {
3591
3697
  if (this._checkFakeTimers()) return this._clock.countTimers();
3592
3698
  return 0;
3593
3699
  }
3700
+ setTimerTickMode(mode, interval) {
3701
+ if (this._checkFakeTimers()) if (mode === "manual") this._clock.setTickMode({ mode: "manual" });
3702
+ else if (mode === "nextTimerAsync") this._clock.setTickMode({ mode: "nextAsync" });
3703
+ else if (mode === "interval") this._clock.setTickMode({
3704
+ mode: "interval",
3705
+ delta: interval
3706
+ });
3707
+ else throw new Error(`Invalid tick mode: ${mode}`);
3708
+ }
3594
3709
  configure(config) {
3595
3710
  this._userConfig = config;
3596
3711
  }
@@ -3793,6 +3908,10 @@ function createVitest() {
3793
3908
  timers().clearAllTimers();
3794
3909
  return utils;
3795
3910
  },
3911
+ setTimerTickMode(mode, interval) {
3912
+ timers().setTimerTickMode(mode, interval);
3913
+ return utils;
3914
+ },
3796
3915
  spyOn,
3797
3916
  fn,
3798
3917
  waitFor,
@@ -3814,6 +3933,11 @@ function createVitest() {
3814
3933
  if (typeof path !== "string") throw new TypeError(`vi.doMock() expects a string path, but received a ${typeof path}`);
3815
3934
  const importer = getImporter("doMock");
3816
3935
  _mocker().queueMock(path, importer, typeof factory === "function" ? () => factory(() => _mocker().importActual(path, importer, _mocker().getMockContext().callstack)) : factory);
3936
+ const rv = {};
3937
+ if (Symbol.dispose) rv[Symbol.dispose] = () => {
3938
+ _mocker().queueUnmock(path, importer);
3939
+ };
3940
+ return rv;
3817
3941
  },
3818
3942
  doUnmock(path) {
3819
3943
  if (typeof path !== "string") throw new TypeError(`vi.doUnmock() expects a string path, but received a ${typeof path}`);
@@ -3916,4 +4040,261 @@ function getImporter(name) {
3916
4040
  }) + 1])?.file || "";
3917
4041
  }
3918
4042
 
3919
- export { getSnapshotClient as a, assert as b, createExpect as c, vitest as d, globalExpect as g, inject as i, should as s, vi as v };
4043
+ function createBenchmarkResult(name) {
4044
+ return {
4045
+ name,
4046
+ rank: 0,
4047
+ rme: 0,
4048
+ samples: []
4049
+ };
4050
+ }
4051
+ const benchmarkTasks = /* @__PURE__ */ new WeakMap();
4052
+ async function runBenchmarkSuite(suite, runner) {
4053
+ const { Task, Bench } = await runner.importTinybench();
4054
+ const start = performance.now();
4055
+ const benchmarkGroup = [];
4056
+ const benchmarkSuiteGroup = [];
4057
+ for (const task of suite.tasks) {
4058
+ if (task.mode !== "run" && task.mode !== "queued") continue;
4059
+ if (task.meta?.benchmark) benchmarkGroup.push(task);
4060
+ else if (task.type === "suite") benchmarkSuiteGroup.push(task);
4061
+ }
4062
+ // run sub suites sequentially
4063
+ for (const subSuite of benchmarkSuiteGroup) await runBenchmarkSuite(subSuite, runner);
4064
+ if (benchmarkGroup.length) {
4065
+ const defer = createDefer();
4066
+ suite.result = {
4067
+ state: "run",
4068
+ startTime: start,
4069
+ benchmark: createBenchmarkResult(suite.name)
4070
+ };
4071
+ updateTask$1("suite-prepare", suite);
4072
+ const addBenchTaskListener = (task, benchmark) => {
4073
+ task.addEventListener("complete", (e) => {
4074
+ const taskRes = e.task.result;
4075
+ const result = benchmark.result.benchmark;
4076
+ benchmark.result.state = "pass";
4077
+ Object.assign(result, taskRes);
4078
+ // compute extra stats and free raw samples as early as possible
4079
+ const samples = result.samples;
4080
+ result.sampleCount = samples.length;
4081
+ result.median = samples.length % 2 ? samples[Math.floor(samples.length / 2)] : (samples[samples.length / 2] + samples[samples.length / 2 - 1]) / 2;
4082
+ if (!runner.config.benchmark?.includeSamples) result.samples.length = 0;
4083
+ updateTask$1("test-finished", benchmark);
4084
+ }, { once: true });
4085
+ task.addEventListener("error", (e) => {
4086
+ const task = e.task;
4087
+ defer.reject(benchmark ? task.result.error : e);
4088
+ }, { once: true });
4089
+ };
4090
+ benchmarkGroup.forEach((benchmark) => {
4091
+ const benchmarkInstance = new Bench(getBenchOptions(benchmark));
4092
+ const benchmarkFn = getBenchFn(benchmark);
4093
+ benchmark.result = {
4094
+ state: "run",
4095
+ startTime: start,
4096
+ benchmark: createBenchmarkResult(benchmark.name)
4097
+ };
4098
+ const task = new Task(benchmarkInstance, benchmark.name, benchmarkFn);
4099
+ benchmarkTasks.set(benchmark, task);
4100
+ addBenchTaskListener(task, benchmark);
4101
+ });
4102
+ const { setTimeout } = getSafeTimers();
4103
+ const tasks = [];
4104
+ for (const benchmark of benchmarkGroup) {
4105
+ const task = benchmarkTasks.get(benchmark);
4106
+ updateTask$1("test-prepare", benchmark);
4107
+ await task.warmup();
4108
+ tasks.push([await new Promise((resolve) => setTimeout(async () => {
4109
+ resolve(await task.run());
4110
+ })), benchmark]);
4111
+ }
4112
+ suite.result.duration = performance.now() - start;
4113
+ suite.result.state = "pass";
4114
+ updateTask$1("suite-finished", suite);
4115
+ defer.resolve(null);
4116
+ await defer;
4117
+ }
4118
+ function updateTask$1(event, task) {
4119
+ updateTask(event, task, runner);
4120
+ }
4121
+ }
4122
+ class NodeBenchmarkRunner {
4123
+ moduleRunner;
4124
+ constructor(config) {
4125
+ this.config = config;
4126
+ }
4127
+ async importTinybench() {
4128
+ return await import('tinybench');
4129
+ }
4130
+ importFile(filepath, source) {
4131
+ if (source === "setup") {
4132
+ const moduleNode = getWorkerState().evaluatedModules.getModuleById(filepath);
4133
+ if (moduleNode) getWorkerState().evaluatedModules.invalidateModule(moduleNode);
4134
+ }
4135
+ return this.moduleRunner.import(filepath);
4136
+ }
4137
+ async runSuite(suite) {
4138
+ await runBenchmarkSuite(suite, this);
4139
+ }
4140
+ async runTask() {
4141
+ throw new Error("`test()` and `it()` is only available in test mode.");
4142
+ }
4143
+ }
4144
+
4145
+ // worker context is shared between all tests
4146
+ const workerContext = Object.create(null);
4147
+ class TestRunner {
4148
+ snapshotClient = getSnapshotClient();
4149
+ workerState = getWorkerState();
4150
+ moduleRunner;
4151
+ cancelRun = false;
4152
+ assertionsErrors = /* @__PURE__ */ new WeakMap();
4153
+ pool = this.workerState.ctx.pool;
4154
+ _otel;
4155
+ viteEnvironment;
4156
+ constructor(config) {
4157
+ this.config = config;
4158
+ const environment = this.workerState.environment;
4159
+ this.viteEnvironment = environment.viteEnvironment || environment.name;
4160
+ }
4161
+ importFile(filepath, source) {
4162
+ if (source === "setup") {
4163
+ const moduleNode = this.workerState.evaluatedModules.getModuleById(filepath);
4164
+ if (moduleNode) this.workerState.evaluatedModules.invalidateModule(moduleNode);
4165
+ }
4166
+ return this._otel.$(`vitest.module.import_${source === "setup" ? "setup" : "spec"}`, { attributes: { "code.file.path": filepath } }, () => this.moduleRunner.import(filepath));
4167
+ }
4168
+ onCollectStart(file) {
4169
+ this.workerState.current = file;
4170
+ }
4171
+ onCleanupWorkerContext(listener) {
4172
+ this.workerState.onCleanup(listener);
4173
+ }
4174
+ onAfterRunFiles() {
4175
+ this.snapshotClient.clear();
4176
+ this.workerState.current = void 0;
4177
+ }
4178
+ getWorkerContext() {
4179
+ return workerContext;
4180
+ }
4181
+ async onAfterRunSuite(suite) {
4182
+ if (this.config.logHeapUsage && typeof process !== "undefined") suite.result.heap = process.memoryUsage().heapUsed;
4183
+ if (suite.mode !== "skip" && "filepath" in suite) {
4184
+ // mark snapshots in skipped tests as not obsolete
4185
+ for (const test of getTests(suite)) if (test.mode === "skip") {
4186
+ const name = getNames(test).slice(1).join(" > ");
4187
+ this.snapshotClient.skipTest(suite.file.filepath, name);
4188
+ }
4189
+ const result = await this.snapshotClient.finish(suite.file.filepath);
4190
+ if (this.workerState.config.snapshotOptions.updateSnapshot === "none" && result.unchecked) {
4191
+ let message = `Obsolete snapshots found when no snapshot update is expected.\n`;
4192
+ for (const key of result.uncheckedKeys) message += `· ${key}\n`;
4193
+ suite.result.errors ??= [];
4194
+ suite.result.errors.push(processError(new Error(message)));
4195
+ suite.result.state = "fail";
4196
+ }
4197
+ await rpc().snapshotSaved(result);
4198
+ }
4199
+ this.workerState.current = suite.suite || suite.file;
4200
+ }
4201
+ onAfterRunTask(test) {
4202
+ if (this.config.logHeapUsage && typeof process !== "undefined") test.result.heap = process.memoryUsage().heapUsed;
4203
+ this.workerState.current = test.suite || test.file;
4204
+ }
4205
+ cancel(_reason) {
4206
+ this.cancelRun = true;
4207
+ }
4208
+ injectValue(key) {
4209
+ // inject has a very limiting type controlled by ProvidedContext
4210
+ // some tests override it which causes the build to fail
4211
+ return inject(key);
4212
+ }
4213
+ async onBeforeRunTask(test) {
4214
+ if (this.cancelRun) test.mode = "skip";
4215
+ if (test.mode !== "run" && test.mode !== "queued") return;
4216
+ this.workerState.current = test;
4217
+ }
4218
+ async onBeforeRunSuite(suite) {
4219
+ if (this.cancelRun) suite.mode = "skip";
4220
+ // initialize snapshot state before running file suite
4221
+ if (suite.mode !== "skip" && "filepath" in suite) await this.snapshotClient.setup(suite.file.filepath, this.workerState.config.snapshotOptions);
4222
+ this.workerState.current = suite;
4223
+ }
4224
+ onBeforeTryTask(test) {
4225
+ clearModuleMocks(this.config);
4226
+ this.snapshotClient.clearTest(test.file.filepath, test.id);
4227
+ setState({
4228
+ assertionCalls: 0,
4229
+ isExpectingAssertions: false,
4230
+ isExpectingAssertionsError: null,
4231
+ expectedAssertionsNumber: null,
4232
+ expectedAssertionsNumberErrorGen: null,
4233
+ currentTestName: getTestName(test),
4234
+ snapshotState: this.snapshotClient.getSnapshotState(test.file.filepath)
4235
+ }, globalThis[GLOBAL_EXPECT]);
4236
+ }
4237
+ onAfterTryTask(test) {
4238
+ const { assertionCalls, expectedAssertionsNumber, expectedAssertionsNumberErrorGen, isExpectingAssertions, isExpectingAssertionsError } = test.context._local ? test.context.expect.getState() : getState(globalThis[GLOBAL_EXPECT]);
4239
+ if (expectedAssertionsNumber !== null && assertionCalls !== expectedAssertionsNumber) throw expectedAssertionsNumberErrorGen();
4240
+ if (isExpectingAssertions === true && assertionCalls === 0) throw isExpectingAssertionsError;
4241
+ if (this.config.expect.requireAssertions && assertionCalls === 0) throw this.assertionsErrors.get(test);
4242
+ }
4243
+ extendTaskContext(context) {
4244
+ // create error during the test initialization so we have a nice stack trace
4245
+ if (this.config.expect.requireAssertions) this.assertionsErrors.set(context.task, /* @__PURE__ */ new Error("expected any number of assertion, but got none"));
4246
+ let _expect;
4247
+ Object.defineProperty(context, "expect", { get() {
4248
+ if (!_expect) _expect = createExpect(context.task);
4249
+ return _expect;
4250
+ } });
4251
+ Object.defineProperty(context, "_local", { get() {
4252
+ return _expect != null;
4253
+ } });
4254
+ return context;
4255
+ }
4256
+ getImportDurations() {
4257
+ const importDurations = {};
4258
+ const entries = this.workerState.moduleExecutionInfo?.entries() || [];
4259
+ for (const [filepath, { duration, selfTime, external, importer }] of entries) importDurations[normalize(filepath)] = {
4260
+ selfTime,
4261
+ totalTime: duration,
4262
+ external,
4263
+ importer
4264
+ };
4265
+ return importDurations;
4266
+ }
4267
+ trace = (name, attributes, cb) => {
4268
+ const options = typeof attributes === "object" ? { attributes } : {};
4269
+ return this._otel.$(`vitest.test.runner.${name}`, options, cb || attributes);
4270
+ };
4271
+ __setTraces(traces) {
4272
+ this._otel = traces;
4273
+ }
4274
+ static createTaskCollector = createTaskCollector;
4275
+ static getCurrentSuite = getCurrentSuite;
4276
+ static getCurrentTest = getCurrentTest;
4277
+ static createChainable = createChainable;
4278
+ static getSuiteHooks = getHooks;
4279
+ static getTestFn = getFn;
4280
+ static setSuiteHooks = getHooks;
4281
+ static setTestFn = getFn;
4282
+ /**
4283
+ * @deprecated
4284
+ */
4285
+ static getBenchFn = getBenchFn;
4286
+ /**
4287
+ * @deprecated
4288
+ */
4289
+ static getBenchOptions = getBenchOptions;
4290
+ }
4291
+ function clearModuleMocks(config) {
4292
+ const { clearMocks, mockReset, restoreMocks, unstubEnvs, unstubGlobals } = config;
4293
+ if (restoreMocks) vi.restoreAllMocks();
4294
+ if (mockReset) vi.resetAllMocks();
4295
+ if (clearMocks) vi.clearAllMocks();
4296
+ if (unstubEnvs) vi.unstubAllEnvs();
4297
+ if (unstubGlobals) vi.unstubAllGlobals();
4298
+ }
4299
+
4300
+ export { NodeBenchmarkRunner as N, TestRunner as T, assert as a, vitest as b, createExpect as c, globalExpect as g, inject as i, should as s, vi as v };