vitest 4.0.0-beta.10 → 4.0.0-beta.12

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 (69) hide show
  1. package/LICENSE.md +85 -101
  2. package/dist/browser.d.ts +10 -6
  3. package/dist/browser.js +8 -5
  4. package/dist/chunks/{benchmark.CJUa-Hsa.js → benchmark.DHKMYAts.js} +2 -2
  5. package/dist/chunks/{browser.d.yFAklsD1.d.ts → browser.d.D9YV3JvA.d.ts} +1 -1
  6. package/dist/chunks/{cac.DCxo_nSu.js → cac.r1gel_VZ.js} +18 -11
  7. package/dist/chunks/{cli-api.BJJXh9BV.js → cli-api.CpywZzJV.js} +153 -176
  8. package/dist/chunks/{config.d.B_LthbQq.d.ts → config.d.DGazh2r6.d.ts} +3 -1
  9. package/dist/chunks/{console.7h5kHUIf.js → console.CTJL2nuH.js} +4 -6
  10. package/dist/chunks/{coverage.BCU-r2QL.js → coverage.CiB0fs_7.js} +57 -79
  11. package/dist/chunks/{creator.08Gi-vCA.js → creator.DfXDsUyL.js} +6 -8
  12. package/dist/chunks/{global.d.BK3X7FW1.d.ts → global.d.BcFPD2LN.d.ts} +0 -13
  13. package/dist/chunks/{globals.DG-S3xFe.js → globals.DC4ntO86.js} +8 -6
  14. package/dist/chunks/{index.DIWhzsUh.js → index.Bt-upxGS.js} +6 -12
  15. package/dist/chunks/{index.BIP7prJq.js → index.CHrBLuEH.js} +94 -103
  16. package/dist/chunks/{index.X0nbfr6-.js → index.Dc3xnDvT.js} +48 -289
  17. package/dist/chunks/{index.CMfqw92x.js → index.Dnl38iQ_.js} +2 -2
  18. package/dist/chunks/{index.BjKEiSn0.js → index.uLUz1RDt.js} +3 -3
  19. package/dist/chunks/{inspector.CvQD-Nie.js → inspector.Br76Q2Mb.js} +1 -4
  20. package/dist/chunks/{moduleRunner.d.D9nBoC4p.d.ts → moduleRunner.d.CeYc7nZ0.d.ts} +1 -1
  21. package/dist/chunks/{node.CyipiPvJ.js → node.BwAWWjHZ.js} +3 -4
  22. package/dist/chunks/{plugin.d.BMVSnsGV.d.ts → plugin.d.XreRXLXS.d.ts} +1 -1
  23. package/dist/chunks/{reporters.d.BUWjmRYq.d.ts → reporters.d.CJVTaaWb.d.ts} +54 -13
  24. package/dist/chunks/{resolveSnapshotEnvironment.Bkht6Yor.js → resolveSnapshotEnvironment.BsJpmVZR.js} +7 -8
  25. package/dist/chunks/{rpc.BKr6mtxz.js → rpc.cD77ENhU.js} +13 -14
  26. package/dist/chunks/{setup-common.uiMcU3cv.js → setup-common.BewgbkTd.js} +6 -6
  27. package/dist/chunks/{startModuleRunner.p67gbNo9.js → startModuleRunner.DPBo3mme.js} +65 -56
  28. package/dist/chunks/{test.BiqSKISg.js → test.CTuWuHYH.js} +7 -7
  29. package/dist/chunks/{typechecker.DB-fIMaH.js → typechecker.BfOQ86_a.js} +624 -14
  30. package/dist/chunks/{utils.D2R2NiOH.js → utils.CG9h5ccR.js} +2 -5
  31. package/dist/chunks/{vi.ZPgvtBao.js → vi.B2--mG9U.js} +38 -145
  32. package/dist/{worker.js → chunks/worker.DVTUM2IW.js} +71 -42
  33. package/dist/chunks/{worker.d.BDsXGkwh.d.ts → worker.d.buwuBpBt.d.ts} +2 -77
  34. package/dist/cli.js +7 -5
  35. package/dist/config.d.ts +6 -6
  36. package/dist/coverage.d.ts +5 -5
  37. package/dist/coverage.js +4 -5
  38. package/dist/environments.js +1 -1
  39. package/dist/index.d.ts +8 -8
  40. package/dist/index.js +8 -6
  41. package/dist/module-evaluator.d.ts +3 -3
  42. package/dist/module-evaluator.js +11 -13
  43. package/dist/module-runner.js +5 -5
  44. package/dist/node.d.ts +14 -11
  45. package/dist/node.js +18 -14
  46. package/dist/reporters.d.ts +5 -5
  47. package/dist/reporters.js +7 -5
  48. package/dist/runners.d.ts +1 -1
  49. package/dist/runners.js +9 -7
  50. package/dist/snapshot.js +3 -3
  51. package/dist/suite.js +4 -3
  52. package/dist/{chunks/base.Cjha6usc.js → worker-base.js} +104 -32
  53. package/dist/{chunks/vm.Ca0Y0W5f.js → worker-vm.js} +81 -31
  54. package/dist/workers/runVmTests.js +14 -11
  55. package/package.json +26 -26
  56. package/browser.d.ts +0 -1
  57. package/dist/chunks/moduleTransport.I-bgQy0S.js +0 -19
  58. package/dist/chunks/resolver.Bx6lE0iq.js +0 -119
  59. package/dist/chunks/utils.C2YI6McM.js +0 -52
  60. package/dist/chunks/worker.d.BNcX_2mH.d.ts +0 -8
  61. package/dist/workers/forks.js +0 -67
  62. package/dist/workers/threads.js +0 -55
  63. package/dist/workers/vmForks.js +0 -48
  64. package/dist/workers/vmThreads.js +0 -38
  65. package/dist/workers.d.ts +0 -38
  66. package/dist/workers.js +0 -48
  67. package/execute.d.ts +0 -1
  68. package/utils.d.ts +0 -1
  69. package/workers.d.ts +0 -1
@@ -1,18 +1,18 @@
1
- import fs, { promises, existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
1
+ import fs, { promises, existsSync, readFileSync, statSync, readdirSync, mkdirSync, writeFileSync } from 'node:fs';
2
2
  import { relative, resolve, dirname, extname, normalize, join, basename, isAbsolute } from 'pathe';
3
3
  import { C as CoverageProviderMap } from './coverage.D_JHT54q.js';
4
4
  import path, { resolve as resolve$1 } from 'node:path';
5
- import { noop, createDefer, slash, highlight, toArray, cleanUrl, deepMerge, KNOWN_ASSET_RE, nanoid, deepClone, isPrimitive, notNullish } from '@vitest/utils';
6
- import { f as findUp, p as prompt } from './index.X0nbfr6-.js';
5
+ import { noop, createDefer, slash, toArray, cleanUrl, deepMerge, nanoid, deepClone, isPrimitive, notNullish } from '@vitest/utils/helpers';
6
+ import { a as any, p as prompt } from './index.Dc3xnDvT.js';
7
7
  import * as vite from 'vite';
8
8
  import { parseAst, searchForWorkspaceRoot, version, mergeConfig, createServer } from 'vite';
9
9
  import { A as API_PATH, c as configFiles, d as defaultBrowserPort, a as defaultPort } from './constants.D_Q9UYh-.js';
10
10
  import nodeos__default, { tmpdir } from 'node:os';
11
- import { generateHash as generateHash$1, calculateSuiteHash, someTasksAreOnly, interpretTaskModes, generateFileHash, limitConcurrency, createFileTask as createFileTask$1, hasFailed, getTasks, getTests } from '@vitest/runner/utils';
11
+ import { generateHash as generateHash$1, calculateSuiteHash, someTasksAreOnly, interpretTaskModes, generateFileHash, limitConcurrency, createFileTask as createFileTask$1, hasFailed, getTasks, isTestCase } from '@vitest/runner/utils';
12
12
  import { SnapshotManager } from '@vitest/snapshot/manager';
13
- import { v as version$1 } from './cac.DCxo_nSu.js';
13
+ import { v as version$1 } from './cac.r1gel_VZ.js';
14
14
  import { c as createBirpc } from './index.Bgo3tNWt.js';
15
- 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.BIP7prJq.js';
15
+ import { p as parse, d as stringify, e as printError, f as formatProjectName, w as withLabel, h as errorBanner, i as divider, j as generateCodeFrame, R as ReportersMap, B as BlobReporter, r as readBlobs, H as HangingProcessReporter } from './index.CHrBLuEH.js';
16
16
  import require$$0$3 from 'events';
17
17
  import require$$1$1 from 'https';
18
18
  import require$$2 from 'http';
@@ -26,14 +26,14 @@ import require$$0$1 from 'buffer';
26
26
  import { g as getDefaultExportFromCjs } from './_commonjsHelpers.BFTU3MAI.js';
27
27
  import crypto, { createHash } from 'node:crypto';
28
28
  import { distDir, rootDir } from '../path.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.BCU-r2QL.js';
30
- import { b as ancestor, c as createDefinesScript, d as convertTasksToEvents } from './typechecker.DB-fIMaH.js';
31
- import { TraceMap, originalPositionFor, parseErrorStacktrace } from '@vitest/utils/source-map';
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.CiB0fs_7.js';
30
+ import { b as TraceMap, o as originalPositionFor, c as ancestor, d as createDefinesScript, e as convertTasksToEvents } from './typechecker.BfOQ86_a.js';
32
31
  import createDebug from 'debug';
33
32
  import { VitestModuleEvaluator } from '#module-evaluator';
34
33
  import { ModuleRunner } from 'vite/module-runner';
35
34
  import { Console } from 'node:console';
36
35
  import c from 'tinyrainbow';
36
+ import { highlight } from '@vitest/utils/highlight';
37
37
  import { createRequire, builtinModules, isBuiltin } from 'node:module';
38
38
  import url, { pathToFileURL } from 'node:url';
39
39
  import { i as isTTY, a as isWindows } from './env.D4Lgay0q.js';
@@ -43,11 +43,13 @@ import { glob, isDynamicPattern } from 'tinyglobby';
43
43
  import MagicString from 'magic-string';
44
44
  import { hoistMocksPlugin, automockPlugin } from '@vitest/mocker/node';
45
45
  import { c as configDefaults } from './defaults.CXFFjsi8.js';
46
- import { f as findNearestPackageData } from './resolver.Bx6lE0iq.js';
46
+ import { KNOWN_ASSET_RE } from '@vitest/utils/constants';
47
+ import { findNearestPackageData } from '@vitest/utils/resolver';
47
48
  import * as esModuleLexer from 'es-module-lexer';
48
- import { a as BenchmarkReportsMap } from './index.BjKEiSn0.js';
49
+ import { a as BenchmarkReportsMap } from './index.uLUz1RDt.js';
49
50
  import assert$1 from 'node:assert';
50
- import { serializeError as serializeError$1 } from '@vitest/utils/error';
51
+ import { serializeValue } from '@vitest/utils/serialize';
52
+ import { parseErrorStacktrace } from '@vitest/utils/source-map';
51
53
  import readline from 'node:readline';
52
54
  import { stripVTControlCharacters } from 'node:util';
53
55
 
@@ -5081,8 +5083,8 @@ catch {}
5081
5083
  }
5082
5084
 
5083
5085
  function setup(ctx, _server) {
5084
- const wss = new WebSocketServer({ noServer: true }), clients = /* @__PURE__ */ new Map(), server = _server || ctx.vite;
5085
- server.httpServer?.on("upgrade", (request, socket, head) => {
5086
+ const wss = new WebSocketServer({ noServer: true }), clients = /* @__PURE__ */ new Map();
5087
+ (_server || ctx.vite).httpServer?.on("upgrade", (request, socket, head) => {
5086
5088
  if (!request.url) return;
5087
5089
  const { pathname } = new URL(request.url, "http://localhost");
5088
5090
  if (pathname === API_PATH) {
@@ -5148,8 +5150,7 @@ function setup(ctx, _server) {
5148
5150
  return ctx.state.getUnhandledErrors();
5149
5151
  },
5150
5152
  async getTestFiles() {
5151
- const spec = await ctx.globTestSpecifications();
5152
- return spec.map((spec) => [
5153
+ return (await ctx.globTestSpecifications()).map((spec) => [
5153
5154
  {
5154
5155
  name: spec.project.config.name,
5155
5156
  root: spec.project.config.root
@@ -5338,17 +5339,13 @@ function createFailedFileTask(project, filepath, error) {
5338
5339
  return file.file = file, file;
5339
5340
  }
5340
5341
  function serializeError(ctx, error) {
5341
- if ("errors" in error && "pluginCode" in error) {
5342
- const errors = error.errors.map((e) => {
5343
- return {
5344
- name: error.name,
5345
- message: e.text,
5346
- stack: e.location ? `${error.name}: ${e.text}\n at ${relative(ctx.config.root, e.location.file)}:${e.location.line}:${e.location.column}` : ""
5347
- };
5348
- });
5349
- return errors;
5350
- }
5351
- return [{
5342
+ return "errors" in error && "pluginCode" in error ? error.errors.map((e) => {
5343
+ return {
5344
+ name: error.name,
5345
+ message: e.text,
5346
+ stack: e.location ? `${error.name}: ${e.text}\n at ${relative(ctx.config.root, e.location.file)}:${e.location.line}:${e.location.column}` : ""
5347
+ };
5348
+ }) : [{
5352
5349
  name: error.name,
5353
5350
  stack: error.stack,
5354
5351
  message: error.message
@@ -5616,13 +5613,11 @@ class ServerModuleRunner extends ModuleRunner {
5616
5613
  const fetchModule = createFetchModuleFunction(resolver, false);
5617
5614
  super({
5618
5615
  hmr: false,
5619
- sourcemapInterceptor: "node",
5620
5616
  transport: { async invoke(event) {
5621
5617
  if (event.type !== "custom") throw new Error(`Vitest Module Runner doesn't support Vite HMR events.`);
5622
5618
  const { data } = event.data;
5623
5619
  try {
5624
- const result = await fetchModule(data[0], data[1], environment, data[2]);
5625
- return { result };
5620
+ return { result: await fetchModule(data[0], data[1], environment, data[2]) };
5626
5621
  } catch (error) {
5627
5622
  return { error };
5628
5623
  }
@@ -5761,8 +5756,8 @@ class Logger {
5761
5756
  const projectsFilter = toArray(config.project);
5762
5757
  if (projectsFilter.length) this.console.error(c.dim("projects: ") + c.yellow(projectsFilter.join(comma)));
5763
5758
  this.ctx.projects.forEach((project) => {
5764
- const config = project.config, printConfig = !project.isRootProject() && project.name;
5765
- if (printConfig) this.console.error(`\n${formatProjectName(project)}\n`);
5759
+ const config = project.config;
5760
+ if (!project.isRootProject() && project.name) this.console.error(`\n${formatProjectName(project)}\n`);
5766
5761
  if (config.include) this.console.error(c.dim("include: ") + c.yellow(config.include.join(comma)));
5767
5762
  if (config.exclude) this.console.error(c.dim("exclude: ") + c.yellow(config.exclude.join(comma)));
5768
5763
  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)));
@@ -5853,7 +5848,7 @@ class VitestPackageInstaller {
5853
5848
  }
5854
5849
  if (/* @__PURE__ */ isPackageExists(dependency, { paths: [root, __dirname] })) return true;
5855
5850
  if (process.stderr.write(c.red(`${c.inverse(c.red(" MISSING DEPENDENCY "))} Cannot find dependency '${dependency}'\n\n`)), !isTTY) return false;
5856
- const prompts = await import('./index.X0nbfr6-.js').then(function (n) { return n.i; }), { install } = await prompts.default({
5851
+ const { install } = await (await import('./index.Dc3xnDvT.js').then(function (n) { return n.i; })).default({
5857
5852
  type: "confirm",
5858
5853
  name: "install",
5859
5854
  message: c.reset(`Do you want to install ${c.green(dependency)}?`)
@@ -5965,7 +5960,8 @@ function serializeConfig(project) {
5965
5960
  screenshotFailures: browser.screenshotFailures,
5966
5961
  locators: { testIdAttribute: browser.locators.testIdAttribute },
5967
5962
  providerOptions: provider?.name === "playwright" ? { actionTimeout: provider?.options?.actionTimeout } : {},
5968
- trackUnhandledErrors: browser.trackUnhandledErrors ?? true
5963
+ trackUnhandledErrors: browser.trackUnhandledErrors ?? true,
5964
+ trace: browser.trace.mode
5969
5965
  };
5970
5966
  })(config.browser),
5971
5967
  standalone: config.standalone,
@@ -6501,7 +6497,7 @@ function MetaEnvReplacerPlugin() {
6501
6497
  transform(code, id) {
6502
6498
  if (!/\bimport\.meta\.env\b/.test(code)) return null;
6503
6499
  let s = null;
6504
- const cleanCode = stripLiteral(code), envs = cleanCode.matchAll(/\bimport\.meta\.env\b/g);
6500
+ const envs = stripLiteral(code).matchAll(/\bimport\.meta\.env\b/g);
6505
6501
  for (const env of envs) {
6506
6502
  s ||= new MagicString(code);
6507
6503
  const startIndex = env.index, endIndex = startIndex + env[0].length;
@@ -6633,9 +6629,7 @@ function isInline(id) {
6633
6629
  return cssInlineRE.test(id);
6634
6630
  }
6635
6631
  function getCSSModuleProxyReturn(strategy, filename) {
6636
- if (strategy === "non-scoped") return "style";
6637
- const hash = generateCssFilenameHash(filename);
6638
- return `\`_\${style}_${hash}\``;
6632
+ return strategy === "non-scoped" ? "style" : `\`_\${style}_${generateCssFilenameHash(filename)}\``;
6639
6633
  }
6640
6634
  function CSSEnablerPlugin(ctx) {
6641
6635
  const shouldProcessCSS = (id) => {
@@ -6657,12 +6651,12 @@ function CSSEnablerPlugin(ctx) {
6657
6651
  // return proxy for css modules, so that imported module has names:
6658
6652
  // styles.foo returns a "foo" instead of "undefined"
6659
6653
  // we don't use code content to generate hash for "scoped", because it's empty
6660
- 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), {
6654
+ const scopeStrategy = typeof ctx.config.css !== "boolean" && ctx.config.css.modules?.classNameStrategy || "stable";
6655
+ return { code: `export default new Proxy(Object.create(null), {
6661
6656
  get(_, style) {
6662
- return ${proxyReturn};
6657
+ return ${getCSSModuleProxyReturn(scopeStrategy, relative(ctx.config.root, id))};
6663
6658
  },
6664
- })`;
6665
- return { code };
6659
+ })` };
6666
6660
  }
6667
6661
  return { code: "export default \"\"" };
6668
6662
  }
@@ -6777,12 +6771,7 @@ function getDefaultResolveOptions() {
6777
6771
  };
6778
6772
  }
6779
6773
  function getDefaultServerConditions() {
6780
- const viteMajor = Number(version.split(".")[0]);
6781
- if (viteMajor >= 6) {
6782
- const conditions = vite.defaultServerConditions;
6783
- return conditions.filter((c) => c !== "module");
6784
- }
6785
- return ["node"];
6774
+ return Number(version.split(".")[0]) >= 6 ? vite.defaultServerConditions.filter((c) => c !== "module") : ["node"];
6786
6775
  }
6787
6776
 
6788
6777
  function ModuleRunnerTransform() {
@@ -6840,15 +6829,10 @@ function VitestProjectResolver(ctx) {
6840
6829
  name: "vitest:resolve-root",
6841
6830
  enforce: "pre",
6842
6831
  async resolveId(id, _, { ssr }) {
6843
- if (id === "vitest" || id.startsWith("@vitest/") || id.startsWith("vitest/")) {
6844
- // always redirect the request to the root vitest plugin since
6845
- // it will be the one used to run Vitest
6846
- const resolved = await ctx.vite.pluginContainer.resolveId(id, void 0, {
6847
- skip: new Set([plugin]),
6848
- ssr
6849
- });
6850
- return resolved;
6851
- }
6832
+ if (id === "vitest" || id.startsWith("@vitest/") || id.startsWith("vitest/")) return await ctx.vite.pluginContainer.resolveId(id, void 0, {
6833
+ skip: new Set([plugin]),
6834
+ ssr
6835
+ });
6852
6836
  }
6853
6837
  };
6854
6838
  return plugin;
@@ -6883,22 +6867,19 @@ function WorkspaceVitestPlugin(project, options) {
6883
6867
  if (existsSync(pkgJsonPath)) name = JSON.parse(readFileSync(pkgJsonPath, "utf-8")).name;
6884
6868
  if (typeof name !== "string" || !name) name = basename(dir);
6885
6869
  } else name = options.workspacePath.toString();
6886
- const isUserBrowserEnabled = viteConfig.test?.browser?.enabled, isBrowserEnabled = isUserBrowserEnabled ?? (viteConfig.test?.browser && project.vitest._cliOptions.browser?.enabled), workspaceNames = [name], browser = viteConfig.test.browser || {};
6870
+ const isBrowserEnabled = viteConfig.test?.browser?.enabled ?? (viteConfig.test?.browser && project.vitest._cliOptions.browser?.enabled), workspaceNames = [name], browser = viteConfig.test.browser || {};
6887
6871
  if (isBrowserEnabled && browser.name && !browser.instances?.length)
6888
6872
  // vitest injects `instances` in this case later on
6889
6873
  workspaceNames.push(name ? `${name} (${browser.name})` : browser.name);
6890
- viteConfig.test?.browser?.instances?.forEach((instance) => {
6891
- if (instance.name ??= name ? `${name} (${instance.browser})` : instance.browser, isBrowserEnabled) workspaceNames.push(instance.name);
6892
- });
6893
- const filters = project.vitest.config.project;
6894
6874
  // if there is `--project=...` filter, check if any of the potential projects match
6895
6875
  // if projects don't match, we ignore the test project altogether
6896
6876
  // if some of them match, they will later be filtered again by `resolveWorkspace`
6897
- if (filters.length) {
6898
- const hasProject = workspaceNames.some((name) => {
6877
+ if (viteConfig.test?.browser?.instances?.forEach((instance) => {
6878
+ if (instance.name ??= name ? `${name} (${instance.browser})` : instance.browser, isBrowserEnabled) workspaceNames.push(instance.name);
6879
+ }), project.vitest.config.project.length) {
6880
+ if (!workspaceNames.some((name) => {
6899
6881
  return project.vitest.matchesProjectFilter(name);
6900
- });
6901
- if (!hasProject) throw new VitestFilteredOutProjectError();
6882
+ })) throw new VitestFilteredOutProjectError();
6902
6883
  }
6903
6884
  return {
6904
6885
  environments: { __vitest__: { dev: {} } },
@@ -7039,9 +7020,7 @@ async function isValidNodeImport(id) {
7039
7020
  const extension = extname(id);
7040
7021
  if (BUILTIN_EXTENSIONS.has(extension)) return true;
7041
7022
  if (extension !== ".js") return false;
7042
- id = id.replace("file:///", "");
7043
- const package_ = findNearestPackageData(dirname(id));
7044
- if (package_.type === "module") return true;
7023
+ if (id = id.replace("file:///", ""), findNearestPackageData(dirname(id)).type === "module") return true;
7045
7024
  if (/\.(?:\w+-)?esm?(?:-\w+)?\.js$|\/esm?\//.test(id)) return false;
7046
7025
  try {
7047
7026
  await esModuleLexer.init;
@@ -7065,8 +7044,8 @@ async function _shouldExternalize(id, options) {
7065
7044
  // Unless the user explicitly opted to inline them, externalize Vite deps.
7066
7045
  // They are too big to inline by default.
7067
7046
  if (matchExternalizePattern(id, moduleDirectories, options?.external) || options?.cacheDir && id.includes(options.cacheDir)) return id;
7068
- const isLibraryModule = moduleDirectories.some((dir) => id.includes(dir)), guessCJS = isLibraryModule && options?.fallbackCJS;
7069
- return id = guessCJS ? guessCJSversion(id) || id : id, matchExternalizePattern(id, moduleDirectories, defaultInline) ? false : matchExternalizePattern(id, moduleDirectories, depsExternal) || isLibraryModule && await isValidNodeImport(id) ? id : false;
7047
+ const isLibraryModule = moduleDirectories.some((dir) => id.includes(dir));
7048
+ return id = isLibraryModule && options?.fallbackCJS ? guessCJSversion(id) || id : id, matchExternalizePattern(id, moduleDirectories, defaultInline) ? false : matchExternalizePattern(id, moduleDirectories, depsExternal) || isLibraryModule && await isValidNodeImport(id) ? id : false;
7070
7049
  }
7071
7050
  function matchExternalizePattern(id, moduleDirectories, patterns) {
7072
7051
  if (patterns == null) return false;
@@ -7108,7 +7087,7 @@ class TestSpecification {
7108
7087
  */
7109
7088
  get testModule() {
7110
7089
  const task = this.project.vitest.state.idMap.get(this.taskId);
7111
- return task ? this.project.vitest.state.getReportedEntity(task) : void 0;
7090
+ if (task) return this.project.vitest.state.getReportedEntity(task);
7112
7091
  }
7113
7092
  toJSON() {
7114
7093
  return [
@@ -7337,16 +7316,15 @@ class TestProject {
7337
7316
  }
7338
7317
  /** @internal */
7339
7318
  async globFiles(include, exclude, cwd) {
7340
- const globOptions = {
7319
+ // keep the slashes consistent with Vite
7320
+ // we are not using the pathe here because it normalizes the drive letter on Windows
7321
+ // and we want to keep it the same as working dir
7322
+ return (await glob(include, {
7341
7323
  dot: true,
7342
7324
  cwd,
7343
7325
  ignore: exclude,
7344
7326
  expandDirectories: false
7345
- }, files = await glob(include, globOptions);
7346
- // keep the slashes consistent with Vite
7347
- // we are not using the pathe here because it normalizes the drive letter on Windows
7348
- // and we want to keep it the same as working dir
7349
- return files.map((file) => slash(path.resolve(cwd, file)));
7327
+ })).map((file) => slash(path.resolve(cwd, file)));
7350
7328
  }
7351
7329
  /**
7352
7330
  * Test if a file matches the test globs. This does the actual glob matching if the test is not cached, unlike `isCachedTestFile`.
@@ -7415,6 +7393,8 @@ class TestProject {
7415
7393
  this.browser?.close(),
7416
7394
  this.clearTmpDir()
7417
7395
  ].filter(Boolean)).then(() => {
7396
+ if (!this.runner.isClosed()) return this.runner.close();
7397
+ }).then(() => {
7418
7398
  this._provided = {}, this._vite = void 0;
7419
7399
  });
7420
7400
  return this.closingPromise;
@@ -7511,8 +7491,13 @@ function generateHash(str) {
7511
7491
  return `${hash}`;
7512
7492
  }
7513
7493
 
7494
+ // vitest.config.*
7495
+ // vite.config.*
7496
+ // vitest.unit.config.*
7497
+ // vite.unit.config.*
7498
+ const CONFIG_REGEXP = /^vite(?:st)?(?:\.\w+)?\.config\./;
7514
7499
  async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projectsDefinition, names) {
7515
- const { configFiles, projectConfigs, nonConfigDirectories } = await resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDefinition), overridesOptions = [
7500
+ const { configFiles, projectConfigs, nonConfigDirectories } = await resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDefinition), cliOverrides = [
7516
7501
  "logHeapUsage",
7517
7502
  "allowOnly",
7518
7503
  "sequence",
@@ -7531,7 +7516,7 @@ async function resolveProjects(vitest, cliOptions, workspaceConfigPath, projects
7531
7516
  "inspect",
7532
7517
  "inspectBrk",
7533
7518
  "fileParallelism"
7534
- ], cliOverrides = overridesOptions.reduce((acc, name) => {
7519
+ ].reduce((acc, name) => {
7535
7520
  if (name in cliOptions) acc[name] = cliOptions[name];
7536
7521
  return acc;
7537
7522
  }, {}), projectPromises = [], fileProjects = [...configFiles, ...nonConfigDirectories], concurrent = limitConcurrency(nodeos__default.availableParallelism?.() || nodeos__default.cpus().length || 5);
@@ -7647,7 +7632,7 @@ async function resolveBrowserProjects(vitest, names, resolvedProjects) {
7647
7632
  if (headedBrowserProjects.length > 1) {
7648
7633
  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("");
7649
7634
  if (!isTTY) throw new Error(`${message} Please, filter projects with --browser=name or --project=name flag or run tests with "headless: true" option.`);
7650
- const prompts = await import('./index.X0nbfr6-.js').then(function (n) { return n.i; }), { projectName } = await prompts.default({
7635
+ const { projectName } = await (await import('./index.Dc3xnDvT.js').then(function (n) { return n.i; })).default({
7651
7636
  type: "select",
7652
7637
  name: "projectName",
7653
7638
  choices: headedBrowserProjects.map((project) => ({
@@ -7695,11 +7680,14 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDe
7695
7680
  const note = "Projects definition";
7696
7681
  throw new Error(`${note} references a non-existing file or a directory: ${file}`);
7697
7682
  }
7698
- const stats = await promises.stat(file);
7683
+ const stats = statSync(file);
7699
7684
  // user can specify a config file directly
7700
- if (stats.isFile()) projectsConfigFiles.push(file);
7701
- else if (stats.isDirectory()) {
7702
- const configFile = await resolveDirectoryConfig(file);
7685
+ if (stats.isFile()) {
7686
+ const name = basename(file);
7687
+ if (!CONFIG_REGEXP.test(name)) throw new Error(`The file "${relative(vitest.config.root, file)}" must start with "vitest.config"/"vite.config" or match the pattern "(vitest|vite).*.config.*" to be a valid project config.`);
7688
+ projectsConfigFiles.push(file);
7689
+ } else if (stats.isDirectory()) {
7690
+ const configFile = resolveDirectoryConfig(file);
7703
7691
  if (configFile) projectsConfigFiles.push(configFile);
7704
7692
  else {
7705
7693
  const directory = file.at(-1) === "/" ? file : `${file}/`;
@@ -7728,16 +7716,20 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDe
7728
7716
  "**/*.timestamp-*",
7729
7717
  "**/.DS_Store"
7730
7718
  ]
7731
- }, projectsFs = await glob(projectsGlobMatches, globOptions);
7732
- await Promise.all(projectsFs.map(async (path) => {
7719
+ };
7720
+ (await glob(projectsGlobMatches, globOptions)).forEach((path) => {
7733
7721
  // directories are allowed with a glob like `packages/*`
7734
7722
  // in this case every directory is treated as a project
7735
7723
  if (path.endsWith("/")) {
7736
- const configFile = await resolveDirectoryConfig(path);
7724
+ const configFile = resolveDirectoryConfig(path);
7737
7725
  if (configFile) projectsConfigFiles.push(configFile);
7738
7726
  else nonConfigProjectDirectories.push(path);
7739
- } else projectsConfigFiles.push(path);
7740
- }));
7727
+ } else {
7728
+ const name = basename(path);
7729
+ if (!CONFIG_REGEXP.test(name)) throw new Error(`The projects glob matched a file "${relative(vitest.config.root, path)}", but it should also either start with "vitest.config"/"vite.config" or match the pattern "(vitest|vite).*.config.*".`);
7730
+ projectsConfigFiles.push(path);
7731
+ }
7732
+ });
7741
7733
  }
7742
7734
  const projectConfigFiles = Array.from(new Set(projectsConfigFiles));
7743
7735
  return {
@@ -7746,16 +7738,13 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, projectsDe
7746
7738
  configFiles: projectConfigFiles
7747
7739
  };
7748
7740
  }
7749
- async function resolveDirectoryConfig(directory) {
7750
- const files = new Set(await promises.readdir(directory)), configFile = configFiles.find((file) => files.has(file));
7741
+ function resolveDirectoryConfig(directory) {
7742
+ const files = new Set(readdirSync(directory)), configFile = configFiles.find((file) => files.has(file));
7751
7743
  return configFile ? resolve(directory, configFile) : null;
7752
7744
  }
7753
7745
  function getDefaultTestProject(vitest) {
7754
7746
  const filter = vitest.config.project, project = vitest._ensureRootProject();
7755
- if (!filter.length) return project;
7756
- // check for the project name and browser names
7757
- const hasProjects = getPotentialProjectNames(project).some((p) => vitest.matchesProjectFilter(p));
7758
- return hasProjects ? project : null;
7747
+ return !filter.length || getPotentialProjectNames(project).some((p) => vitest.matchesProjectFilter(p)) ? project : null;
7759
7748
  }
7760
7749
  function getPotentialProjectNames(project) {
7761
7750
  const names = [project.name];
@@ -7778,17 +7767,11 @@ function createReporters(reporterReferences, ctx) {
7778
7767
  const runner = ctx.runner, promisedReporters = reporterReferences.map(async (referenceOrInstance) => {
7779
7768
  if (Array.isArray(referenceOrInstance)) {
7780
7769
  const [reporterName, reporterOptions] = referenceOrInstance;
7781
- if (reporterName === "html") {
7782
- await ctx.packageInstaller.ensureInstalled("@vitest/ui", ctx.config.root, ctx.version);
7783
- const CustomReporter = await loadCustomReporterModule("@vitest/ui/reporter", runner);
7784
- return new CustomReporter(reporterOptions);
7785
- } else if (reporterName in ReportersMap) {
7770
+ if (reporterName === "html") return await ctx.packageInstaller.ensureInstalled("@vitest/ui", ctx.config.root, ctx.version), new (await (loadCustomReporterModule("@vitest/ui/reporter", runner)))(reporterOptions);
7771
+ if (reporterName in ReportersMap) {
7786
7772
  const BuiltinReporter = ReportersMap[reporterName];
7787
7773
  return new BuiltinReporter(reporterOptions);
7788
- } else {
7789
- const CustomReporter = await loadCustomReporterModule(reporterName, runner);
7790
- return new CustomReporter(reporterOptions);
7791
- }
7774
+ } else return new (await (loadCustomReporterModule(reporterName, runner)))(reporterOptions);
7792
7775
  }
7793
7776
  return referenceOrInstance;
7794
7777
  });
@@ -7799,10 +7782,7 @@ function createBenchmarkReporters(reporterReferences, runner) {
7799
7782
  if (typeof referenceOrInstance === "string") if (referenceOrInstance in BenchmarkReportsMap) {
7800
7783
  const BuiltinReporter = BenchmarkReportsMap[referenceOrInstance];
7801
7784
  return new BuiltinReporter();
7802
- } else {
7803
- const CustomReporter = await loadCustomReporterModule(referenceOrInstance, runner);
7804
- return new CustomReporter();
7805
- }
7785
+ } else return new (await (loadCustomReporterModule(referenceOrInstance, runner)))();
7806
7786
  return referenceOrInstance;
7807
7787
  });
7808
7788
  return Promise.all(promisedReporters);
@@ -7820,11 +7800,11 @@ function parseFilter(filter) {
7820
7800
  return { filename: filter };
7821
7801
  }
7822
7802
  function groupFilters(filters) {
7823
- const groupedFilters_ = groupBy(filters, (f) => f.filename), groupedFilters = Object.fromEntries(Object.entries(groupedFilters_).map((entry) => {
7803
+ const groupedFilters_ = groupBy(filters, (f) => f.filename);
7804
+ return Object.fromEntries(Object.entries(groupedFilters_).map((entry) => {
7824
7805
  const [filename, filters] = entry, testLocations = filters.map((f) => f.lineNumber);
7825
7806
  return [filename, testLocations.filter((l) => l !== void 0)];
7826
7807
  }));
7827
- return groupedFilters;
7828
7808
  }
7829
7809
 
7830
7810
  class VitestSpecifications {
@@ -7885,7 +7865,7 @@ class VitestSpecifications {
7885
7865
  }
7886
7866
  async filterTestsBySource(specs) {
7887
7867
  if (this.vitest.config.changed && !this.vitest.config.related) {
7888
- const { VitestGit } = await import('./git.BFNcloKD.js'), vitestGit = new VitestGit(this.vitest.config.root), related = await vitestGit.findChangedFiles({ changedSince: this.vitest.config.changed });
7868
+ const { VitestGit } = await import('./git.BFNcloKD.js'), related = await new VitestGit(this.vitest.config.root).findChangedFiles({ changedSince: this.vitest.config.changed });
7889
7869
  if (!related) throw process.exitCode = 1, new GitNotFoundError();
7890
7870
  this.vitest.config.related = Array.from(new Set(related));
7891
7871
  }
@@ -7909,7 +7889,7 @@ class VitestSpecifications {
7909
7889
  const addImports = async (project, filepath) => {
7910
7890
  if (deps.has(filepath)) return;
7911
7891
  deps.add(filepath);
7912
- const mod = project.vite.environments.ssr.moduleGraph.getModuleById(filepath), transformed = mod?.transformResult || await project.vite.environments.ssr.transformRequest(filepath);
7892
+ const transformed = project.vite.environments.ssr.moduleGraph.getModuleById(filepath)?.transformResult || await project.vite.environments.ssr.transformRequest(filepath);
7913
7893
  if (!transformed) return;
7914
7894
  const dependencies = [...transformed.deps || [], ...transformed.dynamicDeps || []];
7915
7895
  await Promise.all(dependencies.map(async (dep) => {
@@ -8047,10 +8027,10 @@ class TestCase extends ReportedTaskImplementation {
8047
8027
  diagnostic() {
8048
8028
  const result = this.task.result;
8049
8029
  // startTime should always be available if the test has properly finished
8050
- if (!result || !result.startTime) return void 0;
8051
- const duration = result.duration || 0, slow = duration > this.project.globalConfig.slowTestThreshold;
8030
+ if (!result || !result.startTime) return;
8031
+ const duration = result.duration || 0;
8052
8032
  return {
8053
- slow,
8033
+ slow: duration > this.project.globalConfig.slowTestThreshold,
8054
8034
  heap: result.heap,
8055
8035
  duration,
8056
8036
  startTime: result.startTime,
@@ -8201,8 +8181,7 @@ class TestModule extends SuiteImplementation {
8201
8181
  * Checks the running state of the test file.
8202
8182
  */
8203
8183
  state() {
8204
- const state = this.task.result?.state;
8205
- return state === "queued" ? "queued" : getSuiteState(this.task);
8184
+ return this.task.result?.state === "queued" ? "queued" : getSuiteState(this.task);
8206
8185
  }
8207
8186
  /**
8208
8187
  * Useful information about the module like duration, memory usage, etc.
@@ -8361,6 +8340,10 @@ class StateManager {
8361
8340
  getReportedEntity(task) {
8362
8341
  return this.reportedTasksMap.get(task);
8363
8342
  }
8343
+ getReportedEntityById(taskId) {
8344
+ const task = this.idMap.get(taskId);
8345
+ return task ? this.reportedTasksMap.get(task) : void 0;
8346
+ }
8364
8347
  updateTasks(packs) {
8365
8348
  for (const [id, result, meta] of packs) {
8366
8349
  const task = this.idMap.get(id);
@@ -8866,7 +8849,7 @@ class TestRun {
8866
8849
  async updated(update, events) {
8867
8850
  this.syncUpdateStacks(update), this.vitest.state.updateTasks(update);
8868
8851
  for (const [id, event, data] of events) await this.reportEvent(id, event, data).catch((error) => {
8869
- this.vitest.state.catchError(serializeError$1(error), "Unhandled Reporter Error");
8852
+ this.vitest.state.catchError(serializeValue(error), "Unhandled Reporter Error");
8870
8853
  });
8871
8854
  // TODO: what is the order or reports here?
8872
8855
  // "onTaskUpdate" in parallel with others or before all or after all?
@@ -8933,9 +8916,8 @@ class TestRun {
8933
8916
  const path = attachment.path;
8934
8917
  if (path && !path.startsWith("http://") && !path.startsWith("https://")) {
8935
8918
  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)}`);
8936
- await mkdir(dirname(newPath), { recursive: true }), await copyFile(currentPath, newPath), attachment.path = newPath;
8937
- const contentType = attachment.contentType ?? mime.getType(basename(currentPath));
8938
- attachment.contentType = contentType || void 0;
8919
+ if (!existsSync(project.config.attachmentsDir)) await mkdir(project.config.attachmentsDir, { recursive: true });
8920
+ await copyFile(currentPath, newPath), attachment.path = newPath, attachment.contentType = (attachment.contentType ?? mime.getType(basename(currentPath))) || void 0;
8939
8921
  }
8940
8922
  return attachment;
8941
8923
  }
@@ -8995,21 +8977,14 @@ class VitestWatcher {
8995
8977
  }), triggered;
8996
8978
  }
8997
8979
  onFileChange = (id) => {
8998
- id = slash(id), this.vitest.logger.clearHighlightCache(id), this.vitest.invalidateFile(id);
8999
- const testFiles = this.getTestFilesFromWatcherTrigger(id);
9000
- if (testFiles) this.scheduleRerun(id);
9001
- else {
9002
- const needsRerun = this.handleFileChanged(id);
9003
- if (needsRerun) this.scheduleRerun(id);
9004
- }
8980
+ if (id = slash(id), this.vitest.logger.clearHighlightCache(id), this.vitest.invalidateFile(id), this.getTestFilesFromWatcherTrigger(id)) this.scheduleRerun(id);
8981
+ else if (this.handleFileChanged(id)) this.scheduleRerun(id);
9005
8982
  };
9006
8983
  onFileDelete = (id) => {
9007
8984
  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);
9008
8985
  };
9009
8986
  onFileCreate = (id) => {
9010
- id = slash(id), this.vitest.invalidateFile(id);
9011
- const testFiles = this.getTestFilesFromWatcherTrigger(id);
9012
- if (testFiles) {
8987
+ if (id = slash(id), this.vitest.invalidateFile(id), this.getTestFilesFromWatcherTrigger(id)) {
9013
8988
  this.scheduleRerun(id);
9014
8989
  return;
9015
8990
  }
@@ -9018,11 +8993,7 @@ class VitestWatcher {
9018
8993
  if (this.vitest.projects.forEach((project) => {
9019
8994
  if (project.matchesTestGlob(id, () => fileContent ??= readFileSync(id, "utf-8"))) matchingProjects.push(project);
9020
8995
  }), matchingProjects.length > 0) this.changedTests.add(id), this.scheduleRerun(id);
9021
- else {
9022
- // it's possible that file was already there but watcher triggered "add" event instead
9023
- const needsRerun = this.handleFileChanged(id);
9024
- if (needsRerun) this.scheduleRerun(id);
9025
- }
8996
+ else if (this.handleFileChanged(id)) this.scheduleRerun(id);
9026
8997
  };
9027
8998
  handleSetupFile(filepath) {
9028
8999
  let isSetupFile = false;
@@ -9042,8 +9013,7 @@ class VitestWatcher {
9042
9013
  if (pm.isMatch(filepath, this.vitest.config.forceRerunTriggers)) return this.vitest.state.getFilepaths().forEach((file) => this.changedTests.add(file)), true;
9043
9014
  if (this.handleSetupFile(filepath)) return true;
9044
9015
  const projects = this.vitest.projects.filter((project) => {
9045
- const moduleGraph = project.browser?.vite.moduleGraph || project.vite.moduleGraph;
9046
- return moduleGraph.getModulesByFile(filepath)?.size;
9016
+ return (project.browser?.vite.moduleGraph || project.vite.moduleGraph).getModulesByFile(filepath)?.size;
9047
9017
  });
9048
9018
  if (!projects.length) return this.vitest.state.filesMap.has(filepath) || this.vitest.projects.some((project) => project._isCachedTestFile(filepath)) ? (this.changedTests.add(filepath), true) : false;
9049
9019
  const files = [];
@@ -9057,9 +9027,7 @@ class VitestWatcher {
9057
9027
  }
9058
9028
  let rerun = false;
9059
9029
  for (const mod of mods) mod.importers.forEach((i) => {
9060
- if (!i.file) return;
9061
- const needsRerun = this.handleFileChanged(i.file);
9062
- if (needsRerun) rerun = true;
9030
+ if (i.file && this.handleFileChanged(i.file)) rerun = true;
9063
9031
  });
9064
9032
  if (rerun) files.push(filepath);
9065
9033
  }
@@ -9183,9 +9151,7 @@ class Vitest {
9183
9151
  server.restart = async (...args) => {
9184
9152
  await Promise.all(this._onRestartListeners.map((fn) => fn())), this.report("onServerRestart"), await this.close(), await serverRestart(...args);
9185
9153
  }, server.watcher.on("change", async (file) => {
9186
- file = normalize(file);
9187
- const isConfig = file === server.config.configFile || this.projects.some((p) => p.vite.config.configFile === file);
9188
- if (isConfig) await Promise.all(this._onRestartListeners.map((fn) => fn("config"))), this.report("onServerRestart", "config"), await this.close(), await serverRestart();
9154
+ if (file = normalize(file), file === server.config.configFile || this.projects.some((p) => p.vite.config.configFile === file)) await Promise.all(this._onRestartListeners.map((fn) => fn("config"))), this.report("onServerRestart", "config"), await this.close(), await serverRestart();
9189
9155
  });
9190
9156
  }
9191
9157
  this.cache.results.setConfig(resolved.root, resolved.cache);
@@ -9194,15 +9160,13 @@ class Vitest {
9194
9160
  } catch {}
9195
9161
  const projects = await this.resolveProjects(this._cliOptions);
9196
9162
  if (this.projects = projects, await Promise.all(projects.flatMap((project) => {
9197
- const hooks = project.vite.config.getSortedPluginHooks("configureVitest");
9198
- return hooks.map((hook) => hook({
9163
+ return project.vite.config.getSortedPluginHooks("configureVitest").map((hook) => hook({
9199
9164
  project,
9200
9165
  vitest: this,
9201
9166
  injectTestProjects: this.injectTestProject
9202
9167
  }));
9203
9168
  })), this._cliOptions.browser?.enabled) {
9204
- const browserProjects = this.projects.filter((p) => p.config.browser.enabled);
9205
- if (!browserProjects.length) throw new Error(`Vitest received --browser flag, but no project had a browser configuration.`);
9169
+ if (!this.projects.filter((p) => p.config.browser.enabled).length) throw new Error(`Vitest received --browser flag, but no project had a browser configuration.`);
9206
9170
  }
9207
9171
  if (!this.projects.length) {
9208
9172
  const filter = toArray(resolved.project).join("\", \"");
@@ -9321,7 +9285,7 @@ class Vitest {
9321
9285
  }, await this.report("onInit", this);
9322
9286
  const specifications = [];
9323
9287
  for (const file of files) {
9324
- const project = this.getProjectByName(file.projectName || ""), specification = project.createSpecification(file.filepath, void 0, file.pool);
9288
+ const specification = this.getProjectByName(file.projectName || "").createSpecification(file.filepath, void 0, file.pool);
9325
9289
  specifications.push(specification);
9326
9290
  }
9327
9291
  await this._testRun.start(specifications).catch(noop);
@@ -9331,6 +9295,12 @@ class Vitest {
9331
9295
  unhandledErrors: this.state.getUnhandledErrors()
9332
9296
  };
9333
9297
  }
9298
+ /**
9299
+ * Returns the seed, if tests are running in a random order.
9300
+ */
9301
+ getSeed() {
9302
+ return this.config.sequence.seed ?? null;
9303
+ }
9334
9304
  /** @internal */
9335
9305
  async _reportFileTask(file) {
9336
9306
  const project = this.getProjectByName(file.projectName || "");
@@ -9654,10 +9624,8 @@ class Vitest {
9654
9624
  */
9655
9625
  invalidateFile(filepath) {
9656
9626
  this.projects.forEach(({ vite, browser }) => {
9657
- const environments = [...Object.values(vite.environments), ...Object.values(browser?.vite.environments || {})];
9658
- environments.forEach(({ moduleGraph }) => {
9659
- const modules = moduleGraph.getModulesByFile(filepath);
9660
- modules?.forEach((module) => moduleGraph.invalidateModule(module));
9627
+ [...Object.values(vite.environments), ...Object.values(browser?.vite.environments || {})].forEach(({ moduleGraph }) => {
9628
+ moduleGraph.getModulesByFile(filepath)?.forEach((module) => moduleGraph.invalidateModule(module));
9661
9629
  });
9662
9630
  });
9663
9631
  }
@@ -9780,8 +9748,7 @@ class Vitest {
9780
9748
  matchesProjectFilter(name) {
9781
9749
  const projects = this._config?.project || this._cliOptions?.project;
9782
9750
  return !projects || !projects.length ? true : toArray(projects).some((project) => {
9783
- const regexp = wildcardPatternToRegExp(project);
9784
- return regexp.test(name);
9751
+ return wildcardPatternToRegExp(project).test(name);
9785
9752
  });
9786
9753
  }
9787
9754
  }
@@ -9810,11 +9777,7 @@ async function VitestPlugin(options = {}, vitest = new Vitest("test", deepClone(
9810
9777
  // however to allow vitest plugins to modify vitest config values
9811
9778
  // this is repeated in configResolved where the config is final
9812
9779
  const testConfig = deepMerge({}, configDefaults, removeUndefinedValues(viteConfig.test ?? {}), options);
9813
- testConfig.api = resolveApiServerConfig(testConfig, defaultPort);
9814
- // store defines for globalThis to make them
9815
- // reassignable when running in worker in src/runtime/setup.ts
9816
- const defines = deleteDefineConfig(viteConfig);
9817
- options.defines = defines;
9780
+ testConfig.api = resolveApiServerConfig(testConfig, defaultPort), options.defines = deleteDefineConfig(viteConfig);
9818
9781
  let open = false;
9819
9782
  if (testConfig.ui && testConfig.open) open = testConfig.uiBase ?? "/__vitest__/";
9820
9783
  const resolveOptions = getDefaultResolveOptions();
@@ -9929,7 +9892,7 @@ function removeUndefinedValues(obj) {
9929
9892
  }
9930
9893
 
9931
9894
  async function createVitest(mode, options, viteOverrides = {}, vitestOptions = {}) {
9932
- 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 });
9895
+ 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) : any(configFiles, { cwd: root });
9933
9896
  options.config = configPath;
9934
9897
  const { browser: _removeBrowser,...restOptions } = options, config = {
9935
9898
  configFile: configPath,
@@ -9981,9 +9944,11 @@ class WatchFilter {
9981
9944
  this.write(`${ESC}1G${ESC}0J`), onSubmit(void 0);
9982
9945
  return;
9983
9946
  case key?.name === "enter":
9984
- case key?.name === "return":
9985
- onSubmit(this.results[this.selectionIndex] || this.currentKeyword || ""), this.currentKeyword = void 0;
9947
+ case key?.name === "return": {
9948
+ const selection = this.results[this.selectionIndex], result = typeof selection === "string" ? selection : selection?.key;
9949
+ onSubmit(result || this.currentKeyword || ""), this.currentKeyword = void 0;
9986
9950
  break;
9951
+ }
9987
9952
  case key?.name === "up":
9988
9953
  if (this.selectionIndex && this.selectionIndex > 0) this.selectionIndex--;
9989
9954
  else this.selectionIndex = -1;
@@ -10045,7 +10010,7 @@ ${c.dim(` ...and ${remainingResultCount} more ${remainingResultCount === 1 ? "
10045
10010
  this.stdout.write(data);
10046
10011
  }
10047
10012
  getLastResults() {
10048
- return this.results;
10013
+ return this.results.map((r) => typeof r === "string" ? r : r.toString());
10049
10014
  }
10050
10015
  }
10051
10016
 
@@ -10071,6 +10036,26 @@ ${c.bold(" Watch Usage")}
10071
10036
  ${keys.map((i) => c.dim(" press ") + c.reset([i[0]].flat().map(c.bold).join(", ")) + c.dim(` to ${i[1]}`)).join("\n")}
10072
10037
  `);
10073
10038
  }
10039
+ function* traverseFilteredTestNames(parentName, filter, t) {
10040
+ if (isTestCase(t)) {
10041
+ if (t.name.match(filter)) {
10042
+ const displayName = `${parentName} > ${t.name}`;
10043
+ yield {
10044
+ key: t.name,
10045
+ toString: () => displayName
10046
+ };
10047
+ }
10048
+ } else {
10049
+ parentName = parentName.length ? `${parentName} > ${t.name}` : t.name;
10050
+ for (const task of t.tasks) yield* traverseFilteredTestNames(parentName, filter, task);
10051
+ }
10052
+ }
10053
+ function* getFilteredTestNames(pattern, suite) {
10054
+ try {
10055
+ const reg = new RegExp(pattern), files = /* @__PURE__ */ new Set();
10056
+ for (const file of suite) if (!files.has(file.name)) files.add(file.name), yield* traverseFilteredTestNames("", reg, file);
10057
+ } catch {}
10058
+ }
10074
10059
  function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
10075
10060
  let latestFilename = "";
10076
10061
  async function _keypressHandler(str, key) {
@@ -10120,15 +10105,8 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
10120
10105
  }
10121
10106
  async function inputNamePattern() {
10122
10107
  off();
10123
- const watchFilter = new WatchFilter("Input test name pattern (RegExp)", stdin, stdout), filter = await watchFilter.filter((str) => {
10124
- const files = ctx.state.getFiles(), tests = getTests(files);
10125
- try {
10126
- const reg = new RegExp(str);
10127
- return tests.map((test) => test.name).filter((testName) => testName.match(reg));
10128
- } catch {
10129
- // `new RegExp` may throw error when input is invalid regexp
10130
- return [];
10131
- }
10108
+ const filter = await new WatchFilter("Input test name pattern (RegExp)", stdin, stdout).filter((str) => {
10109
+ return [...getFilteredTestNames(str, ctx.state.getFiles())];
10132
10110
  });
10133
10111
  if (on(), typeof filter === "undefined") return;
10134
10112
  const files = ctx.state.getFilepaths(), cliFiles = ctx.config.standalone && !files.length ? await ctx._globTestFilepaths() : void 0;
@@ -10147,8 +10125,7 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout) {
10147
10125
  async function inputFilePattern() {
10148
10126
  off();
10149
10127
  const watchFilter = new WatchFilter("Input filename pattern", stdin, stdout), filter = await watchFilter.filter(async (str) => {
10150
- const specifications = await ctx.globTestSpecifications([str]);
10151
- return specifications.map((specification) => relative(ctx.config.root, specification.moduleId)).filter((file, index, all) => all.indexOf(file) === index);
10128
+ return (await ctx.globTestSpecifications([str])).map((specification) => relative(ctx.config.root, specification.moduleId)).filter((file, index, all) => all.indexOf(file) === index);
10152
10129
  });
10153
10130
  if (on(), typeof filter === "undefined") return;
10154
10131
  latestFilename = filter?.trim() || "";