vitest 4.0.0-beta.4 → 4.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 (78) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/browser.d.ts +8 -9
  3. package/dist/browser.js +3 -2
  4. package/dist/chunks/base.BXI97p6t.js +39 -0
  5. package/dist/chunks/{benchmark.CYdenmiT.js → benchmark.UW6Ezvxy.js} +6 -8
  6. package/dist/chunks/{browser.d.BRP8scJf.d.ts → browser.d.Cawq_X_N.d.ts} +1 -1
  7. package/dist/chunks/{cac.CY0IAxC4.js → cac.WE-urWw5.js} +38 -115
  8. package/dist/chunks/{cli-api.B8xRY9Zt.js → cli-api.CZz3evYC.js} +931 -1439
  9. package/dist/chunks/{config.d.DZo8c7fw.d.ts → config.d.CKNVOKm0.d.ts} +3 -8
  10. package/dist/chunks/{console.DoJHFxmj.js → console.B0quX7yH.js} +32 -68
  11. package/dist/chunks/{constants.CXzqaLmq.js → constants.D_Q9UYh-.js} +1 -6
  12. package/dist/chunks/{coverage.C84l9G-M.js → coverage.BPRS6xgn.js} +395 -665
  13. package/dist/chunks/{coverage.DVF1vEu8.js → coverage.D_JHT54q.js} +2 -2
  14. package/dist/chunks/{coverage.d.CNYjU4GF.d.ts → coverage.d.BZtK59WP.d.ts} +7 -5
  15. package/dist/chunks/{creator.yfA2ExGt.js → creator.KEg6n5IC.js} +29 -75
  16. package/dist/chunks/{date.Bq6ZW5rf.js → date.-jtEtIeV.js} +6 -17
  17. package/dist/chunks/{environment.d.Bhm9oc0v.d.ts → environment.d.2fYMoz3o.d.ts} +26 -4
  18. package/dist/chunks/{git.BVQ8w_Sw.js → git.BFNcloKD.js} +1 -2
  19. package/dist/chunks/{global.d.DAhT2emn.d.ts → global.d.K6uBQHzY.d.ts} +1 -1
  20. package/dist/chunks/{globals.Dgo-vS5G.js → globals.lgsmH00r.js} +7 -6
  21. package/dist/chunks/{index.D3SKT3tv.js → index.7w0eqmYM.js} +14 -24
  22. package/dist/chunks/{index.D1_MsKEt.js → index.AR8aAkCC.js} +4 -2
  23. package/dist/chunks/{index.CmSc2RE5.js → index.BG0gqZH-.js} +43 -106
  24. package/dist/chunks/{index.CtUvr1c8.js → index.CsFXYRkW.js} +27 -46
  25. package/dist/chunks/{index.Bz6b0Ib7.js → index.VNI-1z5c.js} +276 -604
  26. package/dist/chunks/{inspector.C914Efll.js → inspector.CvQD-Nie.js} +10 -25
  27. package/dist/chunks/moduleRunner.d.8kKUsuDg.d.ts +202 -0
  28. package/dist/chunks/moduleTransport.I-bgQy0S.js +19 -0
  29. package/dist/chunks/{node.fjCdwEIl.js → node.BOqcT2jW.js} +1 -1
  30. package/dist/chunks/{plugin.d.CLhMcYdD.d.ts → plugin.d.DuiQJfUL.d.ts} +1 -1
  31. package/dist/chunks/{reporters.d.DWg40D2B.d.ts → reporters.d.CqR9-CDJ.d.ts} +52 -101
  32. package/dist/chunks/resolver.Bx6lE0iq.js +119 -0
  33. package/dist/chunks/{rpc.jnQO9F8a.js → rpc.RpPylpp0.js} +7 -21
  34. package/dist/chunks/runBaseTests.D6sfuWBM.js +99 -0
  35. package/dist/chunks/{setup-common.Ebx5x0eP.js → setup-common.hLGRxhC8.js} +15 -27
  36. package/dist/chunks/startModuleRunner.C8TW8zTN.js +655 -0
  37. package/dist/chunks/{typechecker.CMNPqJOo.js → typechecker.Cd1wvxUM.js} +97 -209
  38. package/dist/chunks/{utils.CcGm2cd1.js → utils.C2YI6McM.js} +4 -13
  39. package/dist/chunks/{utils.XdZDrNZV.js → utils.C7__0Iv5.js} +7 -17
  40. package/dist/chunks/{vi.CA0EPI9Y.js → vi.BfdOiD4j.js} +116 -269
  41. package/dist/chunks/{vm.BUnLJt_P.js → vm.BHBje7cC.js} +101 -225
  42. package/dist/chunks/{worker.d.zjyR34Pb.d.ts → worker.d.D9QWnzAe.d.ts} +16 -13
  43. package/dist/chunks/{worker.d.C-1AbnVe.d.ts → worker.d.Db-UVmXc.d.ts} +1 -1
  44. package/dist/cli.js +4 -4
  45. package/dist/config.cjs +3 -9
  46. package/dist/config.d.ts +10 -12
  47. package/dist/config.js +1 -1
  48. package/dist/coverage.d.ts +10 -11
  49. package/dist/coverage.js +5 -6
  50. package/dist/environments.d.ts +2 -2
  51. package/dist/environments.js +1 -1
  52. package/dist/index.d.ts +10 -9
  53. package/dist/index.js +6 -5
  54. package/dist/module-evaluator.d.ts +12 -0
  55. package/dist/module-evaluator.js +276 -0
  56. package/dist/module-runner.js +15 -0
  57. package/dist/node.d.ts +12 -13
  58. package/dist/node.js +19 -24
  59. package/dist/reporters.d.ts +7 -8
  60. package/dist/reporters.js +3 -3
  61. package/dist/runners.d.ts +3 -3
  62. package/dist/runners.js +35 -57
  63. package/dist/snapshot.js +2 -2
  64. package/dist/suite.js +2 -2
  65. package/dist/worker.js +82 -45
  66. package/dist/workers/forks.js +11 -10
  67. package/dist/workers/runVmTests.js +27 -46
  68. package/dist/workers/threads.js +11 -10
  69. package/dist/workers/vmForks.js +11 -10
  70. package/dist/workers/vmThreads.js +11 -10
  71. package/dist/workers.d.ts +5 -4
  72. package/dist/workers.js +17 -16
  73. package/package.json +22 -17
  74. package/dist/chunks/base.BaCDDRPG.js +0 -38
  75. package/dist/chunks/execute.Dt-pCVcL.js +0 -708
  76. package/dist/chunks/runBaseTests.DBVVLMSb.js +0 -129
  77. package/dist/execute.d.ts +0 -148
  78. package/dist/execute.js +0 -13
@@ -1,19 +1,17 @@
1
1
  import fs, { promises, existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
2
2
  import { relative, resolve, dirname, extname, normalize, join, basename, isAbsolute } from 'pathe';
3
- import { C as CoverageProviderMap } from './coverage.DVF1vEu8.js';
3
+ import { C as CoverageProviderMap } from './coverage.D_JHT54q.js';
4
4
  import path, { resolve as resolve$1 } from 'node:path';
5
- import { noop, isPrimitive, createDefer, slash, highlight, toArray, deepMerge, nanoid, deepClone, notNullish } from '@vitest/utils';
5
+ import { noop, isPrimitive, createDefer, slash, highlight, toArray, cleanUrl, deepMerge, KNOWN_ASSET_RE, nanoid, deepClone, notNullish } from '@vitest/utils';
6
6
  import { f as findUp, p as prompt } from './index.X0nbfr6-.js';
7
7
  import * as vite from 'vite';
8
- import { searchForWorkspaceRoot, version, createServer, mergeConfig } from 'vite';
9
- import { A as API_PATH, c as configFiles, d as defaultBrowserPort, a as defaultPort } from './constants.CXzqaLmq.js';
8
+ import { searchForWorkspaceRoot, version, mergeConfig, createServer } from 'vite';
9
+ import { A as API_PATH, c as configFiles, d as defaultBrowserPort, a as defaultPort } from './constants.D_Q9UYh-.js';
10
10
  import { generateFileHash, limitConcurrency, createFileTask, hasFailed, getTasks, getTests } from '@vitest/runner/utils';
11
11
  import { SnapshotManager } from '@vitest/snapshot/manager';
12
- import { ViteNodeRunner } from 'vite-node/client';
13
- import { ViteNodeServer } from 'vite-node/server';
14
- import { v as version$1 } from './cac.CY0IAxC4.js';
12
+ import { v as version$1 } from './cac.WE-urWw5.js';
15
13
  import { c as createBirpc } from './index.Bgo3tNWt.js';
16
- import { p as parse, s as stringify, d as printError, f as formatProjectName, w as withLabel, e as errorBanner, h as divider, i as generateCodeFrame, R as ReportersMap, B as BlobReporter, r as readBlobs, H as HangingProcessReporter } from './index.Bz6b0Ib7.js';
14
+ import { p as parse, s as stringify, d as printError, f as formatProjectName, w as withLabel, e as errorBanner, h as divider, i as generateCodeFrame, R as ReportersMap, B as BlobReporter, r as readBlobs, H as HangingProcessReporter } from './index.VNI-1z5c.js';
17
15
  import require$$0$3 from 'events';
18
16
  import require$$1$1 from 'https';
19
17
  import require$$2 from 'http';
@@ -28,22 +26,25 @@ import { g as getDefaultExportFromCjs } from './_commonjsHelpers.BFTU3MAI.js';
28
26
  import { parseErrorStacktrace } from '@vitest/utils/source-map';
29
27
  import crypto, { createHash } from 'node:crypto';
30
28
  import { distDir, rootDir } from '../path.js';
31
- import { h as hash, R as RandomSequencer, i as isPackageExists, g as getFilePoolName, d as isBrowserEnabled, r as resolveConfig, e as groupBy, f as getCoverageProvider, j as createPool, w as wildcardPatternToRegExp, a as resolveApiServerConfig, s as stdout } from './coverage.C84l9G-M.js';
32
- import { c as convertTasksToEvents } from './typechecker.CMNPqJOo.js';
29
+ import { h as hash, d as createFetchModuleFunction, n as normalizeResolvedIdToUrl, R as RandomSequencer, i as isPackageExists, g as getFilePoolName, e as isBrowserEnabled, r as resolveConfig, f as groupBy, j as getCoverageProvider, k as createPool, w as wildcardPatternToRegExp, a as resolveApiServerConfig, s as stdout } from './coverage.BPRS6xgn.js';
30
+ import { c as convertTasksToEvents } from './typechecker.Cd1wvxUM.js';
31
+ import { VitestModuleEvaluator } from '#module-evaluator';
32
+ import { ModuleRunner } from 'vite/module-runner';
33
33
  import { Console } from 'node:console';
34
34
  import c from 'tinyrainbow';
35
- import { createRequire } from 'node:module';
36
- import url from 'node:url';
35
+ import { createRequire, builtinModules, isBuiltin } from 'node:module';
36
+ import url, { pathToFileURL } from 'node:url';
37
37
  import { i as isTTY, a as isWindows } from './env.D4Lgay0q.js';
38
38
  import { rm, mkdir, copyFile } from 'node:fs/promises';
39
39
  import nodeos__default, { tmpdir } from 'node:os';
40
40
  import pm from 'picomatch';
41
41
  import { glob, isDynamicPattern } from 'tinyglobby';
42
- import { normalizeRequestId, cleanUrl } from 'vite-node/utils';
42
+ import MagicString from 'magic-string';
43
43
  import { hoistMocksPlugin, automockPlugin } from '@vitest/mocker/node';
44
44
  import { c as configDefaults } from './defaults.CXFFjsi8.js';
45
- import MagicString from 'magic-string';
46
- import { a as BenchmarkReportsMap } from './index.D3SKT3tv.js';
45
+ import { f as findNearestPackageData } from './resolver.Bx6lE0iq.js';
46
+ import * as esModuleLexer from 'es-module-lexer';
47
+ import { a as BenchmarkReportsMap } from './index.7w0eqmYM.js';
47
48
  import assert$1 from 'node:assert';
48
49
  import { serializeError } from '@vitest/utils/error';
49
50
  import readline from 'node:readline';
@@ -5016,25 +5017,18 @@ var websocketServerExports = requireWebsocketServer();
5016
5017
  var WebSocketServer = /*@__PURE__*/getDefaultExportFromCjs(websocketServerExports);
5017
5018
 
5018
5019
  async function getModuleGraph(ctx, projectName, id, browser = false) {
5019
- const graph = {};
5020
- const externalized = /* @__PURE__ */ new Set();
5021
- const inlined = /* @__PURE__ */ new Set();
5022
- const project = ctx.getProjectByName(projectName);
5020
+ const graph = {}, externalized = /* @__PURE__ */ new Set(), inlined = /* @__PURE__ */ new Set(), project = ctx.getProjectByName(projectName);
5023
5021
  async function get(mod, seen = /* @__PURE__ */ new Map()) {
5024
- if (!mod || !mod.id) return;
5025
- if (mod.id === "\0@vitest/browser/context") return;
5022
+ if (!mod || !mod.id || mod.id === "\0@vitest/browser/context") return;
5026
5023
  if (seen.has(mod)) return seen.get(mod);
5027
5024
  let id = clearId(mod.id);
5028
5025
  seen.set(mod, id);
5029
- const rewrote = browser ? mod.file?.includes(project.browser.vite.config.cacheDir) ? mod.id : false : await project.vitenode.shouldExternalize(id);
5030
- if (rewrote) {
5031
- id = rewrote;
5032
- externalized.add(id);
5033
- seen.set(mod, id);
5034
- } else inlined.add(id);
5026
+ // TODO: how to know if it was rewritten(?) - what is rewritten?
5027
+ const rewrote = browser ? mod.file?.includes(project.browser.vite.config.cacheDir) ? mod.id : false : false;
5028
+ if (rewrote) id = rewrote, externalized.add(id), seen.set(mod, id);
5029
+ else inlined.add(id);
5035
5030
  const mods = Array.from(mod.importedModules).filter((i) => i.id && !i.id.includes("/vitest/dist/"));
5036
- graph[id] = (await Promise.all(mods.map((m) => get(m, seen)))).filter(Boolean);
5037
- return id;
5031
+ return graph[id] = (await Promise.all(mods.map((m) => get(m, seen)))).filter(Boolean), id;
5038
5032
  }
5039
5033
  if (browser && project.browser) await get(project.browser.vite.moduleGraph.getModuleById(id));
5040
5034
  else await get(project.vite.moduleGraph.getModuleById(id));
@@ -5086,21 +5080,19 @@ catch {}
5086
5080
  }
5087
5081
 
5088
5082
  function setup(ctx, _server) {
5089
- const wss = new WebSocketServer({ noServer: true });
5090
- const clients = /* @__PURE__ */ new Map();
5091
- const server = _server || ctx.server;
5083
+ const wss = new WebSocketServer({ noServer: true }), clients = /* @__PURE__ */ new Map(), server = _server || ctx.server;
5092
5084
  server.httpServer?.on("upgrade", (request, socket, head) => {
5093
5085
  if (!request.url) return;
5094
5086
  const { pathname } = new URL(request.url, "http://localhost");
5095
- if (pathname !== API_PATH) return;
5096
- if (!isValidApiRequest(ctx.config, request)) {
5097
- socket.destroy();
5098
- return;
5087
+ if (pathname === API_PATH) {
5088
+ if (!isValidApiRequest(ctx.config, request)) {
5089
+ socket.destroy();
5090
+ return;
5091
+ }
5092
+ wss.handleUpgrade(request, socket, head, (ws) => {
5093
+ wss.emit("connection", ws, request), setupClient(ws);
5094
+ });
5099
5095
  }
5100
- wss.handleUpgrade(request, socket, head, (ws) => {
5101
- wss.emit("connection", ws, request);
5102
- setupClient(ws);
5103
- });
5104
5096
  });
5105
5097
  function setupClient(ws) {
5106
5098
  const rpc = createBirpc({
@@ -5114,8 +5106,7 @@ function setup(ctx, _server) {
5114
5106
  return ctx.state.getPaths();
5115
5107
  },
5116
5108
  async readTestFile(id) {
5117
- if (!ctx.state.filesMap.has(id) || !existsSync(id)) return null;
5118
- return promises.readFile(id, "utf-8");
5109
+ return !ctx.state.filesMap.has(id) || !existsSync(id) ? null : promises.readFile(id, "utf-8");
5119
5110
  },
5120
5111
  async saveTestFile(id, content) {
5121
5112
  if (!ctx.state.filesMap.has(id) || !existsSync(id)) throw new Error(`Test file "${id}" was not registered, so it cannot be updated using the API.`);
@@ -5137,8 +5128,7 @@ function setup(ctx, _server) {
5137
5128
  }));
5138
5129
  },
5139
5130
  async getTransformResult(projectName, id, browser = false) {
5140
- const project = ctx.getProjectByName(projectName);
5141
- const result = browser ? await project.browser.vite.transformRequest(id) : await project.vitenode.transformRequest(id);
5131
+ const project = ctx.getProjectByName(projectName), result = browser ? await project.browser.vite.transformRequest(id) : await project.vite.transformRequest(id);
5142
5132
  if (result) {
5143
5133
  try {
5144
5134
  result.source = result.source || await promises.readFile(id, "utf-8");
@@ -5181,56 +5171,49 @@ function setup(ctx, _server) {
5181
5171
  deserialize: parse,
5182
5172
  timeout: -1
5183
5173
  });
5184
- clients.set(ws, rpc);
5185
- ws.on("close", () => {
5186
- clients.delete(ws);
5187
- rpc.$close(/* @__PURE__ */ new Error("[vitest-api]: Pending methods while closing rpc"));
5174
+ clients.set(ws, rpc), ws.on("close", () => {
5175
+ clients.delete(ws), rpc.$close(/* @__PURE__ */ new Error("[vitest-api]: Pending methods while closing rpc"));
5188
5176
  });
5189
5177
  }
5190
5178
  ctx.reporters.push(new WebSocketReporter(ctx, wss, clients));
5191
5179
  }
5192
5180
  class WebSocketReporter {
5193
5181
  constructor(ctx, wss, clients) {
5194
- this.ctx = ctx;
5195
- this.wss = wss;
5196
- this.clients = clients;
5182
+ this.ctx = ctx, this.wss = wss, this.clients = clients;
5197
5183
  }
5198
- onCollected(files) {
5199
- if (this.clients.size === 0) return;
5200
- this.clients.forEach((client) => {
5201
- client.onCollected?.(files)?.catch?.(noop);
5184
+ onTestModuleCollected(testModule) {
5185
+ this.clients.size !== 0 && this.clients.forEach((client) => {
5186
+ client.onCollected?.([testModule.task])?.catch?.(noop);
5202
5187
  });
5203
5188
  }
5204
- onSpecsCollected(specs) {
5189
+ onTestRunStart(specifications) {
5205
5190
  if (this.clients.size === 0) return;
5191
+ const serializedSpecs = specifications.map((spec) => spec.toJSON());
5206
5192
  this.clients.forEach((client) => {
5207
- client.onSpecsCollected?.(specs)?.catch?.(noop);
5193
+ client.onSpecsCollected?.(serializedSpecs)?.catch?.(noop);
5208
5194
  });
5209
5195
  }
5210
5196
  async onTestCaseAnnotate(testCase, annotation) {
5211
- if (this.clients.size === 0) return;
5212
- this.clients.forEach((client) => {
5197
+ this.clients.size !== 0 && this.clients.forEach((client) => {
5213
5198
  client.onTestAnnotate?.(testCase.id, annotation)?.catch?.(noop);
5214
5199
  });
5215
5200
  }
5216
5201
  async onTaskUpdate(packs, events) {
5217
- if (this.clients.size === 0) return;
5218
- packs.forEach(([taskId, result]) => {
5219
- const task = this.ctx.state.idMap.get(taskId);
5220
- const isBrowser = task && task.file.pool === "browser";
5202
+ this.clients.size !== 0 && (packs.forEach(([taskId, result]) => {
5203
+ const task = this.ctx.state.idMap.get(taskId), isBrowser = task && task.file.pool === "browser";
5221
5204
  result?.errors?.forEach((error) => {
5222
- if (isPrimitive(error)) return;
5223
- if (isBrowser) {
5205
+ if (!isPrimitive(error)) if (isBrowser) {
5224
5206
  const project = this.ctx.getProjectByName(task.file.projectName || "");
5225
5207
  error.stacks = project.browser?.parseErrorStacktrace(error);
5226
5208
  } else error.stacks = parseErrorStacktrace(error);
5227
5209
  });
5228
- });
5229
- this.clients.forEach((client) => {
5210
+ }), this.clients.forEach((client) => {
5230
5211
  client.onTaskUpdate?.(packs, events)?.catch?.(noop);
5231
- });
5212
+ }));
5232
5213
  }
5233
- onFinished(files, errors) {
5214
+ onTestRunEnd(testModules, unhandledErrors) {
5215
+ if (!this.clients.size) return;
5216
+ const files = testModules.map((testModule) => testModule.task), errors = [...unhandledErrors];
5234
5217
  this.clients.forEach((client) => {
5235
5218
  client.onFinished?.(files, errors)?.catch?.(noop);
5236
5219
  });
@@ -5264,23 +5247,18 @@ class BrowserSessions {
5264
5247
  }
5265
5248
  createSession(sessionId, project, pool) {
5266
5249
  // this promise only waits for the WS connection with the orhcestrator to be established
5267
- const defer = createDefer();
5268
- const timeout = setTimeout(() => {
5250
+ const defer = createDefer(), timeout = setTimeout(() => {
5269
5251
  defer.reject(/* @__PURE__ */ new Error(`Failed to connect to the browser session "${sessionId}" [${project.name}] within the timeout.`));
5270
5252
  }, project.vitest.config.browser.connectTimeout ?? 6e4).unref();
5271
- this.sessions.set(sessionId, {
5253
+ return this.sessions.set(sessionId, {
5272
5254
  project,
5273
5255
  connected: () => {
5274
- defer.resolve();
5275
- clearTimeout(timeout);
5256
+ defer.resolve(), clearTimeout(timeout);
5276
5257
  },
5277
5258
  fail: (error) => {
5278
- defer.resolve();
5279
- clearTimeout(timeout);
5280
- pool.reject(error);
5259
+ defer.resolve(), clearTimeout(timeout), pool.reject(error);
5281
5260
  }
5282
- });
5283
- return defer;
5261
+ }), defer;
5284
5262
  }
5285
5263
  }
5286
5264
 
@@ -5321,37 +5299,25 @@ class ResultsCache {
5321
5299
  return this.cachePath;
5322
5300
  }
5323
5301
  setConfig(root, config) {
5324
- this.root = root;
5325
- if (config) this.cachePath = resolve(config.dir, "results.json");
5302
+ if (this.root = root, config) this.cachePath = resolve(config.dir, "results.json");
5326
5303
  }
5327
5304
  getResults(key) {
5328
5305
  return this.cache.get(key);
5329
5306
  }
5330
5307
  async readFromCache() {
5331
- if (!this.cachePath) return;
5332
- if (!fs.existsSync(this.cachePath)) return;
5333
- const resultsCache = await fs.promises.readFile(this.cachePath, "utf8");
5334
- const { results, version } = JSON.parse(resultsCache || "[]");
5335
- const [major, minor] = version.split(".");
5308
+ if (!this.cachePath || !fs.existsSync(this.cachePath)) return;
5309
+ const resultsCache = await fs.promises.readFile(this.cachePath, "utf8"), { results, version } = JSON.parse(resultsCache || "[]"), [major, minor] = version.split(".");
5336
5310
  // handling changed in 0.30.0
5337
- if (major > 0 || Number(minor) >= 30) {
5338
- this.cache = new Map(results);
5339
- this.version = version;
5340
- results.forEach(([spec]) => {
5341
- const [projectName, relativePath] = spec.split(":");
5342
- const keyMap = this.workspacesKeyMap.get(relativePath) || [];
5343
- keyMap.push(projectName);
5344
- this.workspacesKeyMap.set(relativePath, keyMap);
5345
- });
5346
- }
5311
+ if (major > 0 || Number(minor) >= 30) this.cache = new Map(results), this.version = version, results.forEach(([spec]) => {
5312
+ const [projectName, relativePath] = spec.split(":"), keyMap = this.workspacesKeyMap.get(relativePath) || [];
5313
+ keyMap.push(projectName), this.workspacesKeyMap.set(relativePath, keyMap);
5314
+ });
5347
5315
  }
5348
5316
  updateResults(files) {
5349
5317
  files.forEach((file) => {
5350
5318
  const result = file.result;
5351
5319
  if (!result) return;
5352
- const duration = result.duration || 0;
5353
- // store as relative, so cache would be the same in CI and locally
5354
- const relativePath = relative(this.root, file.filepath);
5320
+ const duration = result.duration || 0, relativePath = relative(this.root, file.filepath);
5355
5321
  this.cache.set(`${file.projectName || ""}:${relativePath}`, {
5356
5322
  duration: duration >= 0 ? duration : 0,
5357
5323
  failed: result.state === "fail"
@@ -5365,8 +5331,7 @@ class ResultsCache {
5365
5331
  }
5366
5332
  async writeToCache() {
5367
5333
  if (!this.cachePath) return;
5368
- const results = Array.from(this.cache.entries());
5369
- const cacheDirname = dirname(this.cachePath);
5334
+ const results = Array.from(this.cache.entries()), cacheDirname = dirname(this.cachePath);
5370
5335
  if (!fs.existsSync(cacheDirname)) await fs.promises.mkdir(cacheDirname, { recursive: true });
5371
5336
  const cache = JSON.stringify({
5372
5337
  version: this.version,
@@ -5394,6 +5359,34 @@ class VitestCache {
5394
5359
  }
5395
5360
  }
5396
5361
 
5362
+ class ServerModuleRunner extends ModuleRunner {
5363
+ constructor(environment, resolver, config) {
5364
+ const fetchModule = createFetchModuleFunction(resolver, false);
5365
+ super({
5366
+ hmr: false,
5367
+ sourcemapInterceptor: "node",
5368
+ transport: { async invoke(event) {
5369
+ if (event.type !== "custom") throw new Error(`Vitest Module Runner doesn't support Vite HMR events.`);
5370
+ const { data } = event.data;
5371
+ try {
5372
+ const result = await fetchModule(data[0], data[1], environment, data[2]);
5373
+ return { result };
5374
+ } catch (error) {
5375
+ return { error };
5376
+ }
5377
+ } }
5378
+ }, new VitestModuleEvaluator()), this.environment = environment, this.config = config;
5379
+ }
5380
+ async import(rawId) {
5381
+ const resolved = await this.environment.pluginContainer.resolveId(rawId, this.config.root);
5382
+ if (!resolved) return super.import(rawId);
5383
+ // Vite will make "@vitest/coverage-v8" into "@vitest/coverage-v8.js" url
5384
+ // instead of using an actual file path-like URL, so we resolve it here first
5385
+ const url = normalizeResolvedIdToUrl(this.environment, resolved.id);
5386
+ return super.import(url);
5387
+ }
5388
+ }
5389
+
5397
5390
  class FilesNotFoundError extends Error {
5398
5391
  code = "VITEST_FILES_NOT_FOUND";
5399
5392
  constructor(mode) {
@@ -5449,43 +5442,26 @@ function highlightCode(id, source, colors) {
5449
5442
  });
5450
5443
  }
5451
5444
 
5452
- const PAD = " ";
5453
- const ESC$1 = "\x1B[";
5454
- const ERASE_DOWN = `${ESC$1}J`;
5455
- const ERASE_SCROLLBACK = `${ESC$1}3J`;
5456
- const CURSOR_TO_START = `${ESC$1}1;1H`;
5457
- const HIDE_CURSOR = `${ESC$1}?25l`;
5458
- const SHOW_CURSOR = `${ESC$1}?25h`;
5459
- const CLEAR_SCREEN = "\x1Bc";
5445
+ const PAD = " ", ESC$1 = "\x1B[", ERASE_DOWN = `${ESC$1}J`, ERASE_SCROLLBACK = `${ESC$1}3J`, CURSOR_TO_START = `${ESC$1}1;1H`, HIDE_CURSOR = `${ESC$1}?25l`, SHOW_CURSOR = `${ESC$1}?25h`, CLEAR_SCREEN = "\x1Bc";
5460
5446
  class Logger {
5461
5447
  _clearScreenPending;
5462
5448
  _highlights = /* @__PURE__ */ new Map();
5463
5449
  cleanupListeners = [];
5464
5450
  console;
5465
5451
  constructor(ctx, outputStream = process.stdout, errorStream = process.stderr) {
5466
- this.ctx = ctx;
5467
- this.outputStream = outputStream;
5468
- this.errorStream = errorStream;
5469
- this.console = new Console({
5452
+ if (this.ctx = ctx, this.outputStream = outputStream, this.errorStream = errorStream, this.console = new Console({
5470
5453
  stdout: outputStream,
5471
5454
  stderr: errorStream
5472
- });
5473
- this._highlights.clear();
5474
- this.addCleanupListeners();
5475
- this.registerUnhandledRejection();
5476
- if (this.outputStream.isTTY) this.outputStream.write(HIDE_CURSOR);
5455
+ }), this._highlights.clear(), this.addCleanupListeners(), this.registerUnhandledRejection(), this.outputStream.isTTY) this.outputStream.write(HIDE_CURSOR);
5477
5456
  }
5478
5457
  log(...args) {
5479
- this._clearScreen();
5480
- this.console.log(...args);
5458
+ this._clearScreen(), this.console.log(...args);
5481
5459
  }
5482
5460
  error(...args) {
5483
- this._clearScreen();
5484
- this.console.error(...args);
5461
+ this._clearScreen(), this.console.error(...args);
5485
5462
  }
5486
5463
  warn(...args) {
5487
- this._clearScreen();
5488
- this.console.warn(...args);
5464
+ this._clearScreen(), this.console.warn(...args);
5489
5465
  }
5490
5466
  clearFullScreen(message = "") {
5491
5467
  if (!this.ctx.config.clearScreen) {
@@ -5500,14 +5476,12 @@ class Logger {
5500
5476
  this.console.log(message);
5501
5477
  return;
5502
5478
  }
5503
- this._clearScreenPending = message;
5504
- if (force) this._clearScreen();
5479
+ if (this._clearScreenPending = message, force) this._clearScreen();
5505
5480
  }
5506
5481
  _clearScreen() {
5507
5482
  if (this._clearScreenPending == null) return;
5508
5483
  const log = this._clearScreenPending;
5509
- this._clearScreenPending = void 0;
5510
- this.console.log(`${CURSOR_TO_START}${ERASE_DOWN}${log}`);
5484
+ this._clearScreenPending = void 0, this.console.log(`${CURSOR_TO_START}${ERASE_DOWN}${log}`);
5511
5485
  }
5512
5486
  printError(err, options = {}) {
5513
5487
  printError(err, this.ctx, this, options);
@@ -5522,8 +5496,7 @@ class Logger {
5522
5496
  highlight(filename, source) {
5523
5497
  if (this._highlights.has(filename)) return this._highlights.get(filename);
5524
5498
  const code = highlightCode(filename, source);
5525
- this._highlights.set(filename, code);
5526
- return code;
5499
+ return this._highlights.set(filename, code), code;
5527
5500
  }
5528
5501
  printNoTestFound(filters) {
5529
5502
  const config = this.ctx.config;
@@ -5536,34 +5509,22 @@ class Logger {
5536
5509
  const projectsFilter = toArray(config.project);
5537
5510
  if (projectsFilter.length) this.console.error(c.dim("projects: ") + c.yellow(projectsFilter.join(comma)));
5538
5511
  this.ctx.projects.forEach((project) => {
5539
- const config = project.config;
5540
- const printConfig = !project.isRootProject() && project.name;
5512
+ const config = project.config, printConfig = !project.isRootProject() && project.name;
5541
5513
  if (printConfig) this.console.error(`\n${formatProjectName(project)}\n`);
5542
5514
  if (config.include) this.console.error(c.dim("include: ") + c.yellow(config.include.join(comma)));
5543
5515
  if (config.exclude) this.console.error(c.dim("exclude: ") + c.yellow(config.exclude.join(comma)));
5544
- if (config.typecheck.enabled) {
5545
- this.console.error(c.dim("typecheck include: ") + c.yellow(config.typecheck.include.join(comma)));
5546
- this.console.error(c.dim("typecheck exclude: ") + c.yellow(config.typecheck.exclude.join(comma)));
5547
- }
5548
- });
5549
- this.console.error();
5516
+ if (config.typecheck.enabled) this.console.error(c.dim("typecheck include: ") + c.yellow(config.typecheck.include.join(comma))), this.console.error(c.dim("typecheck exclude: ") + c.yellow(config.typecheck.exclude.join(comma)));
5517
+ }), this.console.error();
5550
5518
  }
5551
5519
  printBanner() {
5552
5520
  this.log();
5553
- const color = this.ctx.config.watch ? "blue" : "cyan";
5554
- const mode = this.ctx.config.watch ? "DEV" : "RUN";
5555
- this.log(withLabel(color, mode, `v${this.ctx.version} `) + c.gray(this.ctx.config.root));
5556
- if (this.ctx.config.sequence.sequencer === RandomSequencer) this.log(PAD + c.gray(`Running tests with seed "${this.ctx.config.sequence.seed}"`));
5521
+ const color = this.ctx.config.watch ? "blue" : "cyan", mode = this.ctx.config.watch ? "DEV" : "RUN";
5522
+ if (this.log(withLabel(color, mode, `v${this.ctx.version} `) + c.gray(this.ctx.config.root)), this.ctx.config.sequence.sequencer === RandomSequencer) this.log(PAD + c.gray(`Running tests with seed "${this.ctx.config.sequence.seed}"`));
5557
5523
  if (this.ctx.config.ui) {
5558
- const host = this.ctx.config.api?.host || "localhost";
5559
- const port = this.ctx.server.config.server.port;
5560
- const base = this.ctx.config.uiBase;
5524
+ const host = this.ctx.config.api?.host || "localhost", port = this.ctx.server.config.server.port, base = this.ctx.config.uiBase;
5561
5525
  this.log(PAD + c.dim(c.green(`UI started at http://${host}:${c.bold(port)}${base}`)));
5562
5526
  } else if (this.ctx.config.api?.port) {
5563
- const resolvedUrls = this.ctx.server.resolvedUrls;
5564
- // workaround for https://github.com/vitejs/vite/issues/15438, it was fixed in vite 5.1
5565
- const fallbackUrl = `http://${this.ctx.config.api.host || "localhost"}:${this.ctx.config.api.port}`;
5566
- const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0] ?? fallbackUrl;
5527
+ const resolvedUrls = this.ctx.server.resolvedUrls, fallbackUrl = `http://${this.ctx.config.api.host || "localhost"}:${this.ctx.config.api.port}`, origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0] ?? fallbackUrl;
5567
5528
  this.log(PAD + c.dim(c.green(`API started at ${new URL("/", origin)}`)));
5568
5529
  }
5569
5530
  if (this.ctx.coverageProvider) this.log(PAD + c.dim("Coverage enabled with ") + c.yellow(this.ctx.coverageProvider.name));
@@ -5572,35 +5533,26 @@ class Logger {
5572
5533
  }
5573
5534
  printBrowserBanner(project) {
5574
5535
  if (!project.browser) return;
5575
- const resolvedUrls = project.browser.vite.resolvedUrls;
5576
- const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
5536
+ const resolvedUrls = project.browser.vite.resolvedUrls, origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
5577
5537
  if (!origin) return;
5578
- const output = project.isRootProject() ? "" : formatProjectName(project);
5579
- const provider = project.browser.provider.name;
5580
- const providerString = provider === "preview" ? "" : ` by ${c.reset(c.bold(provider))}`;
5538
+ const output = project.isRootProject() ? "" : formatProjectName(project), provider = project.browser.provider.name, providerString = provider === "preview" ? "" : ` by ${c.reset(c.bold(provider))}`;
5581
5539
  this.log(c.dim(`${output}Browser runner started${providerString} ${c.dim("at")} ${c.blue(new URL("/__vitest_test__/", origin))}\n`));
5582
5540
  }
5583
5541
  printUnhandledErrors(errors) {
5584
5542
  const errorMessage = c.red(c.bold(`\nVitest caught ${errors.length} unhandled error${errors.length > 1 ? "s" : ""} during the test run.
5585
5543
  This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.`));
5586
- this.error(errorBanner("Unhandled Errors"));
5587
- this.error(errorMessage);
5588
- errors.forEach((err) => {
5544
+ this.error(errorBanner("Unhandled Errors")), this.error(errorMessage), errors.forEach((err) => {
5589
5545
  this.printError(err, {
5590
5546
  fullStack: true,
5591
5547
  type: err.type || "Unhandled Error"
5592
5548
  });
5593
- });
5594
- this.error(c.red(divider()));
5549
+ }), this.error(c.red(divider()));
5595
5550
  }
5596
5551
  printSourceTypeErrors(errors) {
5597
5552
  const errorMessage = c.red(c.bold(`\nVitest found ${errors.length} error${errors.length > 1 ? "s" : ""} not related to your test files.`));
5598
- this.log(errorBanner("Source Errors"));
5599
- this.log(errorMessage);
5600
- errors.forEach((err) => {
5553
+ this.log(errorBanner("Source Errors")), this.log(errorMessage), errors.forEach((err) => {
5601
5554
  this.printError(err, { fullStack: true });
5602
- });
5603
- this.log(c.red(divider()));
5555
+ }), this.log(c.red(divider()));
5604
5556
  }
5605
5557
  getColumns() {
5606
5558
  return "columns" in this.outputStream ? this.outputStream.columns : 80;
@@ -5610,38 +5562,25 @@ This might cause false positive tests. Resolve unhandled errors to make sure you
5610
5562
  }
5611
5563
  addCleanupListeners() {
5612
5564
  const cleanup = () => {
5613
- this.cleanupListeners.forEach((fn) => fn());
5614
- if (this.outputStream.isTTY) this.outputStream.write(SHOW_CURSOR);
5615
- };
5616
- const onExit = (signal, exitCode) => {
5617
- cleanup();
5565
+ if (this.cleanupListeners.forEach((fn) => fn()), this.outputStream.isTTY) this.outputStream.write(SHOW_CURSOR);
5566
+ }, onExit = (signal, exitCode) => {
5618
5567
  // Interrupted signals don't set exit code automatically.
5619
5568
  // Use same exit code as node: https://nodejs.org/api/process.html#signal-events
5620
- if (process.exitCode === void 0) process.exitCode = exitCode !== void 0 ? 128 + exitCode : Number(signal);
5569
+ if (cleanup(), process.exitCode === void 0) process.exitCode = exitCode !== void 0 ? 128 + exitCode : Number(signal);
5621
5570
  process.exit();
5622
5571
  };
5623
- process.once("SIGINT", onExit);
5624
- process.once("SIGTERM", onExit);
5625
- process.once("exit", onExit);
5626
- this.ctx.onClose(() => {
5627
- process.off("SIGINT", onExit);
5628
- process.off("SIGTERM", onExit);
5629
- process.off("exit", onExit);
5630
- cleanup();
5572
+ process.once("SIGINT", onExit), process.once("SIGTERM", onExit), process.once("exit", onExit), this.ctx.onClose(() => {
5573
+ process.off("SIGINT", onExit), process.off("SIGTERM", onExit), process.off("exit", onExit), cleanup();
5631
5574
  });
5632
5575
  }
5633
5576
  registerUnhandledRejection() {
5634
5577
  const onUnhandledRejection = (err) => {
5635
- process.exitCode = 1;
5636
- this.printError(err, {
5578
+ process.exitCode = 1, this.printError(err, {
5637
5579
  fullStack: true,
5638
5580
  type: "Unhandled Rejection"
5639
- });
5640
- this.error("\n\n");
5641
- process.exit();
5581
+ }), this.error("\n\n"), process.exit();
5642
5582
  };
5643
- process.on("unhandledRejection", onUnhandledRejection);
5644
- this.ctx.onClose(() => {
5583
+ process.on("unhandledRejection", onUnhandledRejection), this.ctx.onClose(() => {
5645
5584
  process.off("unhandledRejection", onUnhandledRejection);
5646
5585
  });
5647
5586
  }
@@ -5657,36 +5596,26 @@ class VitestPackageInstaller {
5657
5596
  if (process.versions.pnp) {
5658
5597
  const targetRequire = createRequire(__dirname);
5659
5598
  try {
5660
- targetRequire.resolve(dependency, { paths: [root, __dirname] });
5661
- return true;
5599
+ return targetRequire.resolve(dependency, { paths: [root, __dirname] }), true;
5662
5600
  } catch {}
5663
5601
  }
5664
5602
  if (/* @__PURE__ */ isPackageExists(dependency, { paths: [root, __dirname] })) return true;
5665
- process.stderr.write(c.red(`${c.inverse(c.red(" MISSING DEPENDENCY "))} Cannot find dependency '${dependency}'\n\n`));
5666
- if (!isTTY) return false;
5667
- const prompts = await import('./index.X0nbfr6-.js').then(function (n) { return n.i; });
5668
- const { install } = await prompts.default({
5603
+ if (process.stderr.write(c.red(`${c.inverse(c.red(" MISSING DEPENDENCY "))} Cannot find dependency '${dependency}'\n\n`)), !isTTY) return false;
5604
+ const prompts = await import('./index.X0nbfr6-.js').then(function (n) { return n.i; }), { install } = await prompts.default({
5669
5605
  type: "confirm",
5670
5606
  name: "install",
5671
5607
  message: c.reset(`Do you want to install ${c.green(dependency)}?`)
5672
5608
  });
5673
5609
  if (install) {
5674
5610
  const packageName = version ? `${dependency}@${version}` : dependency;
5675
- await (await import('./index.D3XRDfWc.js')).installPackage(packageName, { dev: true });
5676
- // TODO: somehow it fails to load the package after installation, remove this when it's fixed
5677
- process.stderr.write(c.yellow(`\nPackage ${packageName} installed, re-run the command to start.\n`));
5678
- process.exit();
5679
- return true;
5611
+ return await (await import('./index.D3XRDfWc.js')).installPackage(packageName, { dev: true }), process.stderr.write(c.yellow(`\nPackage ${packageName} installed, re-run the command to start.\n`)), process.exit(), true;
5680
5612
  }
5681
5613
  return false;
5682
5614
  }
5683
5615
  }
5684
5616
 
5685
5617
  function serializeConfig(config, coreConfig, viteConfig) {
5686
- const optimizer = config.deps?.optimizer;
5687
- const poolOptions = config.poolOptions;
5688
- // Resolve from server.config to avoid comparing against default value
5689
- const isolate = viteConfig?.test?.isolate;
5618
+ const optimizer = config.deps?.optimizer || {}, poolOptions = config.poolOptions, isolate = viteConfig?.test?.isolate;
5690
5619
  return {
5691
5620
  environmentOptions: config.environmentOptions,
5692
5621
  mode: config.mode,
@@ -5720,8 +5649,7 @@ function serializeConfig(config, coreConfig, viteConfig) {
5720
5649
  snapshotEnvironment: config.snapshotEnvironment,
5721
5650
  passWithNoTests: config.passWithNoTests,
5722
5651
  coverage: ((coverage) => {
5723
- const htmlReporter = coverage.reporter.find(([reporterName]) => reporterName === "html");
5724
- const subdir = htmlReporter && htmlReporter[1]?.subdir;
5652
+ const htmlReporter = coverage.reporter.find(([reporterName]) => reporterName === "html"), subdir = htmlReporter && htmlReporter[1]?.subdir;
5725
5653
  return {
5726
5654
  reportsDirectory: coverage.reportsDirectory,
5727
5655
  provider: coverage.provider,
@@ -5745,10 +5673,9 @@ function serializeConfig(config, coreConfig, viteConfig) {
5745
5673
  },
5746
5674
  deps: {
5747
5675
  web: config.deps.web || {},
5748
- optimizer: {
5749
- web: { enabled: optimizer?.web?.enabled ?? true },
5750
- ssr: { enabled: optimizer?.ssr?.enabled ?? true }
5751
- },
5676
+ optimizer: Object.entries(optimizer).reduce((acc, [name, option]) => {
5677
+ return acc[name] = { enabled: option?.enabled ?? false }, acc;
5678
+ }, {}),
5752
5679
  interopDefault: config.deps.interopDefault,
5753
5680
  moduleDirectories: config.deps.moduleDirectories
5754
5681
  },
@@ -5798,7 +5725,7 @@ async function loadGlobalSetupFiles(runner, globalSetup) {
5798
5725
  return Promise.all(globalSetupFiles.map((file) => loadGlobalSetupFile(file, runner)));
5799
5726
  }
5800
5727
  async function loadGlobalSetupFile(file, runner) {
5801
- const m = await runner.executeFile(file);
5728
+ const m = await runner.import(file);
5802
5729
  for (const exp of [
5803
5730
  "default",
5804
5731
  "setup",
@@ -5808,211 +5735,23 @@ async function loadGlobalSetupFile(file, runner) {
5808
5735
  file,
5809
5736
  setup: m.default
5810
5737
  };
5811
- else if (m.setup || m.teardown) return {
5738
+ if (m.setup || m.teardown) return {
5812
5739
  file,
5813
5740
  setup: m.setup,
5814
5741
  teardown: m.teardown
5815
5742
  };
5816
- else throw new Error(`invalid globalSetup file ${file}. Must export setup, teardown or have a default export`);
5743
+ throw new Error(`invalid globalSetup file ${file}. Must export setup, teardown or have a default export`);
5817
5744
  }
5818
5745
 
5819
5746
  function CoverageTransform(ctx) {
5820
5747
  return {
5821
5748
  name: "vitest:coverage-transform",
5822
5749
  transform(srcCode, id) {
5823
- return ctx.coverageProvider?.onFileTransform?.(srcCode, normalizeRequestId(id), this);
5824
- }
5825
- };
5826
- }
5827
-
5828
- function MocksPlugins(options = {}) {
5829
- const normalizedDistDir = normalize(distDir);
5830
- return [hoistMocksPlugin({
5831
- filter(id) {
5832
- if (id.includes(normalizedDistDir)) return false;
5833
- if (options.filter) return options.filter(id);
5834
- return true;
5835
- },
5836
- codeFrameGenerator(node, id, code) {
5837
- return generateCodeFrame(code, 4, node.start + 1);
5838
- }
5839
- }), automockPlugin()];
5840
- }
5841
-
5842
- function generateCssFilenameHash(filepath) {
5843
- return hash("sha1", filepath, "hex").slice(0, 6);
5844
- }
5845
- function generateScopedClassName(strategy, name, filename) {
5846
- // should be configured by Vite defaults
5847
- if (strategy === "scoped") return null;
5848
- if (strategy === "non-scoped") return name;
5849
- const hash = generateCssFilenameHash(filename);
5850
- return `_${name}_${hash}`;
5851
- }
5852
-
5853
- const LogLevels = {
5854
- silent: 0,
5855
- error: 1,
5856
- warn: 2,
5857
- info: 3
5858
- };
5859
- function clearScreen(logger) {
5860
- const repeatCount = process.stdout.rows - 2;
5861
- const blank = repeatCount > 0 ? "\n".repeat(repeatCount) : "";
5862
- logger.clearScreen(blank);
5863
- }
5864
- let lastType;
5865
- let lastMsg;
5866
- let sameCount = 0;
5867
- // Only initialize the timeFormatter when the timestamp option is used, and
5868
- // reuse it across all loggers
5869
- let timeFormatter;
5870
- function getTimeFormatter() {
5871
- timeFormatter ??= new Intl.DateTimeFormat(void 0, {
5872
- hour: "numeric",
5873
- minute: "numeric",
5874
- second: "numeric"
5875
- });
5876
- return timeFormatter;
5877
- }
5878
- // This is copy-pasted and needs to be synced from time to time. Ideally, Vite's `createLogger` should accept a custom `console`
5879
- // https://github.com/vitejs/vite/blob/main/packages/vite/src/node/logger.ts?rgh-link-date=2024-10-16T23%3A29%3A19Z
5880
- // When Vitest supports only Vite 6 and above, we can use Vite's `createLogger({ console })`
5881
- // https://github.com/vitejs/vite/pull/18379
5882
- function createViteLogger(console, level = "info", options = {}) {
5883
- const loggedErrors = /* @__PURE__ */ new WeakSet();
5884
- const { prefix = "[vite]", allowClearScreen = true } = options;
5885
- const thresh = LogLevels[level];
5886
- const canClearScreen = allowClearScreen && process.stdout.isTTY && !process.env.CI;
5887
- const clear = canClearScreen ? clearScreen : () => {};
5888
- function format(type, msg, options = {}) {
5889
- if (options.timestamp) {
5890
- let tag = "";
5891
- if (type === "info") tag = c.cyan(c.bold(prefix));
5892
- else if (type === "warn") tag = c.yellow(c.bold(prefix));
5893
- else tag = c.red(c.bold(prefix));
5894
- const environment = options.environment ? `${options.environment} ` : "";
5895
- return `${c.dim(getTimeFormatter().format(/* @__PURE__ */ new Date()))} ${tag} ${environment}${msg}`;
5896
- } else return msg;
5897
- }
5898
- function output(type, msg, options = {}) {
5899
- if (thresh >= LogLevels[type]) {
5900
- const method = type === "info" ? "log" : type;
5901
- if (options.error) loggedErrors.add(options.error);
5902
- if (canClearScreen) if (type === lastType && msg === lastMsg) {
5903
- sameCount++;
5904
- clear(console);
5905
- console[method](format(type, msg, options), c.yellow(`(x${sameCount + 1})`));
5906
- } else {
5907
- sameCount = 0;
5908
- lastMsg = msg;
5909
- lastType = type;
5910
- if (options.clear) clear(console);
5911
- console[method](format(type, msg, options));
5912
- }
5913
- else console[method](format(type, msg, options));
5914
- }
5915
- }
5916
- const warnedMessages = /* @__PURE__ */ new Set();
5917
- const logger = {
5918
- hasWarned: false,
5919
- info(msg, opts) {
5920
- output("info", msg, opts);
5921
- },
5922
- warn(msg, opts) {
5923
- logger.hasWarned = true;
5924
- output("warn", msg, opts);
5925
- },
5926
- warnOnce(msg, opts) {
5927
- if (warnedMessages.has(msg)) return;
5928
- logger.hasWarned = true;
5929
- output("warn", msg, opts);
5930
- warnedMessages.add(msg);
5931
- },
5932
- error(msg, opts) {
5933
- logger.hasWarned = true;
5934
- output("error", msg, opts);
5935
- },
5936
- clearScreen(type) {
5937
- if (thresh >= LogLevels[type]) clear(console);
5938
- },
5939
- hasErrorLogged(error) {
5940
- return loggedErrors.has(error);
5941
- }
5942
- };
5943
- return logger;
5944
- }
5945
- // silence warning by Vite for statically not analyzable dynamic import
5946
- function silenceImportViteIgnoreWarning(logger) {
5947
- return {
5948
- ...logger,
5949
- warn(msg, options) {
5950
- if (msg.includes("The above dynamic import cannot be analyzed by Vite")) return;
5951
- logger.warn(msg, options);
5750
+ return ctx.coverageProvider?.onFileTransform?.(srcCode, id, this);
5952
5751
  }
5953
5752
  };
5954
5753
  }
5955
5754
 
5956
- const cssLangs = "\\.(?:css|less|sass|scss|styl|stylus|pcss|postcss)(?:$|\\?)";
5957
- const cssLangRE = new RegExp(cssLangs);
5958
- const cssModuleRE = /* @__PURE__ */ new RegExp(`\\.module${cssLangs}`);
5959
- const cssInlineRE = /[?&]inline(?:&|$)/;
5960
- function isCSS(id) {
5961
- return cssLangRE.test(id);
5962
- }
5963
- function isCSSModule(id) {
5964
- return cssModuleRE.test(id);
5965
- }
5966
- // inline css requests are expected to just return the
5967
- // string content directly and not the proxy module
5968
- function isInline(id) {
5969
- return cssInlineRE.test(id);
5970
- }
5971
- function getCSSModuleProxyReturn(strategy, filename) {
5972
- if (strategy === "non-scoped") return "style";
5973
- const hash = generateCssFilenameHash(filename);
5974
- return `\`_\${style}_${hash}\``;
5975
- }
5976
- function CSSEnablerPlugin(ctx) {
5977
- const shouldProcessCSS = (id) => {
5978
- const { css } = ctx.config;
5979
- if (typeof css === "boolean") return css;
5980
- if (toArray(css.exclude).some((re) => re.test(id))) return false;
5981
- if (toArray(css.include).some((re) => re.test(id))) return true;
5982
- return false;
5983
- };
5984
- return [{
5985
- name: "vitest:css-disable",
5986
- enforce: "pre",
5987
- transform(code, id) {
5988
- if (!isCSS(id)) return;
5989
- // css plugin inside Vite won't do anything if the code is empty
5990
- // but it will put __vite__updateStyle anyway
5991
- if (!shouldProcessCSS(id)) return { code: "" };
5992
- }
5993
- }, {
5994
- name: "vitest:css-empty-post",
5995
- enforce: "post",
5996
- transform(_, id) {
5997
- if (!isCSS(id) || shouldProcessCSS(id)) return;
5998
- if (isCSSModule(id) && !isInline(id)) {
5999
- // return proxy for css modules, so that imported module has names:
6000
- // styles.foo returns a "foo" instead of "undefined"
6001
- // we don't use code content to generate hash for "scoped", because it's empty
6002
- const scopeStrategy = typeof ctx.config.css !== "boolean" && ctx.config.css.modules?.classNameStrategy || "stable";
6003
- const proxyReturn = getCSSModuleProxyReturn(scopeStrategy, relative(ctx.config.root, id));
6004
- const code = `export default new Proxy(Object.create(null), {
6005
- get(_, style) {
6006
- return ${proxyReturn};
6007
- },
6008
- })`;
6009
- return { code };
6010
- }
6011
- return { code: "export default \"\"" };
6012
- }
6013
- }];
6014
- }
6015
-
6016
5755
  var jsTokens_1;
6017
5756
  var hasRequiredJsTokens;
6018
5757
 
@@ -6497,136 +6236,208 @@ function stripLiteralDetailed(code, options) {
6497
6236
  return stripLiteralJsTokens(code);
6498
6237
  }
6499
6238
 
6500
- const metaUrlLength = 15;
6501
- const locationString = "self.location".padEnd(metaUrlLength, " ");
6502
- // Vite transforms new URL('./path', import.meta.url) to new URL('/path.js', import.meta.url)
6503
- // This makes "href" equal to "http://localhost:3000/path.js" in the browser, but if we keep it like this,
6504
- // then in tests the URL will become "file:///path.js".
6505
- // To battle this, we replace "import.meta.url" with "self.location" in the code to keep the browser behavior.
6506
- function NormalizeURLPlugin() {
6239
+ // so people can reassign envs at runtime
6240
+ // import.meta.env.VITE_NAME = 'app' -> process.env.VITE_NAME = 'app'
6241
+ function MetaEnvReplacerPlugin() {
6507
6242
  return {
6508
- name: "vitest:normalize-url",
6509
- enforce: "post",
6510
- transform(code, id, options) {
6511
- const ssr = options?.ssr === true;
6512
- if (ssr || !code.includes("new URL") || !code.includes("import.meta.url")) return;
6513
- const cleanString = stripLiteral(code);
6514
- const assetImportMetaUrlRE = /\bnew\s+URL\s*\(\s*(?:'[^']+'|"[^"]+"|`[^`]+`)\s*,\s*(?:'' \+ )?import\.meta\.url\s*(?:,\s*)?\)/g;
6515
- let updatedCode = code;
6516
- let match;
6517
- // eslint-disable-next-line no-cond-assign
6518
- while (match = assetImportMetaUrlRE.exec(cleanString)) {
6519
- const { 0: exp, index } = match;
6520
- const metaUrlIndex = index + exp.indexOf("import.meta.url");
6521
- updatedCode = updatedCode.slice(0, metaUrlIndex) + locationString + updatedCode.slice(metaUrlIndex + metaUrlLength);
6243
+ name: "vitest:meta-env-replacer",
6244
+ enforce: "pre",
6245
+ transform(code, id) {
6246
+ if (!/\bimport\.meta\.env\b/.test(code)) return null;
6247
+ let s = null;
6248
+ const cleanCode = stripLiteral(code), envs = cleanCode.matchAll(/\bimport\.meta\.env\b/g);
6249
+ for (const env of envs) {
6250
+ s ||= new MagicString(code);
6251
+ const startIndex = env.index, endIndex = startIndex + env[0].length;
6252
+ s.overwrite(startIndex, endIndex, `Object.assign(/* istanbul ignore next */ globalThis.__vitest_worker__?.metaEnv ?? import.meta.env)`);
6522
6253
  }
6523
- return {
6524
- code: updatedCode,
6525
- map: null
6254
+ if (s) return {
6255
+ code: s.toString(),
6256
+ map: s.generateMap({
6257
+ hires: "boundary",
6258
+ source: cleanUrl(id)
6259
+ })
6526
6260
  };
6527
6261
  }
6528
6262
  };
6529
6263
  }
6530
6264
 
6531
- function resolveOptimizerConfig(_testOptions, viteOptions) {
6532
- const testOptions = _testOptions || {};
6533
- const newConfig = {};
6534
- const [major, minor, fix] = version.split(".").map(Number);
6535
- const allowed = major >= 5 || major === 4 && minor >= 4 || major === 4 && minor === 3 && fix >= 2;
6536
- if (!allowed && testOptions?.enabled === true) console.warn(`Vitest: "deps.optimizer" is only available in Vite >= 4.3.2, current Vite version: ${version}`);
6537
- else testOptions.enabled ??= false;
6538
- if (!allowed || testOptions?.enabled !== true) {
6539
- newConfig.cacheDir = void 0;
6540
- newConfig.optimizeDeps = {
6541
- disabled: true,
6542
- entries: []
6543
- };
6544
- } else {
6545
- const currentInclude = testOptions.include || viteOptions?.include || [];
6546
- const exclude = [
6547
- "vitest",
6548
- "react",
6549
- "vue",
6550
- ...testOptions.exclude || viteOptions?.exclude || []
6551
- ];
6552
- const runtime = currentInclude.filter((n) => n.endsWith("jsx-dev-runtime") || n.endsWith("jsx-runtime"));
6553
- exclude.push(...runtime);
6554
- const include = (testOptions.include || viteOptions?.include || []).filter((n) => !exclude.includes(n));
6555
- newConfig.optimizeDeps = {
6556
- ...viteOptions,
6557
- ...testOptions,
6558
- noDiscovery: true,
6559
- disabled: false,
6560
- entries: [],
6561
- exclude,
6562
- include
6563
- };
6564
- }
6565
- // `optimizeDeps.disabled` is deprecated since v5.1.0-beta.1
6566
- // https://github.com/vitejs/vite/pull/15184
6567
- if (major >= 5 && minor >= 1 || major >= 6) {
6568
- if (newConfig.optimizeDeps.disabled) {
6569
- newConfig.optimizeDeps.noDiscovery = true;
6570
- newConfig.optimizeDeps.include = [];
6571
- }
6572
- delete newConfig.optimizeDeps.disabled;
6573
- }
6574
- return newConfig;
6575
- }
6576
- function deleteDefineConfig(viteConfig) {
6577
- const defines = {};
6578
- if (viteConfig.define) {
6579
- delete viteConfig.define["import.meta.vitest"];
6580
- delete viteConfig.define["process.env"];
6581
- delete viteConfig.define.process;
6582
- delete viteConfig.define.global;
6583
- }
6584
- for (const key in viteConfig.define) {
6585
- const val = viteConfig.define[key];
6586
- let replacement;
6587
- try {
6588
- replacement = typeof val === "string" ? JSON.parse(val) : val;
6589
- } catch {
6590
- // probably means it contains reference to some variable,
6591
- // like this: "__VAR__": "process.env.VAR"
6592
- continue;
6593
- }
6594
- if (key.startsWith("import.meta.env.")) {
6595
- const envKey = key.slice(16);
6596
- process.env[envKey] = replacement;
6597
- delete viteConfig.define[key];
6598
- } else if (key.startsWith("process.env.")) {
6599
- const envKey = key.slice(12);
6600
- process.env[envKey] = replacement;
6601
- delete viteConfig.define[key];
6602
- } else if (!key.includes(".")) {
6603
- defines[key] = replacement;
6604
- delete viteConfig.define[key];
6265
+ function MocksPlugins(options = {}) {
6266
+ const normalizedDistDir = normalize(distDir);
6267
+ return [hoistMocksPlugin({
6268
+ filter(id) {
6269
+ return id.includes(normalizedDistDir) ? false : options.filter ? options.filter(id) : true;
6270
+ },
6271
+ codeFrameGenerator(node, id, code) {
6272
+ return generateCodeFrame(code, 4, node.start + 1);
6605
6273
  }
6606
- }
6607
- return defines;
6274
+ }), automockPlugin()];
6608
6275
  }
6609
- function resolveFsAllow(projectRoot, rootConfigFile) {
6610
- if (!rootConfigFile) return [searchForWorkspaceRoot(projectRoot), rootDir];
6611
- return [
6612
- dirname(rootConfigFile),
6613
- searchForWorkspaceRoot(projectRoot),
6614
- rootDir
6615
- ];
6276
+
6277
+ function generateCssFilenameHash(filepath) {
6278
+ return hash("sha1", filepath, "hex").slice(0, 6);
6616
6279
  }
6617
- function getDefaultResolveOptions() {
6618
- return {
6619
- mainFields: [],
6620
- conditions: getDefaultServerConditions()
6621
- };
6280
+ function generateScopedClassName(strategy, name, filename) {
6281
+ // should be configured by Vite defaults
6282
+ if (strategy === "scoped") return null;
6283
+ if (strategy === "non-scoped") return name;
6284
+ const hash = generateCssFilenameHash(filename);
6285
+ return `_${name}_${hash}`;
6622
6286
  }
6623
- function getDefaultServerConditions() {
6624
- const viteMajor = Number(version.split(".")[0]);
6625
- if (viteMajor >= 6) {
6626
- const conditions = vite.defaultServerConditions;
6627
- return conditions.filter((c) => c !== "module");
6287
+
6288
+ const LogLevels = {
6289
+ silent: 0,
6290
+ error: 1,
6291
+ warn: 2,
6292
+ info: 3
6293
+ };
6294
+ function clearScreen(logger) {
6295
+ const repeatCount = process.stdout.rows - 2, blank = repeatCount > 0 ? "\n".repeat(repeatCount) : "";
6296
+ logger.clearScreen(blank);
6297
+ }
6298
+ let lastType, lastMsg, sameCount = 0, timeFormatter;
6299
+ function getTimeFormatter() {
6300
+ return timeFormatter ??= new Intl.DateTimeFormat(void 0, {
6301
+ hour: "numeric",
6302
+ minute: "numeric",
6303
+ second: "numeric"
6304
+ }), timeFormatter;
6305
+ }
6306
+ // This is copy-pasted and needs to be synced from time to time. Ideally, Vite's `createLogger` should accept a custom `console`
6307
+ // https://github.com/vitejs/vite/blob/main/packages/vite/src/node/logger.ts?rgh-link-date=2024-10-16T23%3A29%3A19Z
6308
+ // When Vitest supports only Vite 6 and above, we can use Vite's `createLogger({ console })`
6309
+ // https://github.com/vitejs/vite/pull/18379
6310
+ function createViteLogger(console, level = "info", options = {}) {
6311
+ const loggedErrors = /* @__PURE__ */ new WeakSet(), { prefix = "[vite]", allowClearScreen = true } = options, thresh = LogLevels[level], canClearScreen = allowClearScreen && process.stdout.isTTY && !process.env.CI, clear = canClearScreen ? clearScreen : () => {};
6312
+ function format(type, msg, options = {}) {
6313
+ if (options.timestamp) {
6314
+ let tag = "";
6315
+ if (type === "info") tag = c.cyan(c.bold(prefix));
6316
+ else if (type === "warn") tag = c.yellow(c.bold(prefix));
6317
+ else tag = c.red(c.bold(prefix));
6318
+ const environment = options.environment ? `${options.environment} ` : "";
6319
+ return `${c.dim(getTimeFormatter().format(/* @__PURE__ */ new Date()))} ${tag} ${environment}${msg}`;
6320
+ } else return msg;
6628
6321
  }
6629
- return ["node"];
6322
+ function output(type, msg, options = {}) {
6323
+ if (thresh >= LogLevels[type]) {
6324
+ const method = type === "info" ? "log" : type;
6325
+ if (options.error) loggedErrors.add(options.error);
6326
+ if (canClearScreen) if (type === lastType && msg === lastMsg) sameCount++, clear(console), console[method](format(type, msg, options), c.yellow(`(x${sameCount + 1})`));
6327
+ else {
6328
+ if (sameCount = 0, lastMsg = msg, lastType = type, options.clear) clear(console);
6329
+ console[method](format(type, msg, options));
6330
+ }
6331
+ else console[method](format(type, msg, options));
6332
+ }
6333
+ }
6334
+ const warnedMessages = /* @__PURE__ */ new Set(), logger = {
6335
+ hasWarned: false,
6336
+ info(msg, opts) {
6337
+ output("info", msg, opts);
6338
+ },
6339
+ warn(msg, opts) {
6340
+ logger.hasWarned = true, output("warn", msg, opts);
6341
+ },
6342
+ warnOnce(msg, opts) {
6343
+ warnedMessages.has(msg) || (logger.hasWarned = true, output("warn", msg, opts), warnedMessages.add(msg));
6344
+ },
6345
+ error(msg, opts) {
6346
+ logger.hasWarned = true, output("error", msg, opts);
6347
+ },
6348
+ clearScreen(type) {
6349
+ if (thresh >= LogLevels[type]) clear(console);
6350
+ },
6351
+ hasErrorLogged(error) {
6352
+ return loggedErrors.has(error);
6353
+ }
6354
+ };
6355
+ return logger;
6356
+ }
6357
+ // silence warning by Vite for statically not analyzable dynamic import
6358
+ function silenceImportViteIgnoreWarning(logger) {
6359
+ return {
6360
+ ...logger,
6361
+ warn(msg, options) {
6362
+ msg.includes("The above dynamic import cannot be analyzed by Vite") || logger.warn(msg, options);
6363
+ }
6364
+ };
6365
+ }
6366
+
6367
+ const cssLangs = "\\.(?:css|less|sass|scss|styl|stylus|pcss|postcss)(?:$|\\?)", cssLangRE = new RegExp(cssLangs), cssModuleRE = /* @__PURE__ */ new RegExp(`\\.module${cssLangs}`), cssInlineRE = /[?&]inline(?:&|$)/;
6368
+ function isCSS(id) {
6369
+ return cssLangRE.test(id);
6370
+ }
6371
+ function isCSSModule(id) {
6372
+ return cssModuleRE.test(id);
6373
+ }
6374
+ // inline css requests are expected to just return the
6375
+ // string content directly and not the proxy module
6376
+ function isInline(id) {
6377
+ return cssInlineRE.test(id);
6378
+ }
6379
+ function getCSSModuleProxyReturn(strategy, filename) {
6380
+ if (strategy === "non-scoped") return "style";
6381
+ const hash = generateCssFilenameHash(filename);
6382
+ return `\`_\${style}_${hash}\``;
6383
+ }
6384
+ function CSSEnablerPlugin(ctx) {
6385
+ const shouldProcessCSS = (id) => {
6386
+ const { css } = ctx.config;
6387
+ return typeof css === "boolean" ? css : toArray(css.exclude).some((re) => re.test(id)) ? false : !!toArray(css.include).some((re) => re.test(id));
6388
+ };
6389
+ return [{
6390
+ name: "vitest:css-disable",
6391
+ enforce: "pre",
6392
+ transform(code, id) {
6393
+ if (isCSS(id) && !shouldProcessCSS(id)) return { code: "" };
6394
+ }
6395
+ }, {
6396
+ name: "vitest:css-empty-post",
6397
+ enforce: "post",
6398
+ transform(_, id) {
6399
+ if (!(!isCSS(id) || shouldProcessCSS(id))) {
6400
+ if (isCSSModule(id) && !isInline(id)) {
6401
+ // return proxy for css modules, so that imported module has names:
6402
+ // styles.foo returns a "foo" instead of "undefined"
6403
+ // we don't use code content to generate hash for "scoped", because it's empty
6404
+ const scopeStrategy = typeof ctx.config.css !== "boolean" && ctx.config.css.modules?.classNameStrategy || "stable", proxyReturn = getCSSModuleProxyReturn(scopeStrategy, relative(ctx.config.root, id)), code = `export default new Proxy(Object.create(null), {
6405
+ get(_, style) {
6406
+ return ${proxyReturn};
6407
+ },
6408
+ })`;
6409
+ return { code };
6410
+ }
6411
+ return { code: "export default \"\"" };
6412
+ }
6413
+ }
6414
+ }];
6415
+ }
6416
+
6417
+ const metaUrlLength = 15, locationString = "self.location".padEnd(metaUrlLength, " ");
6418
+ // Vite transforms new URL('./path', import.meta.url) to new URL('/path.js', import.meta.url)
6419
+ // This makes "href" equal to "http://localhost:3000/path.js" in the browser, but if we keep it like this,
6420
+ // then in tests the URL will become "file:///path.js".
6421
+ // To battle this, we replace "import.meta.url" with "self.location" in the code to keep the browser behavior.
6422
+ function NormalizeURLPlugin() {
6423
+ return {
6424
+ name: "vitest:normalize-url",
6425
+ enforce: "post",
6426
+ transform(code) {
6427
+ if (this.environment.name !== "client" || !code.includes("new URL") || !code.includes("import.meta.url")) return;
6428
+ const cleanString = stripLiteral(code), assetImportMetaUrlRE = /\bnew\s+URL\s*\(\s*(?:'[^']+'|"[^"]+"|`[^`]+`)\s*,\s*(?:'' \+ )?import\.meta\.url\s*(?:,\s*)?\)/g;
6429
+ let updatedCode = code, match;
6430
+ // eslint-disable-next-line no-cond-assign
6431
+ while (match = assetImportMetaUrlRE.exec(cleanString)) {
6432
+ const { 0: exp, index } = match, metaUrlIndex = index + exp.indexOf("import.meta.url");
6433
+ updatedCode = updatedCode.slice(0, metaUrlIndex) + locationString + updatedCode.slice(metaUrlIndex + metaUrlLength);
6434
+ }
6435
+ return {
6436
+ code: updatedCode,
6437
+ map: null
6438
+ };
6439
+ }
6440
+ };
6630
6441
  }
6631
6442
 
6632
6443
  function VitestOptimizer() {
@@ -6635,48 +6446,138 @@ function VitestOptimizer() {
6635
6446
  config: {
6636
6447
  order: "post",
6637
6448
  handler(viteConfig) {
6638
- const testConfig = viteConfig.test || {};
6639
- const webOptimizer = resolveOptimizerConfig(testConfig.deps?.optimizer?.web, viteConfig.optimizeDeps);
6640
- const ssrOptimizer = resolveOptimizerConfig(testConfig.deps?.optimizer?.ssr, viteConfig.ssr?.optimizeDeps);
6641
- const root = resolve(viteConfig.root || process.cwd());
6642
- const name = viteConfig.test?.name;
6643
- const label = typeof name === "string" ? name : name?.label || "";
6449
+ const testConfig = viteConfig.test || {}, root = resolve(viteConfig.root || process.cwd()), name = viteConfig.test?.name, label = typeof name === "string" ? name : name?.label || "";
6644
6450
  viteConfig.cacheDir = VitestCache.resolveCacheDir(resolve(root || process.cwd()), testConfig.cache != null && testConfig.cache !== false ? testConfig.cache.dir : viteConfig.cacheDir, label);
6645
- viteConfig.optimizeDeps = webOptimizer.optimizeDeps;
6646
- viteConfig.ssr ??= {};
6647
- viteConfig.ssr.optimizeDeps = ssrOptimizer.optimizeDeps;
6648
6451
  }
6649
6452
  }
6650
6453
  };
6651
6454
  }
6652
6455
 
6653
- // so people can reassign envs at runtime
6654
- // import.meta.env.VITE_NAME = 'app' -> process.env.VITE_NAME = 'app'
6655
- function SsrReplacerPlugin() {
6456
+ function resolveOptimizerConfig(_testOptions, viteOptions) {
6457
+ const testOptions = _testOptions || {};
6458
+ let optimizeDeps;
6459
+ if (testOptions.enabled !== true) testOptions.enabled ??= false, optimizeDeps = {
6460
+ disabled: true,
6461
+ entries: []
6462
+ };
6463
+ else {
6464
+ const currentInclude = testOptions.include || viteOptions?.include || [], exclude = [
6465
+ "vitest",
6466
+ "react",
6467
+ "vue",
6468
+ ...testOptions.exclude || viteOptions?.exclude || []
6469
+ ], runtime = currentInclude.filter((n) => n.endsWith("jsx-dev-runtime") || n.endsWith("jsx-runtime"));
6470
+ exclude.push(...runtime);
6471
+ const include = (testOptions.include || viteOptions?.include || []).filter((n) => !exclude.includes(n));
6472
+ optimizeDeps = {
6473
+ ...viteOptions,
6474
+ ...testOptions,
6475
+ noDiscovery: true,
6476
+ disabled: false,
6477
+ entries: [],
6478
+ exclude,
6479
+ include
6480
+ };
6481
+ }
6482
+ // `optimizeDeps.disabled` is deprecated since v5.1.0-beta.1
6483
+ // https://github.com/vitejs/vite/pull/15184
6484
+ if (optimizeDeps.disabled) optimizeDeps.noDiscovery = true, optimizeDeps.include = [];
6485
+ return delete optimizeDeps.disabled, optimizeDeps;
6486
+ }
6487
+ function deleteDefineConfig(viteConfig) {
6488
+ const defines = {};
6489
+ if (viteConfig.define) delete viteConfig.define["import.meta.vitest"], delete viteConfig.define["process.env"], delete viteConfig.define.process, delete viteConfig.define.global;
6490
+ for (const key in viteConfig.define) {
6491
+ const val = viteConfig.define[key];
6492
+ let replacement;
6493
+ try {
6494
+ replacement = typeof val === "string" ? JSON.parse(val) : val;
6495
+ } catch {
6496
+ // probably means it contains reference to some variable,
6497
+ // like this: "__VAR__": "process.env.VAR"
6498
+ continue;
6499
+ }
6500
+ if (key.startsWith("import.meta.env.")) {
6501
+ const envKey = key.slice(16);
6502
+ process.env[envKey] = replacement, delete viteConfig.define[key];
6503
+ } else if (key.startsWith("process.env.")) {
6504
+ const envKey = key.slice(12);
6505
+ process.env[envKey] = replacement, delete viteConfig.define[key];
6506
+ } else if (!key.includes(".")) defines[key] = replacement, delete viteConfig.define[key];
6507
+ }
6508
+ return defines;
6509
+ }
6510
+ function resolveFsAllow(projectRoot, rootConfigFile) {
6511
+ return rootConfigFile ? [
6512
+ dirname(rootConfigFile),
6513
+ searchForWorkspaceRoot(projectRoot),
6514
+ rootDir
6515
+ ] : [searchForWorkspaceRoot(projectRoot), rootDir];
6516
+ }
6517
+ function getDefaultResolveOptions() {
6656
6518
  return {
6657
- name: "vitest:ssr-replacer",
6658
- enforce: "pre",
6659
- transform(code, id) {
6660
- if (!/\bimport\.meta\.env\b/.test(code)) return null;
6661
- let s = null;
6662
- const cleanCode = stripLiteral(code);
6663
- const envs = cleanCode.matchAll(/\bimport\.meta\.env\b/g);
6664
- for (const env of envs) {
6665
- s ||= new MagicString(code);
6666
- const startIndex = env.index;
6667
- const endIndex = startIndex + env[0].length;
6668
- s.overwrite(startIndex, endIndex, "__vite_ssr_import_meta__.env");
6519
+ mainFields: [],
6520
+ conditions: getDefaultServerConditions()
6521
+ };
6522
+ }
6523
+ function getDefaultServerConditions() {
6524
+ const viteMajor = Number(version.split(".")[0]);
6525
+ if (viteMajor >= 6) {
6526
+ const conditions = vite.defaultServerConditions;
6527
+ return conditions.filter((c) => c !== "module");
6528
+ }
6529
+ return ["node"];
6530
+ }
6531
+
6532
+ function ModuleRunnerTransform() {
6533
+ // make sure Vite always applies the module runner transform
6534
+ return {
6535
+ name: "vitest:environments-module-runner",
6536
+ config: {
6537
+ order: "post",
6538
+ handler(config) {
6539
+ const testConfig = config.test || {};
6540
+ config.environments ??= {};
6541
+ const names = new Set(Object.keys(config.environments));
6542
+ names.add("client"), names.add("ssr");
6543
+ const pool = config.test?.pool;
6544
+ if (pool === "vmForks" || pool === "vmThreads") names.add("__vitest_vm__");
6545
+ const external = [], noExternal = [];
6546
+ let noExternalAll;
6547
+ for (const name of names) {
6548
+ config.environments[name] ??= {};
6549
+ const environment = config.environments[name];
6550
+ // vm tests run using the native import mechanism
6551
+ if (environment.dev ??= {}, name === "__vitest_vm__") environment.dev.moduleRunnerTransform = false, environment.consumer = "client";
6552
+ else environment.dev.moduleRunnerTransform = true;
6553
+ environment.dev.preTransformRequests = false, environment.keepProcessEnv = true;
6554
+ const resolveExternal = name === "client" ? config.resolve?.external : [], resolveNoExternal = name === "client" ? config.resolve?.noExternal : [], topLevelResolveOptions = {};
6555
+ if (resolveExternal != null) topLevelResolveOptions.external = resolveExternal;
6556
+ if (resolveNoExternal != null) topLevelResolveOptions.noExternal = resolveNoExternal;
6557
+ const currentResolveOptions = mergeConfig(topLevelResolveOptions, environment.resolve || {}), envNoExternal = resolveViteResolveOptions("noExternal", currentResolveOptions);
6558
+ if (envNoExternal === true) noExternalAll = true;
6559
+ else noExternal.push(...envNoExternal);
6560
+ const envExternal = resolveViteResolveOptions("external", currentResolveOptions);
6561
+ if (envExternal !== true) external.push(...envExternal);
6562
+ if (environment.resolve ??= {}, environment.resolve.external = [...builtinModules, ...builtinModules.map((m) => `node:${m}`)], environment.resolve.noExternal = true, name === "__vitest_vm__" || name === "__vitest__") continue;
6563
+ const currentOptimizeDeps = environment.optimizeDeps || (name === "client" ? config.optimizeDeps : name === "ssr" ? config.ssr?.optimizeDeps : void 0), optimizeDeps = resolveOptimizerConfig(testConfig.deps?.optimizer?.[name], currentOptimizeDeps);
6564
+ // Vite respects the root level optimize deps, so we override it instead
6565
+ if (name === "client") config.optimizeDeps = optimizeDeps, environment.optimizeDeps = void 0;
6566
+ else if (name === "ssr") config.ssr ??= {}, config.ssr.optimizeDeps = optimizeDeps, environment.optimizeDeps = void 0;
6567
+ else environment.optimizeDeps = optimizeDeps;
6568
+ }
6569
+ if (testConfig.server ??= {}, testConfig.server.deps ??= {}, testConfig.server.deps.inline !== true) {
6570
+ if (noExternalAll) testConfig.server.deps.inline = true;
6571
+ else if (noExternal.length) testConfig.server.deps.inline ??= [], testConfig.server.deps.inline.push(...noExternal);
6572
+ }
6573
+ if (external.length) testConfig.server.deps.external ??= [], testConfig.server.deps.external.push(...external);
6669
6574
  }
6670
- if (s) return {
6671
- code: s.toString(),
6672
- map: s.generateMap({
6673
- hires: "boundary",
6674
- source: cleanUrl(id)
6675
- })
6676
- };
6677
6575
  }
6678
6576
  };
6679
6577
  }
6578
+ function resolveViteResolveOptions(key, options) {
6579
+ return Array.isArray(options[key]) ? options[key] : typeof options[key] === "string" || options[key] instanceof RegExp ? [options[key]] : typeof options[key] === "boolean" ? true : [];
6580
+ }
6680
6581
 
6681
6582
  function VitestProjectResolver(ctx) {
6682
6583
  const plugin = {
@@ -6722,23 +6623,16 @@ function WorkspaceVitestPlugin(project, options) {
6722
6623
  };
6723
6624
  if (!name) if (typeof options.workspacePath === "string") {
6724
6625
  // if there is a package.json, read the name from it
6725
- const dir = options.workspacePath.endsWith("/") ? options.workspacePath.slice(0, -1) : dirname(options.workspacePath);
6726
- const pkgJsonPath = resolve(dir, "package.json");
6626
+ const dir = options.workspacePath.endsWith("/") ? options.workspacePath.slice(0, -1) : dirname(options.workspacePath), pkgJsonPath = resolve(dir, "package.json");
6727
6627
  if (existsSync(pkgJsonPath)) name = JSON.parse(readFileSync(pkgJsonPath, "utf-8")).name;
6728
6628
  if (typeof name !== "string" || !name) name = basename(dir);
6729
6629
  } else name = options.workspacePath.toString();
6730
- const isUserBrowserEnabled = viteConfig.test?.browser?.enabled;
6731
- const isBrowserEnabled = isUserBrowserEnabled ?? (viteConfig.test?.browser && project.vitest._cliOptions.browser?.enabled);
6732
- // keep project names to potentially filter it out
6733
- const workspaceNames = [name];
6734
- const browser = viteConfig.test.browser || {};
6630
+ const isUserBrowserEnabled = viteConfig.test?.browser?.enabled, isBrowserEnabled = isUserBrowserEnabled ?? (viteConfig.test?.browser && project.vitest._cliOptions.browser?.enabled), workspaceNames = [name], browser = viteConfig.test.browser || {};
6735
6631
  if (isBrowserEnabled && browser.name && !browser.instances?.length)
6736
6632
  // vitest injects `instances` in this case later on
6737
6633
  workspaceNames.push(name ? `${name} (${browser.name})` : browser.name);
6738
6634
  viteConfig.test?.browser?.instances?.forEach((instance) => {
6739
- // every instance is a potential project
6740
- instance.name ??= name ? `${name} (${instance.browser})` : instance.browser;
6741
- if (isBrowserEnabled) workspaceNames.push(instance.name);
6635
+ if (instance.name ??= name ? `${name} (${instance.browser})` : instance.browser, isBrowserEnabled) workspaceNames.push(instance.name);
6742
6636
  });
6743
6637
  const filters = project.vitest.config.project;
6744
6638
  // if there is `--project=...` filter, check if any of the potential projects match
@@ -6750,10 +6644,13 @@ function WorkspaceVitestPlugin(project, options) {
6750
6644
  });
6751
6645
  if (!hasProject) throw new VitestFilteredOutProjectError();
6752
6646
  }
6753
- return { test: { name: {
6754
- label: name,
6755
- color
6756
- } } };
6647
+ return {
6648
+ environments: { __vitest__: { dev: {} } },
6649
+ test: { name: {
6650
+ label: name,
6651
+ color
6652
+ } }
6653
+ };
6757
6654
  }
6758
6655
  },
6759
6656
  {
@@ -6763,22 +6660,14 @@ function WorkspaceVitestPlugin(project, options) {
6763
6660
  this.meta.watchMode = false;
6764
6661
  },
6765
6662
  config(viteConfig) {
6766
- const defines = deleteDefineConfig(viteConfig);
6767
- const testConfig = viteConfig.test || {};
6768
- const root = testConfig.root || viteConfig.root || options.root;
6769
- const resolveOptions = getDefaultResolveOptions();
6770
- const config = {
6663
+ const defines = deleteDefineConfig(viteConfig), testConfig = viteConfig.test || {}, root = testConfig.root || viteConfig.root || options.root, resolveOptions = getDefaultResolveOptions();
6664
+ let config = {
6771
6665
  root,
6772
6666
  define: { "process.env.NODE_ENV": "process.env.NODE_ENV" },
6773
6667
  resolve: {
6774
6668
  ...resolveOptions,
6775
6669
  alias: testConfig.alias
6776
6670
  },
6777
- esbuild: viteConfig.esbuild === false ? false : {
6778
- target: viteConfig.esbuild?.target || "node18",
6779
- sourcemap: "external",
6780
- legalComments: "inline"
6781
- },
6782
6671
  server: {
6783
6672
  watch: null,
6784
6673
  open: false,
@@ -6791,19 +6680,27 @@ function WorkspaceVitestPlugin(project, options) {
6791
6680
  environments: { ssr: { resolve: resolveOptions } },
6792
6681
  test: {}
6793
6682
  };
6683
+ if ("rolldownVersion" in vite) config = {
6684
+ ...config,
6685
+ oxc: viteConfig.oxc === false ? false : { target: viteConfig.oxc?.target || "node18" }
6686
+ };
6687
+ else config = {
6688
+ ...config,
6689
+ esbuild: viteConfig.esbuild === false ? false : {
6690
+ target: viteConfig.esbuild?.target || "node18",
6691
+ sourcemap: "external",
6692
+ legalComments: "inline"
6693
+ }
6694
+ };
6794
6695
  config.test.defines = defines;
6795
6696
  const classNameStrategy = typeof testConfig.css !== "boolean" && testConfig.css?.modules?.classNameStrategy || "stable";
6796
6697
  if (classNameStrategy !== "scoped") {
6797
- config.css ??= {};
6798
- config.css.modules ??= {};
6799
- if (config.css.modules) config.css.modules.generateScopedName = (name, filename) => {
6698
+ if (config.css ??= {}, config.css.modules ??= {}, config.css.modules) config.css.modules.generateScopedName = (name, filename) => {
6800
6699
  const root = project.config.root;
6801
6700
  return generateScopedClassName(classNameStrategy, name, relative(root, filename));
6802
6701
  };
6803
6702
  }
6804
- config.customLogger = createViteLogger(project.vitest.logger, viteConfig.logLevel || "warn", { allowClearScreen: false });
6805
- config.customLogger = silenceImportViteIgnoreWarning(config.customLogger);
6806
- return config;
6703
+ return config.customLogger = createViteLogger(project.vitest.logger, viteConfig.logLevel || "warn", { allowClearScreen: false }), config.customLogger = silenceImportViteIgnoreWarning(config.customLogger), config;
6807
6704
  }
6808
6705
  },
6809
6706
  {
@@ -6811,20 +6708,119 @@ function WorkspaceVitestPlugin(project, options) {
6811
6708
  enforce: "post",
6812
6709
  async configureServer(server) {
6813
6710
  const options = deepMerge({}, configDefaults, server.config.test || {});
6814
- await project._configureServer(options, server);
6815
- await server.watcher.close();
6711
+ await project._configureServer(options, server), await server.watcher.close();
6816
6712
  }
6817
6713
  },
6818
- SsrReplacerPlugin(),
6714
+ MetaEnvReplacerPlugin(),
6819
6715
  ...CSSEnablerPlugin(project),
6820
6716
  CoverageTransform(project.vitest),
6821
6717
  ...MocksPlugins(),
6822
6718
  VitestProjectResolver(project.vitest),
6823
6719
  VitestOptimizer(),
6824
- NormalizeURLPlugin()
6720
+ NormalizeURLPlugin(),
6721
+ ModuleRunnerTransform()
6825
6722
  ];
6826
6723
  }
6827
6724
 
6725
+ class VitestResolver {
6726
+ options;
6727
+ externalizeCache = /* @__PURE__ */ new Map();
6728
+ constructor(cacheDir, config) {
6729
+ this.options = {
6730
+ moduleDirectories: config.deps.moduleDirectories,
6731
+ inlineFiles: config.setupFiles.flatMap((file) => {
6732
+ if (file.startsWith("file://")) return file;
6733
+ const resolvedId = resolve(file);
6734
+ return [resolvedId, pathToFileURL(resolvedId).href];
6735
+ }),
6736
+ cacheDir,
6737
+ inline: config.server.deps?.inline,
6738
+ external: config.server.deps?.external
6739
+ };
6740
+ }
6741
+ shouldExternalize(file) {
6742
+ return shouldExternalize(normalizeId(file), this.options, this.externalizeCache);
6743
+ }
6744
+ }
6745
+ function normalizeId(id) {
6746
+ if (id.startsWith("/@fs/")) id = id.slice(isWindows ? 5 : 4);
6747
+ return id;
6748
+ }
6749
+ const BUILTIN_EXTENSIONS = new Set([
6750
+ ".mjs",
6751
+ ".cjs",
6752
+ ".node",
6753
+ ".wasm"
6754
+ ]), ESM_EXT_RE = /\.(es|esm|esm-browser|esm-bundler|es6|module)\.js$/, ESM_FOLDER_RE = /\/(es|esm)\/(.*\.js)$/, defaultInline = [
6755
+ /virtual:/,
6756
+ /\.[mc]?ts$/,
6757
+ /[?&](init|raw|url|inline)\b/,
6758
+ KNOWN_ASSET_RE,
6759
+ /^(?!.*node_modules).*\.mjs$/,
6760
+ /^(?!.*node_modules).*\.cjs\.js$/,
6761
+ /vite\w*\/dist\/client\/env.mjs/
6762
+ ], depsExternal = [/\/node_modules\/.*\.cjs\.js$/, /\/node_modules\/.*\.mjs$/];
6763
+ function guessCJSversion(id) {
6764
+ if (id.match(ESM_EXT_RE)) {
6765
+ for (const i of [
6766
+ id.replace(ESM_EXT_RE, ".mjs"),
6767
+ id.replace(ESM_EXT_RE, ".umd.js"),
6768
+ id.replace(ESM_EXT_RE, ".cjs.js"),
6769
+ id.replace(ESM_EXT_RE, ".js")
6770
+ ]) if (existsSync(i)) return i;
6771
+ }
6772
+ if (id.match(ESM_FOLDER_RE)) {
6773
+ for (const i of [
6774
+ id.replace(ESM_FOLDER_RE, "/umd/$1"),
6775
+ id.replace(ESM_FOLDER_RE, "/cjs/$1"),
6776
+ id.replace(ESM_FOLDER_RE, "/lib/$1"),
6777
+ id.replace(ESM_FOLDER_RE, "/$1")
6778
+ ]) if (existsSync(i)) return i;
6779
+ }
6780
+ }
6781
+ // The code from https://github.com/unjs/mlly/blob/c5bcca0cda175921344fd6de1bc0c499e73e5dac/src/syntax.ts#L51-L98
6782
+ async function isValidNodeImport(id) {
6783
+ const extension = extname(id);
6784
+ if (BUILTIN_EXTENSIONS.has(extension)) return true;
6785
+ if (extension !== ".js") return false;
6786
+ id = id.replace("file:///", "");
6787
+ const package_ = findNearestPackageData(dirname(id));
6788
+ if (package_.type === "module") return true;
6789
+ if (/\.(?:\w+-)?esm?(?:-\w+)?\.js$|\/esm?\//.test(id)) return false;
6790
+ try {
6791
+ await esModuleLexer.init;
6792
+ const code = await promises.readFile(id, "utf8"), [, , , hasModuleSyntax] = esModuleLexer.parse(code);
6793
+ return !hasModuleSyntax;
6794
+ } catch {
6795
+ return false;
6796
+ }
6797
+ }
6798
+ async function shouldExternalize(id, options, cache) {
6799
+ if (!cache.has(id)) cache.set(id, _shouldExternalize(id, options));
6800
+ return cache.get(id);
6801
+ }
6802
+ async function _shouldExternalize(id, options) {
6803
+ // data: should be processed by native import,
6804
+ // since it is a feature of ESM.
6805
+ // also externalize network imports since nodejs allows it when --experimental-network-imports
6806
+ if (isBuiltin(id) || id.startsWith("data:") || /^(?:https?:)?\/\//.test(id)) return id;
6807
+ const moduleDirectories = options?.moduleDirectories || ["/node_modules/"];
6808
+ if (matchExternalizePattern(id, moduleDirectories, options?.inline) || options?.inlineFiles && options?.inlineFiles.includes(id)) return false;
6809
+ // Unless the user explicitly opted to inline them, externalize Vite deps.
6810
+ // They are too big to inline by default.
6811
+ if (matchExternalizePattern(id, moduleDirectories, options?.external) || options?.cacheDir && id.includes(options.cacheDir)) return id;
6812
+ const isLibraryModule = moduleDirectories.some((dir) => id.includes(dir)), guessCJS = isLibraryModule && options?.fallbackCJS;
6813
+ return id = guessCJS ? guessCJSversion(id) || id : id, matchExternalizePattern(id, moduleDirectories, defaultInline) ? false : matchExternalizePattern(id, moduleDirectories, depsExternal) || isLibraryModule && await isValidNodeImport(id) ? id : false;
6814
+ }
6815
+ function matchExternalizePattern(id, moduleDirectories, patterns) {
6816
+ if (patterns == null) return false;
6817
+ if (patterns === true) return true;
6818
+ for (const ex of patterns) if (typeof ex === "string") {
6819
+ if (moduleDirectories.some((dir) => id.includes(join(dir, ex)))) return true;
6820
+ } else if (ex.test(id)) return true;
6821
+ return false;
6822
+ }
6823
+
6828
6824
  class TestSpecification {
6829
6825
  /**
6830
6826
  * @deprecated use `project` instead
@@ -6860,24 +6856,16 @@ class TestSpecification {
6860
6856
  */
6861
6857
  testLines;
6862
6858
  constructor(project, moduleId, pool, testLines) {
6863
- this[0] = project;
6864
- this[1] = moduleId;
6865
- this[2] = { pool };
6866
- const name = project.config.name;
6867
- const hashName = pool !== "typescript" ? name : name ? `${name}:__typecheck__` : "__typecheck__";
6868
- this.taskId = generateFileHash(relative(project.config.root, moduleId), hashName);
6869
- this.project = project;
6870
- this.moduleId = moduleId;
6871
- this.pool = pool;
6872
- this.testLines = testLines;
6859
+ this[0] = project, this[1] = moduleId, this[2] = { pool };
6860
+ const name = project.config.name, hashName = pool !== "typescript" ? name : name ? `${name}:__typecheck__` : "__typecheck__";
6861
+ this.taskId = generateFileHash(relative(project.config.root, moduleId), hashName), this.project = project, this.moduleId = moduleId, this.pool = pool, this.testLines = testLines;
6873
6862
  }
6874
6863
  /**
6875
6864
  * Test module associated with the specification.
6876
6865
  */
6877
6866
  get testModule() {
6878
6867
  const task = this.project.vitest.state.idMap.get(this.taskId);
6879
- if (!task) return void 0;
6880
- return this.project.vitest.state.getReportedEntity(task);
6868
+ return task ? this.project.vitest.state.getReportedEntity(task) : void 0;
6881
6869
  }
6882
6870
  toJSON() {
6883
6871
  return [
@@ -6897,9 +6885,7 @@ class TestSpecification {
6897
6885
  * @deprecated
6898
6886
  */
6899
6887
  *[Symbol.iterator]() {
6900
- yield this.project;
6901
- yield this.moduleId;
6902
- yield this.pool;
6888
+ yield this.project, yield this.moduleId, yield this.pool;
6903
6889
  }
6904
6890
  }
6905
6891
 
@@ -6908,12 +6894,10 @@ async function createViteServer(inlineConfig) {
6908
6894
  // But Vitest works correctly either way
6909
6895
  const error = console.error;
6910
6896
  console.error = (...args) => {
6911
- if (typeof args[0] === "string" && args[0].includes("WebSocket server error:")) return;
6912
- error(...args);
6897
+ typeof args[0] === "string" && args[0].includes("WebSocket server error:") || error(...args);
6913
6898
  };
6914
6899
  const server = await createServer(inlineConfig);
6915
- console.error = error;
6916
- return server;
6900
+ return console.error = error, server;
6917
6901
  }
6918
6902
 
6919
6903
  class TestProject {
@@ -6936,11 +6920,11 @@ class TestProject {
6936
6920
  * Temporary directory for the project. This is unique for each project. Vitest stores transformed content here.
6937
6921
  */
6938
6922
  tmpDir = join(tmpdir(), nanoid());
6939
- /** @internal */ vitenode;
6940
6923
  /** @internal */ typechecker;
6941
6924
  /** @internal */ _config;
6942
6925
  /** @internal */ _vite;
6943
6926
  /** @internal */ _hash;
6927
+ /** @internal */ _resolver;
6944
6928
  runner;
6945
6929
  closingPromise;
6946
6930
  testFilesList = null;
@@ -6948,11 +6932,7 @@ class TestProject {
6948
6932
  _globalSetups;
6949
6933
  _provided = {};
6950
6934
  constructor(path, vitest, options) {
6951
- this.path = path;
6952
- this.options = options;
6953
- this.vitest = vitest;
6954
- this.ctx = vitest;
6955
- this.globalConfig = vitest.config;
6935
+ this.path = path, this.options = options, this.vitest = vitest, this.ctx = vitest, this.globalConfig = vitest.config;
6956
6936
  }
6957
6937
  /**
6958
6938
  * The unique hash of this project. This value is consistent between the reruns.
@@ -6981,10 +6961,9 @@ class TestProject {
6981
6961
  * Get the provided context. The project context is merged with the global context.
6982
6962
  */
6983
6963
  getProvidedContext() {
6984
- if (this.isRootProject()) return this._provided;
6985
6964
  // globalSetup can run even if core workspace is not part of the test run
6986
6965
  // so we need to inherit its provided context
6987
- return {
6966
+ return this.isRootProject() ? this._provided : {
6988
6967
  ...this.vitest.getRootProject().getProvidedContext(),
6989
6968
  ...this._provided
6990
6969
  };
@@ -7008,13 +6987,11 @@ class TestProject {
7008
6987
  */
7009
6988
  get vite() {
7010
6989
  if (!this._vite) throw new Error("The server was not set. It means that `project.vite` was called before the Vite server was established.");
7011
- // checking it once should be enough
7012
- Object.defineProperty(this, "vite", {
6990
+ return Object.defineProperty(this, "vite", {
7013
6991
  configurable: true,
7014
6992
  writable: true,
7015
6993
  value: this._vite
7016
- });
7017
- return this._vite;
6994
+ }), this._vite;
7018
6995
  }
7019
6996
  /**
7020
6997
  * Resolved project configuration.
@@ -7071,13 +7048,14 @@ class TestProject {
7071
7048
  }
7072
7049
  /** @internal */
7073
7050
  async _initializeGlobalSetup() {
7074
- if (this._globalSetups) return;
7075
- this._globalSetups = await loadGlobalSetupFiles(this.runner, this.config.globalSetup);
7076
- for (const globalSetupFile of this._globalSetups) {
7077
- const teardown = await globalSetupFile.setup?.(this);
7078
- if (teardown == null || !!globalSetupFile.teardown) continue;
7079
- if (typeof teardown !== "function") throw new TypeError(`invalid return value in globalSetup file ${globalSetupFile.file}. Must return a function`);
7080
- globalSetupFile.teardown = teardown;
7051
+ if (!this._globalSetups) {
7052
+ this._globalSetups = await loadGlobalSetupFiles(this.runner, this.config.globalSetup);
7053
+ for (const globalSetupFile of this._globalSetups) {
7054
+ const teardown = await globalSetupFile.setup?.(this);
7055
+ if (teardown == null || !!globalSetupFile.teardown) continue;
7056
+ if (typeof teardown !== "function") throw new TypeError(`invalid return value in globalSetup file ${globalSetupFile.file}. Must return a function`);
7057
+ globalSetupFile.teardown = teardown;
7058
+ }
7081
7059
  }
7082
7060
  }
7083
7061
  onTestsRerun(cb) {
@@ -7089,8 +7067,7 @@ class TestProject {
7089
7067
  }
7090
7068
  /** @internal */
7091
7069
  async _teardownGlobalSetup() {
7092
- if (!this._globalSetups) return;
7093
- for (const globalSetupFile of [...this._globalSetups].reverse()) await globalSetupFile.teardown?.();
7070
+ if (this._globalSetups) for (const globalSetupFile of [...this._globalSetups].reverse()) await globalSetupFile.teardown?.();
7094
7071
  }
7095
7072
  /** @deprecated use `vitest.logger` instead */
7096
7073
  get logger() {
@@ -7120,12 +7097,8 @@ class TestProject {
7120
7097
  * @param filters String filters to match the test files.
7121
7098
  */
7122
7099
  async globTestFiles(filters = []) {
7123
- const dir = this.config.dir || this.config.root;
7124
- const { include, exclude, includeSource } = this.config;
7125
- const typecheck = this.config.typecheck;
7126
- const [testFiles, typecheckTestFiles] = await Promise.all([typecheck.enabled && typecheck.only ? [] : this.globAllTestFiles(include, exclude, includeSource, dir), typecheck.enabled ? this.typecheckFilesList || this.globFiles(typecheck.include, typecheck.exclude, dir) : []]);
7127
- this.typecheckFilesList = typecheckTestFiles;
7128
- return {
7100
+ const dir = this.config.dir || this.config.root, { include, exclude, includeSource } = this.config, typecheck = this.config.typecheck, [testFiles, typecheckTestFiles] = await Promise.all([typecheck.enabled && typecheck.only ? [] : this.globAllTestFiles(include, exclude, includeSource, dir), typecheck.enabled ? this.typecheckFilesList || this.globFiles(typecheck.include, typecheck.exclude, dir) : []]);
7101
+ return this.typecheckFilesList = typecheckTestFiles, {
7129
7102
  testFiles: this.filterFiles(testFiles, filters, dir),
7130
7103
  typecheckTestFiles: this.filterFiles(typecheckTestFiles, filters, dir)
7131
7104
  };
@@ -7144,8 +7117,7 @@ class TestProject {
7144
7117
  }
7145
7118
  }));
7146
7119
  }
7147
- this.testFilesList = testFiles;
7148
- return testFiles;
7120
+ return this.testFilesList = testFiles, testFiles;
7149
7121
  }
7150
7122
  isBrowserEnabled() {
7151
7123
  return isBrowserEnabled(this.config);
@@ -7182,8 +7154,7 @@ class TestProject {
7182
7154
  cwd,
7183
7155
  ignore: exclude,
7184
7156
  expandDirectories: false
7185
- };
7186
- const files = await glob(include, globOptions);
7157
+ }, files = await glob(include, globOptions);
7187
7158
  // keep the slashes consistent with Vite
7188
7159
  // we are not using the pathe here because it normalizes the drive letter on Windows
7189
7160
  // and we want to keep it the same as working dir
@@ -7196,16 +7167,10 @@ class TestProject {
7196
7167
  if (this._isCachedTestFile(moduleId)) return true;
7197
7168
  const relativeId = relative(this.config.dir || this.config.root, moduleId);
7198
7169
  if (pm.isMatch(relativeId, this.config.exclude)) return false;
7199
- if (pm.isMatch(relativeId, this.config.include)) {
7200
- this.markTestFile(moduleId);
7201
- return true;
7202
- }
7170
+ if (pm.isMatch(relativeId, this.config.include)) return this.markTestFile(moduleId), true;
7203
7171
  if (this.config.includeSource?.length && pm.isMatch(relativeId, this.config.includeSource)) {
7204
7172
  const code = source?.() || readFileSync(moduleId, "utf-8");
7205
- if (this.isInSourceTestCode(code)) {
7206
- this.markTestFile(moduleId);
7207
- return true;
7208
- }
7173
+ if (this.isInSourceTestCode(code)) return this.markTestFile(moduleId), true;
7209
7174
  }
7210
7175
  return false;
7211
7176
  }
@@ -7218,7 +7183,7 @@ class TestProject {
7218
7183
  }
7219
7184
  filterFiles(testFiles, filters, dir) {
7220
7185
  if (filters.length && process.platform === "win32") filters = filters.map((f) => slash(f));
7221
- if (filters.length) return testFiles.filter((t) => {
7186
+ return filters.length ? testFiles.filter((t) => {
7222
7187
  const testFile = relative(dir, t).toLocaleLowerCase();
7223
7188
  return filters.some((f) => {
7224
7189
  // if filter is a full file path, we should include it if it's in the same folder
@@ -7226,8 +7191,7 @@ class TestProject {
7226
7191
  const relativePath = f.endsWith("/") ? join(relative(dir, f), "/") : relative(dir, f);
7227
7192
  return testFile.includes(f.toLocaleLowerCase()) || testFile.includes(relativePath.toLocaleLowerCase());
7228
7193
  });
7229
- });
7230
- return testFiles;
7194
+ }) : testFiles;
7231
7195
  }
7232
7196
  _parentBrowser;
7233
7197
  /** @internal */
@@ -7238,25 +7202,23 @@ class TestProject {
7238
7202
  await this.vitest.packageInstaller.ensureInstalled("@vitest/browser", this.config.root, this.vitest.version);
7239
7203
  const { createBrowserServer, distRoot } = await import('@vitest/browser');
7240
7204
  let cacheDir;
7241
- const browser = await createBrowserServer(this, this.vite.config.configFile, [{
7242
- name: "vitest:browser-cacheDir",
7243
- configResolved(config) {
7244
- cacheDir = config.cacheDir;
7245
- }
7246
- }, ...MocksPlugins({ filter(id) {
7247
- if (id.includes(distRoot) || id.includes(cacheDir)) return false;
7248
- return true;
7249
- } })], [CoverageTransform(this.vitest)]);
7250
- this._parentBrowser = browser;
7251
- if (this.config.browser.ui) setup(this.vitest, browser.vite);
7205
+ const browser = await createBrowserServer(this, this.vite.config.configFile, [
7206
+ {
7207
+ name: "vitest:browser-cacheDir",
7208
+ configResolved(config) {
7209
+ cacheDir = config.cacheDir;
7210
+ }
7211
+ },
7212
+ ...MocksPlugins({ filter(id) {
7213
+ return !(id.includes(distRoot) || id.includes(cacheDir));
7214
+ } }),
7215
+ MetaEnvReplacerPlugin()
7216
+ ], [CoverageTransform(this.vitest)]);
7217
+ if (this._parentBrowser = browser, this.config.browser.ui) setup(this.vitest, browser.vite);
7252
7218
  });
7253
7219
  /** @internal */
7254
7220
  _initBrowserServer = deduped(async () => {
7255
- await this._parent?._initParentBrowser();
7256
- if (!this.browser && this._parent?._parentBrowser) {
7257
- this.browser = this._parent._parentBrowser.spawn(this);
7258
- await this.vitest.report("onBrowserInit", this);
7259
- }
7221
+ if (await this._parent?._initParentBrowser(), !this.browser && this._parent?._parentBrowser) this.browser = this._parent._parentBrowser.spawn(this), await this.vitest.report("onBrowserInit", this);
7260
7222
  });
7261
7223
  /**
7262
7224
  * Closes the project and all associated resources. This can only be called once; the closing promise is cached until the server restarts.
@@ -7269,8 +7231,7 @@ class TestProject {
7269
7231
  this.browser?.close(),
7270
7232
  this.clearTmpDir()
7271
7233
  ].filter(Boolean)).then(() => {
7272
- this._provided = {};
7273
- this._vite = void 0;
7234
+ this._provided = {}, this._vite = void 0;
7274
7235
  });
7275
7236
  return this.closingPromise;
7276
7237
  }
@@ -7279,7 +7240,7 @@ class TestProject {
7279
7240
  * @param moduleId The ID of the module in Vite module graph
7280
7241
  */
7281
7242
  import(moduleId) {
7282
- return this.runner.executeId(moduleId);
7243
+ return this.runner.import(moduleId);
7283
7244
  }
7284
7245
  /** @deprecated use `name` instead */
7285
7246
  getName() {
@@ -7294,36 +7255,22 @@ class TestProject {
7294
7255
  }
7295
7256
  /** @internal */
7296
7257
  async _configureServer(options, server) {
7297
- this._config = resolveConfig(this.vitest, {
7258
+ for (const _providedKey in this._config = resolveConfig(this.vitest, {
7298
7259
  ...options,
7299
7260
  coverage: this.vitest.config.coverage
7300
- }, server.config);
7301
- this._setHash();
7302
- for (const _providedKey in this.config.provide) {
7261
+ }, server.config), this._setHash(), this.config.provide) {
7303
7262
  const providedKey = _providedKey;
7304
7263
  // type is very strict here, so we cast it to any
7305
7264
  this.provide(providedKey, this.config.provide[providedKey]);
7306
7265
  }
7307
- this.closingPromise = void 0;
7308
- this._vite = server;
7309
- this.vitenode = new ViteNodeServer(server, this.config.server);
7310
- const node = this.vitenode;
7311
- this.runner = new ViteNodeRunner({
7312
- root: server.config.root,
7313
- base: server.config.base,
7314
- fetchModule(id) {
7315
- return node.fetchModule(id);
7316
- },
7317
- resolveId(id, importer) {
7318
- return node.resolveId(id, importer);
7319
- }
7320
- });
7266
+ this.closingPromise = void 0, this._resolver = new VitestResolver(server.config.cacheDir, this._config), this._vite = server;
7267
+ const environment = server.environments.__vitest__;
7268
+ this.runner = new ServerModuleRunner(environment, this._resolver, this._config);
7321
7269
  }
7322
7270
  _serializeOverriddenConfig() {
7323
7271
  // TODO: serialize the config _once_ or when needed
7324
7272
  const config = serializeConfig(this.config, this.vitest.config, this.vite.config);
7325
- if (!this.vitest.configOverride) return config;
7326
- return deepMerge(config, this.vitest.configOverride);
7273
+ return this.vitest.configOverride ? deepMerge(config, this.vitest.configOverride) : config;
7327
7274
  }
7328
7275
  async clearTmpDir() {
7329
7276
  try {
@@ -7336,9 +7283,10 @@ class TestProject {
7336
7283
  }
7337
7284
  /** @internal */
7338
7285
  _initBrowserProvider = deduped(async () => {
7339
- if (!this.isBrowserEnabled() || this.browser?.provider) return;
7340
- if (!this.browser) await this._initBrowserServer();
7341
- await this.browser?.initBrowserProvider(this);
7286
+ if (!(!this.isBrowserEnabled() || this.browser?.provider)) {
7287
+ if (!this.browser) await this._initBrowserServer();
7288
+ await this.browser?.initBrowserProvider(this);
7289
+ }
7342
7290
  });
7343
7291
  /** @internal */
7344
7292
  _provideObject(context) {
@@ -7351,40 +7299,25 @@ class TestProject {
7351
7299
  /** @internal */
7352
7300
  static _createBasicProject(vitest) {
7353
7301
  const project = new TestProject(vitest.config.name || vitest.config.root, vitest);
7354
- project.vitenode = vitest.vitenode;
7355
- project.runner = vitest.runner;
7356
- project._vite = vitest.server;
7357
- project._config = vitest.config;
7358
- project._setHash();
7359
- project._provideObject(vitest.config.provide);
7360
- return project;
7302
+ return project.runner = vitest.runner, project._vite = vitest.server, project._config = vitest.config, project._resolver = vitest._resolver, project._setHash(), project._provideObject(vitest.config.provide), project;
7361
7303
  }
7362
7304
  /** @internal */
7363
7305
  static _cloneBrowserProject(parent, config) {
7364
7306
  const clone = new TestProject(parent.path, parent.vitest);
7365
- clone.vitenode = parent.vitenode;
7366
- clone.runner = parent.runner;
7367
- clone._vite = parent._vite;
7368
- clone._config = config;
7369
- clone._setHash();
7370
- clone._parent = parent;
7371
- clone._provideObject(config.provide);
7372
- return clone;
7307
+ return clone.runner = parent.runner, clone._vite = parent._vite, clone._resolver = parent._resolver, clone._config = config, clone._setHash(), clone._parent = parent, clone._provideObject(config.provide), clone;
7373
7308
  }
7374
7309
  }
7375
7310
  function deduped(cb) {
7376
7311
  let _promise;
7377
- return (...args) => {
7312
+ return ((...args) => {
7378
7313
  if (!_promise) _promise = cb(...args).finally(() => {
7379
7314
  _promise = void 0;
7380
7315
  });
7381
7316
  return _promise;
7382
- };
7317
+ });
7383
7318
  }
7384
7319
  async function initializeProject(workspacePath, ctx, options) {
7385
- const project = new TestProject(workspacePath, ctx, options);
7386
- const { configFile,...restOptions } = options;
7387
- const config = {
7320
+ const project = new TestProject(workspacePath, ctx, options), { configFile,...restOptions } = options, config = {
7388
7321
  ...restOptions,
7389
7322
  configFile,
7390
7323
  configLoader: ctx.vite.config.inlineConfig.configLoader,
@@ -7394,25 +7327,20 @@ async function initializeProject(workspacePath, ctx, options) {
7394
7327
  workspacePath
7395
7328
  })]
7396
7329
  };
7397
- await createViteServer(config);
7398
- return project;
7330
+ return await createViteServer(config), project;
7399
7331
  }
7400
7332
  function generateHash(str) {
7401
7333
  let hash = 0;
7402
7334
  if (str.length === 0) return `${hash}`;
7403
7335
  for (let i = 0; i < str.length; i++) {
7404
7336
  const char = str.charCodeAt(i);
7405
- hash = (hash << 5) - hash + char;
7406
- hash = hash & hash;
7337
+ hash = (hash << 5) - hash + char, hash = hash & hash;
7407
7338
  }
7408
7339
  return `${hash}`;
7409
7340
  }
7410
7341
 
7411
7342
  async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projectsDefinition, names) {
7412
- const { configFiles, projectConfigs, nonConfigDirectories } = await resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDefinition);
7413
- // cli options that affect the project config,
7414
- // not all options are allowed to be overridden
7415
- const overridesOptions = [
7343
+ const { configFiles, projectConfigs, nonConfigDirectories } = await resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDefinition), overridesOptions = [
7416
7344
  "logHeapUsage",
7417
7345
  "allowOnly",
7418
7346
  "sequence",
@@ -7431,21 +7359,12 @@ async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projects
7431
7359
  "inspect",
7432
7360
  "inspectBrk",
7433
7361
  "fileParallelism"
7434
- ];
7435
- const cliOverrides = overridesOptions.reduce((acc, name) => {
7362
+ ], cliOverrides = overridesOptions.reduce((acc, name) => {
7436
7363
  if (name in cliOptions) acc[name] = cliOptions[name];
7437
7364
  return acc;
7438
- }, {});
7439
- const projectPromises = [];
7440
- const fileProjects = [...configFiles, ...nonConfigDirectories];
7441
- const concurrent = limitConcurrency(nodeos__default.availableParallelism?.() || nodeos__default.cpus().length || 5);
7365
+ }, {}), projectPromises = [], fileProjects = [...configFiles, ...nonConfigDirectories], concurrent = limitConcurrency(nodeos__default.availableParallelism?.() || nodeos__default.cpus().length || 5);
7442
7366
  projectConfigs.forEach((options, index) => {
7443
- const configRoot = vitest.config.root;
7444
- // if extends a config file, resolve the file path
7445
- const configFile = typeof options.extends === "string" ? resolve(configRoot, options.extends) : options.extends === true ? vitest.vite.config.configFile || false : false;
7446
- // if `root` is configured, resolve it relative to the workspace file or vite root (like other options)
7447
- // if `root` is not specified, inline configs use the same root as the root project
7448
- const root = options.root ? resolve(configRoot, options.root) : vitest.config.root;
7367
+ const configRoot = vitest.config.root, configFile = typeof options.extends === "string" ? resolve(configRoot, options.extends) : options.extends === true ? vitest.vite.config.configFile || false : false, root = options.root ? resolve(configRoot, options.root) : vitest.config.root;
7449
7368
  projectPromises.push(concurrent(() => initializeProject(index, vitest, {
7450
7369
  ...options,
7451
7370
  root,
@@ -7463,8 +7382,7 @@ async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projects
7463
7382
  if (project) projectPromises.push(Promise.resolve(project));
7464
7383
  continue;
7465
7384
  }
7466
- const configFile = path.endsWith("/") ? false : path;
7467
- const root = path.endsWith("/") ? path : dirname(path);
7385
+ const configFile = path.endsWith("/") ? false : path, root = path.endsWith("/") ? path : dirname(path);
7468
7386
  projectPromises.push(concurrent(() => initializeProject(path, vitest, {
7469
7387
  root,
7470
7388
  configFile,
@@ -7477,9 +7395,7 @@ async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projects
7477
7395
  vitest.config.project.length ? `The filter matched no projects: ${vitest.config.project.join(", ")}. ` : "",
7478
7396
  `The projects definition: ${JSON.stringify(projectsDefinition, null, 4)}.`
7479
7397
  ].join(""));
7480
- const resolvedProjectsPromises = await Promise.allSettled(projectPromises);
7481
- const errors = [];
7482
- const resolvedProjects = [];
7398
+ const resolvedProjectsPromises = await Promise.allSettled(projectPromises), errors = [], resolvedProjects = [];
7483
7399
  for (const result of resolvedProjectsPromises) if (result.status === "rejected") {
7484
7400
  if (result.reason instanceof VitestFilteredOutProjectError)
7485
7401
  // filter out filtered out projects
@@ -7491,8 +7407,7 @@ async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projects
7491
7407
  for (const project of resolvedProjects) {
7492
7408
  const name = project.name;
7493
7409
  if (names.has(name)) {
7494
- const duplicate = resolvedProjects.find((p) => p.name === name && p !== project);
7495
- const filesError = fileProjects.length ? [
7410
+ const duplicate = resolvedProjects.find((p) => p.name === name && p !== project), filesError = fileProjects.length ? [
7496
7411
  "\n\nYour config matched these files:\n",
7497
7412
  fileProjects.map((p) => ` - ${relative(vitest.config.root, p)}`).join("\n"),
7498
7413
  "\n\n"
@@ -7514,24 +7429,18 @@ async function resolveBrowserProjects(vitest, names, resolvedProjects) {
7514
7429
  const removeProjects = /* @__PURE__ */ new Set();
7515
7430
  resolvedProjects.forEach((project) => {
7516
7431
  if (!project.config.browser.enabled) return;
7517
- const instances = project.config.browser.instances || [];
7518
- const browser = project.config.browser.name;
7519
- if (instances.length === 0 && browser) {
7520
- instances.push({
7521
- browser,
7522
- name: project.name ? `${project.name} (${browser})` : browser
7523
- });
7524
- vitest.logger.warn(withLabel("yellow", "Vitest", [
7525
- `No browser "instances" were defined`,
7526
- project.name ? ` for the "${project.name}" project. ` : ". ",
7527
- `Running tests in "${project.config.browser.name}" browser. `,
7528
- "The \"browser.name\" field is deprecated since Vitest 3. ",
7529
- "Read more: https://vitest.dev/guide/browser/config#browser-instances"
7530
- ].filter(Boolean).join("")));
7531
- }
7532
- const originalName = project.config.name;
7533
- // if original name is in the --project=name filter, keep all instances
7534
- const filteredInstances = vitest.matchesProjectFilter(originalName) ? instances : instances.filter((instance) => {
7432
+ const instances = project.config.browser.instances || [], browser = project.config.browser.name;
7433
+ if (instances.length === 0 && browser) instances.push({
7434
+ browser,
7435
+ name: project.name ? `${project.name} (${browser})` : browser
7436
+ }), vitest.logger.warn(withLabel("yellow", "Vitest", [
7437
+ `No browser "instances" were defined`,
7438
+ project.name ? ` for the "${project.name}" project. ` : ". ",
7439
+ `Running tests in "${project.config.browser.name}" browser. `,
7440
+ "The \"browser.name\" field is deprecated since Vitest 3. ",
7441
+ "Read more: https://vitest.dev/guide/browser/config#browser-instances"
7442
+ ].filter(Boolean).join("")));
7443
+ const originalName = project.config.name, filteredInstances = vitest.matchesProjectFilter(originalName) ? instances : instances.filter((instance) => {
7535
7444
  const newName = instance.name;
7536
7445
  return vitest.matchesProjectFilter(newName);
7537
7446
  });
@@ -7544,8 +7453,7 @@ async function resolveBrowserProjects(vitest, names, resolvedProjects) {
7544
7453
  filteredInstances.forEach((config, index) => {
7545
7454
  const browser = config.browser;
7546
7455
  if (!browser) {
7547
- const nth = index + 1;
7548
- const ending = nth === 2 ? "nd" : nth === 3 ? "rd" : "th";
7456
+ const nth = index + 1, ending = nth === 2 ? "nd" : nth === 3 ? "rd" : "th";
7549
7457
  throw new Error(`The browser configuration must have a "browser" property. The ${nth}${ending} item in "browser.instances" doesn't have it. Make sure your${originalName ? ` "${originalName}"` : ""} configuration is correct.`);
7550
7458
  }
7551
7459
  const name = config.name;
@@ -7560,18 +7468,15 @@ async function resolveBrowserProjects(vitest, names, resolvedProjects) {
7560
7468
  clonedConfig.name = name;
7561
7469
  const clone = TestProject._cloneBrowserProject(project, clonedConfig);
7562
7470
  resolvedProjects.push(clone);
7563
- });
7564
- removeProjects.add(project);
7565
- });
7566
- resolvedProjects = resolvedProjects.filter((project) => !removeProjects.has(project));
7471
+ }), removeProjects.add(project);
7472
+ }), resolvedProjects = resolvedProjects.filter((project) => !removeProjects.has(project));
7567
7473
  const headedBrowserProjects = resolvedProjects.filter((project) => {
7568
7474
  return project.config.browser.enabled && !project.config.browser.headless;
7569
7475
  });
7570
7476
  if (headedBrowserProjects.length > 1) {
7571
7477
  const message = [`Found multiple projects that run browser tests in headed mode: "${headedBrowserProjects.map((p) => p.name).join("\", \"")}".`, ` Vitest cannot run multiple headed browsers at the same time.`].join("");
7572
7478
  if (!isTTY) throw new Error(`${message} Please, filter projects with --browser=name or --project=name flag or run tests with "headless: true" option.`);
7573
- const prompts = await import('./index.X0nbfr6-.js').then(function (n) { return n.i; });
7574
- const { projectName } = await prompts.default({
7479
+ const prompts = await import('./index.X0nbfr6-.js').then(function (n) { return n.i; }), { projectName } = await prompts.default({
7575
7480
  type: "select",
7576
7481
  name: "projectName",
7577
7482
  choices: headedBrowserProjects.map((project) => ({
@@ -7586,10 +7491,9 @@ async function resolveBrowserProjects(vitest, names, resolvedProjects) {
7586
7491
  return resolvedProjects;
7587
7492
  }
7588
7493
  function cloneConfig(project, { browser,...config }) {
7589
- const { locators, viewport, testerHtmlPath, headless, screenshotDirectory, screenshotFailures, browser: _browser, name,...overrideConfig } = config;
7590
- const currentConfig = project.config.browser;
7494
+ const { locators, viewport, testerHtmlPath, headless, screenshotDirectory, screenshotFailures, browser: _browser, name,...overrideConfig } = config, currentConfig = project.config.browser, clonedConfig = deepClone(project.config);
7591
7495
  return mergeConfig({
7592
- ...deepClone(project.config),
7496
+ ...clonedConfig,
7593
7497
  browser: {
7594
7498
  ...project.config.browser,
7595
7499
  locators: locators ? { testIdAttribute: locators.testIdAttribute ?? currentConfig.locators.testIdAttribute } : project.config.browser.locators,
@@ -7601,18 +7505,15 @@ function cloneConfig(project, { browser,...config }) {
7601
7505
  name: browser,
7602
7506
  providerOptions: config,
7603
7507
  instances: void 0
7604
- }
7508
+ },
7509
+ include: overrideConfig.include && overrideConfig.include.length > 0 ? [] : clonedConfig.include,
7510
+ exclude: overrideConfig.exclude && overrideConfig.exclude.length > 0 ? [] : clonedConfig.exclude,
7511
+ includeSource: overrideConfig.includeSource && overrideConfig.includeSource.length > 0 ? [] : clonedConfig.includeSource
7605
7512
  }, overrideConfig);
7606
7513
  }
7607
7514
  async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDefinition) {
7608
7515
  // project configurations that were specified directly
7609
- const projectsOptions = [];
7610
- // custom config files that were specified directly or resolved from a directory
7611
- const projectsConfigFiles = [];
7612
- // custom glob matches that should be resolved as directories or config files
7613
- const projectsGlobMatches = [];
7614
- // directories that don't have a config file inside, but should be treated as projects
7615
- const nonConfigProjectDirectories = [];
7516
+ const projectsOptions = [], projectsConfigFiles = [], projectsGlobMatches = [], nonConfigProjectDirectories = [];
7616
7517
  for (const definition of projectsDefinition) if (typeof definition === "string") {
7617
7518
  const stringOption = definition.replace("<rootDir>", vitest.config.root);
7618
7519
  // if the string doesn't contain a glob, we can resolve it directly
@@ -7656,8 +7557,7 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDe
7656
7557
  "**/*.timestamp-*",
7657
7558
  "**/.DS_Store"
7658
7559
  ]
7659
- };
7660
- const projectsFs = await glob(projectsGlobMatches, globOptions);
7560
+ }, projectsFs = await glob(projectsGlobMatches, globOptions);
7661
7561
  await Promise.all(projectsFs.map(async (path) => {
7662
7562
  // directories are allowed with a glob like `packages/*`
7663
7563
  // in this case every directory is treated as a project
@@ -7676,21 +7576,15 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDe
7676
7576
  };
7677
7577
  }
7678
7578
  async function resolveDirectoryConfig(directory) {
7679
- const files = new Set(await promises.readdir(directory));
7680
- // default resolution looks for vitest.config.* or vite.config.* files
7681
- // this simulates how `findUp` works in packages/vitest/src/node/create.ts:29
7682
- const configFile = configFiles.find((file) => files.has(file));
7683
- if (configFile) return resolve(directory, configFile);
7684
- return null;
7579
+ const files = new Set(await promises.readdir(directory)), configFile = configFiles.find((file) => files.has(file));
7580
+ return configFile ? resolve(directory, configFile) : null;
7685
7581
  }
7686
7582
  function getDefaultTestProject(vitest) {
7687
- const filter = vitest.config.project;
7688
- const project = vitest._ensureRootProject();
7583
+ const filter = vitest.config.project, project = vitest._ensureRootProject();
7689
7584
  if (!filter.length) return project;
7690
7585
  // check for the project name and browser names
7691
7586
  const hasProjects = getPotentialProjectNames(project).some((p) => vitest.matchesProjectFilter(p));
7692
- if (hasProjects) return project;
7693
- return null;
7587
+ return hasProjects ? project : null;
7694
7588
  }
7695
7589
  function getPotentialProjectNames(project) {
7696
7590
  const names = [project.name];
@@ -7702,7 +7596,7 @@ function getPotentialProjectNames(project) {
7702
7596
  async function loadCustomReporterModule(path, runner) {
7703
7597
  let customReporterModule;
7704
7598
  try {
7705
- customReporterModule = await runner.executeId(path);
7599
+ customReporterModule = await runner.import(path);
7706
7600
  } catch (customReporterModuleError) {
7707
7601
  throw new Error(`Failed to load custom Reporter from ${path}`, { cause: customReporterModuleError });
7708
7602
  }
@@ -7710,12 +7604,11 @@ async function loadCustomReporterModule(path, runner) {
7710
7604
  return customReporterModule.default;
7711
7605
  }
7712
7606
  function createReporters(reporterReferences, ctx) {
7713
- const runner = ctx.runner;
7714
- const promisedReporters = reporterReferences.map(async (referenceOrInstance) => {
7607
+ const runner = ctx.runner, promisedReporters = reporterReferences.map(async (referenceOrInstance) => {
7715
7608
  if (Array.isArray(referenceOrInstance)) {
7716
7609
  const [reporterName, reporterOptions] = referenceOrInstance;
7717
7610
  if (reporterName === "html") {
7718
- await ctx.packageInstaller.ensureInstalled("@vitest/ui", runner.root, ctx.version);
7611
+ await ctx.packageInstaller.ensureInstalled("@vitest/ui", ctx.config.root, ctx.version);
7719
7612
  const CustomReporter = await loadCustomReporterModule("@vitest/ui/reporter", runner);
7720
7613
  return new CustomReporter(reporterOptions);
7721
7614
  } else if (reporterName in ReportersMap) {
@@ -7752,14 +7645,12 @@ function parseFilter(filter) {
7752
7645
  filename: parsedFilename,
7753
7646
  lineNumber: Number.parseInt(lineNumber)
7754
7647
  };
7755
- else if (lineNumber.match(/^\d+-\d+$/)) throw new RangeLocationFilterProvidedError(filter);
7756
- else return { filename: filter };
7648
+ if (lineNumber.match(/^\d+-\d+$/)) throw new RangeLocationFilterProvidedError(filter);
7649
+ return { filename: filter };
7757
7650
  }
7758
7651
  function groupFilters(filters) {
7759
- const groupedFilters_ = groupBy(filters, (f) => f.filename);
7760
- const groupedFilters = Object.fromEntries(Object.entries(groupedFilters_).map((entry) => {
7761
- const [filename, filters] = entry;
7762
- const testLocations = filters.map((f) => f.lineNumber);
7652
+ const groupedFilters_ = groupBy(filters, (f) => f.filename), groupedFilters = Object.fromEntries(Object.entries(groupedFilters_).map((entry) => {
7653
+ const [filename, filters] = entry, testLocations = filters.map((f) => f.lineNumber);
7763
7654
  return [filename, testLocations.filter((l) => l !== void 0)];
7764
7655
  }));
7765
7656
  return groupedFilters;
@@ -7778,45 +7669,35 @@ class VitestSpecifications {
7778
7669
  if (project._isCachedTestFile(moduleId)) specs.push(project.createSpecification(moduleId));
7779
7670
  if (project._isCachedTypecheckFile(moduleId)) specs.push(project.createSpecification(moduleId, [], "typescript"));
7780
7671
  }
7781
- specs.forEach((spec) => this.ensureSpecificationCached(spec));
7782
- return specs;
7672
+ return specs.forEach((spec) => this.ensureSpecificationCached(spec)), specs;
7783
7673
  }
7784
7674
  async getRelevantTestSpecifications(filters = []) {
7785
7675
  return this.filterTestsBySource(await this.globTestSpecifications(filters));
7786
7676
  }
7787
7677
  async globTestSpecifications(filters = []) {
7788
- const files = [];
7789
- const dir = process.cwd();
7790
- const parsedFilters = filters.map((f) => parseFilter(f));
7678
+ const files = [], dir = process.cwd(), parsedFilters = filters.map((f) => parseFilter(f));
7791
7679
  // Require includeTaskLocation when a location filter is passed
7792
7680
  if (!this.vitest.config.includeTaskLocation && parsedFilters.some((f) => f.lineNumber !== void 0)) throw new IncludeTaskLocationDisabledError();
7793
7681
  const testLines = groupFilters(parsedFilters.map((f) => ({
7794
7682
  ...f,
7795
7683
  filename: resolve(dir, f.filename)
7796
- })));
7797
- // Key is file and val specifies whether we have matched this file with testLocation
7798
- const testLocHasMatch = {};
7799
- await Promise.all(this.vitest.projects.map(async (project) => {
7684
+ }))), testLocHasMatch = {};
7685
+ return await Promise.all(this.vitest.projects.map(async (project) => {
7800
7686
  const { testFiles, typecheckTestFiles } = await project.globTestFiles(parsedFilters.map((f) => f.filename));
7801
7687
  testFiles.forEach((file) => {
7802
7688
  const lines = testLines[file];
7803
7689
  testLocHasMatch[file] = true;
7804
7690
  const spec = project.createSpecification(file, lines);
7805
- this.ensureSpecificationCached(spec);
7806
- files.push(spec);
7807
- });
7808
- typecheckTestFiles.forEach((file) => {
7691
+ this.ensureSpecificationCached(spec), files.push(spec);
7692
+ }), typecheckTestFiles.forEach((file) => {
7809
7693
  const lines = testLines[file];
7810
7694
  testLocHasMatch[file] = true;
7811
7695
  const spec = project.createSpecification(file, lines, "typescript");
7812
- this.ensureSpecificationCached(spec);
7813
- files.push(spec);
7696
+ this.ensureSpecificationCached(spec), files.push(spec);
7814
7697
  });
7815
- }));
7816
- Object.entries(testLines).forEach(([filepath, loc]) => {
7698
+ })), Object.entries(testLines).forEach(([filepath, loc]) => {
7817
7699
  if (loc.length !== 0 && !testLocHasMatch[filepath]) throw new LocationFilterFileNotFoundError(relative(dir, filepath));
7818
- });
7819
- return files;
7700
+ }), files;
7820
7701
  }
7821
7702
  clearCache(moduleId) {
7822
7703
  if (moduleId) this._cachedSpecs.delete(moduleId);
@@ -7826,30 +7707,20 @@ class VitestSpecifications {
7826
7707
  return this._cachedSpecs.get(moduleId);
7827
7708
  }
7828
7709
  ensureSpecificationCached(spec) {
7829
- const file = spec.moduleId;
7830
- const specs = this._cachedSpecs.get(file) || [];
7831
- const index = specs.findIndex((_s) => _s.project === spec.project && _s.pool === spec.pool);
7832
- if (index === -1) {
7833
- specs.push(spec);
7834
- this._cachedSpecs.set(file, specs);
7835
- } else specs.splice(index, 1, spec);
7710
+ const file = spec.moduleId, specs = this._cachedSpecs.get(file) || [], index = specs.findIndex((_s) => _s.project === spec.project && _s.pool === spec.pool);
7711
+ if (index === -1) specs.push(spec), this._cachedSpecs.set(file, specs);
7712
+ else specs.splice(index, 1, spec);
7836
7713
  return specs;
7837
7714
  }
7838
7715
  async filterTestsBySource(specs) {
7839
7716
  if (this.vitest.config.changed && !this.vitest.config.related) {
7840
- const { VitestGit } = await import('./git.BVQ8w_Sw.js');
7841
- const vitestGit = new VitestGit(this.vitest.config.root);
7842
- const related = await vitestGit.findChangedFiles({ changedSince: this.vitest.config.changed });
7843
- if (!related) {
7844
- process.exitCode = 1;
7845
- throw new GitNotFoundError();
7846
- }
7717
+ const { VitestGit } = await import('./git.BFNcloKD.js'), vitestGit = new VitestGit(this.vitest.config.root), related = await vitestGit.findChangedFiles({ changedSince: this.vitest.config.changed });
7718
+ if (!related) throw process.exitCode = 1, new GitNotFoundError();
7847
7719
  this.vitest.config.related = Array.from(new Set(related));
7848
7720
  }
7849
7721
  const related = this.vitest.config.related;
7850
7722
  if (!related) return specs;
7851
- const forceRerunTriggers = this.vitest.config.forceRerunTriggers;
7852
- const matcher = forceRerunTriggers.length ? pm(forceRerunTriggers) : void 0;
7723
+ const forceRerunTriggers = this.vitest.config.forceRerunTriggers, matcher = forceRerunTriggers.length ? pm(forceRerunTriggers) : void 0;
7853
7724
  if (matcher && related.some((file) => matcher(file))) return specs;
7854
7725
  // don't run anything if no related sources are found
7855
7726
  // if we are in watch mode, we want to process all tests
@@ -7857,8 +7728,7 @@ class VitestSpecifications {
7857
7728
  const testGraphs = await Promise.all(specs.map(async (spec) => {
7858
7729
  const deps = await this.getTestDependencies(spec);
7859
7730
  return [spec, deps];
7860
- }));
7861
- const runningTests = [];
7731
+ })), runningTests = [];
7862
7732
  for (const [specification, deps] of testGraphs)
7863
7733
  // if deps or the test itself were changed
7864
7734
  if (related.some((path) => path === specification.moduleId || deps.has(path))) runningTests.push(specification);
@@ -7868,8 +7738,7 @@ class VitestSpecifications {
7868
7738
  const addImports = async (project, filepath) => {
7869
7739
  if (deps.has(filepath)) return;
7870
7740
  deps.add(filepath);
7871
- const mod = project.vite.moduleGraph.getModuleById(filepath);
7872
- const transformed = mod?.ssrTransformResult || await project.vitenode.transformRequest(filepath);
7741
+ const mod = project.vite.environments.ssr.moduleGraph.getModuleById(filepath), transformed = mod?.transformResult || await project.vite.environments.ssr.transformRequest(filepath);
7873
7742
  if (!transformed) return;
7874
7743
  const dependencies = [...transformed.deps || [], ...transformed.dynamicDeps || []];
7875
7744
  await Promise.all(dependencies.map(async (dep) => {
@@ -7877,9 +7746,7 @@ class VitestSpecifications {
7877
7746
  if (!fsPath.includes("node_modules") && !deps.has(fsPath) && existsSync(fsPath)) await addImports(project, fsPath);
7878
7747
  }));
7879
7748
  };
7880
- await addImports(spec.project, spec.moduleId);
7881
- deps.delete(spec.moduleId);
7882
- return deps;
7749
+ return await addImports(spec.project, spec.moduleId), deps.delete(spec.moduleId), deps;
7883
7750
  }
7884
7751
  }
7885
7752
 
@@ -7905,10 +7772,7 @@ class ReportedTaskImplementation {
7905
7772
  location;
7906
7773
  /** @internal */
7907
7774
  constructor(task, project) {
7908
- this.task = task;
7909
- this.project = project;
7910
- this.id = task.id;
7911
- this.location = task.location;
7775
+ this.task = task, this.project = project, this.id = task.id, this.location = task.location;
7912
7776
  }
7913
7777
  /**
7914
7778
  * Checks if the test did not fail the suite.
@@ -7930,8 +7794,7 @@ class ReportedTaskImplementation {
7930
7794
  */
7931
7795
  static register(task, project) {
7932
7796
  const state = new this(task, project);
7933
- storeTask(project, task, state);
7934
- return state;
7797
+ return storeTask(project, task, state), state;
7935
7798
  }
7936
7799
  }
7937
7800
  class TestCase extends ReportedTaskImplementation {
@@ -7955,9 +7818,7 @@ class TestCase extends ReportedTaskImplementation {
7955
7818
  parent;
7956
7819
  /** @internal */
7957
7820
  constructor(task, project) {
7958
- super(task, project);
7959
- this.name = task.name;
7960
- this.module = getReportedTask(project, task.file);
7821
+ super(task, project), this.name = task.name, this.module = getReportedTask(project, task.file);
7961
7822
  const suite = this.task.suite;
7962
7823
  if (suite) this.parent = getReportedTask(project, suite);
7963
7824
  else this.parent = this.module;
@@ -7979,8 +7840,7 @@ class TestCase extends ReportedTaskImplementation {
7979
7840
  * - **skipped**: Test was skipped during collection or dynamically with `ctx.skip()`.
7980
7841
  */
7981
7842
  result() {
7982
- const result = this.task.result;
7983
- const mode = result?.state || this.task.mode;
7843
+ const result = this.task.result, mode = result?.state || this.task.mode;
7984
7844
  if (!result && (mode === "skip" || mode === "todo")) return {
7985
7845
  state: "skipped",
7986
7846
  note: void 0,
@@ -7991,16 +7851,14 @@ class TestCase extends ReportedTaskImplementation {
7991
7851
  errors: void 0
7992
7852
  };
7993
7853
  const state = result.state === "fail" ? "failed" : result.state === "pass" ? "passed" : "skipped";
7994
- if (state === "skipped") return {
7854
+ return state === "skipped" ? {
7995
7855
  state,
7996
7856
  note: result.note,
7997
7857
  errors: void 0
7998
- };
7999
- if (state === "passed") return {
7858
+ } : state === "passed" ? {
8000
7859
  state,
8001
7860
  errors: result.errors
8002
- };
8003
- return {
7861
+ } : {
8004
7862
  state,
8005
7863
  errors: result.errors || []
8006
7864
  };
@@ -8019,8 +7877,7 @@ class TestCase extends ReportedTaskImplementation {
8019
7877
  const result = this.task.result;
8020
7878
  // startTime should always be available if the test has properly finished
8021
7879
  if (!result || !result.startTime) return void 0;
8022
- const duration = result.duration || 0;
8023
- const slow = duration > this.project.globalConfig.slowTestThreshold;
7880
+ const duration = result.duration || 0, slow = duration > this.project.globalConfig.slowTestThreshold;
8024
7881
  return {
8025
7882
  slow,
8026
7883
  heap: result.heap,
@@ -8036,8 +7893,7 @@ class TestCollection {
8036
7893
  #task;
8037
7894
  #project;
8038
7895
  constructor(task, project) {
8039
- this.#task = task;
8040
- this.#project = project;
7896
+ this.#task = task, this.#project = project;
8041
7897
  }
8042
7898
  /**
8043
7899
  * Returns the test or suite at a specific index.
@@ -8090,10 +7946,7 @@ class TestCollection {
8090
7946
  * Filters all suites that are part of this collection and its children.
8091
7947
  */
8092
7948
  *allSuites() {
8093
- for (const child of this) if (child.type === "suite") {
8094
- yield child;
8095
- yield* child.children.allSuites();
8096
- }
7949
+ for (const child of this) if (child.type === "suite") yield child, yield* child.children.allSuites();
8097
7950
  }
8098
7951
  *[Symbol.iterator]() {
8099
7952
  for (const task of this.#task.tasks) yield getReportedTask(this.#project, task);
@@ -8106,8 +7959,7 @@ class SuiteImplementation extends ReportedTaskImplementation {
8106
7959
  children;
8107
7960
  /** @internal */
8108
7961
  constructor(task, project) {
8109
- super(task, project);
8110
- this.children = new TestCollection(task, project);
7962
+ super(task, project), this.children = new TestCollection(task, project);
8111
7963
  }
8112
7964
  /**
8113
7965
  * Errors that happened outside of the test run during collection, like syntax errors.
@@ -8137,9 +7989,7 @@ class TestSuite extends SuiteImplementation {
8137
7989
  options;
8138
7990
  /** @internal */
8139
7991
  constructor(task, project) {
8140
- super(task, project);
8141
- this.name = task.name;
8142
- this.module = getReportedTask(project, task.file);
7992
+ super(task, project), this.name = task.name, this.module = getReportedTask(project, task.file);
8143
7993
  const suite = this.task.suite;
8144
7994
  if (suite) this.parent = getReportedTask(project, suite);
8145
7995
  else this.parent = this.module;
@@ -8170,29 +8020,21 @@ class TestModule extends SuiteImplementation {
8170
8020
  moduleId;
8171
8021
  /** @internal */
8172
8022
  constructor(task, project) {
8173
- super(task, project);
8174
- this.moduleId = task.filepath;
8023
+ super(task, project), this.moduleId = task.filepath;
8175
8024
  }
8176
8025
  /**
8177
8026
  * Checks the running state of the test file.
8178
8027
  */
8179
8028
  state() {
8180
8029
  const state = this.task.result?.state;
8181
- if (state === "queued") return "queued";
8182
- return getSuiteState(this.task);
8030
+ return state === "queued" ? "queued" : getSuiteState(this.task);
8183
8031
  }
8184
8032
  /**
8185
8033
  * Useful information about the module like duration, memory usage, etc.
8186
8034
  * If the module was not executed yet, all diagnostic values will return `0`.
8187
8035
  */
8188
8036
  diagnostic() {
8189
- const setupDuration = this.task.setupDuration || 0;
8190
- const collectDuration = this.task.collectDuration || 0;
8191
- const prepareDuration = this.task.prepareDuration || 0;
8192
- const environmentSetupDuration = this.task.environmentLoad || 0;
8193
- const duration = this.task.result?.duration || 0;
8194
- const heap = this.task.result?.heap;
8195
- const importDurations = this.task.importDurations ?? {};
8037
+ const setupDuration = this.task.setupDuration || 0, collectDuration = this.task.collectDuration || 0, prepareDuration = this.task.prepareDuration || 0, environmentSetupDuration = this.task.environmentLoad || 0, duration = this.task.result?.duration || 0, heap = this.task.result?.heap, importDurations = this.task.importDurations ?? {};
8196
8038
  return {
8197
8039
  environmentSetupDuration,
8198
8040
  prepareDuration,
@@ -8224,8 +8066,7 @@ function getReportedTask(project, runnerTask) {
8224
8066
  return reportedTask;
8225
8067
  }
8226
8068
  function getSuiteState(task) {
8227
- const mode = task.mode;
8228
- const state = task.result?.state;
8069
+ const mode = task.mode, state = task.result?.state;
8229
8070
  if (mode === "skip" || mode === "todo" || state === "skip" || state === "todo") return "skipped";
8230
8071
  if (state == null || state === "run" || state === "only") return "pending";
8231
8072
  if (state === "fail") return "failed";
@@ -8234,8 +8075,7 @@ function getSuiteState(task) {
8234
8075
  }
8235
8076
 
8236
8077
  function isAggregateError(err) {
8237
- if (typeof AggregateError !== "undefined" && err instanceof AggregateError) return true;
8238
- return err instanceof Error && "errors" in err;
8078
+ return typeof AggregateError !== "undefined" && err instanceof AggregateError ? true : err instanceof Error && "errors" in err;
8239
8079
  }
8240
8080
  class StateManager {
8241
8081
  filesMap = /* @__PURE__ */ new Map();
@@ -8246,6 +8086,7 @@ class StateManager {
8246
8086
  processTimeoutCauses = /* @__PURE__ */ new Set();
8247
8087
  reportedTasksMap = /* @__PURE__ */ new WeakMap();
8248
8088
  blobs;
8089
+ transformTime = 0;
8249
8090
  onUnhandledError;
8250
8091
  /** @internal */
8251
8092
  _data = {
@@ -8265,12 +8106,7 @@ class StateManager {
8265
8106
  const _error = error;
8266
8107
  if (_error && typeof _error === "object" && _error.code === "VITEST_PENDING") {
8267
8108
  const task = this.idMap.get(_error.taskId);
8268
- if (task) {
8269
- task.mode = "skip";
8270
- task.result ??= { state: "skip" };
8271
- task.result.state = "skip";
8272
- task.result.note = _error.note;
8273
- }
8109
+ if (task) task.mode = "skip", task.result ??= { state: "skip" }, task.result.state = "skip", task.result.note = _error.note;
8274
8110
  return;
8275
8111
  }
8276
8112
  if (!this.onUnhandledError || this.onUnhandledError(error) !== false) this.errorsSet.add(error);
@@ -8294,12 +8130,8 @@ class StateManager {
8294
8130
  * Return files that were running or collected.
8295
8131
  */
8296
8132
  getFiles(keys) {
8297
- if (keys) return keys.map((key) => this.filesMap.get(key)).flat().filter((file) => file && !file.local);
8298
- return Array.from(this.filesMap.values()).flat().filter((file) => !file.local).sort((f1, f2) => {
8299
- // print typecheck files first
8300
- if (f1.meta?.typecheck && f2.meta?.typecheck) return 0;
8301
- if (f1.meta?.typecheck) return -1;
8302
- return 1;
8133
+ return keys ? keys.map((key) => this.filesMap.get(key)).flat().filter((file) => file && !file.local) : Array.from(this.filesMap.values()).flat().filter((file) => !file.local).sort((f1, f2) => {
8134
+ return f1.meta?.typecheck && f2.meta?.typecheck ? 0 : f1.meta?.typecheck ? -1 : 1;
8303
8135
  });
8304
8136
  }
8305
8137
  getTestModules(keys) {
@@ -8318,25 +8150,17 @@ class StateManager {
8318
8150
  }
8319
8151
  collectFiles(project, files = []) {
8320
8152
  files.forEach((file) => {
8321
- const existing = this.filesMap.get(file.filepath) || [];
8322
- const otherFiles = existing.filter((i) => i.projectName !== file.projectName || i.meta.typecheck !== file.meta.typecheck);
8323
- const currentFile = existing.find((i) => i.projectName === file.projectName);
8153
+ const existing = this.filesMap.get(file.filepath) || [], otherFiles = existing.filter((i) => i.projectName !== file.projectName || i.meta.typecheck !== file.meta.typecheck), currentFile = existing.find((i) => i.projectName === file.projectName);
8324
8154
  // keep logs for the previous file because it should always be initiated before the collections phase
8325
8155
  // which means that all logs are collected during the collection and not inside tests
8326
8156
  if (currentFile) file.logs = currentFile.logs;
8327
- otherFiles.push(file);
8328
- this.filesMap.set(file.filepath, otherFiles);
8329
- this.updateId(file, project);
8157
+ otherFiles.push(file), this.filesMap.set(file.filepath, otherFiles), this.updateId(file, project);
8330
8158
  });
8331
8159
  }
8332
8160
  clearFiles(project, paths = []) {
8333
8161
  paths.forEach((path) => {
8334
- const files = this.filesMap.get(path);
8335
- const fileTask = createFileTask(path, project.config.root, project.config.name);
8336
- fileTask.local = true;
8337
- TestModule.register(fileTask, project);
8338
- this.idMap.set(fileTask.id, fileTask);
8339
- if (!files) {
8162
+ const files = this.filesMap.get(path), fileTask = createFileTask(path, project.config.root, project.config.name);
8163
+ if (fileTask.local = true, TestModule.register(fileTask, project), this.idMap.set(fileTask.id, fileTask), !files) {
8340
8164
  this.filesMap.set(path, [fileTask]);
8341
8165
  return;
8342
8166
  }
@@ -8347,14 +8171,14 @@ class StateManager {
8347
8171
  });
8348
8172
  }
8349
8173
  updateId(task, project) {
8350
- if (this.idMap.get(task.id) === task) return;
8351
- if (task.type === "suite" && "filepath" in task) TestModule.register(task, project);
8352
- else if (task.type === "suite") TestSuite.register(task, project);
8353
- else TestCase.register(task, project);
8354
- this.idMap.set(task.id, task);
8355
- if (task.type === "suite") task.tasks.forEach((task) => {
8356
- this.updateId(task, project);
8357
- });
8174
+ if (this.idMap.get(task.id) !== task) {
8175
+ if (task.type === "suite" && "filepath" in task) TestModule.register(task, project);
8176
+ else if (task.type === "suite") TestSuite.register(task, project);
8177
+ else TestCase.register(task, project);
8178
+ if (this.idMap.set(task.id, task), task.type === "suite") task.tasks.forEach((task) => {
8179
+ this.updateId(task, project);
8180
+ });
8181
+ }
8358
8182
  }
8359
8183
  getReportedEntity(task) {
8360
8184
  return this.reportedTasksMap.get(task);
@@ -8363,10 +8187,8 @@ class StateManager {
8363
8187
  for (const [id, result, meta] of packs) {
8364
8188
  const task = this.idMap.get(id);
8365
8189
  if (task) {
8366
- task.result = result;
8367
- task.meta = meta;
8368
8190
  // skipped with new PendingError
8369
- if (result?.state === "skip") task.mode = "skip";
8191
+ if (task.result = result, task.meta = meta, result?.state === "skip") task.mode = "skip";
8370
8192
  }
8371
8193
  }
8372
8194
  }
@@ -8843,10 +8665,7 @@ class TestRun {
8843
8665
  }
8844
8666
  async start(specifications) {
8845
8667
  const filepaths = specifications.map((spec) => spec.moduleId);
8846
- this.vitest.state.collectPaths(filepaths);
8847
- await this.vitest.report("onPathsCollected", Array.from(new Set(filepaths)));
8848
- await this.vitest.report("onSpecsCollected", specifications.map((spec) => spec.toJSON()));
8849
- await this.vitest.report("onTestRunStart", [...specifications]);
8668
+ this.vitest.state.collectPaths(filepaths), await this.vitest.report("onTestRunStart", [...specifications]);
8850
8669
  }
8851
8670
  async enqueued(project, file) {
8852
8671
  this.vitest.state.collectFiles(project, [file]);
@@ -8854,25 +8673,17 @@ class TestRun {
8854
8673
  await this.vitest.report("onTestModuleQueued", testModule);
8855
8674
  }
8856
8675
  async collected(project, files) {
8857
- this.vitest.state.collectFiles(project, files);
8858
- await Promise.all([this.vitest.report("onCollected", files), ...files.map((file) => {
8676
+ this.vitest.state.collectFiles(project, files), await Promise.all(files.map((file) => {
8859
8677
  const testModule = this.vitest.state.getReportedEntity(file);
8860
8678
  return this.vitest.report("onTestModuleCollected", testModule);
8861
- })]);
8679
+ }));
8862
8680
  }
8863
8681
  async log(log) {
8864
- this.vitest.state.updateUserLog(log);
8865
- await this.vitest.report("onUserConsoleLog", log);
8682
+ this.vitest.state.updateUserLog(log), await this.vitest.report("onUserConsoleLog", log);
8866
8683
  }
8867
8684
  async annotate(testId, annotation) {
8868
- const task = this.vitest.state.idMap.get(testId);
8869
- const entity = task && this.vitest.state.getReportedEntity(task);
8870
- assert$1(task && entity, `Entity must be found for task ${task?.name || testId}`);
8871
- assert$1(entity.type === "test", `Annotation can only be added to a test, instead got ${entity.type}`);
8872
- await this.resolveTestAttachment(entity, annotation);
8873
- entity.task.annotations.push(annotation);
8874
- await this.vitest.report("onTestCaseAnnotate", entity, annotation);
8875
- return annotation;
8685
+ const task = this.vitest.state.idMap.get(testId), entity = task && this.vitest.state.getReportedEntity(task);
8686
+ return assert$1(task && entity, `Entity must be found for task ${task?.name || testId}`), assert$1(entity.type === "test", `Annotation can only be added to a test, instead got ${entity.type}`), await this.resolveTestAttachment(entity, annotation), entity.task.annotations.push(annotation), await this.vitest.report("onTestCaseAnnotate", entity, annotation), annotation;
8876
8687
  }
8877
8688
  async updated(update, events) {
8878
8689
  this.vitest.state.updateTasks(update);
@@ -8885,30 +8696,21 @@ class TestRun {
8885
8696
  await this.vitest.report("onTaskUpdate", update, events);
8886
8697
  }
8887
8698
  async end(specifications, errors, coverage) {
8699
+ if (coverage) await this.vitest.report("onCoverage", coverage);
8888
8700
  // specification won't have the File task if they were filtered by the --shard command
8889
- const modules = specifications.map((spec) => spec.testModule).filter((s) => s != null);
8890
- const files = modules.map((m) => m.task);
8891
- const state = this.vitest.isCancelling ? "interrupted" : this.hasFailed(modules) ? "failed" : "passed";
8701
+ const modules = specifications.map((spec) => spec.testModule).filter((s) => s != null), state = this.vitest.isCancelling ? "interrupted" : this.hasFailed(modules) ? "failed" : "passed";
8892
8702
  if (state !== "passed") process.exitCode = 1;
8893
- try {
8894
- await Promise.all([this.vitest.report("onTestRunEnd", modules, [...errors], state), this.vitest.report("onFinished", files, errors, coverage)]);
8895
- } finally {
8896
- if (coverage) await this.vitest.report("onCoverage", coverage);
8897
- }
8703
+ this.vitest.report("onTestRunEnd", modules, [...errors], state);
8898
8704
  }
8899
8705
  hasFailed(modules) {
8900
- if (!modules.length) return !this.vitest.config.passWithNoTests;
8901
- return modules.some((m) => !m.ok());
8706
+ return modules.length ? modules.some((m) => !m.ok()) : !this.vitest.config.passWithNoTests;
8902
8707
  }
8903
8708
  async reportEvent(id, event, data) {
8904
- const task = this.vitest.state.idMap.get(id);
8905
- const entity = task && this.vitest.state.getReportedEntity(task);
8906
- assert$1(task && entity, `Entity must be found for task ${task?.name || id}`);
8907
- if (event === "suite-prepare" && entity.type === "suite") return await this.vitest.report("onTestSuiteReady", entity);
8709
+ const task = this.vitest.state.idMap.get(id), entity = task && this.vitest.state.getReportedEntity(task);
8710
+ if (assert$1(task && entity, `Entity must be found for task ${task?.name || id}`), event === "suite-prepare" && entity.type === "suite") return await this.vitest.report("onTestSuiteReady", entity);
8908
8711
  if (event === "suite-prepare" && entity.type === "module") return await this.vitest.report("onTestModuleStart", entity);
8909
8712
  if (event === "suite-finished") {
8910
- assert$1(entity.type === "suite" || entity.type === "module", "Entity type must be suite or module");
8911
- if (entity.state() === "skipped")
8713
+ if (assert$1(entity.type === "suite" || entity.type === "module", "Entity type must be suite or module"), entity.state() === "skipped")
8912
8714
  // everything inside suite or a module is skipped,
8913
8715
  // so we won't get any children events
8914
8716
  // we need to report everything manually
@@ -8920,8 +8722,7 @@ class TestRun {
8920
8722
  if (event === "test-prepare" && entity.type === "test") return await this.vitest.report("onTestCaseReady", entity);
8921
8723
  if (event === "test-finished" && entity.type === "test") return await this.vitest.report("onTestCaseResult", entity);
8922
8724
  if (event.startsWith("before-hook") || event.startsWith("after-hook")) {
8923
- const isBefore = event.startsWith("before-hook");
8924
- const hook = entity.type === "test" ? {
8725
+ const isBefore = event.startsWith("before-hook"), hook = entity.type === "test" ? {
8925
8726
  name: isBefore ? "beforeEach" : "afterEach",
8926
8727
  entity
8927
8728
  } : {
@@ -8933,37 +8734,25 @@ class TestRun {
8933
8734
  // this can only happen in --merge-reports, and annotation is already resolved
8934
8735
  if (event === "test-annotation") {
8935
8736
  const annotation = data?.annotation;
8936
- assert$1(annotation && entity.type === "test");
8937
- await this.vitest.report("onTestCaseAnnotate", entity, annotation);
8737
+ assert$1(annotation && entity.type === "test"), await this.vitest.report("onTestCaseAnnotate", entity, annotation);
8938
8738
  }
8939
8739
  }
8940
8740
  }
8941
8741
  async resolveTestAttachment(test, annotation) {
8942
- const project = test.project;
8943
- const attachment = annotation.attachment;
8742
+ const project = test.project, attachment = annotation.attachment;
8944
8743
  if (!attachment) return attachment;
8945
8744
  const path = attachment.path;
8946
8745
  if (path && !path.startsWith("http://") && !path.startsWith("https://")) {
8947
- const currentPath = resolve(project.config.root, path);
8948
- const hash = createHash("sha1").update(currentPath).digest("hex");
8949
- const newPath = resolve(project.config.attachmentsDir, `${sanitizeFilePath(annotation.message)}-${hash}${extname(currentPath)}`);
8950
- await mkdir(dirname(newPath), { recursive: true });
8951
- await copyFile(currentPath, newPath);
8952
- attachment.path = newPath;
8746
+ const currentPath = resolve(project.config.root, path), hash = createHash("sha1").update(currentPath).digest("hex"), newPath = resolve(project.config.attachmentsDir, `${sanitizeFilePath(annotation.message)}-${hash}${extname(currentPath)}`);
8747
+ await mkdir(dirname(newPath), { recursive: true }), await copyFile(currentPath, newPath), attachment.path = newPath;
8953
8748
  const contentType = attachment.contentType ?? mime.getType(basename(currentPath));
8954
8749
  attachment.contentType = contentType || void 0;
8955
8750
  }
8956
8751
  return attachment;
8957
8752
  }
8958
8753
  async reportChildren(children) {
8959
- for (const child of children) if (child.type === "test") {
8960
- await this.vitest.report("onTestCaseReady", child);
8961
- await this.vitest.report("onTestCaseResult", child);
8962
- } else {
8963
- await this.vitest.report("onTestSuiteReady", child);
8964
- await this.reportChildren(child.children);
8965
- await this.vitest.report("onTestSuiteResult", child);
8966
- }
8754
+ for (const child of children) if (child.type === "test") await this.vitest.report("onTestCaseReady", child), await this.vitest.report("onTestCaseResult", child);
8755
+ else await this.vitest.report("onTestSuiteReady", child), await this.reportChildren(child.children), await this.vitest.report("onTestSuiteResult", child);
8967
8756
  }
8968
8757
  }
8969
8758
  function sanitizeFilePath(s) {
@@ -8991,23 +8780,15 @@ class VitestWatcher {
8991
8780
  * @internal
8992
8781
  */
8993
8782
  onWatcherRerun(cb) {
8994
- this._onRerun.push(cb);
8995
- return this;
8783
+ return this._onRerun.push(cb), this;
8996
8784
  }
8997
8785
  unregisterWatcher = noop;
8998
8786
  registerWatcher() {
8999
8787
  const watcher = this.vitest.vite.watcher;
9000
8788
  if (this.vitest.config.forceRerunTriggers.length) watcher.add(this.vitest.config.forceRerunTriggers);
9001
- watcher.on("change", this.onChange);
9002
- watcher.on("unlink", this.onUnlink);
9003
- watcher.on("add", this.onAdd);
9004
- this.unregisterWatcher = () => {
9005
- watcher.off("change", this.onChange);
9006
- watcher.off("unlink", this.onUnlink);
9007
- watcher.off("add", this.onAdd);
9008
- this.unregisterWatcher = noop;
9009
- };
9010
- return this;
8789
+ return watcher.on("change", this.onChange), watcher.on("unlink", this.onUnlink), watcher.on("add", this.onAdd), this.unregisterWatcher = () => {
8790
+ watcher.off("change", this.onChange), watcher.off("unlink", this.onUnlink), watcher.off("add", this.onAdd), this.unregisterWatcher = noop;
8791
+ }, this;
9011
8792
  }
9012
8793
  scheduleRerun(file) {
9013
8794
  this._onRerun.forEach((cb) => cb(file));
@@ -9015,25 +8796,17 @@ class VitestWatcher {
9015
8796
  getTestFilesFromWatcherTrigger(id) {
9016
8797
  if (!this.vitest.config.watchTriggerPatterns) return false;
9017
8798
  let triggered = false;
9018
- this.vitest.config.watchTriggerPatterns.forEach((definition) => {
8799
+ return this.vitest.config.watchTriggerPatterns.forEach((definition) => {
9019
8800
  const exec = definition.pattern.exec(id);
9020
8801
  if (exec) {
9021
8802
  const files = definition.testsToRun(id, exec);
9022
- if (Array.isArray(files)) {
9023
- triggered = true;
9024
- files.forEach((file) => this.changedTests.add(resolve(this.vitest.config.root, file)));
9025
- } else if (typeof files === "string") {
9026
- triggered = true;
9027
- this.changedTests.add(resolve(this.vitest.config.root, files));
9028
- }
8803
+ if (Array.isArray(files)) triggered = true, files.forEach((file) => this.changedTests.add(resolve(this.vitest.config.root, file)));
8804
+ else if (typeof files === "string") triggered = true, this.changedTests.add(resolve(this.vitest.config.root, files));
9029
8805
  }
9030
- });
9031
- return triggered;
8806
+ }), triggered;
9032
8807
  }
9033
8808
  onChange = (id) => {
9034
- id = slash(id);
9035
- this.vitest.logger.clearHighlightCache(id);
9036
- this.vitest.invalidateFile(id);
8809
+ id = slash(id), this.vitest.logger.clearHighlightCache(id), this.vitest.invalidateFile(id);
9037
8810
  const testFiles = this.getTestFilesFromWatcherTrigger(id);
9038
8811
  if (testFiles) this.scheduleRerun(id);
9039
8812
  else {
@@ -9042,21 +8815,10 @@ class VitestWatcher {
9042
8815
  }
9043
8816
  };
9044
8817
  onUnlink = (id) => {
9045
- id = slash(id);
9046
- this.vitest.logger.clearHighlightCache(id);
9047
- this.invalidates.add(id);
9048
- if (this.vitest.state.filesMap.has(id)) {
9049
- this.vitest.projects.forEach((project) => project._removeCachedTestFile(id));
9050
- this.vitest.state.filesMap.delete(id);
9051
- this.vitest.cache.results.removeFromCache(id);
9052
- this.vitest.cache.stats.removeStats(id);
9053
- this.changedTests.delete(id);
9054
- this.vitest.report("onTestRemoved", id);
9055
- }
8818
+ if (id = slash(id), this.vitest.logger.clearHighlightCache(id), this.invalidates.add(id), this.vitest.state.filesMap.has(id)) this.vitest.projects.forEach((project) => project._removeCachedTestFile(id)), this.vitest.state.filesMap.delete(id), this.vitest.cache.results.removeFromCache(id), this.vitest.cache.stats.removeStats(id), this.changedTests.delete(id), this.vitest.report("onTestRemoved", id);
9056
8819
  };
9057
8820
  onAdd = (id) => {
9058
- id = slash(id);
9059
- this.vitest.invalidateFile(id);
8821
+ id = slash(id), this.vitest.invalidateFile(id);
9060
8822
  const testFiles = this.getTestFilesFromWatcherTrigger(id);
9061
8823
  if (testFiles) {
9062
8824
  this.scheduleRerun(id);
@@ -9064,13 +8826,10 @@ class VitestWatcher {
9064
8826
  }
9065
8827
  let fileContent;
9066
8828
  const matchingProjects = [];
9067
- this.vitest.projects.forEach((project) => {
8829
+ if (this.vitest.projects.forEach((project) => {
9068
8830
  if (project.matchesTestGlob(id, () => fileContent ??= readFileSync(id, "utf-8"))) matchingProjects.push(project);
9069
- });
9070
- if (matchingProjects.length > 0) {
9071
- this.changedTests.add(id);
9072
- this.scheduleRerun(id);
9073
- } else {
8831
+ }), matchingProjects.length > 0) this.changedTests.add(id), this.scheduleRerun(id);
8832
+ else {
9074
8833
  // it's possible that file was already there but watcher triggered "add" event instead
9075
8834
  const needsRerun = this.handleFileChanged(id);
9076
8835
  if (needsRerun) this.scheduleRerun(id);
@@ -9078,51 +8837,33 @@ class VitestWatcher {
9078
8837
  };
9079
8838
  handleSetupFile(filepath) {
9080
8839
  let isSetupFile = false;
9081
- this.vitest.projects.forEach((project) => {
9082
- if (!project.config.setupFiles.includes(filepath)) return;
9083
- this.vitest.state.filesMap.forEach((files) => {
8840
+ return this.vitest.projects.forEach((project) => {
8841
+ project.config.setupFiles.includes(filepath) && this.vitest.state.filesMap.forEach((files) => {
9084
8842
  files.forEach((file) => {
9085
- if (file.projectName === project.name) {
9086
- isSetupFile = true;
9087
- this.changedTests.add(file.filepath);
9088
- }
8843
+ if (file.projectName === project.name) isSetupFile = true, this.changedTests.add(file.filepath);
9089
8844
  });
9090
8845
  });
9091
- });
9092
- return isSetupFile;
8846
+ }), isSetupFile;
9093
8847
  }
9094
8848
  /**
9095
8849
  * @returns A value indicating whether rerun is needed (changedTests was mutated)
9096
8850
  */
9097
8851
  handleFileChanged(filepath) {
9098
8852
  if (this.changedTests.has(filepath) || this.invalidates.has(filepath)) return false;
9099
- if (pm.isMatch(filepath, this.vitest.config.forceRerunTriggers)) {
9100
- this.vitest.state.getFilepaths().forEach((file) => this.changedTests.add(file));
9101
- return true;
9102
- }
8853
+ if (pm.isMatch(filepath, this.vitest.config.forceRerunTriggers)) return this.vitest.state.getFilepaths().forEach((file) => this.changedTests.add(file)), true;
9103
8854
  if (this.handleSetupFile(filepath)) return true;
9104
8855
  const projects = this.vitest.projects.filter((project) => {
9105
8856
  const moduleGraph = project.browser?.vite.moduleGraph || project.vite.moduleGraph;
9106
8857
  return moduleGraph.getModulesByFile(filepath)?.size;
9107
8858
  });
9108
- if (!projects.length) {
9109
- // if there are no modules it's possible that server was restarted
9110
- // we don't have information about importers anymore, so let's check if the file is a test file at least
9111
- if (this.vitest.state.filesMap.has(filepath) || this.vitest.projects.some((project) => project._isCachedTestFile(filepath))) {
9112
- this.changedTests.add(filepath);
9113
- return true;
9114
- }
9115
- return false;
9116
- }
8859
+ if (!projects.length) return this.vitest.state.filesMap.has(filepath) || this.vitest.projects.some((project) => project._isCachedTestFile(filepath)) ? (this.changedTests.add(filepath), true) : false;
9117
8860
  const files = [];
9118
8861
  for (const project of projects) {
9119
8862
  const mods = project.browser?.vite.moduleGraph.getModulesByFile(filepath) || project.vite.moduleGraph.getModulesByFile(filepath);
9120
8863
  if (!mods || !mods.size) continue;
9121
- this.invalidates.add(filepath);
9122
8864
  // one of test files that we already run, or one of test files that we can run
9123
- if (this.vitest.state.filesMap.has(filepath) || project._isCachedTestFile(filepath)) {
9124
- this.changedTests.add(filepath);
9125
- files.push(filepath);
8865
+ if (this.invalidates.add(filepath), this.vitest.state.filesMap.has(filepath) || project._isCachedTestFile(filepath)) {
8866
+ this.changedTests.add(filepath), files.push(filepath);
9126
8867
  continue;
9127
8868
  }
9128
8869
  let rerun = false;
@@ -9179,9 +8920,9 @@ class Vitest {
9179
8920
  /** @internal */ _browserSessions = new BrowserSessions();
9180
8921
  /** @internal */ _cliOptions = {};
9181
8922
  /** @internal */ reporters = [];
9182
- /** @internal */ vitenode = void 0;
9183
- /** @internal */ runner = void 0;
8923
+ /** @internal */ runner;
9184
8924
  /** @internal */ _testRun = void 0;
8925
+ /** @internal */ _resolver;
9185
8926
  isFirstRun = true;
9186
8927
  restartsCount = 0;
9187
8928
  specifications;
@@ -9193,12 +8934,7 @@ class Vitest {
9193
8934
  _cache;
9194
8935
  _snapshot;
9195
8936
  constructor(mode, cliOptions, options = {}) {
9196
- this.mode = mode;
9197
- this._cliOptions = cliOptions;
9198
- this.logger = new Logger(this, options.stdout, options.stderr);
9199
- this.packageInstaller = options.packageInstaller || new VitestPackageInstaller();
9200
- this.specifications = new VitestSpecifications(this);
9201
- this.watcher = new VitestWatcher(this).onWatcherRerun((file) => this.scheduleRerun([file]));
8937
+ this.mode = mode, this._cliOptions = cliOptions, this.logger = new Logger(this, options.stdout, options.stderr), this.packageInstaller = options.packageInstaller || new VitestPackageInstaller(), this.specifications = new VitestSpecifications(this), this.watcher = new VitestWatcher(this).onWatcherRerun((file) => this.scheduleRerun([file]));
9202
8938
  }
9203
8939
  _onRestartListeners = [];
9204
8940
  _onClose = [];
@@ -9218,8 +8954,7 @@ class Vitest {
9218
8954
  * The global config.
9219
8955
  */
9220
8956
  get config() {
9221
- assert(this._config, "config");
9222
- return this._config;
8957
+ return assert(this._config, "config"), this._config;
9223
8958
  }
9224
8959
  /** @deprecated use `vitest.vite` instead */
9225
8960
  get server() {
@@ -9229,30 +8964,26 @@ class Vitest {
9229
8964
  * Global Vite's dev server instance.
9230
8965
  */
9231
8966
  get vite() {
9232
- assert(this._vite, "vite", "server");
9233
- return this._vite;
8967
+ return assert(this._vite, "vite", "server"), this._vite;
9234
8968
  }
9235
8969
  /**
9236
8970
  * The global test state manager.
9237
8971
  * @experimental The State API is experimental and not subject to semver.
9238
8972
  */
9239
8973
  get state() {
9240
- assert(this._state, "state");
9241
- return this._state;
8974
+ return assert(this._state, "state"), this._state;
9242
8975
  }
9243
8976
  /**
9244
8977
  * The global snapshot manager. You can access the current state on `snapshot.summary`.
9245
8978
  */
9246
8979
  get snapshot() {
9247
- assert(this._snapshot, "snapshot", "snapshot manager");
9248
- return this._snapshot;
8980
+ return assert(this._snapshot, "snapshot", "snapshot manager"), this._snapshot;
9249
8981
  }
9250
8982
  /**
9251
8983
  * Test results and test file stats cache. Primarily used by the sequencer to sort tests.
9252
8984
  */
9253
8985
  get cache() {
9254
- assert(this._cache, "cache");
9255
- return this._cache;
8986
+ return assert(this._cache, "cache"), this._cache;
9256
8987
  }
9257
8988
  /** @deprecated internal */
9258
8989
  setServer(options, server) {
@@ -9260,57 +8991,21 @@ class Vitest {
9260
8991
  }
9261
8992
  /** @internal */
9262
8993
  async _setServer(options, server) {
9263
- this.watcher.unregisterWatcher();
9264
- clearTimeout(this._rerunTimer);
9265
- this.restartsCount += 1;
9266
- this.pool?.close?.();
9267
- this.pool = void 0;
9268
- this.closingPromise = void 0;
9269
- this.projects = [];
9270
- this.coverageProvider = void 0;
9271
- this.runningPromise = void 0;
9272
- this.coreWorkspaceProject = void 0;
9273
- this.specifications.clearCache();
9274
- this._onUserTestsRerun = [];
9275
- this._vite = server;
8994
+ this.watcher.unregisterWatcher(), clearTimeout(this._rerunTimer), this.restartsCount += 1, this.pool?.close?.(), this.pool = void 0, this.closingPromise = void 0, this.projects = [], this.coverageProvider = void 0, this.runningPromise = void 0, this.coreWorkspaceProject = void 0, this.specifications.clearCache(), this._onUserTestsRerun = [], this._vite = server;
9276
8995
  const resolved = resolveConfig(this, options, server.config);
9277
- this._config = resolved;
9278
- this._state = new StateManager({ onUnhandledError: resolved.onUnhandledError });
9279
- this._cache = new VitestCache(this.version);
9280
- this._snapshot = new SnapshotManager({ ...resolved.snapshotOptions });
9281
- this._testRun = new TestRun(this);
9282
- if (this.config.watch) this.watcher.registerWatcher();
9283
- this.vitenode = new ViteNodeServer(server, this.config.server);
9284
- const node = this.vitenode;
9285
- this.runner = new ViteNodeRunner({
9286
- root: server.config.root,
9287
- base: server.config.base,
9288
- fetchModule(id) {
9289
- return node.fetchModule(id);
9290
- },
9291
- resolveId(id, importer) {
9292
- return node.resolveId(id, importer);
9293
- }
9294
- });
9295
- if (this.config.watch) {
8996
+ if (this._config = resolved, this._state = new StateManager({ onUnhandledError: resolved.onUnhandledError }), this._cache = new VitestCache(this.version), this._snapshot = new SnapshotManager({ ...resolved.snapshotOptions }), this._testRun = new TestRun(this), this.config.watch) this.watcher.registerWatcher();
8997
+ this._resolver = new VitestResolver(server.config.cacheDir, resolved);
8998
+ const environment = server.environments.__vitest__;
8999
+ if (this.runner = new ServerModuleRunner(environment, this._resolver, resolved), this.config.watch) {
9296
9000
  // hijack server restart
9297
9001
  const serverRestart = server.restart;
9298
- server.restart = async (...args) => {
9299
- await Promise.all(this._onRestartListeners.map((fn) => fn()));
9300
- this.report("onServerRestart");
9301
- await this.close();
9302
- await serverRestart(...args);
9303
- };
9304
9002
  // since we set `server.hmr: false`, Vite does not auto restart itself
9305
- server.watcher.on("change", async (file) => {
9003
+ server.restart = async (...args) => {
9004
+ await Promise.all(this._onRestartListeners.map((fn) => fn())), this.report("onServerRestart"), await this.close(), await serverRestart(...args);
9005
+ }, server.watcher.on("change", async (file) => {
9306
9006
  file = normalize(file);
9307
9007
  const isConfig = file === server.config.configFile || this.projects.some((p) => p.vite.config.configFile === file);
9308
- if (isConfig) {
9309
- await Promise.all(this._onRestartListeners.map((fn) => fn("config")));
9310
- this.report("onServerRestart", "config");
9311
- await this.close();
9312
- await serverRestart();
9313
- }
9008
+ if (isConfig) await Promise.all(this._onRestartListeners.map((fn) => fn("config"))), this.report("onServerRestart", "config"), await this.close(), await serverRestart();
9314
9009
  });
9315
9010
  }
9316
9011
  this.cache.results.setConfig(resolved.root, resolved.cache);
@@ -9318,28 +9013,24 @@ class Vitest {
9318
9013
  await this.cache.results.readFromCache();
9319
9014
  } catch {}
9320
9015
  const projects = await this.resolveProjects(this._cliOptions);
9321
- this.projects = projects;
9322
- await Promise.all(projects.flatMap((project) => {
9016
+ if (this.projects = projects, await Promise.all(projects.flatMap((project) => {
9323
9017
  const hooks = project.vite.config.getSortedPluginHooks("configureVitest");
9324
9018
  return hooks.map((hook) => hook({
9325
9019
  project,
9326
9020
  vitest: this,
9327
9021
  injectTestProjects: this.injectTestProject
9328
9022
  }));
9329
- }));
9330
- if (this._cliOptions.browser?.enabled) {
9023
+ })), this._cliOptions.browser?.enabled) {
9331
9024
  const browserProjects = this.projects.filter((p) => p.config.browser.enabled);
9332
9025
  if (!browserProjects.length) throw new Error(`Vitest received --browser flag, but no project had a browser configuration.`);
9333
9026
  }
9334
9027
  if (!this.projects.length) {
9335
9028
  const filter = toArray(resolved.project).join("\", \"");
9336
- if (filter) throw new Error(`No projects matched the filter "${filter}".`);
9337
- else throw new Error(`Vitest wasn't able to resolve any project.`);
9029
+ throw filter ? new Error(`No projects matched the filter "${filter}".`) : new Error(`Vitest wasn't able to resolve any project.`);
9338
9030
  }
9339
9031
  if (!this.coreWorkspaceProject) this.coreWorkspaceProject = TestProject._createBasicProject(this);
9340
9032
  if (this.config.testNamePattern) this.configOverride.testNamePattern = this.config.testNamePattern;
9341
- this.reporters = resolved.mode === "benchmark" ? await createBenchmarkReporters(toArray(resolved.benchmark?.reporters), this.runner) : await createReporters(resolved.reporters, this);
9342
- await Promise.all(this._onSetServer.map((fn) => fn()));
9033
+ this.reporters = resolved.mode === "benchmark" ? await createBenchmarkReporters(toArray(resolved.benchmark?.reporters), this.runner) : await createReporters(resolved.reporters, this), await Promise.all(this._onSetServer.map((fn) => fn()));
9343
9034
  }
9344
9035
  /**
9345
9036
  * Inject new test projects into the workspace.
@@ -9347,10 +9038,8 @@ class Vitest {
9347
9038
  * @returns An array of new test projects. Can be empty if the name was filtered out.
9348
9039
  */
9349
9040
  injectTestProject = async (config) => {
9350
- const currentNames = new Set(this.projects.map((p) => p.name));
9351
- const projects = await resolveProjects(this, this._cliOptions, void 0, Array.isArray(config) ? config : [config], currentNames);
9352
- this.projects.push(...projects);
9353
- return projects;
9041
+ const currentNames = new Set(this.projects.map((p) => p.name)), projects = await resolveProjects(this, this._cliOptions, void 0, Array.isArray(config) ? config : [config], currentNames);
9042
+ return this.projects.push(...projects), projects;
9354
9043
  };
9355
9044
  /**
9356
9045
  * Provide a value to the test context. This value will be available to all tests with `inject`.
@@ -9366,9 +9055,7 @@ class Vitest {
9366
9055
  }
9367
9056
  /** @internal */
9368
9057
  _ensureRootProject() {
9369
- if (this.coreWorkspaceProject) return this.coreWorkspaceProject;
9370
- this.coreWorkspaceProject = TestProject._createBasicProject(this);
9371
- return this.coreWorkspaceProject;
9058
+ return this.coreWorkspaceProject ||= TestProject._createBasicProject(this), this.coreWorkspaceProject;
9372
9059
  }
9373
9060
  /** @deprecated use `getRootProject` instead */
9374
9061
  getCoreWorkspaceProject() {
@@ -9385,8 +9072,7 @@ class Vitest {
9385
9072
  * @deprecated use Reported Task API instead
9386
9073
  */
9387
9074
  getProjectByTaskId(taskId) {
9388
- const task = this.state.idMap.get(taskId);
9389
- const projectName = task.projectName || task?.file?.projectName || "";
9075
+ const task = this.state.idMap.get(taskId), projectName = task.projectName || task?.file?.projectName || "";
9390
9076
  return this.getProjectByName(projectName);
9391
9077
  }
9392
9078
  getProjectByName(name) {
@@ -9399,7 +9085,7 @@ class Vitest {
9399
9085
  * @param moduleId The ID of the module in Vite module graph
9400
9086
  */
9401
9087
  import(moduleId) {
9402
- return this.runner.executeId(moduleId);
9088
+ return this.runner.import(moduleId);
9403
9089
  }
9404
9090
  async resolveProjects(cliOptions) {
9405
9091
  const names = /* @__PURE__ */ new Set();
@@ -9408,8 +9094,7 @@ class Vitest {
9408
9094
  // user can filter projects with --project flag, `getDefaultTestProject`
9409
9095
  // returns the project only if it matches the filter
9410
9096
  const project = getDefaultTestProject(this);
9411
- if (!project) return [];
9412
- return resolveBrowserProjects(this, new Set([project.name]), [project]);
9097
+ return project ? resolveBrowserProjects(this, new Set([project.name]), [project]) : [];
9413
9098
  }
9414
9099
  /**
9415
9100
  * Glob test files in every project and create a TestSpecification for each file and pool.
@@ -9419,13 +9104,10 @@ class Vitest {
9419
9104
  return this.specifications.globTestSpecifications(filters);
9420
9105
  }
9421
9106
  async initCoverageProvider() {
9422
- if (this.coverageProvider !== void 0) return;
9423
- this.coverageProvider = await getCoverageProvider(this.config.coverage, this.runner);
9424
- if (this.coverageProvider) {
9425
- await this.coverageProvider.initialize(this);
9426
- this.config.coverage = this.coverageProvider.resolveOptions();
9107
+ if (this.coverageProvider === void 0) {
9108
+ if (this.coverageProvider = await getCoverageProvider(this.config.coverage, this.runner), this.coverageProvider) await this.coverageProvider.initialize(this), this.config.coverage = this.coverageProvider.resolveOptions();
9109
+ return this.coverageProvider;
9427
9110
  }
9428
- return this.coverageProvider;
9429
9111
  }
9430
9112
  /**
9431
9113
  * Merge reports from multiple runs located in the specified directory (value from `--merge-reports` if not specified).
@@ -9438,23 +9120,15 @@ class Vitest {
9438
9120
  errors,
9439
9121
  coverages,
9440
9122
  executionTimes
9441
- };
9442
- await this.report("onInit", this);
9443
- await this.report("onPathsCollected", files.flatMap((f) => f.filepath));
9123
+ }, await this.report("onInit", this);
9444
9124
  const specifications = [];
9445
9125
  for (const file of files) {
9446
- const project = this.getProjectByName(file.projectName || "");
9447
- const specification = project.createSpecification(file.filepath, void 0, file.pool);
9126
+ const project = this.getProjectByName(file.projectName || ""), specification = project.createSpecification(file.filepath, void 0, file.pool);
9448
9127
  specifications.push(specification);
9449
9128
  }
9450
- await this.report("onSpecsCollected", specifications.map((spec) => spec.toJSON()));
9451
9129
  await this._testRun.start(specifications).catch(noop);
9452
9130
  for (const file of files) await this._reportFileTask(file);
9453
- this._checkUnhandledErrors(errors);
9454
- await this._testRun.end(specifications, errors).catch(noop);
9455
- await this.initCoverageProvider();
9456
- await this.coverageProvider?.mergeReports?.(coverages);
9457
- return {
9131
+ return this._checkUnhandledErrors(errors), await this._testRun.end(specifications, errors).catch(noop), await this.initCoverageProvider(), await this.coverageProvider?.mergeReports?.(coverages), {
9458
9132
  testModules: this.state.getTestModules(),
9459
9133
  unhandledErrors: this.state.getUnhandledErrors()
9460
9134
  };
@@ -9462,10 +9136,8 @@ class Vitest {
9462
9136
  /** @internal */
9463
9137
  async _reportFileTask(file) {
9464
9138
  const project = this.getProjectByName(file.projectName || "");
9465
- await this._testRun.enqueued(project, file).catch(noop);
9466
- await this._testRun.collected(project, [file]).catch(noop);
9467
- const logs = [];
9468
- const { packs, events } = convertTasksToEvents(file, (task) => {
9139
+ await this._testRun.enqueued(project, file).catch(noop), await this._testRun.collected(project, [file]).catch(noop);
9140
+ const logs = [], { packs, events } = convertTasksToEvents(file, (task) => {
9469
9141
  if (task.logs) logs.push(...task.logs);
9470
9142
  });
9471
9143
  logs.sort((log1, log2) => log1.time - log2.time);
@@ -9474,12 +9146,10 @@ class Vitest {
9474
9146
  }
9475
9147
  async collect(filters) {
9476
9148
  const files = await this.specifications.getRelevantTestSpecifications(filters);
9477
- // if run with --changed, don't exit if no tests are found
9478
- if (!files.length) return {
9149
+ return files.length ? this.collectTests(files) : {
9479
9150
  testModules: [],
9480
9151
  unhandledErrors: []
9481
9152
  };
9482
- return this.collectTests(files);
9483
9153
  }
9484
9154
  /** @deprecated use `getRelevantTestSpecifications` instead */
9485
9155
  listFiles(filters) {
@@ -9502,8 +9172,7 @@ class Vitest {
9502
9172
  */
9503
9173
  async start(filters) {
9504
9174
  try {
9505
- await this.initCoverageProvider();
9506
- await this.coverageProvider?.clean(this.config.coverage.clean);
9175
+ await this.initCoverageProvider(), await this.coverageProvider?.clean(this.config.coverage.clean);
9507
9176
  } finally {
9508
9177
  await this.report("onInit", this);
9509
9178
  }
@@ -9513,20 +9182,13 @@ class Vitest {
9513
9182
  if (!files.length) {
9514
9183
  await this._testRun.start([]);
9515
9184
  const coverage = await this.coverageProvider?.generateCoverage?.({ allTestsRun: true });
9516
- await this._testRun.end([], [], coverage);
9517
- // Report coverage for uncovered files
9518
- await this.reportCoverage(coverage, true);
9519
- if (!this.config.watch || !(this.config.changed || this.config.related?.length)) throw new FilesNotFoundError(this.mode);
9185
+ if (await this._testRun.end([], [], coverage), await this.reportCoverage(coverage, true), !this.config.watch || !(this.config.changed || this.config.related?.length)) throw new FilesNotFoundError(this.mode);
9520
9186
  }
9521
9187
  let testModules = {
9522
9188
  testModules: [],
9523
9189
  unhandledErrors: []
9524
9190
  };
9525
- if (files.length) {
9526
- // populate once, update cache on watch
9527
- await this.cache.stats.populateStats(this.config.root, files);
9528
- testModules = await this.runFiles(files, true);
9529
- }
9191
+ if (files.length) await this.cache.stats.populateStats(this.config.root, files), testModules = await this.runFiles(files, true);
9530
9192
  if (this.config.watch) await this.report("onWatcherStart");
9531
9193
  return testModules;
9532
9194
  }
@@ -9536,14 +9198,11 @@ class Vitest {
9536
9198
  */
9537
9199
  async init() {
9538
9200
  try {
9539
- await this.initCoverageProvider();
9540
- await this.coverageProvider?.clean(this.config.coverage.clean);
9201
+ await this.initCoverageProvider(), await this.coverageProvider?.clean(this.config.coverage.clean);
9541
9202
  } finally {
9542
9203
  await this.report("onInit", this);
9543
9204
  }
9544
- // populate test files cache so watch mode can trigger a file rerun
9545
- await this.globTestSpecifications();
9546
- if (this.config.watch) await this.report("onWatcherStart");
9205
+ if (await this.globTestSpecifications(), this.config.watch) await this.report("onWatcherStart");
9547
9206
  }
9548
9207
  /**
9549
9208
  * @deprecated remove when vscode extension supports "getModuleSpecifications"
@@ -9576,8 +9235,7 @@ class Vitest {
9576
9235
  * @param allTestsRun Indicates whether all tests were run. This only matters for coverage.
9577
9236
  */
9578
9237
  runTestSpecifications(specifications, allTestsRun = false) {
9579
- specifications.forEach((spec) => this.specifications.ensureSpecificationCached(spec));
9580
- return this.runFiles(specifications, allTestsRun);
9238
+ return specifications.forEach((spec) => this.specifications.ensureSpecificationCached(spec)), this.runFiles(specifications, allTestsRun);
9581
9239
  }
9582
9240
  /**
9583
9241
  * Rerun files and trigger `onWatcherRerun`, `onWatcherStart` and `onTestsRerun` events.
@@ -9589,24 +9247,14 @@ class Vitest {
9589
9247
  const files = specifications.map((spec) => spec.moduleId);
9590
9248
  await Promise.all([this.report("onWatcherRerun", files, "rerun test"), ...this._onUserTestsRerun.map((fn) => fn(specifications))]);
9591
9249
  const result = await this.runTestSpecifications(specifications, allTestsRun);
9592
- await this.report("onWatcherStart", this.state.getFiles(files));
9593
- return result;
9250
+ return await this.report("onWatcherStart", this.state.getFiles(files)), result;
9594
9251
  }
9595
9252
  async runFiles(specs, allTestsRun) {
9596
- await this._testRun.start(specs);
9597
- // previous run
9598
- await this.runningPromise;
9599
- this._onCancelListeners = [];
9600
- this.isCancelling = false;
9601
- // schedule the new run
9602
- this.runningPromise = (async () => {
9253
+ return await this._testRun.start(specs), await this.runningPromise, this._onCancelListeners = [], this.isCancelling = false, this.runningPromise = (async () => {
9603
9254
  try {
9604
9255
  if (!this.pool) this.pool = createPool(this);
9605
9256
  const invalidates = Array.from(this.watcher.invalidates);
9606
- this.watcher.invalidates.clear();
9607
- this.snapshot.clear();
9608
- this.state.clearErrors();
9609
- if (!this.isFirstRun && this.config.coverage.cleanOnRerun) await this.coverageProvider?.clean();
9257
+ if (this.watcher.invalidates.clear(), this.snapshot.clear(), this.state.clearErrors(), !this.isFirstRun && this.config.coverage.cleanOnRerun) await this.coverageProvider?.clean();
9610
9258
  await this.initializeGlobalSetup(specs);
9611
9259
  try {
9612
9260
  await this.pool.runTests(specs, invalidates);
@@ -9623,21 +9271,12 @@ class Vitest {
9623
9271
  unhandledErrors: this.state.getUnhandledErrors()
9624
9272
  };
9625
9273
  } finally {
9626
- // TODO: wait for coverage only if `onFinished` is defined
9627
- const coverage = await this.coverageProvider?.generateCoverage({ allTestsRun });
9628
- const errors = this.state.getUnhandledErrors();
9629
- this._checkUnhandledErrors(errors);
9630
- await this._testRun.end(specs, errors, coverage);
9631
- await this.reportCoverage(coverage, allTestsRun);
9274
+ const coverage = await this.coverageProvider?.generateCoverage({ allTestsRun }), errors = this.state.getUnhandledErrors();
9275
+ this._checkUnhandledErrors(errors), await this._testRun.end(specs, errors, coverage), await this.reportCoverage(coverage, allTestsRun);
9632
9276
  }
9633
9277
  })().finally(() => {
9634
- this.runningPromise = void 0;
9635
- this.isFirstRun = false;
9636
- // all subsequent runs will treat this as a fresh run
9637
- this.config.changed = false;
9638
- this.config.related = void 0;
9639
- });
9640
- return await this.runningPromise;
9278
+ this.runningPromise = void 0, this.isFirstRun = false, this.config.changed = false, this.config.related = void 0;
9279
+ }), await this.runningPromise;
9641
9280
  }
9642
9281
  /**
9643
9282
  * Collect tests in specified modules. Vitest will run the files to collect tests.
@@ -9645,19 +9284,10 @@ class Vitest {
9645
9284
  */
9646
9285
  async collectTests(specifications) {
9647
9286
  const filepaths = specifications.map((spec) => spec.moduleId);
9648
- this.state.collectPaths(filepaths);
9649
- // previous run
9650
- await this.runningPromise;
9651
- this._onCancelListeners = [];
9652
- this.isCancelling = false;
9653
- // schedule the new run
9654
- this.runningPromise = (async () => {
9287
+ return this.state.collectPaths(filepaths), await this.runningPromise, this._onCancelListeners = [], this.isCancelling = false, this.runningPromise = (async () => {
9655
9288
  if (!this.pool) this.pool = createPool(this);
9656
9289
  const invalidates = Array.from(this.watcher.invalidates);
9657
- this.watcher.invalidates.clear();
9658
- this.snapshot.clear();
9659
- this.state.clearErrors();
9660
- await this.initializeGlobalSetup(specifications);
9290
+ this.watcher.invalidates.clear(), this.snapshot.clear(), this.state.clearErrors(), await this.initializeGlobalSetup(specifications);
9661
9291
  try {
9662
9292
  await this.pool.collectTests(specifications, invalidates);
9663
9293
  } catch (err) {
@@ -9672,28 +9302,21 @@ class Vitest {
9672
9302
  unhandledErrors: this.state.getUnhandledErrors()
9673
9303
  };
9674
9304
  })().finally(() => {
9675
- this.runningPromise = void 0;
9676
- // all subsequent runs will treat this as a fresh run
9677
- this.config.changed = false;
9678
- this.config.related = void 0;
9679
- });
9680
- return await this.runningPromise;
9305
+ this.runningPromise = void 0, this.config.changed = false, this.config.related = void 0;
9306
+ }), await this.runningPromise;
9681
9307
  }
9682
9308
  /**
9683
9309
  * Gracefully cancel the current test run. Vitest will wait until all running tests are finished before cancelling.
9684
9310
  */
9685
9311
  async cancelCurrentRun(reason) {
9686
- this.isCancelling = true;
9687
- await Promise.all(this._onCancelListeners.splice(0).map((listener) => listener(reason)));
9688
- await this.runningPromise;
9312
+ this.isCancelling = true, await Promise.all(this._onCancelListeners.splice(0).map((listener) => listener(reason))), await this.runningPromise;
9689
9313
  }
9690
9314
  /** @internal */
9691
9315
  async _initBrowserServers() {
9692
9316
  await Promise.all(this.projects.map((p) => p._initBrowserServer()));
9693
9317
  }
9694
9318
  async initializeGlobalSetup(paths) {
9695
- const projects = new Set(paths.map((spec) => spec.project));
9696
- const coreProject = this.getRootProject();
9319
+ const projects = new Set(paths.map((spec) => spec.project)), coreProject = this.getRootProject();
9697
9320
  if (!projects.has(coreProject)) projects.add(coreProject);
9698
9321
  for (const project of projects) await project._initializeGlobalSetup();
9699
9322
  }
@@ -9707,8 +9330,7 @@ class Vitest {
9707
9330
  const specifications = files.flatMap((file) => this.getModuleSpecifications(file));
9708
9331
  await Promise.all([this.report("onWatcherRerun", files, trigger), ...this._onUserTestsRerun.map((fn) => fn(specifications))]);
9709
9332
  const testResult = await this.runFiles(specifications, allTestsRun);
9710
- await this.report("onWatcherStart", this.state.getFiles(files));
9711
- return testResult;
9333
+ return await this.report("onWatcherStart", this.state.getFiles(files)), testResult;
9712
9334
  }
9713
9335
  /** @internal */
9714
9336
  async rerunTask(id) {
@@ -9728,9 +9350,8 @@ class Vitest {
9728
9350
  // Empty test name pattern should reset filename pattern as well
9729
9351
  if (pattern === "") this.filenamePattern = void 0;
9730
9352
  const testNamePattern = pattern ? new RegExp(pattern) : void 0;
9731
- this.configOverride.testNamePattern = testNamePattern;
9732
9353
  // filter only test files that have tests matching the pattern
9733
- if (testNamePattern) files = files.filter((filepath) => {
9354
+ if (this.configOverride.testNamePattern = testNamePattern, testNamePattern) files = files.filter((filepath) => {
9734
9355
  const files = this.state.getFiles([filepath]);
9735
9356
  return !files.length || files.some((file) => {
9736
9357
  const tasks = getTasks(file);
@@ -9754,9 +9375,7 @@ class Vitest {
9754
9375
  * @param files The list of files on the file system
9755
9376
  */
9756
9377
  async updateSnapshot(files) {
9757
- // default to failed files
9758
- files = files || [...this.state.getFailedFilepaths(), ...this.snapshot.summary.uncheckedKeysByFile.map((s) => s.filePath)];
9759
- this.enableSnapshotUpdate();
9378
+ files = files || [...this.state.getFailedFilepaths(), ...this.snapshot.summary.uncheckedKeysByFile.map((s) => s.filePath)], this.enableSnapshotUpdate();
9760
9379
  try {
9761
9380
  return await this.rerunFiles(files, "update snapshot", false);
9762
9381
  } finally {
@@ -9774,15 +9393,13 @@ class Vitest {
9774
9393
  this.configOverride.snapshotOptions = {
9775
9394
  updateSnapshot: "all",
9776
9395
  snapshotEnvironment: null
9777
- };
9778
- this.snapshot.options.updateSnapshot = "all";
9396
+ }, this.snapshot.options.updateSnapshot = "all";
9779
9397
  }
9780
9398
  /**
9781
9399
  * Disable the mode that allows updating snapshots when running tests.
9782
9400
  */
9783
9401
  resetSnapshotUpdate() {
9784
- delete this.configOverride.snapshotOptions;
9785
- this.snapshot.options.updateSnapshot = this.config.snapshotOptions.updateSnapshot;
9402
+ delete this.configOverride.snapshotOptions, this.snapshot.options.updateSnapshot = this.config.snapshotOptions.updateSnapshot;
9786
9403
  }
9787
9404
  /**
9788
9405
  * Set the global test name pattern to a regexp.
@@ -9802,51 +9419,37 @@ class Vitest {
9802
9419
  // we can't use a single `triggerId` yet because vscode extension relies on this
9803
9420
  async scheduleRerun(triggerId) {
9804
9421
  const currentCount = this.restartsCount;
9805
- clearTimeout(this._rerunTimer);
9806
- await this.runningPromise;
9807
- clearTimeout(this._rerunTimer);
9808
- // server restarted
9809
- if (this.restartsCount !== currentCount) return;
9810
- this._rerunTimer = setTimeout(async () => {
9422
+ clearTimeout(this._rerunTimer), await this.runningPromise, clearTimeout(this._rerunTimer), this.restartsCount === currentCount && (this._rerunTimer = setTimeout(async () => {
9811
9423
  if (this.watcher.changedTests.size === 0) {
9812
9424
  this.watcher.invalidates.clear();
9813
9425
  return;
9814
9426
  }
9815
9427
  // server restarted
9816
9428
  if (this.restartsCount !== currentCount) return;
9817
- this.isFirstRun = false;
9818
- this.snapshot.clear();
9429
+ this.isFirstRun = false, this.snapshot.clear();
9819
9430
  let files = Array.from(this.watcher.changedTests);
9820
9431
  if (this.filenamePattern) {
9821
9432
  const filteredFiles = await this.globTestSpecifications(this.filenamePattern);
9822
- files = files.filter((file) => filteredFiles.some((f) => f.moduleId === file));
9823
9433
  // A file that does not match the current filename pattern was changed
9824
- if (files.length === 0) return;
9434
+ if (files = files.filter((file) => filteredFiles.some((f) => f.moduleId === file)), files.length === 0) return;
9825
9435
  }
9826
9436
  this.watcher.changedTests.clear();
9827
- const triggerIds = new Set(triggerId.map((id) => relative(this.config.root, id)));
9828
- const triggerLabel = Array.from(triggerIds).join(", ");
9829
- // get file specifications and filter them if needed
9830
- const specifications = files.flatMap((file) => this.getModuleSpecifications(file)).filter((specification) => {
9831
- if (this._onFilterWatchedSpecification.length === 0) return true;
9832
- return this._onFilterWatchedSpecification.every((fn) => fn(specification));
9437
+ const triggerIds = new Set(triggerId.map((id) => relative(this.config.root, id))), triggerLabel = Array.from(triggerIds).join(", "), specifications = files.flatMap((file) => this.getModuleSpecifications(file)).filter((specification) => {
9438
+ return this._onFilterWatchedSpecification.length === 0 ? true : this._onFilterWatchedSpecification.every((fn) => fn(specification));
9833
9439
  });
9834
- await Promise.all([this.report("onWatcherRerun", files, triggerLabel), ...this._onUserTestsRerun.map((fn) => fn(specifications))]);
9835
- await this.runFiles(specifications, false);
9836
- await this.report("onWatcherStart", this.state.getFiles(files));
9837
- }, WATCHER_DEBOUNCE);
9440
+ await Promise.all([this.report("onWatcherRerun", files, triggerLabel), ...this._onUserTestsRerun.map((fn) => fn(specifications))]), await this.runFiles(specifications, false), await this.report("onWatcherStart", this.state.getFiles(files));
9441
+ }, WATCHER_DEBOUNCE));
9838
9442
  }
9839
9443
  /**
9840
9444
  * Invalidate a file in all projects.
9841
9445
  */
9842
9446
  invalidateFile(filepath) {
9843
9447
  this.projects.forEach(({ vite, browser }) => {
9844
- const serverMods = vite.moduleGraph.getModulesByFile(filepath);
9845
- serverMods?.forEach((mod) => vite.moduleGraph.invalidateModule(mod));
9846
- if (browser) {
9847
- const browserMods = browser.vite.moduleGraph.getModulesByFile(filepath);
9848
- browserMods?.forEach((mod) => browser.vite.moduleGraph.invalidateModule(mod));
9849
- }
9448
+ const environments = [...Object.values(vite.environments), ...Object.values(browser?.vite.environments || {})];
9449
+ environments.forEach(({ moduleGraph }) => {
9450
+ const modules = moduleGraph.getModulesByFile(filepath);
9451
+ modules?.forEach((module) => moduleGraph.invalidateModule(module));
9452
+ });
9850
9453
  });
9851
9454
  }
9852
9455
  /** @deprecated use `invalidateFile` */
@@ -9859,8 +9462,7 @@ class Vitest {
9859
9462
  }
9860
9463
  async reportCoverage(coverage, allTestsRun) {
9861
9464
  if (this.state.getCountOfFailedTests() > 0) {
9862
- await this.coverageProvider?.onTestFailure?.();
9863
- if (!this.config.coverage.reportOnFailure) return;
9465
+ if (await this.coverageProvider?.onTestFailure?.(), !this.config.coverage.reportOnFailure) return;
9864
9466
  }
9865
9467
  if (this.coverageProvider) {
9866
9468
  await this.coverageProvider.reportCoverage(coverage, { allTestsRun });
@@ -9883,11 +9485,9 @@ class Vitest {
9883
9485
  // it's possible that it's not initialized at all because it's not running any tests
9884
9486
  if (this.coreWorkspaceProject && !this.projects.includes(this.coreWorkspaceProject)) closePromises.push(this.coreWorkspaceProject.close().then(() => this._vite = void 0));
9885
9487
  if (this.pool) closePromises.push((async () => {
9886
- await this.pool?.close?.();
9887
- this.pool = void 0;
9488
+ await this.pool?.close?.(), this.pool = void 0;
9888
9489
  })());
9889
- closePromises.push(...this._onClose.map((fn) => fn()));
9890
- return Promise.allSettled(closePromises).then((results) => {
9490
+ return closePromises.push(...this._onClose.map((fn) => fn())), Promise.allSettled(closePromises).then((results) => {
9891
9491
  results.forEach((r) => {
9892
9492
  if (r.status === "rejected") this.logger.error("error during close", r.reason);
9893
9493
  });
@@ -9900,11 +9500,9 @@ class Vitest {
9900
9500
  * @param force If true, the process will exit immediately after closing the projects.
9901
9501
  */
9902
9502
  async exit(force = false) {
9903
- setTimeout(() => {
9503
+ if (setTimeout(() => {
9904
9504
  this.report("onProcessTimeout").then(() => {
9905
- console.warn(`close timed out after ${this.config.teardownTimeout}ms`);
9906
- this.state.getProcessTimeoutCauses().forEach((cause) => console.warn(cause));
9907
- if (!this.pool) {
9505
+ if (console.warn(`close timed out after ${this.config.teardownTimeout}ms`), this.state.getProcessTimeoutCauses().forEach((cause) => console.warn(cause)), !this.pool) {
9908
9506
  const runningServers = [this._vite, ...this.projects.map((p) => p._vite)].filter(Boolean).length;
9909
9507
  if (runningServers === 1) console.warn("Tests closed successfully but something prevents Vite server from exiting");
9910
9508
  else if (runningServers > 1) console.warn(`Tests closed successfully but something prevents ${runningServers} Vite servers from exiting`);
@@ -9913,9 +9511,7 @@ class Vitest {
9913
9511
  }
9914
9512
  process.exit();
9915
9513
  });
9916
- }, this.config.teardownTimeout).unref();
9917
- await this.close();
9918
- if (force) process.exit();
9514
+ }, this.config.teardownTimeout).unref(), await this.close(), force) process.exit();
9919
9515
  }
9920
9516
  /** @internal */
9921
9517
  async report(name, ...args) {
@@ -9997,9 +9593,7 @@ class Vitest {
9997
9593
  */
9998
9594
  matchesProjectFilter(name) {
9999
9595
  const projects = this._config?.project || this._cliOptions?.project;
10000
- // no filters applied, any project can be included
10001
- if (!projects || !projects.length) return true;
10002
- return toArray(projects).some((project) => {
9596
+ return !projects || !projects.length ? true : toArray(projects).some((project) => {
10003
9597
  const regexp = wildcardPatternToRegExp(project);
10004
9598
  return regexp.test(name);
10005
9599
  });
@@ -10012,8 +9606,7 @@ function assert(condition, property, name = property) {
10012
9606
  async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(options))) {
10013
9607
  const userConfig = deepMerge({}, options);
10014
9608
  async function UIPlugin() {
10015
- await vitest.packageInstaller.ensureInstalled("@vitest/ui", options.root || process.cwd(), vitest.version);
10016
- return (await import('@vitest/ui')).default(vitest);
9609
+ return await vitest.packageInstaller.ensureInstalled("@vitest/ui", options.root || process.cwd(), vitest.version), (await import('@vitest/ui')).default(vitest);
10017
9610
  }
10018
9611
  return [
10019
9612
  {
@@ -10039,14 +9632,9 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
10039
9632
  let open = false;
10040
9633
  if (testConfig.ui && testConfig.open) open = testConfig.uiBase ?? "/__vitest__/";
10041
9634
  const resolveOptions = getDefaultResolveOptions();
10042
- const config = {
9635
+ let config = {
10043
9636
  root: viteConfig.test?.root || options.root,
10044
9637
  define: { "process.env.NODE_ENV": "process.env.NODE_ENV" },
10045
- esbuild: viteConfig.esbuild === false ? false : {
10046
- target: viteConfig.esbuild?.target || "node18",
10047
- sourcemap: "external",
10048
- legalComments: "inline"
10049
- },
10050
9638
  resolve: {
10051
9639
  ...resolveOptions,
10052
9640
  alias: testConfig.alias
@@ -10063,7 +9651,10 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
10063
9651
  outDir: "dummy-non-existing-folder",
10064
9652
  emptyOutDir: false
10065
9653
  },
10066
- environments: { ssr: { resolve: resolveOptions } },
9654
+ environments: {
9655
+ ssr: { resolve: resolveOptions },
9656
+ __vitest__: { dev: {} }
9657
+ },
10067
9658
  test: {
10068
9659
  poolOptions: {
10069
9660
  threads: { isolate: options.poolOptions?.threads?.isolate ?? options.isolate ?? testConfig.poolOptions?.threads?.isolate ?? viteConfig.test?.isolate },
@@ -10073,33 +9664,29 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
10073
9664
  deps: testConfig.deps ?? viteConfig.test?.deps
10074
9665
  }
10075
9666
  };
9667
+ if ("rolldownVersion" in vite) config = {
9668
+ ...config,
9669
+ oxc: viteConfig.oxc === false ? false : { target: viteConfig.oxc?.target || "node18" }
9670
+ };
9671
+ else config = {
9672
+ ...config,
9673
+ esbuild: viteConfig.esbuild === false ? false : {
9674
+ target: viteConfig.esbuild?.target || "node18",
9675
+ sourcemap: "external",
9676
+ legalComments: "inline"
9677
+ }
9678
+ };
10076
9679
  // inherit so it's available in VitestOptimizer
10077
9680
  // I cannot wait to rewrite all of this in Vitest 4
10078
9681
  if (options.cache != null) config.test.cache = options.cache;
10079
9682
  if (vitest.configOverride.project)
10080
9683
  // project filter was set by the user, so we need to filter the project
10081
9684
  options.project = vitest.configOverride.project;
10082
- config.customLogger = createViteLogger(vitest.logger, viteConfig.logLevel || "warn", { allowClearScreen: false });
10083
- config.customLogger = silenceImportViteIgnoreWarning(config.customLogger);
10084
- // we want inline dependencies to be resolved by analyser plugin so module graph is populated correctly
10085
- if (viteConfig.ssr?.noExternal !== true) {
10086
- const inline = testConfig.server?.deps?.inline;
10087
- if (inline === true) config.ssr = { noExternal: true };
10088
- else {
10089
- const noExternal = viteConfig.ssr?.noExternal;
10090
- const noExternalArray = typeof noExternal !== "undefined" ? toArray(noExternal) : void 0;
10091
- // filter the same packages
10092
- const uniqueInline = inline && noExternalArray ? inline.filter((dep) => !noExternalArray.includes(dep)) : inline;
10093
- config.ssr = { noExternal: uniqueInline };
10094
- }
10095
- }
10096
9685
  // chokidar fsevents is unstable on macos when emitting "ready" event
10097
- if (process.platform === "darwin" && false);
9686
+ if (config.customLogger = createViteLogger(vitest.logger, viteConfig.logLevel || "warn", { allowClearScreen: false }), config.customLogger = silenceImportViteIgnoreWarning(config.customLogger), process.platform === "darwin" && false);
10098
9687
  const classNameStrategy = typeof testConfig.css !== "boolean" && testConfig.css?.modules?.classNameStrategy || "stable";
10099
9688
  if (classNameStrategy !== "scoped") {
10100
- config.css ??= {};
10101
- config.css.modules ??= {};
10102
- if (config.css.modules) config.css.modules.generateScopedName = (name, filename) => {
9689
+ if (config.css ??= {}, config.css.modules ??= {}, config.css.modules) config.css.modules.generateScopedName = (name, filename) => {
10103
9690
  const root = vitest.config.root || options.root || process.cwd();
10104
9691
  return generateScopedClassName(classNameStrategy, name, relative(root, filename));
10105
9692
  };
@@ -10110,17 +9697,11 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
10110
9697
  const viteConfigTest = viteConfig.test || {};
10111
9698
  if (viteConfigTest.watch === false) viteConfigTest.run = true;
10112
9699
  if ("alias" in viteConfigTest) delete viteConfigTest.alias;
10113
- // viteConfig.test is final now, merge it for real
10114
- options = deepMerge({}, configDefaults, viteConfigTest, options);
10115
- options.api = resolveApiServerConfig(options, defaultPort);
9700
+ options = deepMerge({}, configDefaults, viteConfigTest, options), options.api = resolveApiServerConfig(options, defaultPort);
10116
9701
  // we replace every "import.meta.env" with "process.env"
10117
9702
  // to allow reassigning, so we need to put all envs on process.env
10118
9703
  const { PROD, DEV,...envs } = viteConfig.env;
10119
- // process.env can have only string values and will cast string on it if we pass other type,
10120
- // so we are making them truthy
10121
- process.env.PROD ??= PROD ? "1" : "";
10122
- process.env.DEV ??= DEV ? "1" : "";
10123
- for (const name in envs) process.env[name] ??= envs[name];
9704
+ for (const name in process.env.PROD ??= PROD ? "1" : "", process.env.DEV ??= DEV ? "1" : "", envs) process.env[name] ??= envs[name];
10124
9705
  // don't watch files in run mode
10125
9706
  if (!options.watch) viteConfig.server.watch = null;
10126
9707
  if (options.ui)
@@ -10140,20 +9721,20 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
10140
9721
  order: "post",
10141
9722
  async handler(server) {
10142
9723
  if (options.watch && false);
10143
- await vitest._setServer(options, server);
10144
- if (options.api && options.watch) (await Promise.resolve().then(function () { return setup$1; })).setup(vitest);
9724
+ if (await vitest._setServer(options, server), options.api && options.watch) (await Promise.resolve().then(function () { return setup$1; })).setup(vitest);
10145
9725
  // #415, in run mode we don't need the watcher, close it would improve the performance
10146
9726
  if (!options.watch) await server.watcher.close();
10147
9727
  }
10148
9728
  }
10149
9729
  },
10150
- SsrReplacerPlugin(),
9730
+ MetaEnvReplacerPlugin(),
10151
9731
  ...CSSEnablerPlugin(vitest),
10152
9732
  CoverageTransform(vitest),
10153
9733
  VitestCoreResolver(vitest),
10154
9734
  ...MocksPlugins(),
10155
9735
  VitestOptimizer(),
10156
- NormalizeURLPlugin()
9736
+ NormalizeURLPlugin(),
9737
+ ModuleRunnerTransform()
10157
9738
  ].filter(notNullish);
10158
9739
  }
10159
9740
  function removeUndefinedValues(obj) {
@@ -10162,25 +9743,19 @@ function removeUndefinedValues(obj) {
10162
9743
  }
10163
9744
 
10164
9745
  async function createVitest(mode, options, viteOverrides = {}, vitestOptions = {}) {
10165
- const ctx = new Vitest(mode, deepClone(options), vitestOptions);
10166
- const root = slash(resolve$1(options.root || process.cwd()));
10167
- const configPath = options.config === false ? false : options.config ? resolve$1(root, options.config) : await findUp(configFiles, { cwd: root });
9746
+ const ctx = new Vitest(mode, deepClone(options), vitestOptions), root = slash(resolve$1(options.root || process.cwd())), configPath = options.config === false ? false : options.config ? resolve$1(root, options.config) : await findUp(configFiles, { cwd: root });
10168
9747
  options.config = configPath;
10169
- const { browser: _removeBrowser,...restOptions } = options;
10170
- const config = {
9748
+ const { browser: _removeBrowser,...restOptions } = options, config = {
10171
9749
  configFile: configPath,
10172
9750
  configLoader: options.configLoader,
10173
9751
  mode: options.mode || mode,
10174
9752
  plugins: await VitestPlugin(restOptions, ctx)
10175
- };
10176
- const server = await createViteServer(mergeConfig(config, mergeConfig(viteOverrides, { root: options.root })));
9753
+ }, server = await createViteServer(mergeConfig(config, mergeConfig(viteOverrides, { root: options.root })));
10177
9754
  if (ctx.config.api?.port) await server.listen();
10178
9755
  return ctx;
10179
9756
  }
10180
9757
 
10181
- const MAX_RESULT_COUNT = 10;
10182
- const SELECTION_MAX_INDEX = 7;
10183
- const ESC = "\x1B[";
9758
+ const MAX_RESULT_COUNT = 10, SELECTION_MAX_INDEX = 7, ESC = "\x1B[";
10184
9759
  class WatchFilter {
10185
9760
  filterRL;
10186
9761
  currentKeyword = void 0;
@@ -10191,23 +9766,17 @@ class WatchFilter {
10191
9766
  stdin;
10192
9767
  stdout;
10193
9768
  constructor(message, stdin = process.stdin, stdout$1 = stdout()) {
10194
- this.message = message;
10195
- this.stdin = stdin;
10196
- this.stdout = stdout$1;
10197
- this.filterRL = readline.createInterface({
9769
+ if (this.message = message, this.stdin = stdin, this.stdout = stdout$1, this.filterRL = readline.createInterface({
10198
9770
  input: this.stdin,
10199
9771
  escapeCodeTimeout: 50
10200
- });
10201
- readline.emitKeypressEvents(this.stdin, this.filterRL);
10202
- if (this.stdin.isTTY) this.stdin.setRawMode(true);
9772
+ }), readline.emitKeypressEvents(this.stdin, this.filterRL), this.stdin.isTTY) this.stdin.setRawMode(true);
10203
9773
  }
10204
9774
  async filter(filterFunc) {
10205
9775
  this.write(this.promptLine());
10206
9776
  const resultPromise = createDefer();
10207
9777
  this.onKeyPress = this.filterHandler(filterFunc, (result) => {
10208
9778
  resultPromise.resolve(result);
10209
- });
10210
- this.stdin.on("keypress", this.onKeyPress);
9779
+ }), this.stdin.on("keypress", this.onKeyPress);
10211
9780
  try {
10212
9781
  return await resultPromise;
10213
9782
  } finally {
@@ -10223,13 +9792,11 @@ class WatchFilter {
10223
9792
  break;
10224
9793
  case key?.ctrl && key?.name === "c":
10225
9794
  case key?.name === "escape":
10226
- this.write(`${ESC}1G${ESC}0J`);
10227
- onSubmit(void 0);
9795
+ this.write(`${ESC}1G${ESC}0J`), onSubmit(void 0);
10228
9796
  return;
10229
9797
  case key?.name === "enter":
10230
9798
  case key?.name === "return":
10231
- onSubmit(this.results[this.selectionIndex] || this.currentKeyword || "");
10232
- this.currentKeyword = void 0;
9799
+ onSubmit(this.results[this.selectionIndex] || this.currentKeyword || ""), this.currentKeyword = void 0;
10233
9800
  break;
10234
9801
  case key?.name === "up":
10235
9802
  if (this.selectionIndex && this.selectionIndex > 0) this.selectionIndex--;
@@ -10256,17 +9823,13 @@ class WatchFilter {
10256
9823
  const resultCountLine = this.results.length === 1 ? `Pattern matches ${this.results.length} result` : `Pattern matches ${this.results.length} results`;
10257
9824
  let resultBody = "";
10258
9825
  if (this.results.length > MAX_RESULT_COUNT) {
10259
- const offset = this.selectionIndex > SELECTION_MAX_INDEX ? this.selectionIndex - SELECTION_MAX_INDEX : 0;
10260
- const displayResults = this.results.slice(offset, MAX_RESULT_COUNT + offset);
10261
- const remainingResultCount = this.results.length - offset - displayResults.length;
10262
- resultBody = `${displayResults.map((result, index) => index + offset === this.selectionIndex ? c.green(` › ${result}`) : c.dim(` › ${result}`)).join("\n")}`;
10263
- if (remainingResultCount > 0) resultBody += `
9826
+ const offset = this.selectionIndex > SELECTION_MAX_INDEX ? this.selectionIndex - SELECTION_MAX_INDEX : 0, displayResults = this.results.slice(offset, MAX_RESULT_COUNT + offset), remainingResultCount = this.results.length - offset - displayResults.length;
9827
+ if (resultBody = `${displayResults.map((result, index) => index + offset === this.selectionIndex ? c.green(` › ${result}`) : c.dim(` › ${result}`)).join("\n")}`, remainingResultCount > 0) resultBody += `
10264
9828
  ${c.dim(` ...and ${remainingResultCount} more ${remainingResultCount === 1 ? "result" : "results"}`)}`;
10265
9829
  } else resultBody = this.results.map((result, index) => index === this.selectionIndex ? c.green(` › ${result}`) : c.dim(` › ${result}`)).join("\n");
10266
9830
  printStr += `\n${resultCountLine}\n${resultBody}`;
10267
9831
  }
10268
- this.eraseAndPrint(printStr);
10269
- this.restoreCursor();
9832
+ this.eraseAndPrint(printStr), this.restoreCursor();
10270
9833
  }
10271
9834
  keywordOffset() {
10272
9835
  return `? ${this.message} › `.length + 1;
@@ -10282,14 +9845,10 @@ ${c.dim(` ...and ${remainingResultCount} more ${remainingResultCount === 1 ? "
10282
9845
  // We have to take care of screen width in case of long lines
10283
9846
  rows += 1 + Math.floor(Math.max(stripVTControlCharacters(line).length - 1, 0) / columns);
10284
9847
  }
10285
- this.write(`${ESC}1G`);
10286
- this.write(`${ESC}J`);
10287
- this.write(str);
10288
- this.write(`${ESC}${rows - 1}A`);
9848
+ this.write(`${ESC}1G`), this.write(`${ESC}J`), this.write(str), this.write(`${ESC}${rows - 1}A`);
10289
9849
  }
10290
9850
  close() {
10291
- this.filterRL.close();
10292
- if (this.onKeyPress) this.stdin.removeListener("keypress", this.onKeyPress);
9851
+ if (this.filterRL.close(), this.onKeyPress) this.stdin.removeListener("keypress", this.onKeyPress);
10293
9852
  if (this.stdin.isTTY) this.stdin.setRawMode(false);
10294
9853
  }
10295
9854
  restoreCursor() {
@@ -10314,8 +9873,7 @@ const keys = [
10314
9873
  ["w", "filter by a project name"],
10315
9874
  ["b", "start the browser server if not started yet"],
10316
9875
  ["q", "quit"]
10317
- ];
10318
- const cancelKeys = [
9876
+ ], cancelKeys = [
10319
9877
  "space",
10320
9878
  "c",
10321
9879
  "h",
@@ -10333,17 +9891,12 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
10333
9891
  // Cancel run and exit when ctrl-c or esc is pressed.
10334
9892
  // If cancelling takes long and key is pressed multiple times, exit forcefully.
10335
9893
  if (str === "" || str === "\x1B" || key && key.ctrl && key.name === "c") {
10336
- if (!ctx.isCancelling) {
10337
- ctx.logger.log(c.red("Cancelling test run. Press CTRL+c again to exit forcefully.\n"));
10338
- process.exitCode = 130;
10339
- await ctx.cancelCurrentRun("keyboard-input");
10340
- }
9894
+ if (!ctx.isCancelling) ctx.logger.log(c.red("Cancelling test run. Press CTRL+c again to exit forcefully.\n")), process.exitCode = 130, await ctx.cancelCurrentRun("keyboard-input");
10341
9895
  return ctx.exit(true);
10342
9896
  }
10343
9897
  // window not support suspend
10344
9898
  if (!isWindows && key && key.ctrl && key.name === "z") {
10345
- process.kill(process.ppid, "SIGTSTP");
10346
- process.kill(process.pid, "SIGTSTP");
9899
+ process.kill(process.ppid, "SIGTSTP"), process.kill(process.pid, "SIGTSTP");
10347
9900
  return;
10348
9901
  }
10349
9902
  const name = key?.name;
@@ -10372,24 +9925,17 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
10372
9925
  if (name === "t") return inputNamePattern();
10373
9926
  // change fileNamePattern
10374
9927
  if (name === "p") return inputFilePattern();
10375
- if (name === "b") {
10376
- await ctx._initBrowserServers();
10377
- ctx.projects.forEach((project) => {
10378
- ctx.logger.log();
10379
- ctx.logger.printBrowserBanner(project);
10380
- });
10381
- return null;
10382
- }
9928
+ if (name === "b") return await ctx._initBrowserServers(), ctx.projects.forEach((project) => {
9929
+ ctx.logger.log(), ctx.logger.printBrowserBanner(project);
9930
+ }), null;
10383
9931
  }
10384
9932
  async function keypressHandler(str, key) {
10385
9933
  await _keypressHandler(str, key);
10386
9934
  }
10387
9935
  async function inputNamePattern() {
10388
9936
  off();
10389
- const watchFilter = new WatchFilter("Input test name pattern (RegExp)", stdin, stdout);
10390
- const filter = await watchFilter.filter((str) => {
10391
- const files = ctx.state.getFiles();
10392
- const tests = getTests(files);
9937
+ const watchFilter = new WatchFilter("Input test name pattern (RegExp)", stdin, stdout), filter = await watchFilter.filter((str) => {
9938
+ const files = ctx.state.getFiles(), tests = getTests(files);
10393
9939
  try {
10394
9940
  const reg = new RegExp(str);
10395
9941
  return tests.map((test) => test.name).filter((testName) => testName.match(reg));
@@ -10398,11 +9944,8 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
10398
9944
  return [];
10399
9945
  }
10400
9946
  });
10401
- on();
10402
- if (typeof filter === "undefined") return;
10403
- const files = ctx.state.getFilepaths();
10404
- // if running in standalone mode, Vitest instance doesn't know about any test file
10405
- const cliFiles = ctx.config.standalone && !files.length ? await ctx._globTestFilepaths() : void 0;
9947
+ if (on(), typeof filter === "undefined") return;
9948
+ const files = ctx.state.getFilepaths(), cliFiles = ctx.config.standalone && !files.length ? await ctx._globTestFilepaths() : void 0;
10406
9949
  await ctx.changeNamePattern(filter?.trim() || "", cliFiles, "change pattern");
10407
9950
  }
10408
9951
  async function inputProjectName() {
@@ -10413,41 +9956,31 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
10413
9956
  message: "Input a single project name",
10414
9957
  initial: ctx.config.project[0] || ""
10415
9958
  }]);
10416
- on();
10417
- await ctx.changeProjectName(filter.trim());
9959
+ on(), await ctx.changeProjectName(filter.trim());
10418
9960
  }
10419
9961
  async function inputFilePattern() {
10420
9962
  off();
10421
- const watchFilter = new WatchFilter("Input filename pattern", stdin, stdout);
10422
- const filter = await watchFilter.filter(async (str) => {
9963
+ const watchFilter = new WatchFilter("Input filename pattern", stdin, stdout), filter = await watchFilter.filter(async (str) => {
10423
9964
  const files = await ctx.globTestFiles([str]);
10424
9965
  return files.map((file) => relative(ctx.config.root, file[1])).filter((file, index, all) => all.indexOf(file) === index);
10425
9966
  });
10426
- on();
10427
- if (typeof filter === "undefined") return;
9967
+ if (on(), typeof filter === "undefined") return;
10428
9968
  latestFilename = filter?.trim() || "";
10429
9969
  const lastResults = watchFilter.getLastResults();
10430
9970
  await ctx.changeFilenamePattern(latestFilename, filter && lastResults.length ? lastResults.map((i) => resolve(ctx.config.root, i)) : void 0);
10431
9971
  }
10432
9972
  let rl;
10433
9973
  function on() {
10434
- off();
10435
- rl = readline.createInterface({
9974
+ if (off(), rl = readline.createInterface({
10436
9975
  input: stdin,
10437
9976
  escapeCodeTimeout: 50
10438
- });
10439
- readline.emitKeypressEvents(stdin, rl);
10440
- if (stdin.isTTY) stdin.setRawMode(true);
9977
+ }), readline.emitKeypressEvents(stdin, rl), stdin.isTTY) stdin.setRawMode(true);
10441
9978
  stdin.on("keypress", keypressHandler);
10442
9979
  }
10443
9980
  function off() {
10444
- rl?.close();
10445
- rl = void 0;
10446
- stdin.removeListener("keypress", keypressHandler);
10447
- if (stdin.isTTY) stdin.setRawMode(false);
9981
+ if (rl?.close(), rl = void 0, stdin.removeListener("keypress", keypressHandler), stdin.isTTY) stdin.setRawMode(false);
10448
9982
  }
10449
- on();
10450
- return function cleanup() {
9983
+ return on(), function cleanup() {
10451
9984
  off();
10452
9985
  };
10453
9986
  }
@@ -10458,20 +9991,14 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
10458
9991
  * Returns a Vitest instance if initialized successfully.
10459
9992
  */
10460
9993
  async function startVitest(mode, cliFilters = [], options = {}, viteOverrides, vitestOptions) {
10461
- const root = resolve(options.root || process.cwd());
10462
- const ctx = await prepareVitest(mode, options, viteOverrides, vitestOptions, cliFilters);
9994
+ const root = resolve(options.root || process.cwd()), ctx = await prepareVitest(mode, options, viteOverrides, vitestOptions, cliFilters);
10463
9995
  if (mode === "test" && ctx.config.coverage.enabled) {
10464
- const provider = ctx.config.coverage.provider || "v8";
10465
- const requiredPackages = CoverageProviderMap[provider];
9996
+ const provider = ctx.config.coverage.provider || "v8", requiredPackages = CoverageProviderMap[provider];
10466
9997
  if (requiredPackages) {
10467
- if (!await ctx.packageInstaller.ensureInstalled(requiredPackages, root, ctx.version)) {
10468
- process.exitCode = 1;
10469
- return ctx;
10470
- }
9998
+ if (!await ctx.packageInstaller.ensureInstalled(requiredPackages, root, ctx.version)) return process.exitCode = 1, ctx;
10471
9999
  }
10472
10000
  }
10473
- const stdin = vitestOptions?.stdin || process.stdin;
10474
- const stdout = vitestOptions?.stdout || process.stdout;
10001
+ const stdin = vitestOptions?.stdin || process.stdin, stdout = vitestOptions?.stdout || process.stdout;
10475
10002
  let stdinCleanup;
10476
10003
  if (stdin.isTTY && ctx.config.watch) stdinCleanup = registerConsoleShortcuts(ctx, stdin, stdout);
10477
10004
  ctx.onAfterSetServer(() => {
@@ -10483,55 +10010,27 @@ async function startVitest(mode, cliFilters = [], options = {}, viteOverrides, v
10483
10010
  else if (ctx.config.standalone) await ctx.init();
10484
10011
  else await ctx.start(cliFilters);
10485
10012
  } catch (e) {
10486
- if (e instanceof FilesNotFoundError) return ctx;
10487
- if (e instanceof GitNotFoundError) {
10488
- ctx.logger.error(e.message);
10489
- return ctx;
10490
- }
10491
- if (e instanceof IncludeTaskLocationDisabledError || e instanceof RangeLocationFilterProvidedError || e instanceof LocationFilterFileNotFoundError) {
10492
- ctx.logger.printError(e, { verbose: false });
10493
- return ctx;
10494
- }
10495
- process.exitCode = 1;
10496
- ctx.logger.printError(e, {
10013
+ return e instanceof FilesNotFoundError ? ctx : e instanceof GitNotFoundError ? (ctx.logger.error(e.message), ctx) : e instanceof IncludeTaskLocationDisabledError || e instanceof RangeLocationFilterProvidedError || e instanceof LocationFilterFileNotFoundError ? (ctx.logger.printError(e, { verbose: false }), ctx) : (process.exitCode = 1, ctx.logger.printError(e, {
10497
10014
  fullStack: true,
10498
10015
  type: "Unhandled Error"
10499
- });
10500
- ctx.logger.error("\n\n");
10501
- return ctx;
10016
+ }), ctx.logger.error("\n\n"), ctx);
10502
10017
  }
10503
- if (ctx.shouldKeepServer()) return ctx;
10504
- stdinCleanup?.();
10505
- await ctx.close();
10506
- return ctx;
10018
+ return ctx.shouldKeepServer() ? ctx : (stdinCleanup?.(), await ctx.close(), ctx);
10507
10019
  }
10508
10020
  async function prepareVitest(mode, options = {}, viteOverrides, vitestOptions, cliFilters) {
10509
- process.env.TEST = "true";
10510
- process.env.VITEST = "true";
10511
- process.env.NODE_ENV ??= "test";
10512
- if (options.run) options.watch = false;
10021
+ if (process.env.TEST = "true", process.env.VITEST = "true", process.env.NODE_ENV ??= "test", options.run) options.watch = false;
10513
10022
  if (options.standalone && (cliFilters?.length || 0) > 0) options.standalone = false;
10514
10023
  // this shouldn't affect _application root_ that can be changed inside config
10515
- const root = resolve(options.root || process.cwd());
10516
- const ctx = await createVitest(mode, options, viteOverrides, vitestOptions);
10517
- const environmentPackage = getEnvPackageName(ctx.config.environment);
10518
- if (environmentPackage && !await ctx.packageInstaller.ensureInstalled(environmentPackage, root)) {
10519
- process.exitCode = 1;
10520
- return ctx;
10521
- }
10522
- return ctx;
10024
+ const root = resolve(options.root || process.cwd()), ctx = await createVitest(mode, options, viteOverrides, vitestOptions), environmentPackage = getEnvPackageName(ctx.config.environment);
10025
+ return environmentPackage && !await ctx.packageInstaller.ensureInstalled(environmentPackage, root) && (process.exitCode = 1), ctx;
10523
10026
  }
10524
10027
  function processCollected(ctx, files, options) {
10525
10028
  let errorsPrinted = false;
10526
- forEachSuite(files, (suite) => {
10029
+ if (forEachSuite(files, (suite) => {
10527
10030
  suite.errors().forEach((error) => {
10528
- errorsPrinted = true;
10529
- ctx.logger.printError(error, { project: suite.project });
10031
+ errorsPrinted = true, ctx.logger.printError(error, { project: suite.project });
10530
10032
  });
10531
- });
10532
- if (errorsPrinted) return;
10533
- if (typeof options.json !== "undefined") return processJsonOutput(files, options);
10534
- return formatCollectedAsString(files).forEach((test) => console.log(test));
10033
+ }), !errorsPrinted) return typeof options.json === "undefined" ? formatCollectedAsString(files).forEach((test) => console.log(test)) : processJsonOutput(files, options);
10535
10034
  }
10536
10035
  function outputFileList(files, options) {
10537
10036
  if (typeof options.json !== "undefined") return outputJsonFileList(files, options);
@@ -10541,8 +10040,7 @@ function outputJsonFileList(files, options) {
10541
10040
  if (typeof options.json === "boolean") return console.log(JSON.stringify(formatFilesAsJSON(files), null, 2));
10542
10041
  if (typeof options.json === "string") {
10543
10042
  const jsonPath = resolve(options.root || process.cwd(), options.json);
10544
- mkdirSync(dirname(jsonPath), { recursive: true });
10545
- writeFileSync(jsonPath, JSON.stringify(formatFilesAsJSON(files), null, 2));
10043
+ mkdirSync(dirname(jsonPath), { recursive: true }), writeFileSync(jsonPath, JSON.stringify(formatFilesAsJSON(files), null, 2));
10546
10044
  }
10547
10045
  }
10548
10046
  function formatFilesAsJSON(files) {
@@ -10563,8 +10061,7 @@ function processJsonOutput(files, options) {
10563
10061
  if (typeof options.json === "boolean") return console.log(JSON.stringify(formatCollectedAsJSON(files), null, 2));
10564
10062
  if (typeof options.json === "string") {
10565
10063
  const jsonPath = resolve(options.root || process.cwd(), options.json);
10566
- mkdirSync(dirname(jsonPath), { recursive: true });
10567
- writeFileSync(jsonPath, JSON.stringify(formatCollectedAsJSON(files), null, 2));
10064
+ mkdirSync(dirname(jsonPath), { recursive: true }), writeFileSync(jsonPath, JSON.stringify(formatCollectedAsJSON(files), null, 2));
10568
10065
  }
10569
10066
  }
10570
10067
  function forEachSuite(modules, callback) {
@@ -10575,7 +10072,7 @@ function forEachSuite(modules, callback) {
10575
10072
  }
10576
10073
  function formatCollectedAsJSON(files) {
10577
10074
  const results = [];
10578
- files.forEach((file) => {
10075
+ return files.forEach((file) => {
10579
10076
  for (const test of file.children.allTests()) {
10580
10077
  if (test.result().state === "skipped") continue;
10581
10078
  const result = {
@@ -10586,19 +10083,17 @@ function formatCollectedAsJSON(files) {
10586
10083
  if (test.location) result.location = test.location;
10587
10084
  results.push(result);
10588
10085
  }
10589
- });
10590
- return results;
10086
+ }), results;
10591
10087
  }
10592
10088
  function formatCollectedAsString(testModules) {
10593
10089
  const results = [];
10594
- testModules.forEach((testModule) => {
10090
+ return testModules.forEach((testModule) => {
10595
10091
  for (const test of testModule.children.allTests()) {
10596
10092
  if (test.result().state === "skipped") continue;
10597
10093
  const fullName = `${test.module.task.name} > ${test.fullName}`;
10598
10094
  results.push((test.project.name ? `[${test.project.name}] ` : "") + fullName);
10599
10095
  }
10600
- });
10601
- return results;
10096
+ }), results;
10602
10097
  }
10603
10098
  const envPackageNames = {
10604
10099
  "jsdom": "jsdom",
@@ -10606,10 +10101,7 @@ const envPackageNames = {
10606
10101
  "edge-runtime": "@edge-runtime/vm"
10607
10102
  };
10608
10103
  function getEnvPackageName(env) {
10609
- if (env === "node") return null;
10610
- if (env in envPackageNames) return envPackageNames[env];
10611
- if (env[0] === "." || isAbsolute(env)) return null;
10612
- return `vitest-environment-${env}`;
10104
+ return env === "node" ? null : env in envPackageNames ? envPackageNames[env] : env[0] === "." || isAbsolute(env) ? null : `vitest-environment-${env}`;
10613
10105
  }
10614
10106
 
10615
10107
  var cliApi = /*#__PURE__*/Object.freeze({