vitest 4.0.0-beta.1 → 4.0.0-beta.3

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 (59) hide show
  1. package/dist/browser.d.ts +6 -6
  2. package/dist/browser.js +1 -1
  3. package/dist/chunks/{base.Bj3pWTr1.js → base.D5_IXzht.js} +2 -2
  4. package/dist/chunks/{benchmark.d.BwvBVTda.d.ts → benchmark.d.DAaHLpsq.d.ts} +4 -4
  5. package/dist/chunks/{browser.d.q8Z0P0q1.d.ts → browser.d.BSPEQIuf.d.ts} +5 -5
  6. package/dist/chunks/{cac.D3EzDDZd.js → cac.C30xmylc.js} +11 -18
  7. package/dist/chunks/{cli-api.Dn5gKePv.js → cli-api.DE98RCgs.js} +53 -80
  8. package/dist/chunks/{config.d.HJdfX-8k.d.ts → config.d.DZo8c7fw.d.ts} +58 -58
  9. package/dist/chunks/{console.CtFJOzRO.js → console.DoJHFxmj.js} +3 -3
  10. package/dist/chunks/{constants.DnKduX2e.js → constants.CXzqaLmq.js} +1 -4
  11. package/dist/chunks/{coverage.Cwa-XhJt.js → coverage.OOpN1tMC.js} +54 -46
  12. package/dist/chunks/{coverage.d.S9RMNXIe.d.ts → coverage.d.CNYjU4GF.d.ts} +4 -4
  13. package/dist/chunks/{creator.GK6I-cL4.js → creator.CJNzQTzZ.js} +5 -5
  14. package/dist/chunks/{environment.d.CUq4cUgQ.d.ts → environment.d.Bhm9oc0v.d.ts} +1 -1
  15. package/dist/chunks/{execute.B7h3T_Hc.js → execute.Dt-pCVcL.js} +1 -1
  16. package/dist/chunks/{global.d.CVbXEflG.d.ts → global.d.DAhT2emn.d.ts} +2 -2
  17. package/dist/chunks/{globals.Cxal6MLI.js → globals.Dgo-vS5G.js} +3 -3
  18. package/dist/chunks/{index.CZI_8rVt.js → index.Bz6b0Ib7.js} +5 -5
  19. package/dist/chunks/{index.BWf_gE5n.js → index.D1_MsKEt.js} +1 -1
  20. package/dist/chunks/{index.TfbsX-3I.js → index.D3SKT3tv.js} +1 -1
  21. package/dist/chunks/{index.D-VkfKhf.js → index.Dppt57hu.js} +1 -1
  22. package/dist/chunks/{plugin.d.C2EcJUjo.d.ts → plugin.d.CKCmge5g.d.ts} +1 -1
  23. package/dist/chunks/{reporters.d.DxZg19fy.d.ts → reporters.d.BBuiUFDc.d.ts} +115 -145
  24. package/dist/chunks/{runBaseTests.BC7ZIH5L.js → runBaseTests.Bbi_gTJQ.js} +5 -5
  25. package/dist/chunks/{setup-common.D7ZqXFx-.js → setup-common.Ebx5x0eP.js} +1 -1
  26. package/dist/chunks/{suite.d.FvehnV49.d.ts → suite.d.BJWk38HB.d.ts} +1 -1
  27. package/dist/chunks/{typechecker.CVytUJuF.js → typechecker.CMNPqJOo.js} +3 -3
  28. package/dist/chunks/{utils.CAioKnHs.js → utils.CcGm2cd1.js} +1 -1
  29. package/dist/chunks/{vi.bdSIJ99Y.js → vi.CA0EPI9Y.js} +11 -11
  30. package/dist/chunks/{vm.BThCzidc.js → vm.BUnLJt_P.js} +11 -3
  31. package/dist/chunks/{worker.d.CmvJfRGs.d.ts → worker.d.DyXSTmRq.d.ts} +1 -1
  32. package/dist/chunks/{worker.d.DoNjFAiv.d.ts → worker.d.xTcinSQw.d.ts} +9 -15
  33. package/dist/cli.js +4 -4
  34. package/dist/config.d.ts +44 -44
  35. package/dist/config.js +1 -1
  36. package/dist/coverage.d.ts +20 -18
  37. package/dist/coverage.js +3 -3
  38. package/dist/environments.d.ts +9 -9
  39. package/dist/execute.d.ts +7 -7
  40. package/dist/execute.js +1 -1
  41. package/dist/index.d.ts +29 -27
  42. package/dist/index.js +2 -2
  43. package/dist/node.d.ts +23 -24
  44. package/dist/node.js +9 -9
  45. package/dist/reporters.d.ts +7 -7
  46. package/dist/reporters.js +3 -3
  47. package/dist/runners.d.ts +1 -1
  48. package/dist/runners.js +10 -3
  49. package/dist/suite.d.ts +2 -2
  50. package/dist/worker.js +1 -1
  51. package/dist/workers/forks.js +3 -3
  52. package/dist/workers/runVmTests.js +4 -4
  53. package/dist/workers/threads.js +3 -3
  54. package/dist/workers/vmForks.js +4 -4
  55. package/dist/workers/vmThreads.js +4 -4
  56. package/dist/workers.d.ts +4 -4
  57. package/dist/workers.js +5 -5
  58. package/globals.d.ts +17 -17
  59. package/package.json +17 -17
@@ -98,68 +98,68 @@ interface SerializedConfig {
98
98
  maxConcurrency: number;
99
99
  defines: Record<string, any>;
100
100
  expect: {
101
- requireAssertions?: boolean
101
+ requireAssertions?: boolean;
102
102
  poll?: {
103
- timeout?: number
104
- interval?: number
105
- }
103
+ timeout?: number;
104
+ interval?: number;
105
+ };
106
106
  };
107
107
  printConsoleTrace: boolean | undefined;
108
108
  sequence: {
109
- shuffle?: boolean
110
- concurrent?: boolean
111
- seed: number
112
- hooks: SequenceHooks
113
- setupFiles: SequenceSetupFiles
109
+ shuffle?: boolean;
110
+ concurrent?: boolean;
111
+ seed: number;
112
+ hooks: SequenceHooks;
113
+ setupFiles: SequenceSetupFiles;
114
114
  };
115
115
  poolOptions: {
116
116
  forks: {
117
- singleFork: boolean
118
- isolate: boolean
119
- }
117
+ singleFork: boolean;
118
+ isolate: boolean;
119
+ };
120
120
  threads: {
121
- singleThread: boolean
122
- isolate: boolean
123
- }
121
+ singleThread: boolean;
122
+ isolate: boolean;
123
+ };
124
124
  vmThreads: {
125
- singleThread: boolean
126
- }
125
+ singleThread: boolean;
126
+ };
127
127
  vmForks: {
128
- singleFork: boolean
129
- }
128
+ singleFork: boolean;
129
+ };
130
130
  };
131
131
  deps: {
132
132
  web: {
133
- transformAssets?: boolean
134
- transformCss?: boolean
135
- transformGlobPattern?: RegExp | RegExp[]
136
- }
133
+ transformAssets?: boolean;
134
+ transformCss?: boolean;
135
+ transformGlobPattern?: RegExp | RegExp[];
136
+ };
137
137
  optimizer: {
138
138
  web: {
139
- enabled: boolean
140
- }
139
+ enabled: boolean;
140
+ };
141
141
  ssr: {
142
- enabled: boolean
143
- }
144
- }
145
- interopDefault: boolean | undefined
146
- moduleDirectories: string[] | undefined
142
+ enabled: boolean;
143
+ };
144
+ };
145
+ interopDefault: boolean | undefined;
146
+ moduleDirectories: string[] | undefined;
147
147
  };
148
148
  snapshotOptions: {
149
- updateSnapshot: SnapshotUpdateState
150
- expand: boolean | undefined
151
- snapshotFormat: PrettyFormatOptions | undefined
149
+ updateSnapshot: SnapshotUpdateState;
150
+ expand: boolean | undefined;
151
+ snapshotFormat: PrettyFormatOptions | undefined;
152
152
  /**
153
153
  * only exists for tests, not available in the main process
154
154
  */
155
- snapshotEnvironment: SnapshotEnvironment
155
+ snapshotEnvironment: SnapshotEnvironment;
156
156
  };
157
157
  pool: string;
158
158
  snapshotSerializers: string[];
159
159
  chaiConfig: {
160
- includeStack?: boolean
161
- showDiff?: boolean
162
- truncateThreshold?: number
160
+ includeStack?: boolean;
161
+ showDiff?: boolean;
162
+ truncateThreshold?: number;
163
163
  } | undefined;
164
164
  diff: string | SerializedDiffOptions | undefined;
165
165
  retry: number;
@@ -167,52 +167,52 @@ interface SerializedConfig {
167
167
  inspect: boolean | string | undefined;
168
168
  inspectBrk: boolean | string | undefined;
169
169
  inspector: {
170
- enabled?: boolean
171
- port?: number
172
- host?: string
173
- waitForDebugger?: boolean
170
+ enabled?: boolean;
171
+ port?: number;
172
+ host?: string;
173
+ waitForDebugger?: boolean;
174
174
  };
175
175
  watch: boolean;
176
176
  env: Record<string, any>;
177
177
  browser: {
178
- name: string
179
- headless: boolean
180
- isolate: boolean
181
- fileParallelism: boolean
182
- ui: boolean
178
+ name: string;
179
+ headless: boolean;
180
+ isolate: boolean;
181
+ fileParallelism: boolean;
182
+ ui: boolean;
183
183
  viewport: {
184
- width: number
185
- height: number
186
- }
184
+ width: number;
185
+ height: number;
186
+ };
187
187
  locators: {
188
- testIdAttribute: string
189
- }
190
- screenshotFailures: boolean
188
+ testIdAttribute: string;
189
+ };
190
+ screenshotFailures: boolean;
191
191
  providerOptions: {
192
192
  // for playwright
193
- actionTimeout?: number
194
- }
193
+ actionTimeout?: number;
194
+ };
195
195
  };
196
196
  standalone: boolean;
197
197
  logHeapUsage: boolean | undefined;
198
198
  coverage: SerializedCoverageConfig;
199
199
  benchmark: {
200
- includeSamples: boolean
200
+ includeSamples: boolean;
201
201
  } | undefined;
202
202
  }
203
203
  interface SerializedCoverageConfig {
204
204
  provider: "istanbul" | "v8" | "custom" | undefined;
205
205
  reportsDirectory: string;
206
206
  htmlReporter: {
207
- subdir: string | undefined
207
+ subdir: string | undefined;
208
208
  } | undefined;
209
209
  enabled: boolean;
210
210
  customProviderModule: string | undefined;
211
211
  }
212
212
  type RuntimeConfig = Pick<SerializedConfig, "allowOnly" | "testTimeout" | "hookTimeout" | "clearMocks" | "mockReset" | "restoreMocks" | "fakeTimers" | "maxConcurrency" | "expect" | "printConsoleTrace"> & {
213
213
  sequence?: {
214
- hooks?: SequenceHooks
215
- }
214
+ hooks?: SequenceHooks;
215
+ };
216
216
  };
217
217
  type RuntimeOptions = Partial<RuntimeConfig>;
218
218
 
@@ -8,7 +8,7 @@ import { g as getWorkerState } from './utils.XdZDrNZV.js';
8
8
 
9
9
  const UNKNOWN_TEST_ID = "__vitest__unknown_test__";
10
10
  function getTaskIdByStack(root) {
11
- const stack = new Error("STACK_TRACE_ERROR").stack?.split("\n");
11
+ const stack = (/* @__PURE__ */ new Error("STACK_TRACE_ERROR")).stack?.split("\n");
12
12
  if (!stack) return UNKNOWN_TEST_ID;
13
13
  const index = stack.findIndex((line) => line.includes("at Console.value"));
14
14
  const line = index === -1 ? null : stack[index + 2];
@@ -101,7 +101,7 @@ function createCustomConsole(defaultState) {
101
101
  if (state().config.printConsoleTrace) {
102
102
  const limit = Error.stackTraceLimit;
103
103
  Error.stackTraceLimit = limit + 6;
104
- const stack = new Error("STACK_TRACE").stack;
104
+ const stack = (/* @__PURE__ */ new Error("STACK_TRACE")).stack;
105
105
  const trace = stack?.split("\n").slice(7).join("\n");
106
106
  Error.stackTraceLimit = limit;
107
107
  buffer.push([data, trace]);
@@ -129,7 +129,7 @@ function createCustomConsole(defaultState) {
129
129
  if (state().config.printConsoleTrace) {
130
130
  const limit = Error.stackTraceLimit;
131
131
  Error.stackTraceLimit = limit + 6;
132
- const stack = new Error("STACK_TRACE").stack?.split("\n");
132
+ const stack = (/* @__PURE__ */ new Error("STACK_TRACE")).stack?.split("\n");
133
133
  Error.stackTraceLimit = limit;
134
134
  const isTrace = stack?.some((line) => line.includes("at Console.trace"));
135
135
  if (isTrace) buffer.push([data, void 0]);
@@ -9,7 +9,6 @@ const extraInlineDeps = [
9
9
  /vite\w*\/dist\/client\/env.mjs/
10
10
  ];
11
11
  const CONFIG_NAMES = ["vitest.config", "vite.config"];
12
- const WORKSPACES_NAMES = ["vitest.workspace", "vitest.projects"];
13
12
  const CONFIG_EXTENSIONS = [
14
13
  ".ts",
15
14
  ".mts",
@@ -19,8 +18,6 @@ const CONFIG_EXTENSIONS = [
19
18
  ".cjs"
20
19
  ];
21
20
  const configFiles = CONFIG_NAMES.flatMap((name) => CONFIG_EXTENSIONS.map((ext) => name + ext));
22
- const WORKSPACES_EXTENSIONS = [...CONFIG_EXTENSIONS, ".json"];
23
- const workspacesFiles = WORKSPACES_NAMES.flatMap((name) => WORKSPACES_EXTENSIONS.map((ext) => name + ext));
24
21
  const globalApis = [
25
22
  "suite",
26
23
  "test",
@@ -41,4 +38,4 @@ const globalApis = [
41
38
  "onTestFailed"
42
39
  ];
43
40
 
44
- export { API_PATH as A, defaultPort as a, defaultInspectPort as b, configFiles as c, defaultBrowserPort as d, extraInlineDeps as e, globalApis as g, workspacesFiles as w };
41
+ export { API_PATH as A, defaultPort as a, defaultInspectPort as b, configFiles as c, defaultBrowserPort as d, extraInlineDeps as e, globalApis as g };
@@ -16,7 +16,7 @@ import assert from 'node:assert';
16
16
  import v8 from 'node:v8';
17
17
  import { format, inspect } from 'node:util';
18
18
  import { version, mergeConfig } from 'vite';
19
- import { c as configFiles, w as workspacesFiles, e as extraInlineDeps, d as defaultBrowserPort, b as defaultInspectPort, a as defaultPort } from './constants.DnKduX2e.js';
19
+ import { c as configFiles, e as extraInlineDeps, d as defaultBrowserPort, b as defaultInspectPort, a as defaultPort } from './constants.CXzqaLmq.js';
20
20
  import { a as isWindows } from './env.D4Lgay0q.js';
21
21
  import * as nodeos from 'node:os';
22
22
  import nodeos__default from 'node:os';
@@ -24,7 +24,7 @@ import { isatty } from 'node:tty';
24
24
  import EventEmitter from 'node:events';
25
25
  import { c as createBirpc } from './index.B521nVV-.js';
26
26
  import Tinypool$1, { Tinypool } from 'tinypool';
27
- import { w as wrapSerializableConfig, a as Typechecker } from './typechecker.CVytUJuF.js';
27
+ import { w as wrapSerializableConfig, a as Typechecker } from './typechecker.CMNPqJOo.js';
28
28
  import { MessageChannel } from 'node:worker_threads';
29
29
  import { hasFailed } from '@vitest/runner/utils';
30
30
  import { rootDir } from '../path.js';
@@ -2406,14 +2406,7 @@ async function groupFilesByEnv(files) {
2406
2406
  const code = await promises$1.readFile(filepath, "utf-8");
2407
2407
  // 1. Check for control comments in the file
2408
2408
  let env = code.match(/@(?:vitest|jest)-environment\s+([\w-]+)\b/)?.[1];
2409
- // 2. Check for globals
2410
- if (!env) {
2411
- for (const [glob, target] of project.config.environmentMatchGlobs || []) if (pm.isMatch(filepath, glob, { cwd: project.config.root })) {
2412
- env = target;
2413
- break;
2414
- }
2415
- }
2416
- // 3. Fallback to global env
2409
+ // 2. Fallback to global env
2417
2410
  env ||= project.config.environment || "node";
2418
2411
  const transformMode = getTransformMode(project.config.testTransformMode, filepath);
2419
2412
  let envOptionsJson = code.match(/@(?:vitest|jest)-environment-options\s+(.+)/)?.[1];
@@ -3292,11 +3285,7 @@ function getDefaultPoolName(project) {
3292
3285
  if (project.config.browser.enabled) return "browser";
3293
3286
  return project.config.pool;
3294
3287
  }
3295
- function getFilePoolName(project, file) {
3296
- for (const [glob, pool] of project.config.poolMatchGlobs) {
3297
- if (pool === "browser") throw new Error("Since Vitest 0.31.0 \"browser\" pool is not supported in `poolMatchGlobs`. You can create a project to run some of your tests in browser in parallel. Read more: https://vitest.dev/guide/projects");
3298
- if (pm.isMatch(file, glob, { cwd: project.config.root })) return pool;
3299
- }
3288
+ function getFilePoolName(project) {
3300
3289
  return getDefaultPoolName(project);
3301
3290
  }
3302
3291
  function createPool(ctx) {
@@ -3449,9 +3438,7 @@ class BaseSequencer {
3449
3438
  async shard(files) {
3450
3439
  const { config } = this.ctx;
3451
3440
  const { index, count } = config.shard;
3452
- const shardSize = Math.ceil(files.length / count);
3453
- const shardStart = shardSize * (index - 1);
3454
- const shardEnd = shardSize * index;
3441
+ const [shardStart, shardEnd] = this.calculateShardRange(files.length, index, count);
3455
3442
  return [...files].map((spec) => {
3456
3443
  const fullPath = resolve$1(slash(config.root), slash(spec.moduleId));
3457
3444
  const specPath = fullPath?.slice(config.root.length);
@@ -3484,6 +3471,20 @@ class BaseSequencer {
3484
3471
  return bState.duration - aState.duration;
3485
3472
  });
3486
3473
  }
3474
+ // Calculate distributed shard range [start, end] distributed equally
3475
+ calculateShardRange(filesCount, index, count) {
3476
+ const baseShardSize = Math.floor(filesCount / count);
3477
+ const remainderTestFilesCount = filesCount % count;
3478
+ if (remainderTestFilesCount >= index) {
3479
+ const shardSize = baseShardSize + 1;
3480
+ const shardStart = shardSize * (index - 1);
3481
+ const shardEnd = shardSize * index;
3482
+ return [shardStart, shardEnd];
3483
+ }
3484
+ const shardStart = remainderTestFilesCount * (baseShardSize + 1) + (index - remainderTestFilesCount - 1) * baseShardSize;
3485
+ const shardEnd = shardStart + baseShardSize;
3486
+ return [shardStart, shardEnd];
3487
+ }
3487
3488
  }
3488
3489
 
3489
3490
  class RandomSequencer extends BaseSequencer {
@@ -3653,7 +3654,6 @@ function resolveConfig$1(vitest, options, viteConfig) {
3653
3654
  ...resolved.include,
3654
3655
  resolved.config && slash$1(resolved.config),
3655
3656
  ...configFiles,
3656
- ...workspacesFiles,
3657
3657
  "**/virtual:*",
3658
3658
  "**/__x00__*",
3659
3659
  "**/node_modules/**"
@@ -3694,7 +3694,11 @@ function resolveConfig$1(vitest, options, viteConfig) {
3694
3694
  resolved.attachmentsDir = resolve$1(resolved.root, resolved.attachmentsDir ?? ".vitest-attachments");
3695
3695
  if (resolved.snapshotEnvironment) resolved.snapshotEnvironment = resolvePath(resolved.snapshotEnvironment, resolved.root);
3696
3696
  resolved.testNamePattern = resolved.testNamePattern ? resolved.testNamePattern instanceof RegExp ? resolved.testNamePattern : new RegExp(resolved.testNamePattern) : void 0;
3697
- if (resolved.snapshotFormat && "plugins" in resolved.snapshotFormat) resolved.snapshotFormat.plugins = [];
3697
+ if (resolved.snapshotFormat && "plugins" in resolved.snapshotFormat) {
3698
+ resolved.snapshotFormat.plugins = [];
3699
+ // TODO: support it via separate config (like DiffOptions) or via `Function.toString()`
3700
+ if (typeof resolved.snapshotFormat.compareKeys === "function") throw new TypeError(`"snapshotFormat.compareKeys" function is not supported.`);
3701
+ }
3698
3702
  const UPDATE_SNAPSHOT = resolved.update || process.env.UPDATE_SNAPSHOT;
3699
3703
  resolved.snapshotOptions = {
3700
3704
  expand: resolved.expandSnapshotDiff ?? false,
@@ -3766,15 +3770,7 @@ function resolveConfig$1(vitest, options, viteConfig) {
3766
3770
  ["vmForks", "maxForks"]
3767
3771
  ];
3768
3772
  for (const [poolOptionKey, workerOptionKey] of poolForksOptions) if (resolved.poolOptions?.[poolOptionKey]?.[workerOptionKey]) resolved.poolOptions[poolOptionKey][workerOptionKey] = resolveInlineWorkerOption(resolved.poolOptions[poolOptionKey][workerOptionKey]);
3769
- if (typeof resolved.workspace === "string")
3770
- // if passed down from the CLI and it's relative, resolve relative to CWD
3771
- resolved.workspace = typeof options.workspace === "string" && options.workspace[0] === "." ? resolve$1(process.cwd(), options.workspace) : resolvePath(resolved.workspace, resolved.root);
3772
3773
  if (!builtinPools.includes(resolved.pool)) resolved.pool = resolvePath(resolved.pool, resolved.root);
3773
- if (resolved.poolMatchGlobs) logger.deprecate("`poolMatchGlobs` is deprecated. Use `test.projects` to define different configurations instead.");
3774
- resolved.poolMatchGlobs = (resolved.poolMatchGlobs || []).map(([glob, pool]) => {
3775
- if (!builtinPools.includes(pool)) pool = resolvePath(pool, resolved.root);
3776
- return [glob, pool];
3777
- });
3778
3774
  if (mode === "benchmark") {
3779
3775
  resolved.benchmark = {
3780
3776
  ...benchmarkConfigDefaults,
@@ -3872,8 +3868,6 @@ function resolveConfig$1(vitest, options, viteConfig) {
3872
3868
  ...configDefaults.typecheck,
3873
3869
  ...resolved.typecheck
3874
3870
  };
3875
- if (resolved.environmentMatchGlobs) logger.deprecate("\"environmentMatchGlobs\" is deprecated. Use `test.projects` to define different configurations instead.");
3876
- resolved.environmentMatchGlobs = (resolved.environmentMatchGlobs || []).map((i) => [resolve$1(resolved.root, i[0]), i[1]]);
3877
3871
  resolved.typecheck ??= {};
3878
3872
  resolved.typecheck.enabled ??= false;
3879
3873
  if (resolved.typecheck.enabled) logger.console.warn(c.yellow("Testing types with tsc and vue-tsc is an experimental feature.\nBreaking changes might not follow SemVer, please pin Vitest's version when using it."));
@@ -3966,6 +3960,7 @@ class BaseCoverageProvider {
3966
3960
  coverageFiles = /* @__PURE__ */ new Map();
3967
3961
  pendingPromises = [];
3968
3962
  coverageFilesDirectory;
3963
+ roots = [];
3969
3964
  _initialize(ctx) {
3970
3965
  this.ctx = ctx;
3971
3966
  if (ctx.version !== this.version) ctx.logger.warn(c.yellow(`Loaded ${c.inverse(c.yellow(` vitest@${ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/coverage-${this.name}@${this.version} `))}.
@@ -3989,44 +3984,55 @@ Update your dependencies and make sure the versions match.`));
3989
3984
  const shard = this.ctx.config.shard;
3990
3985
  const tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`;
3991
3986
  this.coverageFilesDirectory = resolve$1(this.options.reportsDirectory, tempDirectory);
3987
+ // If --project filter is set pick only roots of resolved projects
3988
+ this.roots = ctx.config.project?.length ? [...new Set(ctx.projects.map((project) => project.config.root))] : [ctx.config.root];
3992
3989
  }
3993
3990
  /**
3994
3991
  * Check if file matches `coverage.include` but not `coverage.exclude`
3995
3992
  */
3996
- isIncluded(_filename) {
3993
+ isIncluded(_filename, root) {
3994
+ const roots = root ? [root] : this.roots;
3997
3995
  const filename = slash(_filename);
3998
3996
  const cacheHit = this.globCache.get(filename);
3999
3997
  if (cacheHit !== void 0) return cacheHit;
4000
3998
  // File outside project root with default allowExternal
4001
- if (this.options.allowExternal === false && !filename.startsWith(this.ctx.config.root)) {
3999
+ if (this.options.allowExternal === false && roots.every((root) => !filename.startsWith(root))) {
4002
4000
  this.globCache.set(filename, false);
4003
4001
  return false;
4004
4002
  }
4005
- const options = {
4006
- contains: true,
4007
- dot: true,
4008
- cwd: this.ctx.config.root,
4009
- ignore: this.options.exclude
4010
- };
4011
4003
  // By default `coverage.include` matches all files, except "coverage.exclude"
4012
4004
  const glob = this.options.include || "**";
4013
- const included = pm.isMatch(filename, glob, options) && existsSync(cleanUrl(filename));
4005
+ let included = roots.some((root) => {
4006
+ const options = {
4007
+ contains: true,
4008
+ dot: true,
4009
+ cwd: root,
4010
+ ignore: this.options.exclude
4011
+ };
4012
+ return pm.isMatch(filename, glob, options);
4013
+ });
4014
+ included &&= existsSync(cleanUrl(filename));
4014
4015
  this.globCache.set(filename, included);
4015
4016
  return included;
4016
4017
  }
4017
- async getUntestedFiles(testedFiles) {
4018
- if (this.options.include == null) return [];
4019
- let includedFiles = await glob(this.options.include, {
4020
- cwd: this.ctx.config.root,
4018
+ async getUntestedFilesByRoot(testedFiles, include, root) {
4019
+ let includedFiles = await glob(include, {
4020
+ cwd: root,
4021
4021
  ignore: [...this.options.exclude, ...testedFiles.map((file) => slash(file))],
4022
4022
  absolute: true,
4023
4023
  dot: true,
4024
4024
  onlyFiles: true
4025
4025
  });
4026
4026
  // Run again through picomatch as tinyglobby's exclude pattern is different ({ "exclude": ["math"] } should ignore "src/math.ts")
4027
- includedFiles = includedFiles.filter((file) => this.isIncluded(file));
4027
+ includedFiles = includedFiles.filter((file) => this.isIncluded(file, root));
4028
4028
  if (this.ctx.config.changed) includedFiles = (this.ctx.config.related || []).filter((file) => includedFiles.includes(file));
4029
- return includedFiles.map((file) => slash(path.resolve(this.ctx.config.root, file)));
4029
+ return includedFiles.map((file) => slash(path.resolve(root, file)));
4030
+ }
4031
+ async getUntestedFiles(testedFiles) {
4032
+ if (this.options.include == null) return [];
4033
+ const rootMapper = this.getUntestedFilesByRoot.bind(this, testedFiles, this.options.include);
4034
+ const matrix = await Promise.all(this.roots.map(rootMapper));
4035
+ return matrix.flatMap((files) => files);
4030
4036
  }
4031
4037
  createCoverageMap() {
4032
4038
  throw new Error("BaseReporter's createCoverageMap was not overwritten");
@@ -4286,7 +4292,9 @@ Update your dependencies and make sure the versions match.`));
4286
4292
  root: project.config.root,
4287
4293
  isBrowserEnabled: project.isBrowserEnabled(),
4288
4294
  vitenode: project.vitenode
4289
- })), {
4295
+ })),
4296
+ // Check core last as it will match all files anyway
4297
+ {
4290
4298
  root: ctx.config.root,
4291
4299
  vitenode: ctx.vitenode,
4292
4300
  isBrowserEnabled: ctx.getRootProject().isBrowserEnabled()
@@ -2,7 +2,7 @@ import { ModuleExecutionInfo } from 'vite-node/client';
2
2
 
3
3
  interface RuntimeCoverageModuleLoader {
4
4
  executeId: (id: string) => Promise<{
5
- default: RuntimeCoverageProviderModule
5
+ default: RuntimeCoverageProviderModule;
6
6
  }>;
7
7
  isBrowser?: boolean;
8
8
  moduleExecutionInfo?: ModuleExecutionInfo;
@@ -16,19 +16,19 @@ interface RuntimeCoverageProviderModule {
16
16
  * Executed before tests are run in the worker thread.
17
17
  */
18
18
  startCoverage?: (runtimeOptions: {
19
- isolate: boolean
19
+ isolate: boolean;
20
20
  }) => unknown | Promise<unknown>;
21
21
  /**
22
22
  * Executed on after each run in the worker thread. Possible to return a payload passed to the provider
23
23
  */
24
24
  takeCoverage?: (runtimeOptions?: {
25
- moduleExecutionInfo?: ModuleExecutionInfo
25
+ moduleExecutionInfo?: ModuleExecutionInfo;
26
26
  }) => unknown | Promise<unknown>;
27
27
  /**
28
28
  * Executed after all tests have been run in the worker thread.
29
29
  */
30
30
  stopCoverage?: (runtimeOptions: {
31
- isolate: boolean
31
+ isolate: boolean;
32
32
  }) => unknown | Promise<unknown>;
33
33
  }
34
34
 
@@ -5,7 +5,7 @@ import { detectPackageManager, installPackage } from './index.D3XRDfWc.js';
5
5
  import { p as prompt, f as findUp } from './index.X0nbfr6-.js';
6
6
  import { x } from 'tinyexec';
7
7
  import c from 'tinyrainbow';
8
- import { c as configFiles } from './constants.DnKduX2e.js';
8
+ import { c as configFiles } from './constants.CXzqaLmq.js';
9
9
  import 'node:process';
10
10
  import 'node:url';
11
11
  import './_commonjsHelpers.BFTU3MAI.js';
@@ -50,7 +50,7 @@ const vueExample = {
50
50
  defineProps({
51
51
  name: String
52
52
  })
53
- </script>
53
+ <\/script>
54
54
 
55
55
  <template>
56
56
  <div>
@@ -63,7 +63,7 @@ defineProps({
63
63
  defineProps<{
64
64
  name: string
65
65
  }>()
66
- </script>
66
+ <\/script>
67
67
 
68
68
  <template>
69
69
  <div>
@@ -89,14 +89,14 @@ const svelteExample = {
89
89
  js: `
90
90
  <script>
91
91
  export let name
92
- </script>
92
+ <\/script>
93
93
 
94
94
  <h1>Hello {name}!</h1>
95
95
  `,
96
96
  ts: `
97
97
  <script lang="ts">
98
98
  export let name: string
99
- </script>
99
+ <\/script>
100
100
 
101
101
  <h1>Hello {name}!</h1>
102
102
  `,
@@ -30,7 +30,7 @@ interface EnvironmentReturn {
30
30
  }
31
31
  interface VmEnvironmentReturn {
32
32
  getVmContext: () => {
33
- [key: string]: any
33
+ [key: string]: any;
34
34
  };
35
35
  teardown: () => Awaitable<void>;
36
36
  }
@@ -207,7 +207,7 @@ const prefixedBuiltins = new Set([
207
207
  const NODE_BUILTIN_NAMESPACE = "node:";
208
208
  function isNodeBuiltin(id) {
209
209
  if (prefixedBuiltins.has(id)) return true;
210
- return builtins.has(id.startsWith(NODE_BUILTIN_NAMESPACE) ? id.slice(NODE_BUILTIN_NAMESPACE.length) : id);
210
+ return builtins.has(id.startsWith(NODE_BUILTIN_NAMESPACE) ? id.slice(5) : id);
211
211
  }
212
212
 
213
213
  const spyModulePath = resolve$1(distDir, "spy.js");
@@ -1,8 +1,8 @@
1
1
  import { PromisifyAssertion, Tester, ExpectStatic } from '@vitest/expect';
2
2
  import { Plugin } from '@vitest/pretty-format';
3
3
  import { SnapshotState } from '@vitest/snapshot';
4
- import { B as BenchmarkResult } from './benchmark.d.BwvBVTda.js';
5
- import { U as UserConsoleLog } from './environment.d.CUq4cUgQ.js';
4
+ import { B as BenchmarkResult } from './benchmark.d.DAaHLpsq.js';
5
+ import { U as UserConsoleLog } from './environment.d.Bhm9oc0v.js';
6
6
 
7
7
  declare global {
8
8
  // eslint-disable-next-line ts/no-namespace
@@ -1,6 +1,6 @@
1
- import { g as globalApis } from './constants.DnKduX2e.js';
2
- import { V as VitestIndex } from './index.BWf_gE5n.js';
3
- import './vi.bdSIJ99Y.js';
1
+ import { g as globalApis } from './constants.CXzqaLmq.js';
2
+ import { V as VitestIndex } from './index.D1_MsKEt.js';
3
+ import './vi.CA0EPI9Y.js';
4
4
  import '@vitest/expect';
5
5
  import '@vitest/runner';
6
6
  import '@vitest/runner/utils';
@@ -1,7 +1,7 @@
1
1
  import { existsSync, readFileSync, promises } from 'node:fs';
2
2
  import { mkdir, writeFile, readdir, stat, readFile } from 'node:fs/promises';
3
3
  import { resolve, dirname, isAbsolute, relative, basename, normalize } from 'pathe';
4
- import { g as getOutputFile, h as hasFailedSnapshot, T as TypeCheckError } from './typechecker.CVytUJuF.js';
4
+ import { g as getOutputFile, h as hasFailedSnapshot, T as TypeCheckError } from './typechecker.CMNPqJOo.js';
5
5
  import { performance as performance$1 } from 'node:perf_hooks';
6
6
  import { getTestName, getFullName, hasFailed, getTests, getSuites, getTasks } from '@vitest/runner/utils';
7
7
  import { slash, toArray, isPrimitive, inspect, positionToOffset, lineSplitRE } from '@vitest/utils';
@@ -772,6 +772,7 @@ class WindowRenderer {
772
772
  renderInterval = void 0;
773
773
  renderScheduled = false;
774
774
  windowHeight = 0;
775
+ started = false;
775
776
  finished = false;
776
777
  cleanups = [];
777
778
  constructor(options) {
@@ -789,9 +790,9 @@ class WindowRenderer {
789
790
  this.flushBuffer();
790
791
  this.stop();
791
792
  });
792
- this.start();
793
793
  }
794
794
  start() {
795
+ this.started = true;
795
796
  this.finished = false;
796
797
  this.renderInterval = setInterval(() => this.schedule(), this.options.interval).unref();
797
798
  }
@@ -865,7 +866,7 @@ class WindowRenderer {
865
866
  const original = stream.write;
866
867
  // @ts-expect-error -- not sure how 2 overloads should be typed
867
868
  stream.write = (chunk, _, callback) => {
868
- if (chunk) if (this.finished) this.write(chunk.toString(), type);
869
+ if (chunk) if (this.finished || !this.started) this.write(chunk.toString(), type);
869
870
  else this.buffer.push({
870
871
  type,
871
872
  message: chunk.toString()
@@ -1341,7 +1342,7 @@ function printErrorInner(error, project, options) {
1341
1342
  stack: String(error)
1342
1343
  };
1343
1344
  if (!e) {
1344
- const error = new Error("unknown error");
1345
+ const error = /* @__PURE__ */ new Error("unknown error");
1345
1346
  e = {
1346
1347
  message: e ?? error.message,
1347
1348
  stack: error.stack
@@ -1883,7 +1884,6 @@ class JUnitReporter {
1883
1884
  };
1884
1885
  if (typeof this.options.classnameTemplate === "function") classname = this.options.classnameTemplate(templateVars);
1885
1886
  else if (typeof this.options.classnameTemplate === "string") classname = this.options.classnameTemplate.replace(/\{filename\}/g, templateVars.filename).replace(/\{filepath\}/g, templateVars.filepath);
1886
- else if (typeof this.options.classname === "string") classname = this.options.classname;
1887
1887
  await this.writeElement("testcase", {
1888
1888
  classname,
1889
1889
  file: this.options.addFileAttribute ? filename : void 0,
@@ -1,4 +1,4 @@
1
- import { c as createExpect, a as globalExpect, i as inject, v as vi, b as vitest } from './vi.bdSIJ99Y.js';
1
+ import { c as createExpect, a as globalExpect, i as inject, v as vi, b as vitest } from './vi.CA0EPI9Y.js';
2
2
  import { b as bench } from './benchmark.CYdenmiT.js';
3
3
  import { expectTypeOf } from 'expect-type';
4
4
  import { afterAll, afterEach, beforeAll, beforeEach, describe, it, onTestFailed, onTestFinished, suite, test } from '@vitest/runner';
@@ -2,7 +2,7 @@ import fs from 'node:fs';
2
2
  import { getTasks, getFullName, getTests } from '@vitest/runner/utils';
3
3
  import * as pathe from 'pathe';
4
4
  import c from 'tinyrainbow';
5
- import { g as getStateSymbol, t as truncateString, F as F_RIGHT, D as DefaultReporter, f as formatProjectName } from './index.CZI_8rVt.js';
5
+ import { g as getStateSymbol, t as truncateString, F as F_RIGHT, D as DefaultReporter, f as formatProjectName } from './index.Bz6b0Ib7.js';
6
6
  import { stripVTControlCharacters } from 'node:util';
7
7
  import { notNullish } from '@vitest/utils';
8
8
 
@@ -1,6 +1,6 @@
1
1
  import * as chai from 'chai';
2
2
  import { resolve } from 'node:path';
3
- import { l as loadDiffConfig, b as loadSnapshotSerializers, t as takeCoverageInsideWorker } from './setup-common.D7ZqXFx-.js';
3
+ import { l as loadDiffConfig, b as loadSnapshotSerializers, t as takeCoverageInsideWorker } from './setup-common.Ebx5x0eP.js';
4
4
  import { distDir } from '../path.js';
5
5
  import { r as rpc } from './rpc.CsFtxqeq.js';
6
6
  import { g as getWorkerState } from './utils.XdZDrNZV.js';
@@ -1,4 +1,4 @@
1
- import { V as Vitest, T as TestProject, a as TestProjectConfiguration } from './reporters.d.DxZg19fy.js';
1
+ import { V as Vitest, T as TestProject, a as TestProjectConfiguration } from './reporters.d.BBuiUFDc.js';
2
2
 
3
3
  interface VitestPluginContext {
4
4
  vitest: Vitest;