vitest 5.0.2 → 5.0.4

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 (79) hide show
  1. package/LICENSE.md +29 -1
  2. package/browser/context.d.ts +7 -1
  3. package/browser/context.js +5 -5
  4. package/dist/browser.d.ts +4 -4
  5. package/dist/browser.js +11 -11
  6. package/dist/chunks/{base.5tQXSzMP.js → base.CYbb9pQW.js} +39 -15
  7. package/dist/chunks/{browser.d.g5Thl309.d.ts → browser.d.FGQ9_rK6.d.ts} +3 -3
  8. package/dist/chunks/{cac.BLbEtnDd.js → cac.DTXWs6Ni.js} +21 -23
  9. package/dist/chunks/cli-api.Bx28WXzL.js +13879 -0
  10. package/dist/chunks/{config.d.CU_b-wJj.d.ts → config.d.QBNYCgFU.d.ts} +33 -24
  11. package/dist/chunks/{console.B09ye7y0.js → console.DtI4yxfN.js} +5 -4
  12. package/dist/chunks/{coverage.AipniaqB.js → coverage.-bm5IxnW.js} +1 -1
  13. package/dist/chunks/{coverage.CX7NN5s7.js → coverage.cTDc4uSS.js} +1 -1
  14. package/dist/chunks/{creator.2VTnpYzN.js → creator.CLL8QFMS.js} +44 -54
  15. package/dist/chunks/{defaults.D2ip7f-X.js → defaults.B1FCaFfh.js} +2 -2
  16. package/dist/chunks/{display.pkpxlVcY.js → display.BlTmubjj.js} +1 -1
  17. package/dist/chunks/{doctor.BCXa6-1R.js → doctor.Bqc8NDDb.js} +40 -41
  18. package/dist/chunks/{env.DzFJjrmK.js → env.BKKtU2WC.js} +1 -1
  19. package/dist/chunks/{environment.d.C6xYahWA.d.ts → environment.d.BY56MoGs.d.ts} +1 -1
  20. package/dist/chunks/{globals.Brdv9iOs.js → globals.CTWMSIPL.js} +10 -10
  21. package/dist/chunks/{index.C-uw7tH9.js → index.B8VfM7Mf.js} +8606 -20822
  22. package/dist/chunks/{index.DXQx-kDM.js → index.BoyTG_B7.js} +9 -4
  23. package/dist/chunks/{index.hTNFpC24.js → index.CPNMO3h-.js} +73 -50
  24. package/dist/chunks/{index.M2dsQ_UQ.js → index.D0heQG4v.js} +557 -183
  25. package/dist/chunks/{index.BgwtGYxD.js → index.GYMZ12wH.js} +5 -5
  26. package/dist/chunks/{index.DGdajAO2.js → index.uwTEEBsB.js} +94 -71
  27. package/dist/chunks/{init-forks.CdGu3HUy.js → init-forks.CbYYa5xq.js} +1 -1
  28. package/dist/chunks/{init-threads.2f_lsHNK.js → init-threads.DtjdvxPl.js} +1 -1
  29. package/dist/chunks/{init.IsjtLXKe.js → init.DrHtV5zd.js} +7 -7
  30. package/dist/chunks/module-dependencies.CwNPkcV4.js +71 -0
  31. package/dist/chunks/{native.CF4uT5hY.js → native.cdzHIdmv.js} +48 -34
  32. package/dist/chunks/{nativeModuleMocker.DwRB4F9R.js → nativeModuleMocker.D8f4cW4A.js} +2 -2
  33. package/dist/chunks/{nativeModuleRunner.J0QLzNtK.js → nativeModuleRunner.xi64Afb2.js} +1 -1
  34. package/dist/chunks/{node.CfQ_OGWr.js → node.uQulW0ei.js} +1 -1
  35. package/dist/chunks/{pathe.M-eThtNZ.DwEga6ro.js → pathe.M-eThtNZ.Ba-7h1rE.js} +9 -7
  36. package/dist/chunks/{plugin.d.My_z-jmU.d.ts → plugin.d.C8mmycim.d.ts} +109 -68
  37. package/dist/chunks/{plugins.Cigb0uSy.js → plugins.DPQHVT0p.js} +1 -1
  38. package/dist/chunks/{resolver.NpfwMKt9.js → resolver.CtCcxIy1.js} +1 -1
  39. package/dist/chunks/{rpc.CJVl3hZH.js → rpc.DpkUyY1N.js} +3 -2
  40. package/dist/chunks/{rpc.d.DA9Utv4e.d.ts → rpc.d.Cft1biqy.d.ts} +2 -1
  41. package/dist/chunks/{run.C5UmxDPh.js → run.Cm2sd7-x.js} +122 -97
  42. package/dist/chunks/{setup-common.Ct8rQvjH.js → setup-common.BABL3z3m.js} +3 -3
  43. package/dist/chunks/{source-map.BH0bbrs9.js → source-map.DdKI5IHB.js} +15 -10
  44. package/dist/chunks/{source-map.d.YqWNcp4e.d.ts → source-map.d.kzFtk_dj.d.ts} +1 -1
  45. package/dist/chunks/{spy.KLHgXex_.js → spy.DDMXghXv.js} +63 -32
  46. package/dist/chunks/{task-utils.d.BZm4GSQD.d.ts → task-utils.d.PFh2BV6Q.d.ts} +1 -1
  47. package/dist/chunks/tinyrainbow.Do8I1XRG.js +88 -0
  48. package/dist/chunks/{utils.CJ0JImL8.js → utils.DSfl_w8V.js} +44 -42
  49. package/dist/chunks/{vm.KI2AYADz.js → vm.Uo_C9Uld.js} +16 -13
  50. package/dist/chunks/{worker.d.MLmnzOJE.d.ts → worker.d.BH-r1bPu.d.ts} +8 -3
  51. package/dist/cli.js +4 -4
  52. package/dist/config.cjs +1 -1
  53. package/dist/config.d.ts +9 -10
  54. package/dist/config.js +2 -2
  55. package/dist/index.d.ts +10 -10
  56. package/dist/index.js +10 -10
  57. package/dist/module-evaluator.d.ts +3 -2
  58. package/dist/module-evaluator.js +8 -5
  59. package/dist/node.d.ts +9 -10
  60. package/dist/node.js +27 -26
  61. package/dist/runtime.d.ts +6 -6
  62. package/dist/runtime.js +4 -4
  63. package/dist/spy.js +1 -1
  64. package/dist/task-utils.js +7 -4
  65. package/dist/worker.d.ts +4 -4
  66. package/dist/worker.js +21 -20
  67. package/dist/workers/forks.js +19 -18
  68. package/dist/workers/runVmTests.js +23 -14
  69. package/dist/workers/threads.js +19 -18
  70. package/dist/workers/vmForks.js +13 -13
  71. package/dist/workers/vmThreads.js +13 -13
  72. package/globals.d.ts +19 -19
  73. package/index.cjs +3 -3
  74. package/optional-runtime-types.d.ts +1 -1
  75. package/optional-types.d.ts +1 -1
  76. package/package.json +35 -29
  77. package/suppress-warnings.cjs +1 -1
  78. package/dist/chunks/cli-api.DL4Bd7Vh.js +0 -528
  79. package/dist/chunks/tinyrainbow.Ht9iggcq.js +0 -95
@@ -1,10 +1,10 @@
1
1
  import * as chai from 'chai';
2
2
  import { createHook } from 'node:async_hooks';
3
- import { t as takeCoverageInsideWorker } from './coverage.AipniaqB.js';
4
- import { r as rpc } from './rpc.CJVl3hZH.js';
5
- import { l as loadDiffConfig, a as loadSnapshotSerializers } from './setup-common.Ct8rQvjH.js';
3
+ import { t as takeCoverageInsideWorker } from './coverage.-bm5IxnW.js';
4
+ import { r as rpc } from './rpc.DpkUyY1N.js';
5
+ import { l as loadDiffConfig, a as loadSnapshotSerializers } from './setup-common.BABL3z3m.js';
6
6
  import { g as getWorkerState } from './utils.DYj33du9.js';
7
- import { T as TestRunner } from './index.DGdajAO2.js';
7
+ import { T as TestRunner } from './index.uwTEEBsB.js';
8
8
 
9
9
  function setupChaiConfig(config) {
10
10
  Object.assign(chai.config, config);
@@ -12,7 +12,7 @@ function setupChaiConfig(config) {
12
12
 
13
13
  async function resolveSnapshotEnvironment(config, moduleRunner) {
14
14
  if (!config.snapshotEnvironment) {
15
- const { VitestNodeSnapshotEnvironment } = await import('./node.CfQ_OGWr.js');
15
+ const { VitestNodeSnapshotEnvironment } = await import('./node.uQulW0ei.js');
16
16
  return new VitestNodeSnapshotEnvironment();
17
17
  }
18
18
  const mod = await moduleRunner.import(config.snapshotEnvironment);
@@ -1,17 +1,17 @@
1
- import { b as printDiffOrStringify, d as diff, a as processError, T as TestSyntaxError, g as getCurrentTest, c as createTaskCollector, e as getCurrentSuite, f as createChainable, h as getHooks, i as getFn, m as matchesTags, j as afterAll, k as afterEach, l as aroundAll, n as aroundEach, o as beforeAll, q as beforeEach, r as describe, t as it, u as onTestFailed, v as onTestFinished, w as recordArtifact, x as suite, y as test } from './run.C5UmxDPh.js';
1
+ import { b as printDiffOrStringify, d as diff, a as processError, T as TestSyntaxError, g as getCurrentTest, c as createTaskCollector, e as getCurrentSuite, f as createChainable, h as getHooks, i as getFn, m as matchesTags, j as afterAll, k as afterEach, l as aroundAll, n as aroundEach, o as beforeAll, q as beforeEach, r as describe, t as it, u as onTestFailed, v as onTestFinished, w as recordArtifact, x as suite, y as test } from './run.Cm2sd7-x.js';
2
2
  import { i as isChildProcess, r as resetModules, g as getWorkerState } from './utils.DYj33du9.js';
3
- import { e as getDefaultExportFromCjs, f as parseErrorStacktrace, h as commonjsGlobal, a as getSafeTimers, i as parseSingleStack, j as delay } from './source-map.BH0bbrs9.js';
4
- import { i as isMockFunction, f as fn, a as spyOn, r as restoreAllMocks, b as resetAllMocks, c as clearAllMocks } from './spy.KLHgXex_.js';
5
- import { u as isObject, B as getCallLastIndex, g as getType, D as noop, x as assertTypes, w as ordinal, E as createSimpleStackTrace, i as isAbsolute, a as relative, n as normalize } from './pathe.M-eThtNZ.DwEga6ro.js';
6
- import { s as stringify, i as inspect } from './display.pkpxlVcY.js';
7
- import { y } from './tinyrainbow.Ht9iggcq.js';
3
+ import { e as parseErrorStacktrace, a as getSafeTimers, f as parseSingleStack, h as delay } from './source-map.DdKI5IHB.js';
4
+ import { i as isMockFunction, f as fn, a as spyOn, r as restoreAllMocks, b as resetAllMocks, c as clearAllMocks } from './spy.DDMXghXv.js';
5
+ import { u as isObject, B as getCallLastIndex, g as getType, D as noop, x as assertTypes, w as ordinal, E as createSimpleStackTrace, i as isAbsolute, a as relative, n as normalize } from './pathe.M-eThtNZ.Ba-7h1rE.js';
6
+ import { g as getDefaultExportFromCjs, f as format, a as commonjsGlobal } from './index.D0heQG4v.js';
7
+ import { s as stringify, i as inspect } from './display.BlTmubjj.js';
8
+ import { $ } from './tinyrainbow.Do8I1XRG.js';
8
9
  import * as chai from 'chai';
9
10
  import { use, util } from 'chai';
10
11
  import { getNames, getTests, getTestName, createFileTask } from '../task-utils.js';
11
- import { g as getSerializers, a as addSerializer } from './plugins.Cigb0uSy.js';
12
+ import { g as getSerializers, a as addSerializer } from './plugins.DPQHVT0p.js';
12
13
  import { p as positionToOffset, o as offsetToLineNumber, l as lineSplitRE } from './offset.Dy-5Fdfn.js';
13
- import { f as format } from './index.M2dsQ_UQ.js';
14
- import { r as rpc, V as VitestEvaluatedModules } from './rpc.CJVl3hZH.js';
14
+ import { r as rpc, V as VitestEvaluatedModules } from './rpc.DpkUyY1N.js';
15
15
  import { Bench } from 'tinybench';
16
16
  import { expectTypeOf } from 'expect-type';
17
17
 
@@ -133,7 +133,8 @@ function serialize(val, indent = 2, formatOverrides = {}) {
133
133
  }));
134
134
  }
135
135
  function escapeBacktickString(str) {
136
- return str.replace(/`|\\|\$\{/g, "\\$&");
136
+ // a raw CR inside a template literal is read back as LF
137
+ return str.replace(/`|\\|\$\{/g, "\\$&").replace(/\r/g, "\\r");
137
138
  }
138
139
  function printBacktickString(str) {
139
140
  return `\`${escapeBacktickString(str)}\``;
@@ -176,9 +177,10 @@ function deepMergeSnapshot(target, source) {
176
177
  if (isObject(target) && isObject(source)) {
177
178
  const mergedOutput = { ...target };
178
179
  Object.keys(source).forEach((key) => {
179
- if (isObject(source[key]) && !source[key].$$typeof) if (!(key in target)) Object.assign(mergedOutput, { [key]: source[key] });
180
- else mergedOutput[key] = deepMergeSnapshot(target[key], source[key]);
181
- else if (Array.isArray(source[key])) mergedOutput[key] = deepMergeArray(target[key], source[key]);
180
+ if (isObject(source[key]) && !source[key].$$typeof) {
181
+ if (!(key in target)) Object.assign(mergedOutput, { [key]: source[key] });
182
+ else mergedOutput[key] = deepMergeSnapshot(target[key], source[key]);
183
+ } else if (Array.isArray(source[key])) mergedOutput[key] = deepMergeArray(target[key], source[key]);
182
184
  else Object.assign(mergedOutput, { [key]: source[key] });
183
185
  });
184
186
  return mergedOutput;
@@ -378,6 +380,7 @@ class SnapshotState {
378
380
  _inlineSnapshotStacks;
379
381
  _testIdToKeys = new DefaultMap(() => []);
380
382
  _rawSnapshots;
383
+ _rawSnapshotFiles = /* @__PURE__ */ new Set();
381
384
  _uncheckedKeys;
382
385
  _snapshotFormat;
383
386
  _environment;
@@ -571,17 +574,18 @@ class SnapshotState {
571
574
  // * The update flag is set to 'none'.
572
575
  // * There's no snapshot file or a file without this snapshot on a CI environment.
573
576
  if (opts.hasSnapshot && this._updateSnapshot === "all" || (!opts.hasSnapshot || !opts.snapshotIsPersisted) && (this._updateSnapshot === "new" || this._updateSnapshot === "all")) {
574
- if (this._updateSnapshot === "all") if (!opts.pass) {
575
- if (opts.hasSnapshot) this.updated.increment(opts.testId);
576
- else this.added.increment(opts.testId);
577
- this._addSnapshot(opts.key, opts.addValue, {
578
- stack: opts.stack,
579
- testId: opts.testId,
580
- rawSnapshot: opts.rawSnapshot,
581
- assertionName: opts.assertionName
582
- });
583
- } else this.matched.increment(opts.testId);
584
- else {
577
+ if (this._updateSnapshot === "all") {
578
+ if (!opts.pass) {
579
+ if (opts.hasSnapshot) this.updated.increment(opts.testId);
580
+ else this.added.increment(opts.testId);
581
+ this._addSnapshot(opts.key, opts.addValue, {
582
+ stack: opts.stack,
583
+ testId: opts.testId,
584
+ rawSnapshot: opts.rawSnapshot,
585
+ assertionName: opts.assertionName
586
+ });
587
+ } else this.matched.increment(opts.testId);
588
+ } else {
585
589
  this._addSnapshot(opts.key, opts.addValue, {
586
590
  stack: opts.stack,
587
591
  testId: opts.testId,
@@ -681,6 +685,7 @@ class SnapshotState {
681
685
  let receivedSerialized = rawSnapshot && typeof received === "string" ? received : serialize(received, void 0, this._snapshotFormat);
682
686
  if (!rawSnapshot) receivedSerialized = addExtraLineBreaks(receivedSerialized);
683
687
  if (rawSnapshot) {
688
+ this._rawSnapshotFiles.add(rawSnapshot.file);
684
689
  // normalize EOL when snapshot contains CRLF but received is LF
685
690
  if (rawSnapshot.content && /\r\n/.test(rawSnapshot.content) && !/\r\n/.test(receivedSerialized)) rawSnapshot.content = normalizeNewlines(rawSnapshot.content);
686
691
  }
@@ -741,6 +746,14 @@ class SnapshotState {
741
746
  assertionName
742
747
  });
743
748
  }
749
+ /**
750
+ * The snapshot file, if the test file stores snapshots in it, and every asserted file snapshot.
751
+ */
752
+ getSnapshotFiles() {
753
+ const files = Array.from(this._rawSnapshotFiles);
754
+ if (this._fileExists || Object.keys(this._snapshotData).length) files.unshift(this.snapshotPath);
755
+ return files;
756
+ }
744
757
  async pack() {
745
758
  const snapshot = {
746
759
  filepath: this.testFilePath,
@@ -1066,7 +1079,7 @@ const ChaiStyleAssertions = (chai, utils) => {
1066
1079
  defMethod("calledOnceWith", "toHaveBeenCalledExactlyOnceWith");
1067
1080
  defMethod("lastCalledWith", "toHaveBeenLastCalledWith");
1068
1081
  defMethod("nthCalledWith", "toHaveBeenNthCalledWith");
1069
- defMethod("returned", "toHaveReturned");
1082
+ defMethod("returned", "toHaveReturnedWith");
1070
1083
  defMethod("returnedWith", "toHaveReturnedWith");
1071
1084
  defMethod("returnedTimes", "toHaveReturnedTimes");
1072
1085
  defMethod("lastReturnedWith", "toHaveLastReturnedWith");
@@ -1107,10 +1120,11 @@ ${printReceived(actual)}`
1107
1120
  },
1108
1121
  toBeOneOf(actual, expected) {
1109
1122
  const { equals, customTesters } = this;
1110
- const { printReceived, printExpected, matcherHint } = this.utils;
1123
+ const { printReceived, printExpected, matcherHint, iterableEquality } = this.utils;
1124
+ const testers = [...customTesters, iterableEquality];
1111
1125
  let pass;
1112
- if (Array.isArray(expected)) pass = expected.length === 0 || expected.some((item) => equals(item, actual, customTesters));
1113
- else if (expected instanceof Set) pass = expected.size === 0 || expected.has(actual) || [...expected].some((item) => equals(item, actual, customTesters));
1126
+ if (Array.isArray(expected)) pass = expected.length === 0 || expected.some((item) => equals(item, actual, testers));
1127
+ else if (expected instanceof Set) pass = expected.size === 0 || expected.has(actual) || [...expected].some((item) => equals(item, actual, testers));
1114
1128
  else throw new TypeError(`You must provide an array or set to ${matcherHint(".toBeOneOf")}, not '${typeof expected}'.`);
1115
1129
  return {
1116
1130
  pass,
@@ -1132,11 +1146,11 @@ ${printReceived(actual)}`
1132
1146
  }
1133
1147
  };
1134
1148
 
1135
- const EXPECTED_COLOR = y.green;
1136
- const RECEIVED_COLOR = y.red;
1137
- const INVERTED_COLOR = y.inverse;
1138
- const BOLD_WEIGHT = y.bold;
1139
- const DIM_COLOR = y.dim;
1149
+ const EXPECTED_COLOR = $.green;
1150
+ const RECEIVED_COLOR = $.red;
1151
+ const INVERTED_COLOR = $.inverse;
1152
+ const BOLD_WEIGHT = $.bold;
1153
+ const DIM_COLOR = $.dim;
1140
1154
  function matcherHint(matcherName, received = "received", expected = "expected", options = {}) {
1141
1155
  const { comment = "", isDirectExpectCall = false, isNot = false, promise = "", secondArgument = "", expectedColor = EXPECTED_COLOR, receivedColor = RECEIVED_COLOR, secondArgumentColor = EXPECTED_COLOR } = options;
1142
1156
  let hint = "";
@@ -1864,7 +1878,6 @@ const JestAsymmetricMatchers = (chai, utils) => {
1864
1878
  utils.addMethod(chai.expect, "stringMatching", (expected) => new StringMatching(expected));
1865
1879
  utils.addMethod(chai.expect, "closeTo", (expected, precision) => new CloseTo(expected, precision));
1866
1880
  utils.addMethod(chai.expect, "schemaMatching", (expected) => new SchemaMatching(expected));
1867
- // defineProperty does not work
1868
1881
  chai.expect.not = {
1869
1882
  stringContaining: (expected) => new StringContaining(expected, true),
1870
1883
  objectContaining: (expected) => new ObjectContaining(expected, true),
@@ -1984,10 +1997,12 @@ const JestChaiExpect = (chai, utils) => {
1984
1997
  if (promise === "rejects") utils.flag(this, "object", () => {
1985
1998
  throw object;
1986
1999
  });
1987
- else if (promise === "resolves" && typeof object !== "function") if (!isNot) {
1988
- const message = utils.flag(this, "message") || "expected promise to throw an error, but it didn't";
1989
- throw new AssertionError(message, { showDiff: false }, utils.flag(this, "ssfi"));
1990
- } else return;
2000
+ else if (promise === "resolves" && typeof object !== "function") {
2001
+ if (!isNot) {
2002
+ const message = utils.flag(this, "message") || "expected promise to throw an error, but it didn't";
2003
+ throw new AssertionError(message, { showDiff: false }, utils.flag(this, "ssfi"));
2004
+ } else return;
2005
+ }
1991
2006
  _super.apply(this, args);
1992
2007
  };
1993
2008
  });
@@ -2080,7 +2095,7 @@ const JestChaiExpect = (chai, utils) => {
2080
2095
  def("toContainEqual", function(expected) {
2081
2096
  const obj = utils.flag(this, "object");
2082
2097
  const index = Array.from(obj).findIndex((item) => {
2083
- return equals(item, expected, customTesters);
2098
+ return equals(item, expected, [...customTesters, iterableEquality]);
2084
2099
  });
2085
2100
  this.assert(index !== -1, "expected #{this} to deep equally contain #{exp}", "expected #{this} to not deep equally contain #{exp}", expected);
2086
2101
  });
@@ -2161,7 +2176,7 @@ const JestChaiExpect = (chai, utils) => {
2161
2176
  return utils.getPathInfo(actual, propertyName);
2162
2177
  };
2163
2178
  const { value, exists } = getValue();
2164
- const pass = exists && (args.length === 1 || equals(expected, value, customTesters));
2179
+ const pass = exists && (args.length === 1 || equals(expected, value, [...customTesters, iterableEquality]));
2165
2180
  const valueString = args.length === 1 ? "" : ` with value ${inspect(expected, { truncate: 40 })}`;
2166
2181
  return this.assert(pass, `expected #{this} to have property "${propertyName}"${valueString}`, `expected #{this} to not have property "${propertyName}"${valueString}`, expected, exists ? value : void 0);
2167
2182
  });
@@ -2291,11 +2306,12 @@ const JestChaiExpect = (chai, utils) => {
2291
2306
  const isNot = utils.flag(this, "negate");
2292
2307
  let thrown = null;
2293
2308
  if (promise === "rejects") thrown = obj;
2294
- else if (promise === "resolves" && typeof obj !== "function") if (!isNot) {
2295
- const message = utils.flag(this, "message") || "expected promise to throw an error, but it didn't";
2296
- throw new AssertionError(message, { showDiff: false }, utils.flag(this, "ssfi"));
2297
- } else return;
2298
- else {
2309
+ else if (promise === "resolves" && typeof obj !== "function") {
2310
+ if (!isNot) {
2311
+ const message = utils.flag(this, "message") || "expected promise to throw an error, but it didn't";
2312
+ throw new AssertionError(message, { showDiff: false }, utils.flag(this, "ssfi"));
2313
+ } else return;
2314
+ } else {
2299
2315
  let isThrow = false;
2300
2316
  try {
2301
2317
  obj();
@@ -2318,7 +2334,7 @@ const JestChaiExpect = (chai, utils) => {
2318
2334
  }
2319
2335
  if (typeof expected === "object" && "asymmetricMatch" in expected && typeof expected.asymmetricMatch === "function") {
2320
2336
  const matcher = expected;
2321
- return this.assert(thrown && matcher.asymmetricMatch(thrown), "expected error to match asymmetric matcher", "expected error not to match asymmetric matcher", matcher, thrown);
2337
+ return this.assert(thrown && matcher.asymmetricMatch(thrown, [...customTesters, iterableEquality]), "expected error to match asymmetric matcher", "expected error not to match asymmetric matcher", matcher, thrown);
2322
2338
  }
2323
2339
  const equal = equals(thrown, expected, [...customTesters, iterableEquality]);
2324
2340
  return this.assert(equal, "expected a thrown value to equal #{exp}", "expected a thrown value not to equal #{exp}", expected, thrown);
@@ -2357,11 +2373,11 @@ const JestChaiExpect = (chai, utils) => {
2357
2373
  });
2358
2374
  [{
2359
2375
  name: "toHaveResolvedWith",
2360
- condition: (spy, value) => spy.mock.settledResults.some(({ type, value: result }) => type === "fulfilled" && equals(value, result)),
2376
+ condition: (spy, value) => spy.mock.settledResults.some(({ type, value: result }) => type === "fulfilled" && equals(value, result, [...customTesters, iterableEquality])),
2361
2377
  action: "resolve"
2362
2378
  }, {
2363
2379
  name: ["toHaveReturnedWith", "toReturnWith"],
2364
- condition: (spy, value) => spy.mock.results.some(({ type, value: result }) => type === "return" && equals(value, result)),
2380
+ condition: (spy, value) => spy.mock.results.some(({ type, value: result }) => type === "return" && equals(value, result, [...customTesters, iterableEquality])),
2365
2381
  action: "return"
2366
2382
  }].forEach(({ name, condition, action }) => {
2367
2383
  def(name, function(value) {
@@ -2385,14 +2401,14 @@ const JestChaiExpect = (chai, utils) => {
2385
2401
  name: "toHaveLastResolvedWith",
2386
2402
  condition: (spy, value) => {
2387
2403
  const result = spy.mock.settledResults.at(-1);
2388
- return Boolean(result && result.type === "fulfilled" && equals(result.value, value));
2404
+ return Boolean(result && result.type === "fulfilled" && equals(result.value, value, [...customTesters, iterableEquality]));
2389
2405
  },
2390
2406
  action: "resolve"
2391
2407
  }, {
2392
2408
  name: "toHaveLastReturnedWith",
2393
2409
  condition: (spy, value) => {
2394
2410
  const result = spy.mock.results.at(-1);
2395
- return Boolean(result && result.type === "return" && equals(result.value, value));
2411
+ return Boolean(result && result.type === "return" && equals(result.value, value, [...customTesters, iterableEquality]));
2396
2412
  },
2397
2413
  action: "return"
2398
2414
  }].forEach(({ name, condition, action }) => {
@@ -2407,14 +2423,14 @@ const JestChaiExpect = (chai, utils) => {
2407
2423
  name: "toHaveNthResolvedWith",
2408
2424
  condition: (spy, index, value) => {
2409
2425
  const result = spy.mock.settledResults[index - 1];
2410
- return result && result.type === "fulfilled" && equals(result.value, value);
2426
+ return result && result.type === "fulfilled" && equals(result.value, value, [...customTesters, iterableEquality]);
2411
2427
  },
2412
2428
  action: "resolve"
2413
2429
  }, {
2414
2430
  name: "toHaveNthReturnedWith",
2415
2431
  condition: (spy, index, value) => {
2416
2432
  const result = spy.mock.results[index - 1];
2417
- return result && result.type === "return" && equals(result.value, value);
2433
+ return result && result.type === "return" && equals(result.value, value, [...customTesters, iterableEquality]);
2418
2434
  },
2419
2435
  action: "return"
2420
2436
  }].forEach(({ name, condition, action }) => {
@@ -2494,25 +2510,25 @@ const JestChaiExpect = (chai, utils) => {
2494
2510
  });
2495
2511
  };
2496
2512
  function formatCalls(spy, msg, showActualCall) {
2497
- if (spy.mock.calls.length) msg += y.gray(`\n\nReceived:\n\n${spy.mock.calls.map((callArg, i) => {
2498
- let methodCall = y.bold(` ${ordinal(i + 1)} ${spy.getMockName()} call:\n\n`);
2513
+ if (spy.mock.calls.length) msg += $.gray(`\n\nReceived:\n\n${spy.mock.calls.map((callArg, i) => {
2514
+ let methodCall = $.bold(` ${ordinal(i + 1)} ${spy.getMockName()} call:\n\n`);
2499
2515
  if (showActualCall) methodCall += diff(showActualCall, callArg, { omitAnnotationLines: true });
2500
2516
  else methodCall += stringify(callArg).split("\n").map((line) => ` ${line}`).join("\n");
2501
2517
  methodCall += "\n";
2502
2518
  return methodCall;
2503
2519
  }).join("\n")}`);
2504
- msg += y.gray(`\n\nNumber of calls: ${y.bold(spy.mock.calls.length)}\n`);
2520
+ msg += $.gray(`\n\nNumber of calls: ${$.bold(spy.mock.calls.length)}\n`);
2505
2521
  return msg;
2506
2522
  }
2507
2523
  function formatReturns(spy, results, msg, showActualReturn) {
2508
- if (results.length) msg += y.gray(`\n\nReceived:\n\n${results.map((callReturn, i) => {
2509
- let methodCall = y.bold(` ${ordinal(i + 1)} ${spy.getMockName()} call return:\n\n`);
2524
+ if (results.length) msg += $.gray(`\n\nReceived:\n\n${results.map((callReturn, i) => {
2525
+ let methodCall = $.bold(` ${ordinal(i + 1)} ${spy.getMockName()} call return:\n\n`);
2510
2526
  if (showActualReturn) methodCall += diff(showActualReturn, callReturn.value, { omitAnnotationLines: true });
2511
2527
  else methodCall += stringify(callReturn).split("\n").map((line) => ` ${line}`).join("\n");
2512
2528
  methodCall += "\n";
2513
2529
  return methodCall;
2514
2530
  }).join("\n")}`);
2515
- msg += y.gray(`\n\nNumber of calls: ${y.bold(spy.mock.calls.length)}\n`);
2531
+ msg += $.gray(`\n\nNumber of calls: ${$.bold(spy.mock.calls.length)}\n`);
2516
2532
  return msg;
2517
2533
  }
2518
2534
 
@@ -2602,8 +2618,12 @@ function JestExtendPlugin(c, expect, matchers) {
2602
2618
  constructor(inverse = false, ...sample) {
2603
2619
  super(sample, inverse);
2604
2620
  }
2605
- asymmetricMatch(other) {
2606
- const { pass } = expectAssertion.call(this.getMatcherContext(expect), other, ...this.sample);
2621
+ asymmetricMatch(other, customTesters) {
2622
+ const context = this.getMatcherContext(expect);
2623
+ const { pass } = expectAssertion.call(customTesters ? {
2624
+ ...context,
2625
+ customTesters
2626
+ } : context, other, ...this.sample);
2607
2627
  return this.inverse ? !pass : pass;
2608
2628
  }
2609
2629
  toString() {
@@ -6880,13 +6900,15 @@ class FakeTimers {
6880
6900
  return 0;
6881
6901
  }
6882
6902
  setTimerTickMode(mode, interval) {
6883
- if (this._checkFakeTimers()) if (mode === "manual") this._clock.setTickMode({ mode: "manual" });
6884
- else if (mode === "nextTimerAsync") this._clock.setTickMode({ mode: "nextAsync" });
6885
- else if (mode === "interval") this._clock.setTickMode({
6886
- mode: "interval",
6887
- delta: interval
6888
- });
6889
- else throw new Error(`Invalid tick mode: ${mode}`);
6903
+ if (this._checkFakeTimers()) {
6904
+ if (mode === "manual") this._clock.setTickMode({ mode: "manual" });
6905
+ else if (mode === "nextTimerAsync") this._clock.setTickMode({ mode: "nextAsync" });
6906
+ else if (mode === "interval") this._clock.setTickMode({
6907
+ mode: "interval",
6908
+ delta: interval
6909
+ });
6910
+ else throw new Error(`Invalid tick mode: ${mode}`);
6911
+ }
6890
6912
  }
6891
6913
  configure(config) {
6892
6914
  this._userConfig = config;
@@ -8240,8 +8262,8 @@ function createBench(test, config, moduleRunner) {
8240
8262
  if (excessiveInvocations?.length) {
8241
8263
  const entries = excessiveInvocations.map(({ moduleId, exportName }) => ` - ${formatModuleId(moduleId, workerState.config.root)} > ${exportName}`).join("\n");
8242
8264
  console.warn([
8243
- y.yellow(y.bold("Benchmark Warning")),
8244
- `Benchmark ${y.bold(`"${groupName(options)}"`)} accessed module export getters too many times.`,
8265
+ $.yellow($.bold("Benchmark Warning")),
8266
+ `Benchmark ${$.bold(`"${groupName(options)}"`)} accessed module export getters too many times.`,
8245
8267
  "",
8246
8268
  "This can make results unreliable because export getters add overhead.",
8247
8269
  "See https://vitest.dev/guide/benchmarking#module-runner-overhead",
@@ -8366,8 +8388,8 @@ function createBench(test, config, moduleRunner) {
8366
8388
  const names = Array.from(pending, (reg) => `"${reg.name}"`).join(", ");
8367
8389
  pending.clear();
8368
8390
  console.warn([
8369
- y.yellow(y.bold("Benchmark Warning")),
8370
- `Test ${y.bold(`"${test.fullTestName}"`)} registered benchmarks that never ran: ${names}.`,
8391
+ $.yellow($.bold("Benchmark Warning")),
8392
+ `Test ${$.bold(`"${test.fullTestName}"`)} registered benchmarks that never ran: ${names}.`,
8371
8393
  "",
8372
8394
  "Call `.run()` on the registration, or pass it to `bench.compare()`.",
8373
8395
  "See https://vitest.dev/guide/benchmarking#defining-a-benchmark"
@@ -8460,6 +8482,7 @@ class TestRunner {
8460
8482
  const name = getNames(test).slice(1).join(" > ");
8461
8483
  this.snapshotClient.skipTest(suite.file.filepath, name);
8462
8484
  }
8485
+ this.snapshotClient.getSnapshotState(suite.file.filepath).getSnapshotFiles().forEach((file) => this.workerState.dependencies?.add(file));
8463
8486
  const result = await this.snapshotClient.finish(suite.file.filepath);
8464
8487
  if (this.workerState.config.snapshotOptions.updateSnapshot === "none" && result.unchecked) {
8465
8488
  let message = `Obsolete snapshots found when no snapshot update is expected.\n`;
@@ -1,4 +1,4 @@
1
- import { i as init } from './init.IsjtLXKe.js';
1
+ import { i as init } from './init.DrHtV5zd.js';
2
2
 
3
3
  if (!process.send) throw new Error("Expected worker to be run in node:child_process");
4
4
  // Store globals in case tests overwrite them
@@ -1,5 +1,5 @@
1
1
  import { isMainThread, parentPort } from 'node:worker_threads';
2
- import { i as init } from './init.IsjtLXKe.js';
2
+ import { i as init } from './init.DrHtV5zd.js';
3
3
 
4
4
  if (isMainThread || !parentPort) throw new Error("Expected worker to be run in node:worker_threads");
5
5
  function workerInit(options) {
@@ -2,13 +2,12 @@ import { readFileSync } from 'node:fs';
2
2
  import module$1, { isBuiltin } from 'node:module';
3
3
  import { pathToFileURL } from 'node:url';
4
4
  import { EvaluatedModules, ModuleRunner } from 'vite/module-runner';
5
- import { e as environments, b as VitestTransport } from './index.hTNFpC24.js';
6
- import { r as resolve } from './pathe.M-eThtNZ.DwEga6ro.js';
7
- import { b as serializeValue, c as createStackString, p as parseStacktrace } from './source-map.BH0bbrs9.js';
8
- import './index.M2dsQ_UQ.js';
9
- import { m } from './tinyrainbow.Ht9iggcq.js';
5
+ import { e as environments, b as VitestTransport } from './index.CPNMO3h-.js';
6
+ import { r as resolve } from './pathe.M-eThtNZ.Ba-7h1rE.js';
7
+ import { b as serializeValue, c as createStackString, p as parseStacktrace } from './source-map.DdKI5IHB.js';
8
+ import { w } from './tinyrainbow.Do8I1XRG.js';
10
9
  import { Traces } from '../traces.js';
11
- import { o as onCancel, V as VitestEvaluatedModules, a as rpcDone, c as createRuntimeRpc } from './rpc.CJVl3hZH.js';
10
+ import { o as onCancel, V as VitestEvaluatedModules, a as rpcDone, c as createRuntimeRpc } from './rpc.DpkUyY1N.js';
12
11
  import { s as setupInspect } from './inspector.CvyFGlXm.js';
13
12
  import { E as EnvironmentTeardownError } from './utils.DYj33du9.js';
14
13
 
@@ -164,6 +163,7 @@ async function execute(method, ctx, worker, traces) {
164
163
  evaluatedModules: new VitestEvaluatedModules(),
165
164
  resolvingModules,
166
165
  moduleExecutionInfo: /* @__PURE__ */ new Map(),
166
+ dependencies: ctx.config.experimental.recordDependencies ? /* @__PURE__ */ new Set() : void 0,
167
167
  config: ctx.config,
168
168
  // this is set later by vm or base
169
169
  environment: null,
@@ -267,7 +267,7 @@ function init(worker) {
267
267
  process.env.VITEST_WORKER_ID = String(message.workerId);
268
268
  reportMemory = message.options.reportMemory;
269
269
  poolId = message.poolId;
270
- if (message.context.config.disableColors) m();
270
+ if (message.context.config.disableColors) w();
271
271
  traces ??= await new Traces({
272
272
  enabled: message.traces.enabled,
273
273
  sdkPath: message.traces.sdkPath
@@ -0,0 +1,71 @@
1
+ import module$1 from 'node:module';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { s as slash } from './pathe.M-eThtNZ.Ba-7h1rE.js';
4
+ import { distDir } from '../path.js';
5
+
6
+ const vitestDistDir = `${slash(distDir)}/`;
7
+ /**
8
+ * Ids of the roots and of every module reachable from them through the runtime import edges.
9
+ */
10
+ function collectDependencies(getImports, ...roots) {
11
+ const visited = /* @__PURE__ */ new Set();
12
+ const queue = [];
13
+ for (const ids of roots) for (const id of ids) if (!visited.has(id)) {
14
+ visited.add(id);
15
+ queue.push(id);
16
+ }
17
+ while (queue.length) {
18
+ const imports = getImports(queue.pop());
19
+ if (!imports) continue;
20
+ for (const id of imports) if (!visited.has(id)) {
21
+ visited.add(id);
22
+ queue.push(id);
23
+ }
24
+ }
25
+ return Array.from(visited);
26
+ }
27
+ function getEvaluatedImports(evaluatedModules) {
28
+ return (id) => evaluatedModules.getModuleById(id)?.imports;
29
+ }
30
+ class NativeImportGraph {
31
+ imports = /* @__PURE__ */ new Map();
32
+ /**
33
+ * Returns the imported file, or `undefined` if the import is not tracked.
34
+ */
35
+ record(url, parentURL) {
36
+ if (!url.startsWith("file:") || url.includes("/node_modules/")) return;
37
+ const file = slash(fileURLToPath(url));
38
+ const importer = parentURL.startsWith("file:") ? slash(fileURLToPath(parentURL)) : parentURL;
39
+ // Vitest imports every test file, its edges would connect unrelated test files
40
+ if (!importer.startsWith(vitestDistDir)) {
41
+ let imports = this.imports.get(importer);
42
+ if (!imports) this.imports.set(importer, imports = /* @__PURE__ */ new Set());
43
+ imports.add(file);
44
+ }
45
+ return file;
46
+ }
47
+ getImports = (id) => this.imports.get(id);
48
+ }
49
+ /**
50
+ * Import edges of the modules loaded with native `import`, reported by a Node.js resolve hook.
51
+ * Node.js never loads a module twice, so the edges are kept as long as the thread runs.
52
+ */
53
+ const nativeImports = new NativeImportGraph();
54
+ let trackingNativeImports = false;
55
+ /**
56
+ * Registers a resolve hook that records the native imports of this thread.
57
+ * Returns `false` if the runtime has no synchronous module hooks.
58
+ */
59
+ function trackNativeImports() {
60
+ if (!trackingNativeImports && typeof module$1.registerHooks === "function") {
61
+ module$1.registerHooks({ resolve(specifier, context, nextResolve) {
62
+ const result = nextResolve(specifier, context);
63
+ if (context.parentURL) nativeImports.record(result.url, context.parentURL);
64
+ return result;
65
+ } });
66
+ trackingNativeImports = true;
67
+ }
68
+ return trackingNativeImports;
69
+ }
70
+
71
+ export { collectDependencies as c, getEvaluatedImports as g, nativeImports as n, trackNativeImports as t };
@@ -2,10 +2,10 @@ import module$1, { isBuiltin } from 'node:module';
2
2
  import { fileURLToPath } from 'node:url';
3
3
  import { MessageChannel } from 'node:worker_threads';
4
4
  import { initSyntaxLexers, hoistMocks } from '@vitest/mocker/transforms';
5
- import { c as cleanUrl, r as resolve } from './pathe.M-eThtNZ.DwEga6ro.js';
5
+ import { c as cleanUrl, r as resolve } from './pathe.M-eThtNZ.Ba-7h1rE.js';
6
6
  import { p as parse } from './acorn.C1kjbUFw.js';
7
7
  import MagicString from 'magic-string';
8
- import { y } from './tinyrainbow.Ht9iggcq.js';
8
+ import { $ } from './tinyrainbow.Do8I1XRG.js';
9
9
  import { distDir } from '../path.js';
10
10
  import { t as toBuiltin } from './modules.BJuCwlRJ.js';
11
11
  import 'node:path';
@@ -13,40 +13,53 @@ import 'node:path';
13
13
  const NOW_LENGTH = Date.now().toString().length;
14
14
  const REGEXP_VITEST = new RegExp(`%3Fvitest=\\d{${NOW_LENGTH}}`);
15
15
  const REGEXP_MOCK_ACTUAL = /\?mock=actual/;
16
- async function setupNodeLoaderHooks(worker) {
16
+ /**
17
+ * Returns `true` if `onImport` is called for every import, the hooks of `module.register` run in another thread
18
+ * and cannot report imports before the test file finishes.
19
+ */
20
+ async function setupNodeLoaderHooks(worker, onImport) {
17
21
  if (module$1.setSourceMapsSupport) module$1.setSourceMapsSupport(true);
18
22
  else if (process.setSourceMapsEnabled) process.setSourceMapsEnabled(true);
19
23
  if (worker.config.experimental.nodeLoader !== false) await initSyntaxLexers();
20
- if (typeof module$1.registerHooks === "function") module$1.registerHooks({
21
- resolve(specifier, context, nextResolve) {
22
- if (specifier.includes("mock=actual")) {
23
- // url is already resolved by `importActual`
24
- const moduleId = specifier.replace(REGEXP_MOCK_ACTUAL, "");
25
- const builtin = isBuiltin(moduleId);
26
- return {
27
- url: builtin ? toBuiltin(moduleId) : moduleId,
28
- format: builtin ? "builtin" : void 0,
29
- shortCircuit: true
30
- };
31
- }
32
- const isVitest = specifier.includes("%3Fvitest=");
33
- const result = nextResolve(isVitest ? specifier.replace(REGEXP_VITEST, "") : specifier, context);
34
- // avoid tracking /node_modules/ module graph for performance reasons
35
- if (context.parentURL && result.url && !result.url.includes("/node_modules/")) worker.rpc.ensureModuleGraphEntry(result.url, context.parentURL).catch(() => {
36
- // ignore errors
37
- });
38
- // this is require for in-source tests to be invalidated if
39
- // one of the files already imported it in --maxWorkers=1 --no-isolate
40
- if (isVitest) result.url = `${result.url}?vitest=${Date.now()}`;
41
- if (worker.config.experimental.nodeLoader === false || !context.parentURL || result.url.includes(distDir) || context.parentURL?.toString().includes(distDir)) return result;
42
- const mockedResult = getNativeMocker()?.resolveMockedModule(result.url, context.parentURL);
43
- if (mockedResult != null) return mockedResult;
44
- return result;
45
- },
46
- load: worker.config.experimental.nodeLoader === false ? void 0 : createLoadHook()
47
- });
48
- else if (module$1.register) {
49
- if (worker.config.experimental.nodeLoader !== false) console.warn(`${y.bgYellow(" WARNING ")} "module.registerHooks" is not supported in Node.js ${process.version}. This means that some features like module mocking or in-source testing are not supported. Upgrade your Node.js version to at least 22.15 or disable "experimental.nodeLoader" flag manually.\n`);
24
+ if (typeof module$1.registerHooks === "function") {
25
+ module$1.registerHooks({
26
+ resolve(specifier, context, nextResolve) {
27
+ if (specifier.includes("mock=actual")) {
28
+ // url is already resolved by `importActual`
29
+ const moduleId = specifier.replace(REGEXP_MOCK_ACTUAL, "");
30
+ const builtin = isBuiltin(moduleId);
31
+ return {
32
+ url: builtin ? toBuiltin(moduleId) : moduleId,
33
+ format: builtin ? "builtin" : void 0,
34
+ shortCircuit: true
35
+ };
36
+ }
37
+ const isVitest = specifier.includes("%3Fvitest=");
38
+ const result = nextResolve(isVitest ? specifier.replace(REGEXP_VITEST, "") : specifier, context);
39
+ // avoid tracking /node_modules/ module graph for performance reasons
40
+ if (context.parentURL && result.url && !result.url.includes("/node_modules/")) {
41
+ worker.rpc.ensureModuleGraphEntry(result.url, context.parentURL).catch(() => {
42
+ // ignore errors
43
+ });
44
+ onImport?.(result.url, context.parentURL);
45
+ }
46
+ // this is require for in-source tests to be invalidated if
47
+ // one of the files already imported it in --maxWorkers=1 --no-isolate
48
+ if (isVitest) result.url = `${result.url}?vitest=${Date.now()}`;
49
+ if (worker.config.experimental.nodeLoader === false || !context.parentURL || result.url.includes(distDir) || context.parentURL?.toString().includes(distDir)) return result;
50
+ const mockedResult = getNativeMocker()?.resolveMockedModule(result.url, context.parentURL);
51
+ if (mockedResult != null) {
52
+ // a `__mocks__` file is loaded in place of the module
53
+ onImport?.(mockedResult.url, context.parentURL);
54
+ return mockedResult;
55
+ }
56
+ return result;
57
+ },
58
+ load: worker.config.experimental.nodeLoader === false ? void 0 : createLoadHook()
59
+ });
60
+ return true;
61
+ } else if (module$1.register) {
62
+ if (worker.config.experimental.nodeLoader !== false) console.warn(`${$.bgYellow(" WARNING ")} "module.registerHooks" is not supported in Node.js ${process.version}. This means that some features like module mocking or in-source testing are not supported. Upgrade your Node.js version to at least 22.15 or disable "experimental.nodeLoader" flag manually.\n`);
50
63
  const { port1, port2 } = new MessageChannel();
51
64
  port1.unref();
52
65
  port2.unref();
@@ -68,12 +81,13 @@ async function setupNodeLoaderHooks(worker) {
68
81
  transferList: [port2]
69
82
  });
70
83
  } else if (!process.versions.deno && !process.versions.bun) console.warn("\"module.registerHooks\" and \"module.register\" are not supported. Some Vitest features may not work. Please, use Node.js 18.19.0 or higher.");
84
+ return false;
71
85
  }
72
86
  function replaceInSourceMarker(url, source, ms) {
73
87
  const re = /import\.meta\.vitest/g;
74
88
  let match;
75
89
  let overridden = false;
76
- // eslint-disable-next-line no-cond-assign
90
+ // oxlint-disable-next-line no-cond-assign
77
91
  while (match = re.exec(source)) {
78
92
  const { index, "0": code } = match;
79
93
  overridden = true;