vitest 3.0.0-beta.4 → 3.0.1

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 (57) hide show
  1. package/dist/browser.d.ts +2 -2
  2. package/dist/browser.js +1 -1
  3. package/dist/chunks/{base.BJ8KO-VX.js → base.gZAre3Yy.js} +3 -3
  4. package/dist/chunks/{cac.BAYqQ2aM.js → cac.Davy6Tyx.js} +24 -24
  5. package/dist/chunks/{cli-api.Dhl34Trr.js → cli-api.DO-hp2Kx.js} +1031 -162
  6. package/dist/chunks/{console.CN7AiMGV.js → console.BxE0RUCr.js} +3 -3
  7. package/dist/chunks/{creator.Ot9GlSGw.js → creator.B8v1wNyQ.js} +3 -3
  8. package/dist/chunks/{execute.BMOaRArH.js → execute.4vt3NSmG.js} +3 -4
  9. package/dist/chunks/global.CnI8_G5V.d.ts +133 -0
  10. package/dist/chunks/{globals.C5RQxaV3.js → globals.BSNBk3vE.js} +2 -2
  11. package/dist/chunks/{index.BQbxGbG9.js → index.Bf4FgyZN.js} +1 -1
  12. package/dist/chunks/{index.BJDntFik.js → index.Bh7wTRhh.js} +8 -8
  13. package/dist/chunks/{index.B2M9nD1V.js → index.C2XSkjNu.js} +5 -5
  14. package/dist/chunks/{index.DQboAxJm.js → index.DfqWks-F.js} +2 -1
  15. package/dist/chunks/{index.CAueP3cK.js → index.DyQPL4DO.js} +200 -945
  16. package/dist/chunks/{index.68735LiX.js → index.TH3f4LSA.js} +2 -2
  17. package/dist/chunks/{index.K90BXFOx.js → index.cYxyd29h.js} +12 -12
  18. package/dist/chunks/{inspector.DKLceBVD.js → inspector.CU9GlB9I.js} +1 -1
  19. package/dist/chunks/{reporters.Dcdq51WE.d.ts → reporters.Y8BYiXBN.d.ts} +340 -239
  20. package/dist/chunks/{resolveConfig.kZFMjKCQ.js → resolveConfig.DATSOo7x.js} +150 -65
  21. package/dist/chunks/{rpc.C3q9uwRX.js → rpc.Bf456uf4.js} +1 -2
  22. package/dist/chunks/{runBaseTests.URiUrnWK.js → runBaseTests.Ba8jtu6O.js} +8 -8
  23. package/dist/chunks/{setup-common.D0zLenuv.js → setup-common.jLbIuaww.js} +1 -1
  24. package/dist/chunks/{RandomSequencer.DB__To1b.js → typechecker.ChNaIV36.js} +62 -115
  25. package/dist/chunks/{utils.yHKcm4dz.js → utils.DJWL04yX.js} +1 -1
  26. package/dist/chunks/{vi.Da_PT3Vw.js → vi.CjhMlMwf.js} +6 -6
  27. package/dist/chunks/{vite.DzluO1Kj.d.ts → vite.CQ0dHgkN.d.ts} +1 -1
  28. package/dist/chunks/{vm.DrFVeTXo.js → vm.CUw7ChSp.js} +5 -5
  29. package/dist/chunks/{worker.BIVMnzXw.d.ts → worker.B1y96qmv.d.ts} +1 -1
  30. package/dist/chunks/{worker.Hz_LAzfd.d.ts → worker.CIpff8Eg.d.ts} +2 -4
  31. package/dist/cli.js +1 -1
  32. package/dist/config.cjs +1 -1
  33. package/dist/config.d.ts +3 -3
  34. package/dist/config.js +1 -1
  35. package/dist/coverage.d.ts +1 -1
  36. package/dist/coverage.js +12 -11
  37. package/dist/environments.js +1 -1
  38. package/dist/execute.d.ts +1 -1
  39. package/dist/execute.js +1 -1
  40. package/dist/index.d.ts +17 -118
  41. package/dist/index.js +2 -2
  42. package/dist/node.d.ts +11 -8
  43. package/dist/node.js +27 -25
  44. package/dist/reporters.d.ts +1 -1
  45. package/dist/reporters.js +4 -6
  46. package/dist/runners.d.ts +1 -0
  47. package/dist/runners.js +10 -10
  48. package/dist/worker.js +5 -5
  49. package/dist/workers/forks.js +2 -2
  50. package/dist/workers/runVmTests.js +7 -7
  51. package/dist/workers/threads.js +2 -2
  52. package/dist/workers/vmForks.js +3 -3
  53. package/dist/workers/vmThreads.js +3 -3
  54. package/dist/workers.d.ts +2 -2
  55. package/dist/workers.js +8 -8
  56. package/package.json +17 -17
  57. package/dist/chunks/types.BOjykUpq.d.ts +0 -27
@@ -1,17 +1,17 @@
1
1
  import fs, { existsSync, readFileSync, promises } from 'node:fs';
2
2
  import { getTests, getTestName, hasFailed, getFullName, getSuites, getTasks } from '@vitest/runner/utils';
3
3
  import * as pathe from 'pathe';
4
- import { extname, relative, normalize, resolve, dirname } from 'pathe';
4
+ import { relative, normalize, resolve, dirname } from 'pathe';
5
5
  import c from 'tinyrainbow';
6
- import { d as divider, F as F_POINTER, t as truncateString, w as withLabel, f as formatProjectName, a as formatTimeString, g as getStateSymbol, b as taskFail, c as F_RIGHT, e as F_CHECK, r as renderSnapshotSummary, p as padSummaryTitle, h as getStateString$1, i as formatTime, j as countTestErrors, k as F_TREE_NODE_END, l as F_TREE_NODE_MIDDLE } from './utils.yHKcm4dz.js';
6
+ import { d as divider, F as F_POINTER, t as truncateString, f as formatTimeString, g as getStateSymbol, a as formatProjectName, b as taskFail, c as F_RIGHT, e as F_CHECK, w as withLabel, r as renderSnapshotSummary, p as padSummaryTitle, h as getStateString$1, i as formatTime, j as countTestErrors, k as F_TREE_NODE_END, l as F_TREE_NODE_MIDDLE } from './utils.DJWL04yX.js';
7
7
  import { stripVTControlCharacters } from 'node:util';
8
- import { highlight, isPrimitive, inspect, positionToOffset, lineSplitRE, toArray, notNullish } from '@vitest/utils';
8
+ import { isPrimitive, inspect, positionToOffset, lineSplitRE, toArray, notNullish } from '@vitest/utils';
9
9
  import { performance as performance$1 } from 'node:perf_hooks';
10
10
  import { parseErrorStacktrace, parseStacktrace } from '@vitest/utils/source-map';
11
- import { T as TypeCheckError, R as RandomSequencer, g as getOutputFile, i as isTTY } from './RandomSequencer.DB__To1b.js';
11
+ import { T as TypeCheckError, g as getOutputFile, i as isTTY, h as hasFailedSnapshot } from './typechecker.ChNaIV36.js';
12
12
  import { mkdir, writeFile, readdir, stat, readFile } from 'node:fs/promises';
13
- import { Writable } from 'node:stream';
14
13
  import { Console } from 'node:console';
14
+ import { Writable } from 'node:stream';
15
15
  import { createRequire } from 'node:module';
16
16
  import { hostname } from 'node:os';
17
17
 
@@ -94,7 +94,7 @@ const parse = (text, reviver) => {
94
94
  */
95
95
  const stringify = (value, replacer, space) => {
96
96
  const $ = replacer && typeof replacer === object ?
97
- (k, v) => (k === '' || -1 < replacer.indexOf(k) ? v : void 0) :
97
+ (k, v) => (k === '' || -1 < replacer.indexOf(k) ? v : undefined) :
98
98
  (replacer || noop);
99
99
  const known = new Map;
100
100
  const input = [];
@@ -122,25 +122,6 @@ const stringify = (value, replacer, space) => {
122
122
  }
123
123
  };
124
124
 
125
- const HIGHLIGHT_SUPPORTED_EXTS = new Set(
126
- ["js", "ts"].flatMap((lang) => [
127
- `.${lang}`,
128
- `.m${lang}`,
129
- `.c${lang}`,
130
- `.${lang}x`,
131
- `.m${lang}x`,
132
- `.c${lang}x`
133
- ])
134
- );
135
- function highlightCode(id, source, colors) {
136
- const ext = extname(id);
137
- if (!HIGHLIGHT_SUPPORTED_EXTS.has(ext)) {
138
- return source;
139
- }
140
- const isJsx = ext.endsWith("x");
141
- return highlight(source, { jsx: isJsx, colors: c });
142
- }
143
-
144
125
  function capturePrintError(error, ctx, options) {
145
126
  let output = "";
146
127
  const writable = new Writable({
@@ -149,14 +130,39 @@ function capturePrintError(error, ctx, options) {
149
130
  callback();
150
131
  }
151
132
  });
152
- const logger = new Logger(ctx, writable, writable);
153
- const result = logger.printError(error, {
133
+ const console = new Console(writable);
134
+ const logger = {
135
+ error: console.error.bind(console),
136
+ highlight: ctx.logger.highlight.bind(ctx.logger)
137
+ };
138
+ const result = printError(error, ctx, logger, {
154
139
  showCodeFrame: false,
155
140
  ...options
156
141
  });
157
142
  return { nearest: result?.nearest, output };
158
143
  }
159
- function printError(error, project, options) {
144
+ function printError(error, ctx, logger, options) {
145
+ const project = options.project ?? ctx.coreWorkspaceProject ?? ctx.projects[0];
146
+ return printErrorInner(error, project, {
147
+ logger,
148
+ type: options.type,
149
+ showCodeFrame: options.showCodeFrame,
150
+ screenshotPaths: options.screenshotPaths,
151
+ printProperties: options.verbose,
152
+ parseErrorStacktrace(error2) {
153
+ if (options.task?.file.pool === "browser" && project.browser) {
154
+ return project.browser.parseErrorStacktrace(error2, {
155
+ ignoreStackEntries: options.fullStack ? [] : undefined
156
+ });
157
+ }
158
+ return parseErrorStacktrace(error2, {
159
+ frameFilter: project.config.onStackTrace,
160
+ ignoreStackEntries: options.fullStack ? [] : undefined
161
+ });
162
+ }
163
+ });
164
+ }
165
+ function printErrorInner(error, project, options) {
160
166
  const { showCodeFrame = true, type, printProperties = true } = options;
161
167
  const logger = options.logger;
162
168
  let e = error;
@@ -212,7 +218,9 @@ Failure screenshot${length > 1 ? "s" : ""}:`);
212
218
  ].filter(Boolean).join("\n"));
213
219
  }
214
220
  if (e.diff) {
215
- displayDiff(e.diff, logger.console);
221
+ logger.error(`
222
+ ${e.diff}
223
+ `);
216
224
  }
217
225
  if (e.frame) {
218
226
  logger.error(c.yellow(e.frame));
@@ -263,7 +271,7 @@ Failure screenshot${length > 1 ? "s" : ""}:`);
263
271
  }
264
272
  if (typeof e.cause === "object" && e.cause && "name" in e.cause) {
265
273
  e.cause.name = `Caused by: ${e.cause.name}`;
266
- printError(e.cause, project, {
274
+ printErrorInner(e.cause, project, {
267
275
  showCodeFrame: false,
268
276
  logger: options.logger,
269
277
  parseErrorStacktrace: options.parseErrorStacktrace
@@ -361,13 +369,6 @@ function printModuleWarningForSourceCode(logger, path) {
361
369
  )
362
370
  );
363
371
  }
364
- function displayDiff(diff, console) {
365
- if (diff) {
366
- console.error(`
367
- ${diff}
368
- `);
369
- }
370
- }
371
372
  function printErrorMessage(error, logger) {
372
373
  const errorName = error.name || error.nameStr || "Unknown Error";
373
374
  if (!error.message) {
@@ -458,284 +459,6 @@ function lineNo(no = "") {
458
459
  return c.gray(`${String(no).padStart(3, " ")}| `);
459
460
  }
460
461
 
461
- const PAD = " ";
462
- const ESC$1 = "\x1B[";
463
- const ERASE_DOWN = `${ESC$1}J`;
464
- const ERASE_SCROLLBACK = `${ESC$1}3J`;
465
- const CURSOR_TO_START = `${ESC$1}1;1H`;
466
- const HIDE_CURSOR = `${ESC$1}?25l`;
467
- const SHOW_CURSOR = `${ESC$1}?25h`;
468
- const CLEAR_SCREEN = "\x1Bc";
469
- class Logger {
470
- constructor(ctx, outputStream = process.stdout, errorStream = process.stderr) {
471
- this.ctx = ctx;
472
- this.outputStream = outputStream;
473
- this.errorStream = errorStream;
474
- this.console = new Console({ stdout: outputStream, stderr: errorStream });
475
- this._highlights.clear();
476
- this.addCleanupListeners();
477
- this.registerUnhandledRejection();
478
- this.outputStream.write(HIDE_CURSOR);
479
- }
480
- _clearScreenPending;
481
- _highlights = /* @__PURE__ */ new Map();
482
- cleanupListeners = [];
483
- console;
484
- log(...args) {
485
- this._clearScreen();
486
- this.console.log(...args);
487
- }
488
- error(...args) {
489
- this._clearScreen();
490
- this.console.error(...args);
491
- }
492
- warn(...args) {
493
- this._clearScreen();
494
- this.console.warn(...args);
495
- }
496
- clearFullScreen(message = "") {
497
- if (!this.ctx.config.clearScreen) {
498
- this.console.log(message);
499
- return;
500
- }
501
- if (message) {
502
- this.console.log(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}${message}`);
503
- } else {
504
- this.outputStream.write(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}`);
505
- }
506
- }
507
- clearScreen(message, force = false) {
508
- if (!this.ctx.config.clearScreen) {
509
- this.console.log(message);
510
- return;
511
- }
512
- this._clearScreenPending = message;
513
- if (force) {
514
- this._clearScreen();
515
- }
516
- }
517
- _clearScreen() {
518
- if (this._clearScreenPending == null) {
519
- return;
520
- }
521
- const log = this._clearScreenPending;
522
- this._clearScreenPending = void 0;
523
- this.console.log(`${CURSOR_TO_START}${ERASE_DOWN}${log}`);
524
- }
525
- printError(err, options = {}) {
526
- const { fullStack = false, type } = options;
527
- const project = options.project ?? this.ctx.coreWorkspaceProject ?? this.ctx.projects[0];
528
- return printError(err, project, {
529
- type,
530
- showCodeFrame: options.showCodeFrame ?? true,
531
- logger: this,
532
- printProperties: options.verbose,
533
- screenshotPaths: options.screenshotPaths,
534
- parseErrorStacktrace: (error) => {
535
- if (options.task?.file.pool === "browser" && project.browser) {
536
- return project.browser.parseErrorStacktrace(error, {
537
- ignoreStackEntries: fullStack ? [] : void 0
538
- });
539
- }
540
- return parseErrorStacktrace(error, {
541
- frameFilter: project.config.onStackTrace,
542
- ignoreStackEntries: fullStack ? [] : void 0
543
- });
544
- }
545
- });
546
- }
547
- clearHighlightCache(filename) {
548
- if (filename) {
549
- this._highlights.delete(filename);
550
- } else {
551
- this._highlights.clear();
552
- }
553
- }
554
- highlight(filename, source) {
555
- if (this._highlights.has(filename)) {
556
- return this._highlights.get(filename);
557
- }
558
- const code = highlightCode(filename, source);
559
- this._highlights.set(filename, code);
560
- return code;
561
- }
562
- printNoTestFound(filters) {
563
- const config = this.ctx.config;
564
- const comma = c.dim(", ");
565
- if (filters?.length) {
566
- this.console.error(c.dim("filter: ") + c.yellow(filters.join(comma)));
567
- }
568
- const projectsFilter = toArray(config.project);
569
- if (projectsFilter.length) {
570
- this.console.error(
571
- c.dim("projects: ") + c.yellow(projectsFilter.join(comma))
572
- );
573
- }
574
- this.ctx.projects.forEach((project) => {
575
- const config2 = project.config;
576
- const output = project.isRootProject() || !project.name ? "" : `[${project.name}]`;
577
- if (output) {
578
- this.console.error(c.bgCyan(`${output} Config`));
579
- }
580
- if (config2.include) {
581
- this.console.error(
582
- c.dim("include: ") + c.yellow(config2.include.join(comma))
583
- );
584
- }
585
- if (config2.exclude) {
586
- this.console.error(
587
- c.dim("exclude: ") + c.yellow(config2.exclude.join(comma))
588
- );
589
- }
590
- if (config2.typecheck.enabled) {
591
- this.console.error(
592
- c.dim("typecheck include: ") + c.yellow(config2.typecheck.include.join(comma))
593
- );
594
- this.console.error(
595
- c.dim("typecheck exclude: ") + c.yellow(config2.typecheck.exclude.join(comma))
596
- );
597
- }
598
- });
599
- if (config.watch && (config.changed || config.related?.length)) {
600
- this.log(`No affected ${config.mode} files found
601
- `);
602
- } else {
603
- if (config.passWithNoTests) {
604
- this.log(`No ${config.mode} files found, exiting with code 0
605
- `);
606
- } else {
607
- this.error(
608
- c.red(`
609
- No ${config.mode} files found, exiting with code 1`)
610
- );
611
- }
612
- }
613
- }
614
- printBanner() {
615
- this.log();
616
- const color = this.ctx.config.watch ? "blue" : "cyan";
617
- const mode = this.ctx.config.watch ? "DEV" : "RUN";
618
- this.log(withLabel(color, mode, `v${this.ctx.version} `) + c.gray(this.ctx.config.root));
619
- if (this.ctx.config.sequence.sequencer === RandomSequencer) {
620
- this.log(PAD + c.gray(`Running tests with seed "${this.ctx.config.sequence.seed}"`));
621
- }
622
- if (this.ctx.config.ui) {
623
- const host = this.ctx.config.api?.host || "localhost";
624
- const port = this.ctx.server.config.server.port;
625
- const base = this.ctx.config.uiBase;
626
- this.log(PAD + c.dim(c.green(`UI started at http://${host}:${c.bold(port)}${base}`)));
627
- } else if (this.ctx.config.api?.port) {
628
- const resolvedUrls = this.ctx.server.resolvedUrls;
629
- const fallbackUrl = `http://${this.ctx.config.api.host || "localhost"}:${this.ctx.config.api.port}`;
630
- const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0] ?? fallbackUrl;
631
- this.log(PAD + c.dim(c.green(`API started at ${new URL("/", origin)}`)));
632
- }
633
- if (this.ctx.coverageProvider) {
634
- this.log(PAD + c.dim("Coverage enabled with ") + c.yellow(this.ctx.coverageProvider.name));
635
- }
636
- if (this.ctx.config.standalone) {
637
- this.log(c.yellow(`
638
- Vitest is running in standalone mode. Edit a test file to rerun tests.`));
639
- } else {
640
- this.log();
641
- }
642
- }
643
- printBrowserBanner(project) {
644
- if (!project.browser) {
645
- return;
646
- }
647
- const resolvedUrls = project.browser.vite.resolvedUrls;
648
- const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
649
- if (!origin) {
650
- return;
651
- }
652
- const output = project.isRootProject() ? "" : formatProjectName(project.name);
653
- const provider = project.browser.provider.name;
654
- const providerString = provider === "preview" ? "" : ` by ${c.reset(c.bold(provider))}`;
655
- this.log(
656
- c.dim(
657
- `${output}Browser runner started${providerString} ${c.dim("at")} ${c.blue(new URL("/", origin))}
658
- `
659
- )
660
- );
661
- }
662
- printUnhandledErrors(errors) {
663
- const errorMessage = c.red(
664
- c.bold(
665
- `
666
- Vitest caught ${errors.length} unhandled error${errors.length > 1 ? "s" : ""} during the test run.
667
- This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.`
668
- )
669
- );
670
- this.error(c.red(divider(c.bold(c.inverse(" Unhandled Errors ")))));
671
- this.error(errorMessage);
672
- errors.forEach((err) => {
673
- this.printError(err, {
674
- fullStack: true,
675
- type: err.type || "Unhandled Error"
676
- });
677
- });
678
- this.error(c.red(divider()));
679
- }
680
- printSourceTypeErrors(errors) {
681
- const errorMessage = c.red(
682
- c.bold(
683
- `
684
- Vitest found ${errors.length} error${errors.length > 1 ? "s" : ""} not related to your test files.`
685
- )
686
- );
687
- this.log(c.red(divider(c.bold(c.inverse(" Source Errors ")))));
688
- this.log(errorMessage);
689
- errors.forEach((err) => {
690
- this.printError(err, { fullStack: true });
691
- });
692
- this.log(c.red(divider()));
693
- }
694
- getColumns() {
695
- return "columns" in this.outputStream ? this.outputStream.columns : 80;
696
- }
697
- onTerminalCleanup(listener) {
698
- this.cleanupListeners.push(listener);
699
- }
700
- addCleanupListeners() {
701
- const cleanup = () => {
702
- this.cleanupListeners.forEach((fn) => fn());
703
- this.outputStream.write(SHOW_CURSOR);
704
- };
705
- const onExit = (signal, exitCode) => {
706
- cleanup();
707
- if (process.exitCode === void 0) {
708
- process.exitCode = exitCode !== void 0 ? 128 + exitCode : Number(signal);
709
- }
710
- process.exit();
711
- };
712
- process.once("SIGINT", onExit);
713
- process.once("SIGTERM", onExit);
714
- process.once("exit", onExit);
715
- this.ctx.onClose(() => {
716
- process.off("SIGINT", onExit);
717
- process.off("SIGTERM", onExit);
718
- process.off("exit", onExit);
719
- cleanup();
720
- });
721
- }
722
- registerUnhandledRejection() {
723
- const onUnhandledRejection = (err) => {
724
- process.exitCode = 1;
725
- this.printError(err, {
726
- fullStack: true,
727
- type: "Unhandled Rejection"
728
- });
729
- this.error("\n\n");
730
- process.exit();
731
- };
732
- process.on("unhandledRejection", onUnhandledRejection);
733
- this.ctx.onClose(() => {
734
- process.off("unhandledRejection", onUnhandledRejection);
735
- });
736
- }
737
- }
738
-
739
462
  class BlobReporter {
740
463
  ctx;
741
464
  options;
@@ -855,12 +578,15 @@ ${blobs.map((b) => `- "${b.file}" uses v${b.version}`).join("\n")}`
855
578
  };
856
579
  }
857
580
 
858
- function hasFailedSnapshot(suite) {
859
- return getTests(suite).some((s) => {
860
- return s.result?.errors?.some(
861
- (e) => typeof e?.message === "string" && e.message.match(/Snapshot .* mismatched/)
862
- );
863
- });
581
+ class HangingProcessReporter {
582
+ whyRunning;
583
+ onInit() {
584
+ const _require = createRequire(import.meta.url);
585
+ this.whyRunning = _require("why-is-node-running");
586
+ }
587
+ onProcessTimeout() {
588
+ this.whyRunning?.();
589
+ }
864
590
  }
865
591
 
866
592
  const BADGE_PADDING = " ";
@@ -870,7 +596,7 @@ class BaseReporter {
870
596
  watchFilters;
871
597
  failedUnwatchedFiles = [];
872
598
  isTTY;
873
- ctx = void 0;
599
+ ctx = undefined;
874
600
  renderSucceed = false;
875
601
  verbose = false;
876
602
  _filesInWatchMode = /* @__PURE__ */ new Map();
@@ -894,7 +620,11 @@ class BaseReporter {
894
620
  }
895
621
  onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
896
622
  this.end = performance$1.now();
897
- this.reportSummary(files, errors);
623
+ if (!files.length && !errors.length) {
624
+ this.ctx.logger.printNoTestFound(this.ctx.filenamePattern);
625
+ } else {
626
+ this.reportSummary(files, errors);
627
+ }
898
628
  }
899
629
  onTaskUpdate(packs) {
900
630
  for (const pack of packs) {
@@ -1022,7 +752,7 @@ class BaseReporter {
1022
752
  const output = log.type === "stdout" ? this.ctx.logger.outputStream : this.ctx.logger.errorStream;
1023
753
  const write = (msg) => output.write(msg);
1024
754
  let headerText = "unknown test";
1025
- const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0;
755
+ const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : undefined;
1026
756
  if (task) {
1027
757
  headerText = getFullName(task, c.dim(" > "));
1028
758
  } else if (log.taskId && log.taskId !== "__vitest__unknown_test__") {
@@ -1142,7 +872,7 @@ class BaseReporter {
1142
872
  const failedTests = tests.filter((i) => i.result?.state === "fail");
1143
873
  const failedTotal = countTestErrors(failedSuites) + countTestErrors(failedTests);
1144
874
  let current = 1;
1145
- const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1)))}
875
+ const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, undefined, 1)))}
1146
876
  `);
1147
877
  if (failedSuites.length) {
1148
878
  this.error(`
@@ -1264,7 +994,7 @@ class WindowRenderer {
1264
994
  options;
1265
995
  streams;
1266
996
  buffer = [];
1267
- renderInterval = void 0;
997
+ renderInterval = undefined;
1268
998
  windowHeight = 0;
1269
999
  finished = false;
1270
1000
  cleanups = [];
@@ -1289,7 +1019,7 @@ class WindowRenderer {
1289
1019
  }
1290
1020
  start() {
1291
1021
  this.finished = false;
1292
- this.renderInterval = setInterval(() => this.flushBuffer(), this.options.interval);
1022
+ this.renderInterval = setInterval(() => this.flushBuffer(), this.options.interval).unref();
1293
1023
  }
1294
1024
  stop() {
1295
1025
  this.cleanups.splice(0).map((fn) => fn());
@@ -1387,88 +1117,23 @@ function getRenderedRowCount(rows, columns) {
1387
1117
  return count;
1388
1118
  }
1389
1119
 
1390
- class TaskParser {
1391
- ctx;
1392
- onInit(ctx) {
1393
- this.ctx = ctx;
1394
- }
1395
- onHookStart(_options) {
1396
- }
1397
- onHookEnd(_options) {
1398
- }
1399
- onTestStart(_test) {
1400
- }
1401
- onTestFinished(_test) {
1402
- }
1403
- onTestFilePrepare(_file) {
1404
- }
1405
- onTestFileFinished(_file) {
1406
- }
1407
- onTaskUpdate(packs) {
1408
- const startingTestFiles = [];
1409
- const finishedTestFiles = [];
1410
- const startingTests = [];
1411
- const finishedTests = [];
1412
- const startingHooks = [];
1413
- const endingHooks = [];
1414
- for (const pack of packs) {
1415
- const task = this.ctx.state.idMap.get(pack[0]);
1416
- if (task?.type === "suite" && "filepath" in task && task.result?.state) {
1417
- if (task?.result?.state === "run" || task?.result?.state === "queued") {
1418
- startingTestFiles.push(task);
1419
- } else {
1420
- for (const test of getTests(task)) {
1421
- if (!test.result || test.result?.state === "skip") {
1422
- finishedTests.push(test);
1423
- }
1424
- }
1425
- finishedTestFiles.push(task.file);
1426
- }
1427
- }
1428
- if (task?.type === "test") {
1429
- if (task.result?.state === "run" || task.result?.state === "queued") {
1430
- startingTests.push(task);
1431
- } else if (task.result?.hooks?.afterEach !== "run") {
1432
- finishedTests.push(task);
1433
- }
1434
- }
1435
- if (task?.result?.hooks) {
1436
- for (const [hook, state] of Object.entries(task.result.hooks)) {
1437
- if (state === "run" || state === "queued") {
1438
- startingHooks.push({ name: hook, file: task.file, id: task.id, type: task.type });
1439
- } else {
1440
- endingHooks.push({ name: hook, file: task.file, id: task.id, type: task.type });
1441
- }
1442
- }
1443
- }
1444
- }
1445
- endingHooks.forEach((hook) => this.onHookEnd(hook));
1446
- finishedTests.forEach((test) => this.onTestFinished(test));
1447
- finishedTestFiles.forEach((file) => this.onTestFileFinished(file));
1448
- startingTestFiles.forEach((file) => this.onTestFilePrepare(file));
1449
- startingTests.forEach((test) => this.onTestStart(test));
1450
- startingHooks.forEach((hook) => this.onHookStart(hook));
1451
- }
1452
- }
1453
-
1454
1120
  const DURATION_UPDATE_INTERVAL_MS = 100;
1455
1121
  const FINISHED_TEST_CLEANUP_TIME_MS = 1e3;
1456
- class SummaryReporter extends TaskParser {
1122
+ class SummaryReporter {
1123
+ ctx;
1457
1124
  options;
1458
1125
  renderer;
1459
- suites = emptyCounters();
1126
+ modules = emptyCounters();
1460
1127
  tests = emptyCounters();
1461
1128
  maxParallelTests = 0;
1462
- /** Currently running tests, may include finished tests too */
1463
- runningTests = /* @__PURE__ */ new Map();
1464
- /** ID of finished `this.runningTests` that are currently being shown */
1465
- finishedTests = /* @__PURE__ */ new Map();
1466
- /** IDs of all finished tests */
1467
- allFinishedTests = /* @__PURE__ */ new Set();
1129
+ /** Currently running test modules, may include finished test modules too */
1130
+ runningModules = /* @__PURE__ */ new Map();
1131
+ /** ID of finished `this.runningModules` that are currently being shown */
1132
+ finishedModules = /* @__PURE__ */ new Map();
1468
1133
  startTime = "";
1469
1134
  currentTime = 0;
1470
1135
  duration = 0;
1471
- durationInterval = void 0;
1136
+ durationInterval = undefined;
1472
1137
  onInit(ctx, options = {}) {
1473
1138
  this.ctx = ctx;
1474
1139
  this.options = {
@@ -1479,61 +1144,43 @@ class SummaryReporter extends TaskParser {
1479
1144
  logger: ctx.logger,
1480
1145
  getWindow: () => this.createSummary()
1481
1146
  });
1482
- this.startTimers();
1483
1147
  this.ctx.onClose(() => {
1484
1148
  clearInterval(this.durationInterval);
1485
1149
  this.renderer.stop();
1486
1150
  });
1487
1151
  }
1488
- onTestModuleQueued(module) {
1489
- this.onTestFilePrepare(module.task);
1490
- }
1491
- onPathsCollected(paths) {
1492
- this.suites.total = (paths || []).length;
1493
- }
1494
- onWatcherRerun() {
1495
- this.runningTests.clear();
1496
- this.finishedTests.clear();
1497
- this.allFinishedTests.clear();
1498
- this.suites = emptyCounters();
1152
+ onTestRunStart(specifications) {
1153
+ this.runningModules.clear();
1154
+ this.finishedModules.clear();
1155
+ this.modules = emptyCounters();
1499
1156
  this.tests = emptyCounters();
1500
1157
  this.startTimers();
1501
1158
  this.renderer.start();
1159
+ this.modules.total = specifications.length;
1502
1160
  }
1503
- onFinished() {
1504
- this.runningTests.clear();
1505
- this.finishedTests.clear();
1506
- this.allFinishedTests.clear();
1161
+ onTestRunEnd() {
1162
+ this.runningModules.clear();
1163
+ this.finishedModules.clear();
1507
1164
  this.renderer.finish();
1508
1165
  clearInterval(this.durationInterval);
1509
1166
  }
1510
- onTestFilePrepare(file) {
1511
- if (this.runningTests.has(file.id)) {
1512
- const stats = this.runningTests.get(file.id);
1513
- if (!stats.total) {
1514
- const total2 = getTests(file).length;
1515
- this.tests.total += total2;
1516
- stats.total = total2;
1517
- }
1518
- return;
1167
+ onTestModuleQueued(module) {
1168
+ if (this.finishedModules.size) {
1169
+ const finished = this.finishedModules.keys().next().value;
1170
+ this.removeTestModule(finished);
1519
1171
  }
1520
- if (this.allFinishedTests.has(file.id)) {
1521
- return;
1172
+ this.runningModules.set(module.id, initializeStats(module));
1173
+ }
1174
+ onTestModuleCollected(module) {
1175
+ let stats = this.runningModules.get(module.id);
1176
+ if (!stats) {
1177
+ stats = initializeStats(module);
1178
+ this.runningModules.set(module.id, stats);
1522
1179
  }
1523
- const total = getTests(file).length;
1180
+ const total = Array.from(module.children.allTests()).length;
1524
1181
  this.tests.total += total;
1525
- if (this.finishedTests.size) {
1526
- const finished = this.finishedTests.keys().next().value;
1527
- this.removeTestFile(finished);
1528
- }
1529
- this.runningTests.set(file.id, {
1530
- total,
1531
- completed: 0,
1532
- filename: file.name,
1533
- projectName: file.projectName,
1534
- tests: /* @__PURE__ */ new Map()
1535
- });
1536
- this.maxParallelTests = Math.max(this.maxParallelTests, this.runningTests.size);
1182
+ stats.total = total;
1183
+ this.maxParallelTests = Math.max(this.maxParallelTests, this.runningModules.size);
1537
1184
  }
1538
1185
  onHookStart(options) {
1539
1186
  const stats = this.getHookStats(options);
@@ -1562,11 +1209,11 @@ class SummaryReporter extends TaskParser {
1562
1209
  stats.hook.onFinish();
1563
1210
  stats.hook.visible = false;
1564
1211
  }
1565
- onTestStart(test) {
1212
+ onTestCaseReady(test) {
1566
1213
  if (!this.options.verbose) {
1567
1214
  return;
1568
1215
  }
1569
- const stats = this.getTestStats(test);
1216
+ const stats = this.runningModules.get(test.module.id);
1570
1217
  if (!stats || stats.tests.has(test.id)) {
1571
1218
  return;
1572
1219
  }
@@ -1586,74 +1233,61 @@ class SummaryReporter extends TaskParser {
1586
1233
  };
1587
1234
  stats.tests.set(test.id, slowTest);
1588
1235
  }
1589
- onTestFinished(test) {
1590
- const stats = this.getTestStats(test);
1236
+ onTestCaseResult(test) {
1237
+ const stats = this.runningModules.get(test.module.id);
1591
1238
  if (!stats) {
1592
1239
  return;
1593
1240
  }
1594
1241
  stats.tests.get(test.id)?.onFinish();
1595
1242
  stats.tests.delete(test.id);
1596
1243
  stats.completed++;
1597
- const result = test.result;
1598
- if (result?.state === "pass") {
1244
+ const result = test.result();
1245
+ if (result?.state === "passed") {
1599
1246
  this.tests.passed++;
1600
- } else if (result?.state === "fail") {
1247
+ } else if (result?.state === "failed") {
1601
1248
  this.tests.failed++;
1602
- } else if (!result?.state || result?.state === "skip" || result?.state === "todo") {
1249
+ } else if (!result?.state || result?.state === "skipped") {
1603
1250
  this.tests.skipped++;
1604
1251
  }
1605
1252
  }
1606
- onTestFileFinished(file) {
1607
- if (this.allFinishedTests.has(file.id)) {
1608
- return;
1609
- }
1610
- this.allFinishedTests.add(file.id);
1611
- this.suites.completed++;
1612
- if (file.result?.state === "pass") {
1613
- this.suites.passed++;
1614
- } else if (file.result?.state === "fail") {
1615
- this.suites.failed++;
1616
- } else if (file.result?.state === "skip") {
1617
- this.suites.skipped++;
1618
- } else if (file.result?.state === "todo") {
1619
- this.suites.todo++;
1620
- }
1621
- const left = this.suites.total - this.suites.completed;
1253
+ onTestModuleEnd(module) {
1254
+ const state = module.state();
1255
+ this.modules.completed++;
1256
+ if (state === "passed") {
1257
+ this.modules.passed++;
1258
+ } else if (state === "failed") {
1259
+ this.modules.failed++;
1260
+ } else if (module.task.mode === "todo" && state === "skipped") {
1261
+ this.modules.todo++;
1262
+ } else if (state === "skipped") {
1263
+ this.modules.skipped++;
1264
+ }
1265
+ const left = this.modules.total - this.modules.completed;
1622
1266
  if (left > this.maxParallelTests) {
1623
- this.finishedTests.set(file.id, setTimeout(() => {
1624
- this.removeTestFile(file.id);
1267
+ this.finishedModules.set(module.id, setTimeout(() => {
1268
+ this.removeTestModule(module.id);
1625
1269
  }, FINISHED_TEST_CLEANUP_TIME_MS).unref());
1626
1270
  } else {
1627
- this.removeTestFile(file.id);
1271
+ this.removeTestModule(module.id);
1628
1272
  }
1629
1273
  }
1630
- getTestStats(test) {
1631
- const file = test.file;
1632
- let stats = this.runningTests.get(file.id);
1633
- if (!stats || stats.total === 0) {
1634
- this.onTestFilePrepare(test.file);
1635
- stats = this.runningTests.get(file.id);
1636
- if (!stats) {
1637
- return;
1638
- }
1639
- }
1640
- return stats;
1641
- }
1642
- getHookStats({ file, id, type }) {
1274
+ getHookStats({ entity }) {
1643
1275
  if (!this.options.verbose) {
1644
1276
  return;
1645
1277
  }
1646
- const stats = this.runningTests.get(file.id);
1278
+ const module = entity.type === "module" ? entity : entity.module;
1279
+ const stats = this.runningModules.get(module.id);
1647
1280
  if (!stats) {
1648
1281
  return;
1649
1282
  }
1650
- return type === "suite" ? stats : stats?.tests.get(id);
1283
+ return entity.type === "test" ? stats.tests.get(entity.id) : stats;
1651
1284
  }
1652
1285
  createSummary() {
1653
1286
  const summary = [""];
1654
- for (const testFile of Array.from(this.runningTests.values()).sort(sortRunningTests)) {
1287
+ for (const testFile of Array.from(this.runningModules.values()).sort(sortRunningModules)) {
1288
+ const typecheck = testFile.typecheck ? `${c.bgBlue(c.bold(" TS "))} ` : "";
1655
1289
  summary.push(
1656
- c.bold(c.yellow(` ${F_POINTER} `)) + formatProjectName(testFile.projectName) + testFile.filename + c.dim(!testFile.completed && !testFile.total ? " [queued]" : ` ${testFile.completed}/${testFile.total}`)
1290
+ c.bold(c.yellow(` ${F_POINTER} `)) + formatProjectName(testFile.projectName) + typecheck + testFile.filename + c.dim(!testFile.completed && !testFile.total ? " [queued]" : ` ${testFile.completed}/${testFile.total}`)
1657
1291
  );
1658
1292
  const slowTasks = [
1659
1293
  testFile.hook,
@@ -1670,10 +1304,10 @@ class SummaryReporter extends TaskParser {
1670
1304
  }
1671
1305
  }
1672
1306
  }
1673
- if (this.runningTests.size > 0) {
1307
+ if (this.runningModules.size > 0) {
1674
1308
  summary.push("");
1675
1309
  }
1676
- summary.push(padSummaryTitle("Test Files") + getStateString(this.suites));
1310
+ summary.push(padSummaryTitle("Test Files") + getStateString(this.modules));
1677
1311
  summary.push(padSummaryTitle("Tests") + getStateString(this.tests));
1678
1312
  summary.push(padSummaryTitle("Start at") + this.startTime);
1679
1313
  summary.push(padSummaryTitle("Duration") + formatTime(this.duration));
@@ -1688,16 +1322,16 @@ class SummaryReporter extends TaskParser {
1688
1322
  this.duration = this.currentTime - start;
1689
1323
  }, DURATION_UPDATE_INTERVAL_MS).unref();
1690
1324
  }
1691
- removeTestFile(id) {
1325
+ removeTestModule(id) {
1692
1326
  if (!id) {
1693
1327
  return;
1694
1328
  }
1695
- const testFile = this.runningTests.get(id);
1329
+ const testFile = this.runningModules.get(id);
1696
1330
  testFile?.hook?.onFinish();
1697
1331
  testFile?.tests?.forEach((test) => test.onFinish());
1698
- this.runningTests.delete(id);
1699
- clearTimeout(this.finishedTests.get(id));
1700
- this.finishedTests.delete(id);
1332
+ this.runningModules.delete(id);
1333
+ clearTimeout(this.finishedModules.get(id));
1334
+ this.finishedModules.delete(id);
1701
1335
  }
1702
1336
  }
1703
1337
  function emptyCounters() {
@@ -1711,7 +1345,7 @@ function getStateString(entry) {
1711
1345
  entry.todo ? c.gray(`${entry.todo} todo`) : null
1712
1346
  ].filter(Boolean).join(c.dim(" | ")) + c.gray(` (${entry.total})`);
1713
1347
  }
1714
- function sortRunningTests(a, b) {
1348
+ function sortRunningModules(a, b) {
1715
1349
  if ((a.projectName || "") > (b.projectName || "")) {
1716
1350
  return 1;
1717
1351
  }
@@ -1720,6 +1354,16 @@ function sortRunningTests(a, b) {
1720
1354
  }
1721
1355
  return a.filename.localeCompare(b.filename);
1722
1356
  }
1357
+ function initializeStats(module) {
1358
+ return {
1359
+ total: 0,
1360
+ completed: 0,
1361
+ filename: module.task.name,
1362
+ projectName: module.project.name,
1363
+ tests: /* @__PURE__ */ new Map(),
1364
+ typecheck: !!module.task.meta.typecheck
1365
+ };
1366
+ }
1723
1367
 
1724
1368
  class DefaultReporter extends BaseReporter {
1725
1369
  options;
@@ -1737,108 +1381,106 @@ class DefaultReporter extends BaseReporter {
1737
1381
  this.summary = new SummaryReporter();
1738
1382
  }
1739
1383
  }
1384
+ onTestRunStart(specifications) {
1385
+ this.summary?.onTestRunStart(specifications);
1386
+ }
1740
1387
  onTestModuleQueued(file) {
1741
1388
  this.summary?.onTestModuleQueued(file);
1742
1389
  }
1390
+ onTestModuleCollected(module) {
1391
+ this.summary?.onTestModuleCollected(module);
1392
+ }
1393
+ onTestModuleEnd(module) {
1394
+ this.summary?.onTestModuleEnd(module);
1395
+ }
1396
+ onTestCaseReady(test) {
1397
+ this.summary?.onTestCaseReady(test);
1398
+ }
1399
+ onTestCaseResult(test) {
1400
+ this.summary?.onTestCaseResult(test);
1401
+ }
1402
+ onHookStart(hook) {
1403
+ this.summary?.onHookStart(hook);
1404
+ }
1405
+ onHookEnd(hook) {
1406
+ this.summary?.onHookEnd(hook);
1407
+ }
1743
1408
  onInit(ctx) {
1744
1409
  super.onInit(ctx);
1745
1410
  this.summary?.onInit(ctx, { verbose: this.verbose });
1746
1411
  }
1747
1412
  onPathsCollected(paths = []) {
1748
1413
  if (this.isTTY) {
1749
- if (this.renderSucceed === void 0) {
1414
+ if (this.renderSucceed === undefined) {
1750
1415
  this.renderSucceed = !!this.renderSucceed;
1751
1416
  }
1752
1417
  if (this.renderSucceed !== true) {
1753
1418
  this.renderSucceed = paths.length <= 1;
1754
1419
  }
1755
1420
  }
1756
- this.summary?.onPathsCollected(paths);
1757
- }
1758
- onTaskUpdate(packs) {
1759
- this.summary?.onTaskUpdate(packs);
1760
- super.onTaskUpdate(packs);
1761
- }
1762
- onWatcherRerun(files, trigger) {
1763
- this.summary?.onWatcherRerun();
1764
- super.onWatcherRerun(files, trigger);
1765
1421
  }
1766
- onFinished(files, errors) {
1767
- this.summary?.onFinished();
1768
- super.onFinished(files, errors);
1422
+ onTestRunEnd() {
1423
+ this.summary?.onTestRunEnd();
1769
1424
  }
1770
1425
  }
1771
1426
 
1772
1427
  class DotReporter extends BaseReporter {
1773
- summary;
1428
+ renderer;
1429
+ tests = /* @__PURE__ */ new Map();
1430
+ finishedTests = /* @__PURE__ */ new Set();
1774
1431
  onInit(ctx) {
1775
1432
  super.onInit(ctx);
1776
1433
  if (this.isTTY) {
1777
- this.summary = new DotSummary();
1778
- this.summary.onInit(ctx);
1434
+ this.renderer = new WindowRenderer({
1435
+ logger: ctx.logger,
1436
+ getWindow: () => this.createSummary()
1437
+ });
1438
+ this.ctx.onClose(() => this.renderer?.stop());
1779
1439
  }
1780
1440
  }
1781
- onTaskUpdate(packs) {
1782
- this.summary?.onTaskUpdate(packs);
1441
+ printTask(task) {
1783
1442
  if (!this.isTTY) {
1784
- super.onTaskUpdate(packs);
1443
+ super.printTask(task);
1785
1444
  }
1786
1445
  }
1787
1446
  onWatcherRerun(files, trigger) {
1788
- this.summary?.onWatcherRerun();
1447
+ this.tests.clear();
1448
+ this.renderer?.start();
1789
1449
  super.onWatcherRerun(files, trigger);
1790
1450
  }
1791
1451
  onFinished(files, errors) {
1792
- this.summary?.onFinished();
1793
- super.onFinished(files, errors);
1794
- }
1795
- }
1796
- class DotSummary extends TaskParser {
1797
- renderer;
1798
- tests = /* @__PURE__ */ new Map();
1799
- finishedTests = /* @__PURE__ */ new Set();
1800
- onInit(ctx) {
1801
- this.ctx = ctx;
1802
- this.renderer = new WindowRenderer({
1803
- logger: ctx.logger,
1804
- getWindow: () => this.createSummary()
1805
- });
1806
- this.ctx.onClose(() => this.renderer.stop());
1807
- }
1808
- onWatcherRerun() {
1809
- this.tests.clear();
1810
- this.renderer.start();
1811
- }
1812
- onFinished() {
1813
- const finalLog = formatTests(Array.from(this.tests.values()));
1814
- this.ctx.logger.log(finalLog);
1452
+ if (this.isTTY) {
1453
+ const finalLog = formatTests(Array.from(this.tests.values()));
1454
+ this.ctx.logger.log(finalLog);
1455
+ }
1815
1456
  this.tests.clear();
1816
- this.renderer.finish();
1457
+ this.renderer?.finish();
1458
+ super.onFinished(files, errors);
1817
1459
  }
1818
- onTestFilePrepare(file) {
1819
- for (const test of getTests(file)) {
1820
- this.onTestStart(test);
1460
+ onTestModuleCollected(module) {
1461
+ for (const test of module.children.allTests()) {
1462
+ this.onTestCaseReady(test);
1821
1463
  }
1822
1464
  }
1823
- onTestStart(test) {
1465
+ onTestCaseReady(test) {
1824
1466
  if (this.finishedTests.has(test.id)) {
1825
1467
  return;
1826
1468
  }
1827
- this.tests.set(test.id, test.mode || "run");
1469
+ this.tests.set(test.id, test.result().state || "run");
1828
1470
  }
1829
- onTestFinished(test) {
1830
- if (this.finishedTests.has(test.id)) {
1831
- return;
1832
- }
1471
+ onTestCaseResult(test) {
1833
1472
  this.finishedTests.add(test.id);
1834
- this.tests.set(test.id, test.result?.state || "skip");
1473
+ this.tests.set(test.id, test.result().state || "skipped");
1835
1474
  }
1836
- onTestFileFinished() {
1475
+ onTestModuleEnd() {
1476
+ if (!this.isTTY) {
1477
+ return;
1478
+ }
1837
1479
  const columns = this.ctx.logger.getColumns();
1838
1480
  if (this.tests.size < columns) {
1839
1481
  return;
1840
1482
  }
1841
- const finishedTests = Array.from(this.tests).filter((entry) => entry[1] !== "run");
1483
+ const finishedTests = Array.from(this.tests).filter((entry) => entry[1] !== "pending");
1842
1484
  if (finishedTests.length < columns) {
1843
1485
  return;
1844
1486
  }
@@ -1866,12 +1508,11 @@ const pending = { char: "*", color: c.yellow };
1866
1508
  const skip = { char: "-", color: (char) => c.dim(c.gray(char)) };
1867
1509
  function getIcon(state) {
1868
1510
  switch (state) {
1869
- case "pass":
1511
+ case "passed":
1870
1512
  return pass;
1871
- case "fail":
1513
+ case "failed":
1872
1514
  return fail;
1873
- case "skip":
1874
- case "todo":
1515
+ case "skipped":
1875
1516
  return skip;
1876
1517
  default:
1877
1518
  return pending;
@@ -1896,7 +1537,7 @@ function formatTests(states) {
1896
1537
  }
1897
1538
 
1898
1539
  class GithubActionsReporter {
1899
- ctx = void 0;
1540
+ ctx = undefined;
1900
1541
  onInit(ctx) {
1901
1542
  this.ctx = ctx;
1902
1543
  }
@@ -1968,17 +1609,6 @@ function escapeProperty(s) {
1968
1609
  return s.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A").replace(/:/g, "%3A").replace(/,/g, "%2C");
1969
1610
  }
1970
1611
 
1971
- class HangingProcessReporter {
1972
- whyRunning;
1973
- onInit() {
1974
- const _require = createRequire(import.meta.url);
1975
- this.whyRunning = _require("why-is-node-running");
1976
- }
1977
- onProcessTimeout() {
1978
- this.whyRunning?.();
1979
- }
1980
- }
1981
-
1982
1612
  const StatusMap = {
1983
1613
  fail: "failed",
1984
1614
  only: "pending",
@@ -2018,7 +1648,7 @@ class JsonReporter {
2018
1648
  ).length;
2019
1649
  const numTodoTests = tests.filter((t) => t.mode === "todo").length;
2020
1650
  const testResults = [];
2021
- const success = numFailedTestSuites === 0 && numFailedTests === 0;
1651
+ const success = !!(files.length > 0 || this.ctx.config.passWithNoTests) && numFailedTestSuites === 0 && numFailedTests === 0;
2022
1652
  for (const file of files) {
2023
1653
  const tests2 = getTests([file]);
2024
1654
  let startTime = tests2.reduce(
@@ -2213,7 +1843,7 @@ class JUnitReporter {
2213
1843
  const pairs = [];
2214
1844
  for (const key in attrs) {
2215
1845
  const attr = attrs[key];
2216
- if (attr === void 0) {
1846
+ if (attr === undefined) {
2217
1847
  continue;
2218
1848
  }
2219
1849
  pairs.push(`${key}="${escapeXML(attr)}"`);
@@ -2259,7 +1889,7 @@ class JUnitReporter {
2259
1889
  "testcase",
2260
1890
  {
2261
1891
  classname,
2262
- file: this.options.addFileAttribute ? filename : void 0,
1892
+ file: this.options.addFileAttribute ? filename : undefined,
2263
1893
  name: task.name,
2264
1894
  time: getDuration(task)
2265
1895
  },
@@ -2388,382 +2018,8 @@ class JUnitReporter {
2388
2018
  this.ctx.logger.log(`JUNIT report written to ${this.reportFile}`);
2389
2019
  }
2390
2020
  await this.fileFd?.close();
2391
- this.fileFd = void 0;
2392
- }
2393
- }
2394
-
2395
- class ReportedTaskImplementation {
2396
- /**
2397
- * Task instance.
2398
- * @internal
2399
- */
2400
- task;
2401
- /**
2402
- * The project associated with the test or suite.
2403
- */
2404
- project;
2405
- /**
2406
- * Unique identifier.
2407
- * This ID is deterministic and will be the same for the same test across multiple runs.
2408
- * The ID is based on the project name, module url and test order.
2409
- */
2410
- id;
2411
- /**
2412
- * Location in the module where the test or suite is defined.
2413
- */
2414
- location;
2415
- /** @internal */
2416
- constructor(task, project) {
2417
- this.task = task;
2418
- this.project = project;
2419
- this.id = task.id;
2420
- this.location = task.location;
2421
- }
2422
- /**
2423
- * Checks if the test did not fail the suite.
2424
- * If the test is not finished yet or was skipped, it will return `true`.
2425
- */
2426
- ok() {
2427
- const result = this.task.result;
2428
- return !result || result.state !== "fail";
2429
- }
2430
- /**
2431
- * Creates a new reported task instance and stores it in the project's state for future use.
2432
- * @internal
2433
- */
2434
- static register(task, project) {
2435
- const state = new this(task, project);
2436
- storeTask(project, task, state);
2437
- return state;
2438
- }
2439
- }
2440
- class TestCase extends ReportedTaskImplementation {
2441
- #fullName;
2442
- type = "test";
2443
- /**
2444
- * Direct reference to the test module where the test or suite is defined.
2445
- */
2446
- module;
2447
- /**
2448
- * Name of the test.
2449
- */
2450
- name;
2451
- /**
2452
- * Options that the test was initiated with.
2453
- */
2454
- options;
2455
- /**
2456
- * Parent suite. If the test was called directly inside the module, the parent will be the module itself.
2457
- */
2458
- parent;
2459
- /** @internal */
2460
- constructor(task, project) {
2461
- super(task, project);
2462
- this.name = task.name;
2463
- this.module = getReportedTask(project, task.file);
2464
- const suite = this.task.suite;
2465
- if (suite) {
2466
- this.parent = getReportedTask(project, suite);
2467
- } else {
2468
- this.parent = this.module;
2469
- }
2470
- this.options = buildOptions(task);
2471
- }
2472
- /**
2473
- * Full name of the test including all parent suites separated with `>`.
2474
- */
2475
- get fullName() {
2476
- if (this.#fullName === void 0) {
2477
- if (this.parent.type !== "module") {
2478
- this.#fullName = `${this.parent.fullName} > ${this.name}`;
2479
- } else {
2480
- this.#fullName = this.name;
2481
- }
2482
- }
2483
- return this.#fullName;
2484
- }
2485
- /**
2486
- * Test results. Will be `undefined` if test is skipped, not finished yet or was just collected.
2487
- */
2488
- result() {
2489
- const result = this.task.result;
2490
- if (!result || result.state === "run" || result.state === "queued") {
2491
- return void 0;
2492
- }
2493
- const state = result.state === "fail" ? "failed" : result.state === "pass" ? "passed" : "skipped";
2494
- if (state === "skipped") {
2495
- return {
2496
- state,
2497
- note: result.note,
2498
- errors: void 0
2499
- };
2500
- }
2501
- if (state === "passed") {
2502
- return {
2503
- state,
2504
- errors: result.errors
2505
- };
2506
- }
2507
- return {
2508
- state,
2509
- errors: result.errors || []
2510
- };
2511
- }
2512
- /**
2513
- * Checks if the test was skipped during collection or dynamically with `ctx.skip()`.
2514
- */
2515
- skipped() {
2516
- const mode = this.task.result?.state || this.task.mode;
2517
- return mode === "skip" || mode === "todo";
2518
- }
2519
- /**
2520
- * Custom metadata that was attached to the test during its execution.
2521
- */
2522
- meta() {
2523
- return this.task.meta;
2524
- }
2525
- /**
2526
- * Useful information about the test like duration, memory usage, etc.
2527
- * Diagnostic is only available after the test has finished.
2528
- */
2529
- diagnostic() {
2530
- const result = this.task.result;
2531
- if (!result || result.state === "run" || result.state === "queued" || !result.startTime) {
2532
- return void 0;
2533
- }
2534
- const duration = result.duration || 0;
2535
- const slow = duration > this.project.globalConfig.slowTestThreshold;
2536
- return {
2537
- slow,
2538
- heap: result.heap,
2539
- duration,
2540
- startTime: result.startTime,
2541
- retryCount: result.retryCount ?? 0,
2542
- repeatCount: result.repeatCount ?? 0,
2543
- flaky: !!result.retryCount && result.state === "pass" && result.retryCount > 0
2544
- };
2545
- }
2546
- }
2547
- class TestCollection {
2548
- #task;
2549
- #project;
2550
- constructor(task, project) {
2551
- this.#task = task;
2552
- this.#project = project;
2553
- }
2554
- /**
2555
- * Returns the test or suite at a specific index.
2556
- */
2557
- at(index) {
2558
- if (index < 0) {
2559
- index = this.size + index;
2560
- }
2561
- return getReportedTask(this.#project, this.#task.tasks[index]);
2562
- }
2563
- /**
2564
- * The number of tests and suites in the collection.
2565
- */
2566
- get size() {
2567
- return this.#task.tasks.length;
2568
- }
2569
- /**
2570
- * Returns the collection in array form for easier manipulation.
2571
- */
2572
- array() {
2573
- return Array.from(this);
2574
- }
2575
- /**
2576
- * Filters all tests that are part of this collection and its children.
2577
- */
2578
- *allTests(state) {
2579
- for (const child of this) {
2580
- if (child.type === "suite") {
2581
- yield* child.children.allTests(state);
2582
- } else if (state) {
2583
- const testState = getTestState(child);
2584
- if (state === testState) {
2585
- yield child;
2586
- }
2587
- } else {
2588
- yield child;
2589
- }
2590
- }
2591
- }
2592
- /**
2593
- * Filters only the tests that are part of this collection.
2594
- */
2595
- *tests(state) {
2596
- for (const child of this) {
2597
- if (child.type !== "test") {
2598
- continue;
2599
- }
2600
- if (state) {
2601
- const testState = getTestState(child);
2602
- if (state === testState) {
2603
- yield child;
2604
- }
2605
- } else {
2606
- yield child;
2607
- }
2608
- }
2609
- }
2610
- /**
2611
- * Filters only the suites that are part of this collection.
2612
- */
2613
- *suites() {
2614
- for (const child of this) {
2615
- if (child.type === "suite") {
2616
- yield child;
2617
- }
2618
- }
2619
- }
2620
- /**
2621
- * Filters all suites that are part of this collection and its children.
2622
- */
2623
- *allSuites() {
2624
- for (const child of this) {
2625
- if (child.type === "suite") {
2626
- yield child;
2627
- yield* child.children.allSuites();
2628
- }
2629
- }
2630
- }
2631
- *[Symbol.iterator]() {
2632
- for (const task of this.#task.tasks) {
2633
- yield getReportedTask(this.#project, task);
2634
- }
2635
- }
2636
- }
2637
- class SuiteImplementation extends ReportedTaskImplementation {
2638
- /**
2639
- * Collection of suites and tests that are part of this suite.
2640
- */
2641
- children;
2642
- /** @internal */
2643
- constructor(task, project) {
2644
- super(task, project);
2645
- this.children = new TestCollection(task, project);
2646
- }
2647
- /**
2648
- * Checks if the suite was skipped during collection.
2649
- */
2650
- skipped() {
2651
- const mode = this.task.mode;
2652
- return mode === "skip" || mode === "todo";
2653
- }
2654
- /**
2655
- * Errors that happened outside of the test run during collection, like syntax errors.
2656
- */
2657
- errors() {
2658
- return this.task.result?.errors || [];
2659
- }
2660
- }
2661
- class TestSuite extends SuiteImplementation {
2662
- #fullName;
2663
- type = "suite";
2664
- /**
2665
- * Name of the test or the suite.
2666
- */
2667
- name;
2668
- /**
2669
- * Direct reference to the test module where the test or suite is defined.
2670
- */
2671
- module;
2672
- /**
2673
- * Parent suite. If suite was called directly inside the module, the parent will be the module itself.
2674
- */
2675
- parent;
2676
- /**
2677
- * Options that suite was initiated with.
2678
- */
2679
- options;
2680
- /** @internal */
2681
- constructor(task, project) {
2682
- super(task, project);
2683
- this.name = task.name;
2684
- this.module = getReportedTask(project, task.file);
2685
- const suite = this.task.suite;
2686
- if (suite) {
2687
- this.parent = getReportedTask(project, suite);
2688
- } else {
2689
- this.parent = this.module;
2690
- }
2691
- this.options = buildOptions(task);
2692
- }
2693
- /**
2694
- * Full name of the suite including all parent suites separated with `>`.
2695
- */
2696
- get fullName() {
2697
- if (this.#fullName === void 0) {
2698
- if (this.parent.type !== "module") {
2699
- this.#fullName = `${this.parent.fullName} > ${this.name}`;
2700
- } else {
2701
- this.#fullName = this.name;
2702
- }
2703
- }
2704
- return this.#fullName;
2705
- }
2706
- }
2707
- class TestModule extends SuiteImplementation {
2708
- type = "module";
2709
- /**
2710
- * This is usually an absolute UNIX file path.
2711
- * It can be a virtual id if the file is not on the disk.
2712
- * This value corresponds to Vite's `ModuleGraph` id.
2713
- */
2714
- moduleId;
2715
- /** @internal */
2716
- constructor(task, project) {
2717
- super(task, project);
2718
- this.moduleId = task.filepath;
2719
- }
2720
- /**
2721
- * Useful information about the module like duration, memory usage, etc.
2722
- * If the module was not executed yet, all diagnostic values will return `0`.
2723
- */
2724
- diagnostic() {
2725
- const setupDuration = this.task.setupDuration || 0;
2726
- const collectDuration = this.task.collectDuration || 0;
2727
- const prepareDuration = this.task.prepareDuration || 0;
2728
- const environmentSetupDuration = this.task.environmentLoad || 0;
2729
- const duration = this.task.result?.duration || 0;
2730
- return {
2731
- environmentSetupDuration,
2732
- prepareDuration,
2733
- collectDuration,
2734
- setupDuration,
2735
- duration
2736
- };
2737
- }
2738
- }
2739
- function buildOptions(task) {
2740
- return {
2741
- each: task.each,
2742
- concurrent: task.concurrent,
2743
- shuffle: task.shuffle,
2744
- retry: task.retry,
2745
- repeats: task.repeats,
2746
- mode: task.mode
2747
- };
2748
- }
2749
- function getTestState(test) {
2750
- if (test.skipped()) {
2751
- return "skipped";
2752
- }
2753
- const result = test.result();
2754
- return result ? result.state : "running";
2755
- }
2756
- function storeTask(project, runnerTask, reportedTask) {
2757
- project.vitest.state.reportedTasksMap.set(runnerTask, reportedTask);
2758
- }
2759
- function getReportedTask(project, runnerTask) {
2760
- const reportedTask = project.vitest.state.getReportedEntity(runnerTask);
2761
- if (!reportedTask) {
2762
- throw new Error(
2763
- `Task instance was not found for ${runnerTask.type} "${runnerTask.name}"`
2764
- );
2021
+ this.fileFd = undefined;
2765
2022
  }
2766
- return reportedTask;
2767
2023
  }
2768
2024
 
2769
2025
  function yamlString(str) {
@@ -3096,7 +2352,7 @@ ${padding}`;
3096
2352
  if (typeof data === "string") {
3097
2353
  data = stripVTControlCharacters(data.trim().split("\n").filter(Boolean).pop());
3098
2354
  if (data === "") {
3099
- data = void 0;
2355
+ data = undefined;
3100
2356
  }
3101
2357
  }
3102
2358
  if (data != null) {
@@ -3187,7 +2443,6 @@ const BenchmarkReportsMap = {
3187
2443
  verbose: VerboseBenchmarkReporter
3188
2444
  };
3189
2445
 
3190
- const TestFile = TestModule;
3191
2446
  const ReportersMap = {
3192
2447
  "default": DefaultReporter,
3193
2448
  "basic": BasicReporter,
@@ -3202,4 +2457,4 @@ const ReportersMap = {
3202
2457
  "github-actions": GithubActionsReporter
3203
2458
  };
3204
2459
 
3205
- export { BasicReporter as B, DefaultReporter as D, GithubActionsReporter as G, HangingProcessReporter as H, JsonReporter as J, Logger as L, ReportersMap as R, TapFlatReporter as T, VerboseReporter as V, DotReporter as a, JUnitReporter as b, TapReporter as c, TestFile as d, TestCase as e, TestModule as f, TestSuite as g, BenchmarkReportsMap as h, generateCodeFrame as i, BlobReporter as j, parse as p, readBlobs as r, stringify as s };
2460
+ export { BasicReporter as B, DefaultReporter as D, GithubActionsReporter as G, HangingProcessReporter as H, JsonReporter as J, ReportersMap as R, TapFlatReporter as T, VerboseBenchmarkReporter as V, BenchmarkReporter as a, BenchmarkReportsMap as b, DotReporter as c, JUnitReporter as d, TapReporter as e, VerboseReporter as f, printError as g, generateCodeFrame as h, BlobReporter as i, parse as p, readBlobs as r, stringify as s };