vitest 3.0.0-beta.4 → 3.0.0

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 (38) hide show
  1. package/dist/browser.d.ts +2 -2
  2. package/dist/chunks/{base.BJ8KO-VX.js → base.CUDzyU2J.js} +1 -1
  3. package/dist/chunks/{cac.BAYqQ2aM.js → cac.DZC9WjGM.js} +6 -6
  4. package/dist/chunks/{cli-api.Dhl34Trr.js → cli-api.CmJw5Cd_.js} +901 -65
  5. package/dist/chunks/{creator.Ot9GlSGw.js → creator.DztqrnyH.js} +1 -1
  6. package/dist/chunks/global.CnI8_G5V.d.ts +133 -0
  7. package/dist/chunks/{index.B2M9nD1V.js → index.CUcwvygK.js} +4 -4
  8. package/dist/chunks/{index.DQboAxJm.js → index.D9C26wCk.js} +1 -0
  9. package/dist/chunks/{index.CAueP3cK.js → index.TKSL1HjN.js} +188 -933
  10. package/dist/chunks/{reporters.Dcdq51WE.d.ts → reporters.Y8BYiXBN.d.ts} +340 -239
  11. package/dist/chunks/{resolveConfig.kZFMjKCQ.js → resolveConfig.CSLLD33d.js} +137 -52
  12. package/dist/chunks/{rpc.C3q9uwRX.js → rpc.TVf73xOu.js} +0 -1
  13. package/dist/chunks/{runBaseTests.URiUrnWK.js → runBaseTests.C0T_TQwH.js} +2 -2
  14. package/dist/chunks/{RandomSequencer.DB__To1b.js → typechecker.BJMkWMXo.js} +53 -106
  15. package/dist/chunks/{utils.yHKcm4dz.js → utils.DJWL04yX.js} +1 -1
  16. package/dist/chunks/{vite.DzluO1Kj.d.ts → vite.CQ0dHgkN.d.ts} +1 -1
  17. package/dist/chunks/{worker.BIVMnzXw.d.ts → worker.B1y96qmv.d.ts} +1 -1
  18. package/dist/chunks/{worker.Hz_LAzfd.d.ts → worker.CIpff8Eg.d.ts} +2 -4
  19. package/dist/cli.js +1 -1
  20. package/dist/config.d.ts +3 -3
  21. package/dist/coverage.d.ts +1 -1
  22. package/dist/coverage.js +5 -4
  23. package/dist/execute.d.ts +1 -1
  24. package/dist/index.d.ts +17 -118
  25. package/dist/node.d.ts +11 -8
  26. package/dist/node.js +25 -23
  27. package/dist/reporters.d.ts +1 -1
  28. package/dist/reporters.js +4 -6
  29. package/dist/runners.d.ts +1 -0
  30. package/dist/runners.js +7 -7
  31. package/dist/worker.js +1 -1
  32. package/dist/workers/forks.js +1 -1
  33. package/dist/workers/runVmTests.js +2 -2
  34. package/dist/workers/threads.js +1 -1
  35. package/dist/workers.d.ts +2 -2
  36. package/dist/workers.js +2 -2
  37. package/package.json +13 -13
  38. package/dist/chunks/types.BOjykUpq.d.ts +0 -27
@@ -1,18 +1,19 @@
1
1
  import { existsSync, promises, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
2
- import { normalize, relative, dirname, resolve, join, basename, isAbsolute } from 'pathe';
2
+ import { extname, normalize, relative, dirname, resolve, join, basename, isAbsolute } from 'pathe';
3
3
  import { g as getCoverageProvider, C as CoverageProviderMap } from './coverage.BWeNbfBa.js';
4
4
  import a, { resolve as resolve$1 } from 'node:path';
5
- import { noop, isPrimitive, createDefer, toArray, deepMerge, nanoid, slash, deepClone, notNullish } from '@vitest/utils';
5
+ import { noop, isPrimitive, createDefer, highlight, toArray, deepMerge, nanoid, slash, deepClone, notNullish } from '@vitest/utils';
6
6
  import { f as findUp, p as prompt } from './index.BJDntFik.js';
7
+ import * as vite from 'vite';
7
8
  import { searchForWorkspaceRoot, version, createServer, mergeConfig } from 'vite';
8
9
  import { A as API_PATH, c as configFiles, a as defaultBrowserPort, w as workspacesFiles, d as defaultPort } from './constants.fzPh7AOq.js';
9
- import { createFileTask, limitConcurrency, getTasks, hasFailed, getTests } from '@vitest/runner/utils';
10
+ import { generateFileHash, createFileTask, limitConcurrency, hasFailed, getTasks, getTests } from '@vitest/runner/utils';
10
11
  import { SnapshotManager } from '@vitest/snapshot/manager';
11
12
  import { ViteNodeRunner } from 'vite-node/client';
12
13
  import { ViteNodeServer } from 'vite-node/server';
13
- import { v as version$1 } from './cac.BAYqQ2aM.js';
14
+ import { v as version$1 } from './cac.DZC9WjGM.js';
14
15
  import { c as createBirpc } from './index.68735LiX.js';
15
- import { s as stringify, p as parse, i as generateCodeFrame, R as ReportersMap, h as BenchmarkReportsMap, f as TestModule, g as TestSuite, e as TestCase, L as Logger, j as BlobReporter, r as readBlobs } from './index.CAueP3cK.js';
16
+ import { s as stringify, p as parse, g as printError, h as generateCodeFrame, R as ReportersMap, b as BenchmarkReportsMap, i as BlobReporter, r as readBlobs, H as HangingProcessReporter } from './index.TKSL1HjN.js';
16
17
  import require$$0$2 from 'stream';
17
18
  import require$$0 from 'zlib';
18
19
  import require$$0$1 from 'buffer';
@@ -26,11 +27,13 @@ import require$$7 from 'url';
26
27
  import { g as getDefaultExportFromCjs, c as commonjsGlobal } from './_commonjsHelpers.BFTU3MAI.js';
27
28
  import { parseErrorStacktrace } from '@vitest/utils/source-map';
28
29
  import { distDir, rootDir } from '../path.js';
29
- import { i as isPackageExists, e as requireMicromatch, V as VitestCache, f as configDefaults, g as getFilePoolName, h as isBrowserEnabled, m as mm, a as resolveConfig, j as groupBy, w as wildcardPatternToRegExp, k as createPool, b as resolveApiServerConfig, c as coverageConfigDefaults, s as stdout } from './resolveConfig.kZFMjKCQ.js';
30
+ import { R as RandomSequencer, i as isPackageExists, e as requireMicromatch, h as hash, V as VitestCache, f as configDefaults, g as getFilePoolName, j as isBrowserEnabled, m as mm, a as resolveConfig, k as groupBy, w as wildcardPatternToRegExp, l as createPool, b as resolveApiServerConfig, s as stdout } from './resolveConfig.CSLLD33d.js';
31
+ import { i as isTTY, b as isWindows, c as convertTasksToEvents } from './typechecker.BJMkWMXo.js';
32
+ import { Console } from 'node:console';
33
+ import c from 'tinyrainbow';
34
+ import { a as formatProjectName, w as withLabel, d as divider } from './utils.DJWL04yX.js';
30
35
  import { createRequire } from 'node:module';
31
36
  import url from 'node:url';
32
- import c from 'tinyrainbow';
33
- import { i as isTTY, h as hash, b as isWindows } from './RandomSequencer.DB__To1b.js';
34
37
  import { rm } from 'node:fs/promises';
35
38
  import nodeos__default, { tmpdir } from 'node:os';
36
39
  import require$$0$4 from 'os';
@@ -39,7 +42,8 @@ import require$$0$6 from 'fs';
39
42
  import { normalizeRequestId, cleanUrl } from 'vite-node/utils';
40
43
  import { hoistMocksPlugin, automockPlugin } from '@vitest/mocker/node';
41
44
  import MagicString from 'magic-string';
42
- import { w as withLabel } from './utils.yHKcm4dz.js';
45
+ import assert$1 from 'node:assert';
46
+ import { serializeError } from '@vitest/utils/error';
43
47
  import readline from 'node:readline';
44
48
  import { stripVTControlCharacters } from 'node:util';
45
49
 
@@ -4900,9 +4904,8 @@ function setup(ctx, _server) {
4900
4904
  function setupClient(ws) {
4901
4905
  const rpc = createBirpc(
4902
4906
  {
4903
- async onTaskUpdate(packs) {
4904
- ctx.state.updateTasks(packs);
4905
- await ctx.report("onTaskUpdate", packs);
4907
+ async onTaskUpdate(packs, events) {
4908
+ await ctx._testRun.updated(packs, events);
4906
4909
  },
4907
4910
  getFiles() {
4908
4911
  return ctx.state.getFiles();
@@ -4933,6 +4936,9 @@ function setup(ctx, _server) {
4933
4936
  getConfig() {
4934
4937
  return ctx.getRootProject().serializedConfig;
4935
4938
  },
4939
+ getResolvedProjectNames() {
4940
+ return ctx.resolvedProjects.map((p) => p.name);
4941
+ },
4936
4942
  async getTransformResult(projectName, id, browser = false) {
4937
4943
  const project = ctx.getProjectByName(projectName);
4938
4944
  const result = browser ? await project.browser.vite.transformRequest(id) : await project.vitenode.transformRequest(id);
@@ -5119,6 +5125,292 @@ class RangeLocationFilterProvidedError extends Error {
5119
5125
  }
5120
5126
  }
5121
5127
 
5128
+ const HIGHLIGHT_SUPPORTED_EXTS = new Set(
5129
+ ["js", "ts"].flatMap((lang) => [
5130
+ `.${lang}`,
5131
+ `.m${lang}`,
5132
+ `.c${lang}`,
5133
+ `.${lang}x`,
5134
+ `.m${lang}x`,
5135
+ `.c${lang}x`
5136
+ ])
5137
+ );
5138
+ function highlightCode(id, source, colors) {
5139
+ const ext = extname(id);
5140
+ if (!HIGHLIGHT_SUPPORTED_EXTS.has(ext)) {
5141
+ return source;
5142
+ }
5143
+ const isJsx = ext.endsWith("x");
5144
+ return highlight(source, { jsx: isJsx, colors: c });
5145
+ }
5146
+
5147
+ const PAD = " ";
5148
+ const ESC$1 = "\x1B[";
5149
+ const ERASE_DOWN = `${ESC$1}J`;
5150
+ const ERASE_SCROLLBACK = `${ESC$1}3J`;
5151
+ const CURSOR_TO_START = `${ESC$1}1;1H`;
5152
+ const HIDE_CURSOR = `${ESC$1}?25l`;
5153
+ const SHOW_CURSOR = `${ESC$1}?25h`;
5154
+ const CLEAR_SCREEN = "\x1Bc";
5155
+ class Logger {
5156
+ constructor(ctx, outputStream = process.stdout, errorStream = process.stderr) {
5157
+ this.ctx = ctx;
5158
+ this.outputStream = outputStream;
5159
+ this.errorStream = errorStream;
5160
+ this.console = new Console({ stdout: outputStream, stderr: errorStream });
5161
+ this._highlights.clear();
5162
+ this.addCleanupListeners();
5163
+ this.registerUnhandledRejection();
5164
+ this.outputStream.write(HIDE_CURSOR);
5165
+ }
5166
+ _clearScreenPending;
5167
+ _highlights = /* @__PURE__ */ new Map();
5168
+ cleanupListeners = [];
5169
+ console;
5170
+ log(...args) {
5171
+ this._clearScreen();
5172
+ this.console.log(...args);
5173
+ }
5174
+ error(...args) {
5175
+ this._clearScreen();
5176
+ this.console.error(...args);
5177
+ }
5178
+ warn(...args) {
5179
+ this._clearScreen();
5180
+ this.console.warn(...args);
5181
+ }
5182
+ clearFullScreen(message = "") {
5183
+ if (!this.ctx.config.clearScreen) {
5184
+ this.console.log(message);
5185
+ return;
5186
+ }
5187
+ if (message) {
5188
+ this.console.log(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}${message}`);
5189
+ } else {
5190
+ this.outputStream.write(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}`);
5191
+ }
5192
+ }
5193
+ clearScreen(message, force = false) {
5194
+ if (!this.ctx.config.clearScreen) {
5195
+ this.console.log(message);
5196
+ return;
5197
+ }
5198
+ this._clearScreenPending = message;
5199
+ if (force) {
5200
+ this._clearScreen();
5201
+ }
5202
+ }
5203
+ _clearScreen() {
5204
+ if (this._clearScreenPending == null) {
5205
+ return;
5206
+ }
5207
+ const log = this._clearScreenPending;
5208
+ this._clearScreenPending = void 0;
5209
+ this.console.log(`${CURSOR_TO_START}${ERASE_DOWN}${log}`);
5210
+ }
5211
+ printError(err, options = {}) {
5212
+ printError(err, this.ctx, this, options);
5213
+ }
5214
+ clearHighlightCache(filename) {
5215
+ if (filename) {
5216
+ this._highlights.delete(filename);
5217
+ } else {
5218
+ this._highlights.clear();
5219
+ }
5220
+ }
5221
+ highlight(filename, source) {
5222
+ if (this._highlights.has(filename)) {
5223
+ return this._highlights.get(filename);
5224
+ }
5225
+ const code = highlightCode(filename, source);
5226
+ this._highlights.set(filename, code);
5227
+ return code;
5228
+ }
5229
+ printNoTestFound(filters) {
5230
+ const config = this.ctx.config;
5231
+ if (config.watch && (config.changed || config.related?.length)) {
5232
+ this.log(`No affected ${config.mode} files found
5233
+ `);
5234
+ } else if (config.watch) {
5235
+ this.log(
5236
+ c.red(`No ${config.mode} files found. You can change the file name pattern by pressing "p"
5237
+ `)
5238
+ );
5239
+ } else {
5240
+ if (config.passWithNoTests) {
5241
+ this.log(`No ${config.mode} files found, exiting with code 0
5242
+ `);
5243
+ } else {
5244
+ this.error(
5245
+ c.red(`No ${config.mode} files found, exiting with code 1
5246
+ `)
5247
+ );
5248
+ }
5249
+ }
5250
+ const comma = c.dim(", ");
5251
+ if (filters?.length) {
5252
+ this.console.error(c.dim("filter: ") + c.yellow(filters.join(comma)));
5253
+ }
5254
+ const projectsFilter = toArray(config.project);
5255
+ if (projectsFilter.length) {
5256
+ this.console.error(
5257
+ c.dim("projects: ") + c.yellow(projectsFilter.join(comma))
5258
+ );
5259
+ }
5260
+ this.ctx.projects.forEach((project) => {
5261
+ const config2 = project.config;
5262
+ const printConfig = !project.isRootProject() && project.name;
5263
+ if (printConfig) {
5264
+ this.console.error(`
5265
+ ${formatProjectName(project.name)}
5266
+ `);
5267
+ }
5268
+ if (config2.include) {
5269
+ this.console.error(
5270
+ c.dim("include: ") + c.yellow(config2.include.join(comma))
5271
+ );
5272
+ }
5273
+ if (config2.exclude) {
5274
+ this.console.error(
5275
+ c.dim("exclude: ") + c.yellow(config2.exclude.join(comma))
5276
+ );
5277
+ }
5278
+ if (config2.typecheck.enabled) {
5279
+ this.console.error(
5280
+ c.dim("typecheck include: ") + c.yellow(config2.typecheck.include.join(comma))
5281
+ );
5282
+ this.console.error(
5283
+ c.dim("typecheck exclude: ") + c.yellow(config2.typecheck.exclude.join(comma))
5284
+ );
5285
+ }
5286
+ });
5287
+ this.console.error();
5288
+ }
5289
+ printBanner() {
5290
+ this.log();
5291
+ const color = this.ctx.config.watch ? "blue" : "cyan";
5292
+ const mode = this.ctx.config.watch ? "DEV" : "RUN";
5293
+ this.log(withLabel(color, mode, `v${this.ctx.version} `) + c.gray(this.ctx.config.root));
5294
+ if (this.ctx.config.sequence.sequencer === RandomSequencer) {
5295
+ this.log(PAD + c.gray(`Running tests with seed "${this.ctx.config.sequence.seed}"`));
5296
+ }
5297
+ if (this.ctx.config.ui) {
5298
+ const host = this.ctx.config.api?.host || "localhost";
5299
+ const port = this.ctx.server.config.server.port;
5300
+ const base = this.ctx.config.uiBase;
5301
+ this.log(PAD + c.dim(c.green(`UI started at http://${host}:${c.bold(port)}${base}`)));
5302
+ } else if (this.ctx.config.api?.port) {
5303
+ const resolvedUrls = this.ctx.server.resolvedUrls;
5304
+ const fallbackUrl = `http://${this.ctx.config.api.host || "localhost"}:${this.ctx.config.api.port}`;
5305
+ const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0] ?? fallbackUrl;
5306
+ this.log(PAD + c.dim(c.green(`API started at ${new URL("/", origin)}`)));
5307
+ }
5308
+ if (this.ctx.coverageProvider) {
5309
+ this.log(PAD + c.dim("Coverage enabled with ") + c.yellow(this.ctx.coverageProvider.name));
5310
+ }
5311
+ if (this.ctx.config.standalone) {
5312
+ this.log(c.yellow(`
5313
+ Vitest is running in standalone mode. Edit a test file to rerun tests.`));
5314
+ } else {
5315
+ this.log();
5316
+ }
5317
+ }
5318
+ printBrowserBanner(project) {
5319
+ if (!project.browser) {
5320
+ return;
5321
+ }
5322
+ const resolvedUrls = project.browser.vite.resolvedUrls;
5323
+ const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
5324
+ if (!origin) {
5325
+ return;
5326
+ }
5327
+ const output = project.isRootProject() ? "" : formatProjectName(project.name);
5328
+ const provider = project.browser.provider.name;
5329
+ const providerString = provider === "preview" ? "" : ` by ${c.reset(c.bold(provider))}`;
5330
+ this.log(
5331
+ c.dim(
5332
+ `${output}Browser runner started${providerString} ${c.dim("at")} ${c.blue(new URL("/", origin))}
5333
+ `
5334
+ )
5335
+ );
5336
+ }
5337
+ printUnhandledErrors(errors) {
5338
+ const errorMessage = c.red(
5339
+ c.bold(
5340
+ `
5341
+ Vitest caught ${errors.length} unhandled error${errors.length > 1 ? "s" : ""} during the test run.
5342
+ This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.`
5343
+ )
5344
+ );
5345
+ this.error(c.red(divider(c.bold(c.inverse(" Unhandled Errors ")))));
5346
+ this.error(errorMessage);
5347
+ errors.forEach((err) => {
5348
+ this.printError(err, {
5349
+ fullStack: true,
5350
+ type: err.type || "Unhandled Error"
5351
+ });
5352
+ });
5353
+ this.error(c.red(divider()));
5354
+ }
5355
+ printSourceTypeErrors(errors) {
5356
+ const errorMessage = c.red(
5357
+ c.bold(
5358
+ `
5359
+ Vitest found ${errors.length} error${errors.length > 1 ? "s" : ""} not related to your test files.`
5360
+ )
5361
+ );
5362
+ this.log(c.red(divider(c.bold(c.inverse(" Source Errors ")))));
5363
+ this.log(errorMessage);
5364
+ errors.forEach((err) => {
5365
+ this.printError(err, { fullStack: true });
5366
+ });
5367
+ this.log(c.red(divider()));
5368
+ }
5369
+ getColumns() {
5370
+ return "columns" in this.outputStream ? this.outputStream.columns : 80;
5371
+ }
5372
+ onTerminalCleanup(listener) {
5373
+ this.cleanupListeners.push(listener);
5374
+ }
5375
+ addCleanupListeners() {
5376
+ const cleanup = () => {
5377
+ this.cleanupListeners.forEach((fn) => fn());
5378
+ this.outputStream.write(SHOW_CURSOR);
5379
+ };
5380
+ const onExit = (signal, exitCode) => {
5381
+ cleanup();
5382
+ if (process.exitCode === void 0) {
5383
+ process.exitCode = exitCode !== void 0 ? 128 + exitCode : Number(signal);
5384
+ }
5385
+ process.exit();
5386
+ };
5387
+ process.once("SIGINT", onExit);
5388
+ process.once("SIGTERM", onExit);
5389
+ process.once("exit", onExit);
5390
+ this.ctx.onClose(() => {
5391
+ process.off("SIGINT", onExit);
5392
+ process.off("SIGTERM", onExit);
5393
+ process.off("exit", onExit);
5394
+ cleanup();
5395
+ });
5396
+ }
5397
+ registerUnhandledRejection() {
5398
+ const onUnhandledRejection = (err) => {
5399
+ process.exitCode = 1;
5400
+ this.printError(err, {
5401
+ fullStack: true,
5402
+ type: "Unhandled Rejection"
5403
+ });
5404
+ this.error("\n\n");
5405
+ process.exit();
5406
+ };
5407
+ process.on("unhandledRejection", onUnhandledRejection);
5408
+ this.ctx.onClose(() => {
5409
+ process.off("unhandledRejection", onUnhandledRejection);
5410
+ });
5411
+ }
5412
+ }
5413
+
5122
5414
  const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
5123
5415
  class VitestPackageInstaller {
5124
5416
  isPackageExists(name, options) {
@@ -5159,7 +5451,7 @@ class VitestPackageInstaller {
5159
5451
  });
5160
5452
  if (install) {
5161
5453
  const packageName = version ? `${dependency}@${version}` : dependency;
5162
- await (await import('./index.DQboAxJm.js')).installPackage(packageName, { dev: true });
5454
+ await (await import('./index.D9C26wCk.js')).installPackage(packageName, { dev: true });
5163
5455
  process.stderr.write(
5164
5456
  c.yellow(
5165
5457
  `
@@ -8669,6 +8961,10 @@ function silenceImportViteIgnoreWarning(logger) {
8669
8961
  };
8670
8962
  }
8671
8963
 
8964
+ function getDefaultServerConditions() {
8965
+ return vite.defaultServerConditions ?? ["node"];
8966
+ }
8967
+
8672
8968
  const cssLangs = "\\.(?:css|less|sass|scss|styl|stylus|pcss|postcss)(?:$|\\?)";
8673
8969
  const cssLangRE = new RegExp(cssLangs);
8674
8970
  const cssModuleRE = new RegExp(`\\.module${cssLangs}`);
@@ -9482,6 +9778,7 @@ function WorkspaceVitestPlugin(project, options) {
9482
9778
  name = options.workspacePath.toString();
9483
9779
  }
9484
9780
  }
9781
+ const conditions = getDefaultServerConditions();
9485
9782
  const config = {
9486
9783
  root,
9487
9784
  resolve: {
@@ -9489,7 +9786,7 @@ function WorkspaceVitestPlugin(project, options) {
9489
9786
  // setting this option can bypass that and fallback to cjs version
9490
9787
  mainFields: [],
9491
9788
  alias: testConfig.alias,
9492
- conditions: ["node"]
9789
+ conditions
9493
9790
  },
9494
9791
  esbuild: viteConfig.esbuild === false ? false : {
9495
9792
  // Lowest target Vitest supports is Node18
@@ -9522,7 +9819,7 @@ function WorkspaceVitestPlugin(project, options) {
9522
9819
  // by default Vite resolves `module` field, which not always a native ESM module
9523
9820
  // setting this option can bypass that and fallback to cjs version
9524
9821
  mainFields: [],
9525
- conditions: ["node"]
9822
+ conditions
9526
9823
  }
9527
9824
  }
9528
9825
  },
@@ -9588,6 +9885,10 @@ class TestSpecification {
9588
9885
  * @deprecated use `pool` instead
9589
9886
  */
9590
9887
  2;
9888
+ /**
9889
+ * The task ID associated with the test module.
9890
+ */
9891
+ taskId;
9591
9892
  /**
9592
9893
  * The test project that the module belongs to.
9593
9894
  */
@@ -9609,11 +9910,27 @@ class TestSpecification {
9609
9910
  this[0] = project;
9610
9911
  this[1] = moduleId;
9611
9912
  this[2] = { pool };
9913
+ const name = project.config.name;
9914
+ const hashName = pool !== "typescript" ? name : name ? `${name}:__typecheck__` : "__typecheck__";
9915
+ this.taskId = generateFileHash(
9916
+ relative(project.config.root, moduleId),
9917
+ hashName
9918
+ );
9612
9919
  this.project = project;
9613
9920
  this.moduleId = moduleId;
9614
9921
  this.pool = pool;
9615
9922
  this.testLines = testLines;
9616
9923
  }
9924
+ /**
9925
+ * Test module associated with the specification.
9926
+ */
9927
+ get testModule() {
9928
+ const task = this.project.vitest.state.idMap.get(this.taskId);
9929
+ if (!task) {
9930
+ return void 0;
9931
+ }
9932
+ return this.project.vitest.state.getReportedEntity(task);
9933
+ }
9617
9934
  toJSON() {
9618
9935
  return [
9619
9936
  {
@@ -9681,13 +9998,14 @@ class TestProject {
9681
9998
  typechecker;
9682
9999
  /** @internal */
9683
10000
  _config;
10001
+ /** @internal */
10002
+ _vite;
9684
10003
  runner;
9685
10004
  closingPromise;
9686
10005
  testFilesList = null;
9687
10006
  typecheckFilesList = null;
9688
10007
  _globalSetups;
9689
10008
  _provided = {};
9690
- _vite;
9691
10009
  // "provide" is a property, not a method to keep the context when destructed in the global setup,
9692
10010
  // making it a method would be a breaking change, and can be done in Vitest 3 at minimum
9693
10011
  /**
@@ -9987,9 +10305,7 @@ class TestProject {
9987
10305
  }
9988
10306
  return testFiles;
9989
10307
  }
9990
- /** @internal */
9991
10308
  _parentBrowser;
9992
- /** @internal */
9993
10309
  _parent;
9994
10310
  /** @internal */
9995
10311
  _initParentBrowser = deduped(async () => {
@@ -10027,6 +10343,7 @@ class TestProject {
10027
10343
  await this._parent?._initParentBrowser();
10028
10344
  if (!this.browser && this._parent?._parentBrowser) {
10029
10345
  this.browser = this._parent._parentBrowser.spawn(this);
10346
+ await this.vitest.report("onBrowserInit", this);
10030
10347
  }
10031
10348
  });
10032
10349
  /**
@@ -10182,7 +10499,7 @@ function deduped(cb) {
10182
10499
  }
10183
10500
  async function initializeProject(workspacePath, ctx, options) {
10184
10501
  const project = new TestProject(workspacePath, ctx, options);
10185
- const { extends: extendsConfig, configFile, ...restOptions } = options;
10502
+ const { configFile, ...restOptions } = options;
10186
10503
  const config = {
10187
10504
  ...restOptions,
10188
10505
  configFile,
@@ -10449,6 +10766,411 @@ class VitestSpecifications {
10449
10766
  }
10450
10767
  }
10451
10768
 
10769
+ class ReportedTaskImplementation {
10770
+ /**
10771
+ * Task instance.
10772
+ * @internal
10773
+ */
10774
+ task;
10775
+ /**
10776
+ * The project associated with the test or suite.
10777
+ */
10778
+ project;
10779
+ /**
10780
+ * Unique identifier.
10781
+ * This ID is deterministic and will be the same for the same test across multiple runs.
10782
+ * The ID is based on the project name, module url and test order.
10783
+ */
10784
+ id;
10785
+ /**
10786
+ * Location in the module where the test or suite is defined.
10787
+ */
10788
+ location;
10789
+ /** @internal */
10790
+ constructor(task, project) {
10791
+ this.task = task;
10792
+ this.project = project;
10793
+ this.id = task.id;
10794
+ this.location = task.location;
10795
+ }
10796
+ /**
10797
+ * Checks if the test did not fail the suite.
10798
+ * If the test is not finished yet or was skipped, it will return `true`.
10799
+ */
10800
+ ok() {
10801
+ const result = this.task.result;
10802
+ return !result || result.state !== "fail";
10803
+ }
10804
+ /**
10805
+ * Creates a new reported task instance and stores it in the project's state for future use.
10806
+ * @internal
10807
+ */
10808
+ static register(task, project) {
10809
+ const state = new this(task, project);
10810
+ storeTask(project, task, state);
10811
+ return state;
10812
+ }
10813
+ }
10814
+ class TestCase extends ReportedTaskImplementation {
10815
+ #fullName;
10816
+ type = "test";
10817
+ /**
10818
+ * Direct reference to the test module where the test or suite is defined.
10819
+ */
10820
+ module;
10821
+ /**
10822
+ * Name of the test.
10823
+ */
10824
+ name;
10825
+ /**
10826
+ * Options that the test was initiated with.
10827
+ */
10828
+ options;
10829
+ /**
10830
+ * Parent suite. If the test was called directly inside the module, the parent will be the module itself.
10831
+ */
10832
+ parent;
10833
+ /** @internal */
10834
+ constructor(task, project) {
10835
+ super(task, project);
10836
+ this.name = task.name;
10837
+ this.module = getReportedTask(project, task.file);
10838
+ const suite = this.task.suite;
10839
+ if (suite) {
10840
+ this.parent = getReportedTask(project, suite);
10841
+ } else {
10842
+ this.parent = this.module;
10843
+ }
10844
+ this.options = buildOptions(task);
10845
+ }
10846
+ /**
10847
+ * Full name of the test including all parent suites separated with `>`.
10848
+ */
10849
+ get fullName() {
10850
+ if (this.#fullName === void 0) {
10851
+ if (this.parent.type !== "module") {
10852
+ this.#fullName = `${this.parent.fullName} > ${this.name}`;
10853
+ } else {
10854
+ this.#fullName = this.name;
10855
+ }
10856
+ }
10857
+ return this.#fullName;
10858
+ }
10859
+ /**
10860
+ * Test results.
10861
+ * - **pending**: Test was collected, but didn't finish running yet.
10862
+ * - **passed**: Test passed successfully
10863
+ * - **failed**: Test failed to execute
10864
+ * - **skipped**: Test was skipped during collection or dynamically with `ctx.skip()`.
10865
+ */
10866
+ result() {
10867
+ const result = this.task.result;
10868
+ const mode = result?.state || this.task.mode;
10869
+ if (!result && (mode === "skip" || mode === "todo")) {
10870
+ return {
10871
+ state: "skipped",
10872
+ note: void 0,
10873
+ errors: void 0
10874
+ };
10875
+ }
10876
+ if (!result || result.state === "run" || result.state === "queued") {
10877
+ return {
10878
+ state: "pending",
10879
+ errors: void 0
10880
+ };
10881
+ }
10882
+ const state = result.state === "fail" ? "failed" : result.state === "pass" ? "passed" : "skipped";
10883
+ if (state === "skipped") {
10884
+ return {
10885
+ state,
10886
+ note: result.note,
10887
+ errors: void 0
10888
+ };
10889
+ }
10890
+ if (state === "passed") {
10891
+ return {
10892
+ state,
10893
+ errors: result.errors
10894
+ };
10895
+ }
10896
+ return {
10897
+ state,
10898
+ errors: result.errors || []
10899
+ };
10900
+ }
10901
+ /**
10902
+ * Custom metadata that was attached to the test during its execution.
10903
+ */
10904
+ meta() {
10905
+ return this.task.meta;
10906
+ }
10907
+ /**
10908
+ * Useful information about the test like duration, memory usage, etc.
10909
+ * Diagnostic is only available after the test has finished.
10910
+ */
10911
+ diagnostic() {
10912
+ const result = this.task.result;
10913
+ if (!result || !result.startTime) {
10914
+ return void 0;
10915
+ }
10916
+ const duration = result.duration || 0;
10917
+ const slow = duration > this.project.globalConfig.slowTestThreshold;
10918
+ return {
10919
+ slow,
10920
+ heap: result.heap,
10921
+ duration,
10922
+ startTime: result.startTime,
10923
+ retryCount: result.retryCount ?? 0,
10924
+ repeatCount: result.repeatCount ?? 0,
10925
+ flaky: !!result.retryCount && result.state === "pass" && result.retryCount > 0
10926
+ };
10927
+ }
10928
+ }
10929
+ class TestCollection {
10930
+ #task;
10931
+ #project;
10932
+ constructor(task, project) {
10933
+ this.#task = task;
10934
+ this.#project = project;
10935
+ }
10936
+ /**
10937
+ * Returns the test or suite at a specific index.
10938
+ */
10939
+ at(index) {
10940
+ if (index < 0) {
10941
+ index = this.size + index;
10942
+ }
10943
+ return getReportedTask(this.#project, this.#task.tasks[index]);
10944
+ }
10945
+ /**
10946
+ * The number of tests and suites in the collection.
10947
+ */
10948
+ get size() {
10949
+ return this.#task.tasks.length;
10950
+ }
10951
+ /**
10952
+ * Returns the collection in array form for easier manipulation.
10953
+ */
10954
+ array() {
10955
+ return Array.from(this);
10956
+ }
10957
+ /**
10958
+ * Filters all tests that are part of this collection and its children.
10959
+ */
10960
+ *allTests(state) {
10961
+ for (const child of this) {
10962
+ if (child.type === "suite") {
10963
+ yield* child.children.allTests(state);
10964
+ } else if (state) {
10965
+ const testState = child.result().state;
10966
+ if (state === testState) {
10967
+ yield child;
10968
+ }
10969
+ } else {
10970
+ yield child;
10971
+ }
10972
+ }
10973
+ }
10974
+ /**
10975
+ * Filters only the tests that are part of this collection.
10976
+ */
10977
+ *tests(state) {
10978
+ for (const child of this) {
10979
+ if (child.type !== "test") {
10980
+ continue;
10981
+ }
10982
+ if (state) {
10983
+ const testState = child.result().state;
10984
+ if (state === testState) {
10985
+ yield child;
10986
+ }
10987
+ } else {
10988
+ yield child;
10989
+ }
10990
+ }
10991
+ }
10992
+ /**
10993
+ * Filters only the suites that are part of this collection.
10994
+ */
10995
+ *suites() {
10996
+ for (const child of this) {
10997
+ if (child.type === "suite") {
10998
+ yield child;
10999
+ }
11000
+ }
11001
+ }
11002
+ /**
11003
+ * Filters all suites that are part of this collection and its children.
11004
+ */
11005
+ *allSuites() {
11006
+ for (const child of this) {
11007
+ if (child.type === "suite") {
11008
+ yield child;
11009
+ yield* child.children.allSuites();
11010
+ }
11011
+ }
11012
+ }
11013
+ *[Symbol.iterator]() {
11014
+ for (const task of this.#task.tasks) {
11015
+ yield getReportedTask(this.#project, task);
11016
+ }
11017
+ }
11018
+ }
11019
+ class SuiteImplementation extends ReportedTaskImplementation {
11020
+ /**
11021
+ * Collection of suites and tests that are part of this suite.
11022
+ */
11023
+ children;
11024
+ /** @internal */
11025
+ constructor(task, project) {
11026
+ super(task, project);
11027
+ this.children = new TestCollection(task, project);
11028
+ }
11029
+ /**
11030
+ * Errors that happened outside of the test run during collection, like syntax errors.
11031
+ */
11032
+ errors() {
11033
+ return this.task.result?.errors || [];
11034
+ }
11035
+ }
11036
+ class TestSuite extends SuiteImplementation {
11037
+ #fullName;
11038
+ type = "suite";
11039
+ /**
11040
+ * Name of the test or the suite.
11041
+ */
11042
+ name;
11043
+ /**
11044
+ * Direct reference to the test module where the test or suite is defined.
11045
+ */
11046
+ module;
11047
+ /**
11048
+ * Parent suite. If suite was called directly inside the module, the parent will be the module itself.
11049
+ */
11050
+ parent;
11051
+ /**
11052
+ * Options that suite was initiated with.
11053
+ */
11054
+ options;
11055
+ /** @internal */
11056
+ constructor(task, project) {
11057
+ super(task, project);
11058
+ this.name = task.name;
11059
+ this.module = getReportedTask(project, task.file);
11060
+ const suite = this.task.suite;
11061
+ if (suite) {
11062
+ this.parent = getReportedTask(project, suite);
11063
+ } else {
11064
+ this.parent = this.module;
11065
+ }
11066
+ this.options = buildOptions(task);
11067
+ }
11068
+ /**
11069
+ * Checks the running state of the suite.
11070
+ */
11071
+ state() {
11072
+ return getSuiteState(this.task);
11073
+ }
11074
+ /**
11075
+ * Full name of the suite including all parent suites separated with `>`.
11076
+ */
11077
+ get fullName() {
11078
+ if (this.#fullName === void 0) {
11079
+ if (this.parent.type !== "module") {
11080
+ this.#fullName = `${this.parent.fullName} > ${this.name}`;
11081
+ } else {
11082
+ this.#fullName = this.name;
11083
+ }
11084
+ }
11085
+ return this.#fullName;
11086
+ }
11087
+ }
11088
+ class TestModule extends SuiteImplementation {
11089
+ type = "module";
11090
+ /**
11091
+ * This is usually an absolute UNIX file path.
11092
+ * It can be a virtual ID if the file is not on the disk.
11093
+ * This value corresponds to the ID in the Vite's module graph.
11094
+ */
11095
+ moduleId;
11096
+ /** @internal */
11097
+ constructor(task, project) {
11098
+ super(task, project);
11099
+ this.moduleId = task.filepath;
11100
+ }
11101
+ /**
11102
+ * Checks the running state of the test file.
11103
+ */
11104
+ state() {
11105
+ const state = this.task.result?.state;
11106
+ if (state === "queued") {
11107
+ return "queued";
11108
+ }
11109
+ return getSuiteState(this.task);
11110
+ }
11111
+ /**
11112
+ * Useful information about the module like duration, memory usage, etc.
11113
+ * If the module was not executed yet, all diagnostic values will return `0`.
11114
+ */
11115
+ diagnostic() {
11116
+ const setupDuration = this.task.setupDuration || 0;
11117
+ const collectDuration = this.task.collectDuration || 0;
11118
+ const prepareDuration = this.task.prepareDuration || 0;
11119
+ const environmentSetupDuration = this.task.environmentLoad || 0;
11120
+ const duration = this.task.result?.duration || 0;
11121
+ return {
11122
+ environmentSetupDuration,
11123
+ prepareDuration,
11124
+ collectDuration,
11125
+ setupDuration,
11126
+ duration
11127
+ };
11128
+ }
11129
+ }
11130
+ function buildOptions(task) {
11131
+ return {
11132
+ each: task.each,
11133
+ fails: task.type === "test" && task.fails,
11134
+ concurrent: task.concurrent,
11135
+ shuffle: task.shuffle,
11136
+ retry: task.retry,
11137
+ repeats: task.repeats,
11138
+ // runner types are too broad, but the public API should be more strict
11139
+ // the queued state exists only on Files and this method is called
11140
+ // only for tests and suites
11141
+ mode: task.mode
11142
+ };
11143
+ }
11144
+ function storeTask(project, runnerTask, reportedTask) {
11145
+ project.vitest.state.reportedTasksMap.set(runnerTask, reportedTask);
11146
+ }
11147
+ function getReportedTask(project, runnerTask) {
11148
+ const reportedTask = project.vitest.state.getReportedEntity(runnerTask);
11149
+ if (!reportedTask) {
11150
+ throw new Error(
11151
+ `Task instance was not found for ${runnerTask.type} "${runnerTask.name}"`
11152
+ );
11153
+ }
11154
+ return reportedTask;
11155
+ }
11156
+ function getSuiteState(task) {
11157
+ const mode = task.mode;
11158
+ const state = task.result?.state;
11159
+ if (mode === "skip" || mode === "todo" || state === "skip" || state === "todo") {
11160
+ return "skipped";
11161
+ }
11162
+ if (state == null || state === "run" || state === "only") {
11163
+ return "pending";
11164
+ }
11165
+ if (state === "fail") {
11166
+ return "failed";
11167
+ }
11168
+ if (state === "pass") {
11169
+ return "passed";
11170
+ }
11171
+ throw new Error(`Unknown suite state: ${state}`);
11172
+ }
11173
+
10452
11174
  function isAggregateError(err) {
10453
11175
  if (typeof AggregateError !== "undefined" && err instanceof AggregateError) {
10454
11176
  return true;
@@ -10630,6 +11352,127 @@ class StateManager {
10630
11352
  }
10631
11353
  }
10632
11354
 
11355
+ class TestRun {
11356
+ constructor(vitest) {
11357
+ this.vitest = vitest;
11358
+ }
11359
+ async start(specifications) {
11360
+ const filepaths = specifications.map((spec) => spec.moduleId);
11361
+ this.vitest.state.collectPaths(filepaths);
11362
+ await this.vitest.report("onPathsCollected", Array.from(new Set(filepaths)));
11363
+ await this.vitest.report("onSpecsCollected", specifications.map((spec) => spec.toJSON()));
11364
+ await this.vitest.report("onTestRunStart", [...specifications]);
11365
+ }
11366
+ async enqueued(project, file) {
11367
+ this.vitest.state.collectFiles(project, [file]);
11368
+ const testModule = this.vitest.state.getReportedEntity(file);
11369
+ await this.vitest.report("onTestModuleQueued", testModule);
11370
+ }
11371
+ async collected(project, files) {
11372
+ this.vitest.state.collectFiles(project, files);
11373
+ await Promise.all([
11374
+ this.vitest.report("onCollected", files),
11375
+ ...files.map((file) => {
11376
+ const testModule = this.vitest.state.getReportedEntity(file);
11377
+ return this.vitest.report("onTestModuleCollected", testModule);
11378
+ })
11379
+ ]);
11380
+ }
11381
+ async log(log) {
11382
+ this.vitest.state.updateUserLog(log);
11383
+ await this.vitest.report("onUserConsoleLog", log);
11384
+ }
11385
+ async updated(update, events) {
11386
+ this.vitest.state.updateTasks(update);
11387
+ await this.vitest.report("onTaskUpdate", update);
11388
+ for (const [id, event] of events) {
11389
+ await this.reportEvent(id, event).catch((error) => {
11390
+ this.vitest.state.catchError(serializeError(error), "Unhandled Reporter Error");
11391
+ });
11392
+ }
11393
+ }
11394
+ async end(specifications, errors, coverage) {
11395
+ const modules = specifications.map((spec) => spec.testModule).filter((s) => s != null);
11396
+ const files = modules.map((m) => m.task);
11397
+ const state = this.vitest.isCancelling ? "interrupted" : process.exitCode ? "failed" : "passed";
11398
+ try {
11399
+ await Promise.all([
11400
+ this.vitest.report("onTestRunEnd", modules, [...errors], state),
11401
+ // TODO: in a perfect world, the coverage should be done in parallel to `onFinished`
11402
+ this.vitest.report("onFinished", files, errors, coverage)
11403
+ ]);
11404
+ } finally {
11405
+ if (coverage) {
11406
+ await this.vitest.report("onCoverage", coverage);
11407
+ }
11408
+ }
11409
+ }
11410
+ async reportEvent(id, event) {
11411
+ const task = this.vitest.state.idMap.get(id);
11412
+ const entity = task && this.vitest.state.getReportedEntity(task);
11413
+ assert$1(task && entity, `Entity must be found for task ${task?.name || id}`);
11414
+ if (event === "suite-prepare" && entity.type === "suite") {
11415
+ return await this.vitest.report("onTestSuiteReady", entity);
11416
+ }
11417
+ if (event === "suite-prepare" && entity.type === "module") {
11418
+ return await this.vitest.report("onTestModuleStart", entity);
11419
+ }
11420
+ if (event === "suite-finished") {
11421
+ assert$1(entity.type === "suite" || entity.type === "module", "Entity type must be suite or module");
11422
+ if (entity.state() === "skipped") {
11423
+ await this.reportChildren(entity.children);
11424
+ } else {
11425
+ for (const test of entity.children.tests("skipped")) {
11426
+ if (test.task.result?.pending) {
11427
+ continue;
11428
+ }
11429
+ await this.vitest.report("onTestCaseReady", test);
11430
+ await this.vitest.report("onTestCaseResult", test);
11431
+ }
11432
+ }
11433
+ if (entity.type === "module") {
11434
+ await this.vitest.report("onTestModuleEnd", entity);
11435
+ } else {
11436
+ await this.vitest.report("onTestSuiteResult", entity);
11437
+ }
11438
+ return;
11439
+ }
11440
+ if (event === "test-prepare" && entity.type === "test") {
11441
+ return await this.vitest.report("onTestCaseReady", entity);
11442
+ }
11443
+ if (event === "test-finished" && entity.type === "test") {
11444
+ return await this.vitest.report("onTestCaseResult", entity);
11445
+ }
11446
+ if (event.startsWith("before-hook") || event.startsWith("after-hook")) {
11447
+ const isBefore = event.startsWith("before-hook");
11448
+ const hook = entity.type === "test" ? {
11449
+ name: isBefore ? "beforeEach" : "afterEach",
11450
+ entity
11451
+ } : {
11452
+ name: isBefore ? "beforeAll" : "afterAll",
11453
+ entity
11454
+ };
11455
+ if (event.endsWith("-start")) {
11456
+ await this.vitest.report("onHookStart", hook);
11457
+ } else {
11458
+ await this.vitest.report("onHookEnd", hook);
11459
+ }
11460
+ }
11461
+ }
11462
+ async reportChildren(children) {
11463
+ for (const child of children) {
11464
+ if (child.type === "test") {
11465
+ await this.vitest.report("onTestCaseReady", child);
11466
+ await this.vitest.report("onTestCaseResult", child);
11467
+ } else {
11468
+ await this.vitest.report("onTestSuiteReady", child);
11469
+ await this.reportChildren(child.children);
11470
+ await this.vitest.report("onTestSuiteResult", child);
11471
+ }
11472
+ }
11473
+ }
11474
+ }
11475
+
10633
11476
  class VitestWatcher {
10634
11477
  constructor(vitest) {
10635
11478
  this.vitest = vitest;
@@ -10839,13 +11682,12 @@ async function resolveWorkspace(vitest, cliOptions, workspaceConfigPath, workspa
10839
11682
  const concurrent = limitConcurrency(nodeos__default.availableParallelism?.() || nodeos__default.cpus().length || 5);
10840
11683
  projectConfigs.forEach((options, index) => {
10841
11684
  const configRoot = workspaceConfigPath ? dirname(workspaceConfigPath) : vitest.config.root;
10842
- const configFile = typeof options.extends === "string" ? resolve(configRoot, options.extends) : false;
10843
- const rootOptions = options.extends === true ? vitest._options : {};
11685
+ const configFile = typeof options.extends === "string" ? resolve(configRoot, options.extends) : options.extends === true ? vitest.vite.config.configFile || false : false;
10844
11686
  const root = options.root ? resolve(configRoot, options.root) : vitest.config.root;
10845
11687
  projectPromises.push(concurrent(() => initializeProject(
10846
11688
  index,
10847
11689
  vitest,
10848
- mergeConfig(rootOptions, { ...options, root, configFile })
11690
+ { ...options, root, configFile }
10849
11691
  )));
10850
11692
  });
10851
11693
  for (const path of fileProjects) {
@@ -11178,6 +12020,8 @@ class Vitest {
11178
12020
  vitenode = void 0;
11179
12021
  /** @internal */
11180
12022
  runner = void 0;
12023
+ /** @internal */
12024
+ _testRun = void 0;
11181
12025
  isFirstRun = true;
11182
12026
  restartsCount = 0;
11183
12027
  specifications;
@@ -11262,6 +12106,7 @@ class Vitest {
11262
12106
  this._workspaceConfigPath = void 0;
11263
12107
  this.coverageProvider = void 0;
11264
12108
  this.runningPromise = void 0;
12109
+ this.coreWorkspaceProject = void 0;
11265
12110
  this.specifications.clearCache();
11266
12111
  this._onUserTestsRerun = [];
11267
12112
  const resolved = resolveConfig(this.mode, options, server.config, this.logger);
@@ -11270,6 +12115,7 @@ class Vitest {
11270
12115
  this._state = new StateManager();
11271
12116
  this._cache = new VitestCache(this.version);
11272
12117
  this._snapshot = new SnapshotManager({ ...resolved.snapshotOptions });
12118
+ this._testRun = new TestRun(this);
11273
12119
  if (this.config.watch) {
11274
12120
  this.watcher.registerWatcher();
11275
12121
  }
@@ -11455,43 +12301,35 @@ class Vitest {
11455
12301
  const { files, errors, coverages } = await readBlobs(this.version, directory || this.config.mergeReports, this.projects);
11456
12302
  await this.report("onInit", this);
11457
12303
  await this.report("onPathsCollected", files.flatMap((f) => f.filepath));
11458
- const workspaceSpecs = /* @__PURE__ */ new Map();
12304
+ const specifications = [];
11459
12305
  for (const file of files) {
11460
12306
  const project = this.getProjectByName(file.projectName || "");
11461
- const specs = workspaceSpecs.get(project) || [];
11462
- specs.push(file);
11463
- workspaceSpecs.set(project, specs);
11464
- }
11465
- for (const [project, files2] of workspaceSpecs) {
11466
- const filepaths = files2.map((f) => f.filepath);
11467
- this.state.clearFiles(project, filepaths);
11468
- files2.forEach((file) => {
11469
- file.logs?.forEach((log) => this.state.updateUserLog(log));
11470
- });
11471
- this.state.collectFiles(project, files2);
12307
+ const specification = project.createSpecification(file.filepath, void 0, file.pool);
12308
+ specifications.push(specification);
11472
12309
  }
11473
- await this.report("onCollected", files).catch(noop);
12310
+ await this.report("onSpecsCollected", specifications.map((spec) => spec.toJSON()));
12311
+ await this._testRun.start(specifications).catch(noop);
11474
12312
  for (const file of files) {
12313
+ const project = this.getProjectByName(file.projectName || "");
12314
+ await this._testRun.enqueued(project, file).catch(noop);
12315
+ await this._testRun.collected(project, [file]).catch(noop);
11475
12316
  const logs = [];
11476
- const taskPacks = [];
11477
- const tasks = getTasks(file);
11478
- for (const task of tasks) {
12317
+ const { packs, events } = convertTasksToEvents(file, (task) => {
11479
12318
  if (task.logs) {
11480
12319
  logs.push(...task.logs);
11481
12320
  }
11482
- taskPacks.push([task.id, task.result, task.meta]);
11483
- }
12321
+ });
11484
12322
  logs.sort((log1, log2) => log1.time - log2.time);
11485
12323
  for (const log of logs) {
11486
- await this.report("onUserConsoleLog", log).catch(noop);
12324
+ await this._testRun.log(log).catch(noop);
11487
12325
  }
11488
- await this.report("onTaskUpdate", taskPacks).catch(noop);
12326
+ await this._testRun.updated(packs, events).catch(noop);
11489
12327
  }
11490
12328
  if (hasFailed(files)) {
11491
12329
  process.exitCode = 1;
11492
12330
  }
11493
12331
  this._checkUnhandledErrors(errors);
11494
- await this.report("onFinished", files, errors);
12332
+ await this._testRun.end(specifications, errors).catch(noop);
11495
12333
  await this.initCoverageProvider();
11496
12334
  await this.coverageProvider?.mergeReports?.(coverages);
11497
12335
  return {
@@ -11537,12 +12375,16 @@ class Vitest {
11537
12375
  this.filenamePattern = filters && filters?.length > 0 ? filters : void 0;
11538
12376
  const files = await this.specifications.getRelevantTestSpecifications(filters);
11539
12377
  if (!files.length) {
12378
+ const throwAnError = !this.config.watch || !(this.config.changed || this.config.related?.length);
12379
+ await this._testRun.start([]);
11540
12380
  const coverage = await this.coverageProvider?.generateCoverage?.({ allTestsRun: true });
11541
- await this.reportCoverage(coverage, true);
11542
- this.logger.printNoTestFound(filters);
11543
- if (!this.config.watch || !(this.config.changed || this.config.related?.length)) {
12381
+ if (throwAnError) {
11544
12382
  const exitCode = this.config.passWithNoTests ? 0 : 1;
11545
12383
  process.exitCode = exitCode;
12384
+ }
12385
+ await this._testRun.end([], [], coverage);
12386
+ await this.reportCoverage(coverage, true);
12387
+ if (throwAnError) {
11546
12388
  throw new FilesNotFoundError(this.mode);
11547
12389
  }
11548
12390
  }
@@ -11627,10 +12469,7 @@ class Vitest {
11627
12469
  return result;
11628
12470
  }
11629
12471
  async runFiles(specs, allTestsRun) {
11630
- const filepaths = specs.map((spec) => spec.moduleId);
11631
- this.state.collectPaths(filepaths);
11632
- await this.report("onPathsCollected", filepaths);
11633
- await this.report("onSpecsCollected", specs.map((spec) => spec.toJSON()));
12472
+ await this._testRun.start(specs);
11634
12473
  await this.runningPromise;
11635
12474
  this._onCancelListeners = [];
11636
12475
  this.isCancelling = false;
@@ -11663,11 +12502,10 @@ class Vitest {
11663
12502
  unhandledErrors: this.state.getUnhandledErrors()
11664
12503
  };
11665
12504
  } finally {
11666
- const files = Array.from(new Set(specs.map((spec) => spec.moduleId)));
11667
- const errors = this.state.getUnhandledErrors();
11668
12505
  const coverage = await this.coverageProvider?.generateCoverage({ allTestsRun });
12506
+ const errors = this.state.getUnhandledErrors();
11669
12507
  this._checkUnhandledErrors(errors);
11670
- await this.report("onFinished", this.state.getFiles(files), errors, coverage);
12508
+ await this._testRun.end(specs, errors, coverage);
11671
12509
  await this.reportCoverage(coverage, allTestsRun);
11672
12510
  }
11673
12511
  })().finally(() => {
@@ -11993,7 +12831,7 @@ class Vitest {
11993
12831
  console.warn(`close timed out after ${this.config.teardownTimeout}ms`);
11994
12832
  this.state.getProcessTimeoutCauses().forEach((cause) => console.warn(cause));
11995
12833
  if (!this.pool) {
11996
- const runningServers = [this.vite, ...this.resolvedProjects.map((p) => p.vite)].filter(Boolean).length;
12834
+ const runningServers = [this._vite, ...this.resolvedProjects.map((p) => p._vite)].filter(Boolean).length;
11997
12835
  if (runningServers === 1) {
11998
12836
  console.warn("Tests closed successfully but something prevents Vite server from exiting");
11999
12837
  } else if (runningServers > 1) {
@@ -12001,7 +12839,9 @@ class Vitest {
12001
12839
  } else {
12002
12840
  console.warn("Tests closed successfully but something prevents the main process from exiting");
12003
12841
  }
12004
- console.warn('You can try to identify the cause by enabling "hanging-process" reporter. See https://vitest.dev/config/#reporters');
12842
+ if (!this.reporters.some((r) => r instanceof HangingProcessReporter)) {
12843
+ console.warn('You can try to identify the cause by enabling "hanging-process" reporter. See https://vitest.dev/config/#reporters');
12844
+ }
12005
12845
  }
12006
12846
  process.exit();
12007
12847
  });
@@ -12121,6 +12961,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
12121
12961
  if (testConfig.ui && testConfig.open) {
12122
12962
  open = testConfig.uiBase ?? "/__vitest__/";
12123
12963
  }
12964
+ const conditions = getDefaultServerConditions();
12124
12965
  const config = {
12125
12966
  root: viteConfig.test?.root || options.root,
12126
12967
  esbuild: viteConfig.esbuild === false ? false : {
@@ -12135,7 +12976,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
12135
12976
  // setting this option can bypass that and fallback to cjs version
12136
12977
  mainFields: [],
12137
12978
  alias: testConfig.alias,
12138
- conditions: ["node"]
12979
+ conditions
12139
12980
  },
12140
12981
  server: {
12141
12982
  ...testConfig.api,
@@ -12164,7 +13005,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
12164
13005
  // by default Vite resolves `module` field, which not always a native ESM module
12165
13006
  // setting this option can bypass that and fallback to cjs version
12166
13007
  mainFields: [],
12167
- conditions: ["node"]
13008
+ conditions
12168
13009
  }
12169
13010
  }
12170
13011
  },
@@ -12189,11 +13030,6 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
12189
13030
  }
12190
13031
  );
12191
13032
  config.customLogger = silenceImportViteIgnoreWarning(config.customLogger);
12192
- if (userConfig.coverage?.enabled && !userConfig.coverage.exclude && userConfig.include && config.test) {
12193
- config.test.coverage = {
12194
- exclude: [...coverageConfigDefaults.exclude, ...userConfig.include]
12195
- };
12196
- }
12197
13033
  if (viteConfig.ssr?.noExternal !== true) {
12198
13034
  const inline = testConfig.server?.deps?.inline;
12199
13035
  if (inline === true) {
@@ -12809,7 +13645,7 @@ function formatCollectedAsJSON(files) {
12809
13645
  const results = [];
12810
13646
  files.forEach((file) => {
12811
13647
  for (const test of file.children.allTests()) {
12812
- if (test.skipped()) {
13648
+ if (test.result().state === "skipped") {
12813
13649
  continue;
12814
13650
  }
12815
13651
  const result = {
@@ -12831,7 +13667,7 @@ function formatCollectedAsString(testModules) {
12831
13667
  const results = [];
12832
13668
  testModules.forEach((testModule) => {
12833
13669
  for (const test of testModule.children.allTests()) {
12834
- if (test.skipped()) {
13670
+ if (test.result().state === "skipped") {
12835
13671
  continue;
12836
13672
  }
12837
13673
  const fullName = `${test.module.task.name} > ${test.fullName}`;
@@ -12870,4 +13706,4 @@ var cliApi = /*#__PURE__*/Object.freeze({
12870
13706
  startVitest: startVitest
12871
13707
  });
12872
13708
 
12873
- export { FilesNotFoundError as F, GitNotFoundError as G, Vitest as V, VitestPlugin as a, VitestPackageInstaller as b, createVitest as c, registerConsoleShortcuts as d, createViteLogger as e, cliApi as f, resolveFsAllow as r, startVitest as s };
13709
+ export { FilesNotFoundError as F, GitNotFoundError as G, TestModule as T, Vitest as V, VitestPlugin as a, VitestPackageInstaller as b, createVitest as c, registerConsoleShortcuts as d, createViteLogger as e, cliApi as f, resolveFsAllow as r, startVitest as s };