vitest 3.2.0-beta.3 → 3.2.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 (65) hide show
  1. package/LICENSE.md +29 -0
  2. package/dist/browser.d.ts +1 -1
  3. package/dist/browser.js +2 -2
  4. package/dist/chunks/{base.D4119yLM.js → base.Cg0miDlQ.js} +10 -14
  5. package/dist/chunks/{benchmark.Cf_PACH1.js → benchmark.CYdenmiT.js} +4 -6
  6. package/dist/chunks/{cac.DWaWHIIE.js → cac.C8BzMmTW.js} +66 -136
  7. package/dist/chunks/{cli-api.CnmEXkxs.js → cli-api.DmupRhea.js} +1251 -1336
  8. package/dist/chunks/{console.Cwr-MFPV.js → console.CtFJOzRO.js} +24 -45
  9. package/dist/chunks/{coverage.0iPg4Wrz.js → coverage.DVF1vEu8.js} +4 -12
  10. package/dist/chunks/{coverage.C73DaDgS.js → coverage.EIiagJJP.js} +484 -1003
  11. package/dist/chunks/{creator.C8WKy2eW.js → creator.GK6I-cL4.js} +29 -76
  12. package/dist/chunks/{date.ByMsSlOr.js → date.Bq6ZW5rf.js} +3 -8
  13. package/dist/chunks/{defaults.DpVH7vbg.js → defaults.B7q_naMc.js} +1 -1
  14. package/dist/chunks/{env.Dq0hM4Xv.js → env.D4Lgay0q.js} +1 -1
  15. package/dist/chunks/{execute.B3q-2LPV.js → execute.B7h3T_Hc.js} +104 -220
  16. package/dist/chunks/{git.DXfdBEfR.js → git.BVQ8w_Sw.js} +1 -3
  17. package/dist/chunks/{global.d.BNLIi6yo.d.ts → global.d.MAmajcmJ.d.ts} +2 -0
  18. package/dist/chunks/{globals.CI21aWXF.js → globals.DEHgCU4V.js} +5 -5
  19. package/dist/chunks/{index.Bter3jj9.js → index.BZ0g1JD2.js} +366 -628
  20. package/dist/chunks/{index.CbT4iuwc.js → index.BbB8_kAK.js} +22 -24
  21. package/dist/chunks/{index.JOzufsrU.js → index.CIyJn3t1.js} +37 -82
  22. package/dist/chunks/{index.DNgLEKsQ.js → index.CdQS2e2Q.js} +2 -2
  23. package/dist/chunks/{index.2jgTs_Q5.js → index.CmSc2RE5.js} +69 -107
  24. package/dist/chunks/{inspector.BFsh5KO0.js → inspector.C914Efll.js} +1 -1
  25. package/dist/chunks/{node.Be-ntJnD.js → node.fjCdwEIl.js} +1 -1
  26. package/dist/chunks/{reporters.d.Bt4IGtsa.d.ts → reporters.d.C1ogPriE.d.ts} +24 -4
  27. package/dist/chunks/{rpc.BKExFSRG.js → rpc.Iovn4oWe.js} +9 -19
  28. package/dist/chunks/{runBaseTests.B_M1TTsK.js → runBaseTests.Dd85QTll.js} +18 -31
  29. package/dist/chunks/{setup-common.CF-O-dZX.js → setup-common.Dd054P77.js} +15 -42
  30. package/dist/chunks/{typechecker.BgzF-6iO.js → typechecker.DRKU1-1g.js} +106 -186
  31. package/dist/chunks/{utils.DPCq3gzW.js → utils.CAioKnHs.js} +6 -14
  32. package/dist/chunks/{utils.BlI4TC7Y.js → utils.XdZDrNZV.js} +5 -13
  33. package/dist/chunks/{vi.pkoYCV6A.js → vi.bdSIJ99Y.js} +118 -267
  34. package/dist/chunks/{vite.d.B-Kx3KCF.d.ts → vite.d.DqE4-hhK.d.ts} +1 -1
  35. package/dist/chunks/{vm.DPYem2so.js → vm.BThCzidc.js} +98 -214
  36. package/dist/chunks/{worker.d.Bl1O4kuf.d.ts → worker.d.DvqK5Vmu.d.ts} +1 -1
  37. package/dist/chunks/{worker.d.BKbBp2ga.d.ts → worker.d.tQu2eJQy.d.ts} +3 -1
  38. package/dist/cli.js +4 -4
  39. package/dist/config.cjs +1 -1
  40. package/dist/config.d.ts +4 -4
  41. package/dist/config.js +2 -2
  42. package/dist/coverage.d.ts +2 -2
  43. package/dist/coverage.js +5 -5
  44. package/dist/environments.js +1 -1
  45. package/dist/execute.d.ts +1 -1
  46. package/dist/execute.js +1 -1
  47. package/dist/index.d.ts +12 -11
  48. package/dist/index.js +5 -5
  49. package/dist/node.d.ts +7 -7
  50. package/dist/node.js +12 -14
  51. package/dist/reporters.d.ts +2 -2
  52. package/dist/reporters.js +4 -4
  53. package/dist/runners.d.ts +5 -2
  54. package/dist/runners.js +51 -80
  55. package/dist/snapshot.js +2 -2
  56. package/dist/suite.js +2 -2
  57. package/dist/worker.js +36 -42
  58. package/dist/workers/forks.js +4 -4
  59. package/dist/workers/runVmTests.js +15 -21
  60. package/dist/workers/threads.js +4 -4
  61. package/dist/workers/vmForks.js +6 -6
  62. package/dist/workers/vmThreads.js +6 -6
  63. package/dist/workers.d.ts +2 -2
  64. package/dist/workers.js +10 -10
  65. package/package.json +16 -14
@@ -4,8 +4,8 @@ import { slash, toArray, isPrimitive, inspect, positionToOffset, lineSplitRE } f
4
4
  import { parseStacktrace, parseErrorStacktrace } from '@vitest/utils/source-map';
5
5
  import { isAbsolute, relative, dirname, basename, resolve, normalize } from 'pathe';
6
6
  import c from 'tinyrainbow';
7
- import { i as isTTY } from './env.Dq0hM4Xv.js';
8
- import { h as hasFailedSnapshot, g as getOutputFile, T as TypeCheckError } from './typechecker.BgzF-6iO.js';
7
+ import { i as isTTY } from './env.D4Lgay0q.js';
8
+ import { h as hasFailedSnapshot, g as getOutputFile, T as TypeCheckError } from './typechecker.DRKU1-1g.js';
9
9
  import { stripVTControlCharacters } from 'node:util';
10
10
  import { existsSync, readFileSync, promises } from 'node:fs';
11
11
  import { mkdir, writeFile, readdir, stat, readFile } from 'node:fs/promises';
@@ -40,9 +40,7 @@ const labelDefaultColors = [
40
40
  ];
41
41
  function getCols(delta = 0) {
42
42
  let length = process.stdout?.columns;
43
- if (!length || Number.isNaN(length)) {
44
- length = 30;
45
- }
43
+ if (!length || Number.isNaN(length)) length = 30;
46
44
  return Math.max(length + delta, 0);
47
45
  }
48
46
  function errorBanner(message) {
@@ -53,9 +51,8 @@ function divider(text, left, right, color) {
53
51
  const c = color || ((text) => text);
54
52
  if (text) {
55
53
  const textLength = stripVTControlCharacters(text).length;
56
- if (left == null && right != null) {
57
- left = cols - textLength - right;
58
- } else {
54
+ if (left == null && right != null) left = cols - textLength - right;
55
+ else {
59
56
  left = left ?? Math.floor((cols - textLength) / 2);
60
57
  right = cols - textLength - left;
61
58
  }
@@ -66,9 +63,7 @@ function divider(text, left, right, color) {
66
63
  return F_LONG_DASH.repeat(cols);
67
64
  }
68
65
  function formatTestPath(root, path) {
69
- if (isAbsolute(path)) {
70
- path = relative(root, path);
71
- }
66
+ if (isAbsolute(path)) path = relative(root, path);
72
67
  const dir = dirname(path);
73
68
  const ext = path.match(/(\.(spec|test)\.[cm]?[tj]sx?)$/)?.[0] || "";
74
69
  const base = basename(path, ext);
@@ -76,22 +71,11 @@ function formatTestPath(root, path) {
76
71
  }
77
72
  function renderSnapshotSummary(rootDir, snapshots) {
78
73
  const summary = [];
79
- if (snapshots.added) {
80
- summary.push(c.bold(c.green(`${snapshots.added} written`)));
81
- }
82
- if (snapshots.unmatched) {
83
- summary.push(c.bold(c.red(`${snapshots.unmatched} failed`)));
84
- }
85
- if (snapshots.updated) {
86
- summary.push(c.bold(c.green(`${snapshots.updated} updated `)));
87
- }
88
- if (snapshots.filesRemoved) {
89
- if (snapshots.didUpdate) {
90
- summary.push(c.bold(c.green(`${snapshots.filesRemoved} files removed `)));
91
- } else {
92
- summary.push(c.bold(c.yellow(`${snapshots.filesRemoved} files obsolete `)));
93
- }
94
- }
74
+ if (snapshots.added) summary.push(c.bold(c.green(`${snapshots.added} written`)));
75
+ if (snapshots.unmatched) summary.push(c.bold(c.red(`${snapshots.unmatched} failed`)));
76
+ if (snapshots.updated) summary.push(c.bold(c.green(`${snapshots.updated} updated `)));
77
+ if (snapshots.filesRemoved) if (snapshots.didUpdate) summary.push(c.bold(c.green(`${snapshots.filesRemoved} files removed `)));
78
+ else summary.push(c.bold(c.yellow(`${snapshots.filesRemoved} files obsolete `)));
95
79
  if (snapshots.filesRemovedList && snapshots.filesRemovedList.length) {
96
80
  const [head, ...tail] = snapshots.filesRemovedList;
97
81
  summary.push(`${c.gray(F_DOWN_RIGHT)} ${formatTestPath(rootDir, head)}`);
@@ -100,11 +84,8 @@ function renderSnapshotSummary(rootDir, snapshots) {
100
84
  });
101
85
  }
102
86
  if (snapshots.unchecked) {
103
- if (snapshots.didUpdate) {
104
- summary.push(c.bold(c.green(`${snapshots.unchecked} removed`)));
105
- } else {
106
- summary.push(c.bold(c.yellow(`${snapshots.unchecked} obsolete`)));
107
- }
87
+ if (snapshots.didUpdate) summary.push(c.bold(c.green(`${snapshots.unchecked} removed`)));
88
+ else summary.push(c.bold(c.yellow(`${snapshots.unchecked} obsolete`)));
108
89
  snapshots.uncheckedKeysByFile.forEach((uncheckedFile) => {
109
90
  summary.push(`${c.gray(F_DOWN_RIGHT)} ${formatTestPath(rootDir, uncheckedFile.filePath)}`);
110
91
  uncheckedFile.keys.forEach((key) => summary.push(` ${c.gray(F_DOT)} ${key}`));
@@ -116,9 +97,7 @@ function countTestErrors(tasks) {
116
97
  return tasks.reduce((c, i) => c + (i.result?.errors?.length || 0), 0);
117
98
  }
118
99
  function getStateString$1(tasks, name = "tests", showTotal = true) {
119
- if (tasks.length === 0) {
120
- return c.dim(`no ${name}`);
121
- }
100
+ if (tasks.length === 0) return c.dim(`no ${name}`);
122
101
  const passed = tasks.filter((i) => i.result?.state === "pass");
123
102
  const failed = tasks.filter((i) => i.result?.state === "fail");
124
103
  const skipped = tasks.filter((i) => i.mode === "skip");
@@ -131,41 +110,25 @@ function getStateString$1(tasks, name = "tests", showTotal = true) {
131
110
  ].filter(Boolean).join(c.dim(" | ")) + (showTotal ? c.gray(` (${tasks.length})`) : "");
132
111
  }
133
112
  function getStateSymbol(task) {
134
- if (task.mode === "skip" || task.mode === "todo") {
135
- return skipped;
136
- }
137
- if (!task.result) {
138
- return pending$1;
139
- }
113
+ if (task.mode === "skip" || task.mode === "todo") return skipped;
114
+ if (!task.result) return pending$1;
140
115
  if (task.result.state === "run" || task.result.state === "queued") {
141
- if (task.type === "suite") {
142
- return pointer;
143
- }
144
- }
145
- if (task.result.state === "pass") {
146
- return task.meta?.benchmark ? benchmarkPass : testPass;
147
- }
148
- if (task.result.state === "fail") {
149
- return task.type === "suite" ? suiteFail : taskFail;
116
+ if (task.type === "suite") return pointer;
150
117
  }
118
+ if (task.result.state === "pass") return task.meta?.benchmark ? benchmarkPass : testPass;
119
+ if (task.result.state === "fail") return task.type === "suite" ? suiteFail : taskFail;
151
120
  return " ";
152
121
  }
153
122
  function formatTimeString(date) {
154
123
  return date.toTimeString().split(" ")[0];
155
124
  }
156
125
  function formatTime(time) {
157
- if (time > 1e3) {
158
- return `${(time / 1e3).toFixed(2)}s`;
159
- }
126
+ if (time > 1e3) return `${(time / 1e3).toFixed(2)}s`;
160
127
  return `${Math.round(time)}ms`;
161
128
  }
162
129
  function formatProjectName(project, suffix = " ") {
163
- if (!project?.name) {
164
- return "";
165
- }
166
- if (!c.isColorSupported) {
167
- return `|${project.name}|${suffix}`;
168
- }
130
+ if (!project?.name) return "";
131
+ if (!c.isColorSupported) return `|${project.name}|${suffix}`;
169
132
  let background = project.color && c[`bg${capitalize(project.color)}`];
170
133
  if (!background) {
171
134
  const index = project.name.split("").reduce((acc, v, idx) => acc + v.charCodeAt(0) + idx, 0);
@@ -182,9 +145,7 @@ function padSummaryTitle(str) {
182
145
  }
183
146
  function truncateString(text, maxLength) {
184
147
  const plainText = stripVTControlCharacters(text);
185
- if (plainText.length <= maxLength) {
186
- return text;
187
- }
148
+ if (plainText.length <= maxLength) return text;
188
149
  return `${plainText.slice(0, maxLength - 1)}…`;
189
150
  }
190
151
  function capitalize(text) {
@@ -222,11 +183,11 @@ class BaseReporter {
222
183
  watchFilters;
223
184
  failedUnwatchedFiles = [];
224
185
  isTTY;
225
- ctx = undefined;
186
+ ctx = void 0;
226
187
  renderSucceed = false;
227
188
  verbose = false;
228
- _filesInWatchMode = new Map();
229
- _timeStart = formatTimeString(new Date());
189
+ _filesInWatchMode = /* @__PURE__ */ new Map();
190
+ _timeStart = formatTimeString(/* @__PURE__ */ new Date());
230
191
  constructor(options = {}) {
231
192
  this.isTTY = options.isTTY ?? isTTY;
232
193
  }
@@ -246,40 +207,25 @@ class BaseReporter {
246
207
  }
247
208
  onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
248
209
  this.end = performance$1.now();
249
- if (!files.length && !errors.length) {
250
- this.ctx.logger.printNoTestFound(this.ctx.filenamePattern);
251
- } else {
252
- this.reportSummary(files, errors);
253
- }
210
+ if (!files.length && !errors.length) this.ctx.logger.printNoTestFound(this.ctx.filenamePattern);
211
+ else this.reportSummary(files, errors);
254
212
  }
255
213
  onTestCaseResult(testCase) {
256
- if (testCase.result().state === "failed") {
257
- this.logFailedTask(testCase.task);
258
- }
214
+ if (testCase.result().state === "failed") this.logFailedTask(testCase.task);
259
215
  }
260
216
  onTestSuiteResult(testSuite) {
261
- if (testSuite.state() === "failed") {
262
- this.logFailedTask(testSuite.task);
263
- }
217
+ if (testSuite.state() === "failed") this.logFailedTask(testSuite.task);
264
218
  }
265
219
  onTestModuleEnd(testModule) {
266
- if (testModule.state() === "failed") {
267
- this.logFailedTask(testModule.task);
268
- }
220
+ if (testModule.state() === "failed") this.logFailedTask(testModule.task);
269
221
  this.printTestModule(testModule);
270
222
  }
271
223
  logFailedTask(task) {
272
- if (this.ctx.config.silent === "passed-only") {
273
- for (const log of task.logs || []) {
274
- this.onUserConsoleLog(log, "failed");
275
- }
276
- }
224
+ if (this.ctx.config.silent === "passed-only") for (const log of task.logs || []) this.onUserConsoleLog(log, "failed");
277
225
  }
278
226
  printTestModule(testModule) {
279
227
  const moduleState = testModule.state();
280
- if (moduleState === "queued" || moduleState === "pending") {
281
- return;
282
- }
228
+ if (moduleState === "queued" || moduleState === "pending") return;
283
229
  let testsCount = 0;
284
230
  let failedCount = 0;
285
231
  let skippedCount = 0;
@@ -289,28 +235,20 @@ class BaseReporter {
289
235
  const originalLog = this.log.bind(this);
290
236
  this.log = (msg) => logs.push(msg);
291
237
  const visit = (suiteState, children) => {
292
- for (const child of children) {
293
- if (child.type === "suite") {
294
- const suiteState = child.state();
295
- // Skipped suites are hidden when --hideSkippedTests, print otherwise
296
- if (!this.ctx.config.hideSkippedTests || suiteState !== "skipped") {
297
- this.printTestSuite(child);
298
- }
299
- visit(suiteState, child.children);
300
- } else {
301
- const testResult = child.result();
302
- testsCount++;
303
- if (testResult.state === "failed") {
304
- failedCount++;
305
- } else if (testResult.state === "skipped") {
306
- skippedCount++;
307
- }
308
- if (this.ctx.config.hideSkippedTests && suiteState === "skipped") {
309
- // Skipped suites are hidden when --hideSkippedTests
310
- continue;
311
- }
312
- this.printTestCase(moduleState, child);
313
- }
238
+ for (const child of children) if (child.type === "suite") {
239
+ const suiteState = child.state();
240
+ // Skipped suites are hidden when --hideSkippedTests, print otherwise
241
+ if (!this.ctx.config.hideSkippedTests || suiteState !== "skipped") this.printTestSuite(child);
242
+ visit(suiteState, child.children);
243
+ } else {
244
+ const testResult = child.result();
245
+ testsCount++;
246
+ if (testResult.state === "failed") failedCount++;
247
+ else if (testResult.state === "skipped") skippedCount++;
248
+ if (this.ctx.config.hideSkippedTests && suiteState === "skipped")
249
+ // Skipped suites are hidden when --hideSkippedTests
250
+ continue;
251
+ this.printTestCase(moduleState, child);
314
252
  }
315
253
  };
316
254
  try {
@@ -330,49 +268,29 @@ class BaseReporter {
330
268
  const { duration, retryCount, repeatCount } = test.diagnostic() || {};
331
269
  const padding = this.getTestIndentation(test.task);
332
270
  let suffix = this.getDurationPrefix(test.task);
333
- if (retryCount != null && retryCount > 0) {
334
- suffix += c.yellow(` (retry x${retryCount})`);
335
- }
336
- if (repeatCount != null && repeatCount > 0) {
337
- suffix += c.yellow(` (repeat x${repeatCount})`);
338
- }
271
+ if (retryCount != null && retryCount > 0) suffix += c.yellow(` (retry x${retryCount})`);
272
+ if (repeatCount != null && repeatCount > 0) suffix += c.yellow(` (repeat x${repeatCount})`);
339
273
  if (testResult.state === "failed") {
340
274
  this.log(c.red(` ${padding}${taskFail} ${this.getTestName(test.task, c.dim(" > "))}`) + suffix);
341
275
  // print short errors, full errors will be at the end in summary
342
276
  testResult.errors.forEach((error) => {
343
277
  const message = this.formatShortError(error);
344
- if (message) {
345
- this.log(c.red(` ${padding}${message}`));
346
- }
278
+ if (message) this.log(c.red(` ${padding}${message}`));
347
279
  });
348
- } else if (duration && duration > this.ctx.config.slowTestThreshold) {
349
- this.log(` ${padding}${c.yellow(c.dim(F_CHECK))} ${this.getTestName(test.task, c.dim(" > "))} ${suffix}`);
350
- } else if (this.ctx.config.hideSkippedTests && testResult.state === "skipped") ; else if (testResult.state === "skipped" && testResult.note) {
351
- this.log(` ${padding}${getStateSymbol(test.task)} ${this.getTestName(test.task, c.dim(" > "))}${c.dim(c.gray(` [${testResult.note}]`))}`);
352
- } else if (this.renderSucceed || moduleState === "failed") {
353
- this.log(` ${padding}${getStateSymbol(test.task)} ${this.getTestName(test.task, c.dim(" > "))}${suffix}`);
354
- }
280
+ } else if (duration && duration > this.ctx.config.slowTestThreshold) this.log(` ${padding}${c.yellow(c.dim(F_CHECK))} ${this.getTestName(test.task, c.dim(" > "))} ${suffix}`);
281
+ else if (this.ctx.config.hideSkippedTests && testResult.state === "skipped") ; else if (testResult.state === "skipped" && testResult.note) this.log(` ${padding}${getStateSymbol(test.task)} ${this.getTestName(test.task, c.dim(" > "))}${c.dim(c.gray(` [${testResult.note}]`))}`);
282
+ else if (this.renderSucceed || moduleState === "failed") this.log(` ${padding}${getStateSymbol(test.task)} ${this.getTestName(test.task, c.dim(" > "))}${suffix}`);
355
283
  }
356
284
  getModuleLog(testModule, counts) {
357
285
  let state = c.dim(`${counts.tests} test${counts.tests > 1 ? "s" : ""}`);
358
- if (counts.failed) {
359
- state += c.dim(" | ") + c.red(`${counts.failed} failed`);
360
- }
361
- if (counts.skipped) {
362
- state += c.dim(" | ") + c.yellow(`${counts.skipped} skipped`);
363
- }
286
+ if (counts.failed) state += c.dim(" | ") + c.red(`${counts.failed} failed`);
287
+ if (counts.skipped) state += c.dim(" | ") + c.yellow(`${counts.skipped} skipped`);
364
288
  let suffix = c.dim("(") + state + c.dim(")") + this.getDurationPrefix(testModule.task);
365
289
  const diagnostic = testModule.diagnostic();
366
- if (diagnostic.heap != null) {
367
- suffix += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`);
368
- }
290
+ if (diagnostic.heap != null) suffix += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`);
369
291
  let title = getStateSymbol(testModule.task);
370
- if (testModule.meta().typecheck) {
371
- title += ` ${c.bgBlue(c.bold(" TS "))}`;
372
- }
373
- if (testModule.project.name) {
374
- title += ` ${formatProjectName(testModule.project, "")}`;
375
- }
292
+ if (testModule.meta().typecheck) title += ` ${c.bgBlue(c.bold(" TS "))}`;
293
+ if (testModule.project.name) title += ` ${formatProjectName(testModule.project, "")}`;
376
294
  return ` ${title} ${testModule.task.name} ${suffix}`;
377
295
  }
378
296
  printTestSuite(_suite) {
@@ -387,28 +305,31 @@ class BaseReporter {
387
305
  getTestIndentation(_test) {
388
306
  return " ";
389
307
  }
308
+ printAnnotations(test, console, padding = 0) {
309
+ const annotations = test.annotations();
310
+ if (!annotations.length) return;
311
+ const PADDING = " ".repeat(padding);
312
+ annotations.forEach(({ location, type, message }) => {
313
+ if (location) {
314
+ const file = relative(test.project.config.root, location.file);
315
+ this[console](`${PADDING}${c.blue(F_POINTER)} ${c.gray(`${file}:${location.line}:${location.column}`)} ${c.bold(type)}`);
316
+ } else this[console](`${PADDING}${c.blue(F_POINTER)} ${c.bold(type)}`);
317
+ this[console](`${PADDING} ${c.blue(F_DOWN_RIGHT)} ${message}`);
318
+ });
319
+ }
390
320
  getDurationPrefix(task) {
391
- if (!task.result?.duration) {
392
- return "";
393
- }
321
+ if (!task.result?.duration) return "";
394
322
  const color = task.result.duration > this.ctx.config.slowTestThreshold ? c.yellow : c.green;
395
323
  return color(` ${Math.round(task.result.duration)}${c.dim("ms")}`);
396
324
  }
397
325
  onWatcherStart(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
398
326
  const failed = errors.length > 0 || hasFailed(files);
399
- if (failed) {
400
- this.log(withLabel("red", "FAIL", "Tests failed. Watching for file changes..."));
401
- } else if (this.ctx.isCancelling) {
402
- this.log(withLabel("red", "CANCELLED", "Test run cancelled. Watching for file changes..."));
403
- } else {
404
- this.log(withLabel("green", "PASS", "Waiting for file changes..."));
405
- }
327
+ if (failed) this.log(withLabel("red", "FAIL", "Tests failed. Watching for file changes..."));
328
+ else if (this.ctx.isCancelling) this.log(withLabel("red", "CANCELLED", "Test run cancelled. Watching for file changes..."));
329
+ else this.log(withLabel("green", "PASS", "Waiting for file changes..."));
406
330
  const hints = [c.dim("press ") + c.bold("h") + c.dim(" to show help")];
407
- if (hasFailedSnapshot(files)) {
408
- hints.unshift(c.dim("press ") + c.bold(c.yellow("u")) + c.dim(" to update snapshot"));
409
- } else {
410
- hints.push(c.dim("press ") + c.bold("q") + c.dim(" to quit"));
411
- }
331
+ if (hasFailedSnapshot(files)) hints.unshift(c.dim("press ") + c.bold(c.yellow("u")) + c.dim(" to update snapshot"));
332
+ else hints.push(c.dim("press ") + c.bold("q") + c.dim(" to quit"));
412
333
  this.log(BADGE_PADDING + hints.join(c.dim(", ")));
413
334
  }
414
335
  onWatcherRerun(files, trigger) {
@@ -426,41 +347,26 @@ class BaseReporter {
426
347
  }
427
348
  this.ctx.logger.clearFullScreen();
428
349
  this.log(withLabel("blue", "RERUN", banner));
429
- if (this.ctx.configOverride.project) {
430
- this.log(BADGE_PADDING + c.dim(" Project name: ") + c.blue(toArray(this.ctx.configOverride.project).join(", ")));
431
- }
432
- if (this.ctx.filenamePattern) {
433
- this.log(BADGE_PADDING + c.dim(" Filename pattern: ") + c.blue(this.ctx.filenamePattern.join(", ")));
434
- }
435
- if (this.ctx.configOverride.testNamePattern) {
436
- this.log(BADGE_PADDING + c.dim(" Test name pattern: ") + c.blue(String(this.ctx.configOverride.testNamePattern)));
437
- }
350
+ if (this.ctx.configOverride.project) this.log(BADGE_PADDING + c.dim(" Project name: ") + c.blue(toArray(this.ctx.configOverride.project).join(", ")));
351
+ if (this.ctx.filenamePattern) this.log(BADGE_PADDING + c.dim(" Filename pattern: ") + c.blue(this.ctx.filenamePattern.join(", ")));
352
+ if (this.ctx.configOverride.testNamePattern) this.log(BADGE_PADDING + c.dim(" Test name pattern: ") + c.blue(String(this.ctx.configOverride.testNamePattern)));
438
353
  this.log("");
439
- for (const testModule of this.failedUnwatchedFiles) {
440
- this.printTestModule(testModule);
441
- }
442
- this._timeStart = formatTimeString(new Date());
354
+ for (const testModule of this.failedUnwatchedFiles) this.printTestModule(testModule);
355
+ this._timeStart = formatTimeString(/* @__PURE__ */ new Date());
443
356
  this.start = performance$1.now();
444
357
  }
445
358
  onUserConsoleLog(log, taskState) {
446
- if (!this.shouldLog(log, taskState)) {
447
- return;
448
- }
359
+ if (!this.shouldLog(log, taskState)) return;
449
360
  const output = log.type === "stdout" ? this.ctx.logger.outputStream : this.ctx.logger.errorStream;
450
361
  const write = (msg) => output.write(msg);
451
362
  let headerText = "unknown test";
452
- const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : undefined;
453
- if (task) {
454
- headerText = getFullName(task, c.dim(" > "));
455
- } else if (log.taskId && log.taskId !== "__vitest__unknown_test__") {
456
- headerText = log.taskId;
457
- }
363
+ const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0;
364
+ if (task) headerText = getFullName(task, c.dim(" > "));
365
+ else if (log.taskId && log.taskId !== "__vitest__unknown_test__") headerText = log.taskId;
458
366
  write(c.gray(log.type + c.dim(` | ${headerText}\n`)) + log.content);
459
367
  if (log.origin) {
460
368
  // browser logs don't have an extra end of line at the end like Node.js does
461
- if (log.browser) {
462
- write("\n");
463
- }
369
+ if (log.browser) write("\n");
464
370
  const project = task ? this.ctx.getProjectByName(task.file.projectName || "") : this.ctx.getRootProject();
465
371
  const stack = log.browser ? project.browser?.parseStacktrace(log.origin) || [] : parseStacktrace(log.origin);
466
372
  const highlight = task && stack.find((i) => i.file === task.file.filepath);
@@ -477,16 +383,10 @@ class BaseReporter {
477
383
  this.log(c.yellow("Test removed...") + (trigger ? c.dim(` [ ${this.relative(trigger)} ]\n`) : ""));
478
384
  }
479
385
  shouldLog(log, taskState) {
480
- if (this.ctx.config.silent === true) {
481
- return false;
482
- }
483
- if (this.ctx.config.silent === "passed-only" && taskState !== "failed") {
484
- return false;
485
- }
386
+ if (this.ctx.config.silent === true) return false;
387
+ if (this.ctx.config.silent === "passed-only" && taskState !== "failed") return false;
486
388
  const shouldLog = this.ctx.config.onConsoleLog?.(log.content, log.type);
487
- if (shouldLog === false) {
488
- return shouldLog;
489
- }
389
+ if (shouldLog === false) return shouldLog;
490
390
  return true;
491
391
  }
492
392
  onServerRestart(reason) {
@@ -494,11 +394,8 @@ class BaseReporter {
494
394
  }
495
395
  reportSummary(files, errors) {
496
396
  this.printErrorsSummary(files, errors);
497
- if (this.ctx.config.mode === "benchmark") {
498
- this.reportBenchmarkSummary(files);
499
- } else {
500
- this.reportTestSummary(files, errors);
501
- }
397
+ if (this.ctx.config.mode === "benchmark") this.reportBenchmarkSummary(files);
398
+ else this.reportTestSummary(files, errors);
502
399
  }
503
400
  reportTestSummary(files, errors) {
504
401
  this.log();
@@ -509,25 +406,20 @@ class BaseReporter {
509
406
  const title = index === 0 ? "Snapshots" : "";
510
407
  this.log(`${padSummaryTitle(title)} ${snapshot}`);
511
408
  }
512
- if (snapshotOutput.length > 1) {
513
- this.log();
514
- }
409
+ if (snapshotOutput.length > 1) this.log();
515
410
  this.log(padSummaryTitle("Test Files"), getStateString$1(affectedFiles));
516
411
  this.log(padSummaryTitle("Tests"), getStateString$1(tests));
517
412
  if (this.ctx.projects.some((c) => c.config.typecheck.enabled)) {
518
413
  const failed = tests.filter((t) => t.meta?.typecheck && t.result?.errors?.length);
519
414
  this.log(padSummaryTitle("Type Errors"), failed.length ? c.bold(c.red(`${failed.length} failed`)) : c.dim("no errors"));
520
415
  }
521
- if (errors.length) {
522
- this.log(padSummaryTitle("Errors"), c.bold(c.red(`${errors.length} error${errors.length > 1 ? "s" : ""}`)));
523
- }
416
+ if (errors.length) this.log(padSummaryTitle("Errors"), c.bold(c.red(`${errors.length} error${errors.length > 1 ? "s" : ""}`)));
524
417
  this.log(padSummaryTitle("Start at"), this._timeStart);
525
418
  const collectTime = sum(files, (file) => file.collectDuration);
526
419
  const testsTime = sum(files, (file) => file.result?.duration);
527
420
  const setupTime = sum(files, (file) => file.setupDuration);
528
- if (this.watchFilters) {
529
- this.log(padSummaryTitle("Duration"), formatTime(collectTime + testsTime + setupTime));
530
- } else {
421
+ if (this.watchFilters) this.log(padSummaryTitle("Duration"), formatTime(collectTime + testsTime + setupTime));
422
+ else {
531
423
  const blobs = this.ctx.state.blobs;
532
424
  // Execution time is either sum of all runs of `--merge-reports` or the current run's time
533
425
  const executionTime = blobs?.executionTimes ? sum(blobs.executionTimes, (time) => time) : this.end - this.start;
@@ -545,9 +437,7 @@ class BaseReporter {
545
437
  typecheck && `typecheck ${formatTime(typecheck)}`
546
438
  ].filter(Boolean).join(", ");
547
439
  this.log(padSummaryTitle("Duration"), formatTime(executionTime) + c.dim(` (${timers})`));
548
- if (blobs?.executionTimes) {
549
- this.log(padSummaryTitle("Per blob") + blobs.executionTimes.map((time) => ` ${formatTime(time)}`).join(""));
550
- }
440
+ if (blobs?.executionTimes) this.log(padSummaryTitle("Per blob") + blobs.executionTimes.map((time) => ` ${formatTime(time)}`).join(""));
551
441
  }
552
442
  this.log();
553
443
  }
@@ -558,7 +448,7 @@ class BaseReporter {
558
448
  const failedTests = tests.filter((i) => i.result?.state === "fail");
559
449
  const failedTotal = countTestErrors(failedSuites) + countTestErrors(failedTests);
560
450
  let current = 1;
561
- const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, undefined, 1)))}\n`);
451
+ const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1)))}\n`);
562
452
  if (failedSuites.length) {
563
453
  this.error(`\n${errorBanner(`Failed Suites ${failedSuites.length}`)}\n`);
564
454
  this.printTaskErrors(failedSuites, errorDivider);
@@ -578,9 +468,7 @@ class BaseReporter {
578
468
  this.log(`\n${withLabel("cyan", "BENCH", "Summary\n")}`);
579
469
  for (const bench of topBenches) {
580
470
  const group = bench.suite || bench.file;
581
- if (!group) {
582
- continue;
583
- }
471
+ if (!group) continue;
584
472
  const groupName = getFullName(group, c.dim(" > "));
585
473
  const project = this.ctx.projects.find((p) => p.name === bench.file.projectName);
586
474
  this.log(` ${formatProjectName(project)}${bench.name}${c.dim(` - ${groupName}`)}`);
@@ -594,36 +482,28 @@ class BaseReporter {
594
482
  }
595
483
  printTaskErrors(tasks, errorDivider) {
596
484
  const errorsQueue = [];
597
- for (const task of tasks) {
598
- // Merge identical errors
599
- task.result?.errors?.forEach((error) => {
600
- let previous;
601
- if (error?.stackStr) {
602
- previous = errorsQueue.find((i) => {
603
- if (i[0]?.stackStr !== error.stackStr) {
604
- return false;
605
- }
606
- const currentProjectName = task?.projectName || task.file?.projectName || "";
607
- const projectName = i[1][0]?.projectName || i[1][0].file?.projectName || "";
608
- return projectName === currentProjectName;
609
- });
610
- }
611
- if (previous) {
612
- previous[1].push(task);
613
- } else {
614
- errorsQueue.push([error, [task]]);
615
- }
485
+ for (const task of tasks)
486
+ // Merge identical errors
487
+ task.result?.errors?.forEach((error) => {
488
+ let previous;
489
+ if (error?.stack) previous = errorsQueue.find((i) => {
490
+ if (i[0]?.stack !== error.stack) return false;
491
+ const currentProjectName = task?.projectName || task.file?.projectName || "";
492
+ const projectName = i[1][0]?.projectName || i[1][0].file?.projectName || "";
493
+ const currentAnnotations = task.type === "test" && task.annotations;
494
+ const itemAnnotations = i[1][0].type === "test" && i[1][0].annotations;
495
+ return projectName === currentProjectName && deepEqual(currentAnnotations, itemAnnotations);
616
496
  });
617
- }
497
+ if (previous) previous[1].push(task);
498
+ else errorsQueue.push([error, [task]]);
499
+ });
618
500
  for (const [error, tasks] of errorsQueue) {
619
501
  for (const task of tasks) {
620
502
  const filepath = task?.filepath || "";
621
503
  const projectName = task?.projectName || task.file?.projectName || "";
622
504
  const project = this.ctx.projects.find((p) => p.name === projectName);
623
505
  let name = getFullName(task, c.dim(" > "));
624
- if (filepath) {
625
- name += c.dim(` [ ${this.relative(filepath)} ]`);
626
- }
506
+ if (filepath) name += c.dim(` [ ${this.relative(filepath)} ]`);
627
507
  this.ctx.logger.error(`${c.bgRed(c.bold(" FAIL "))} ${formatProjectName(project)}${name}`);
628
508
  }
629
509
  const screenshotPaths = tasks.map((t) => t.meta?.failScreenshotPath).filter((screenshot) => screenshot != null);
@@ -633,10 +513,24 @@ class BaseReporter {
633
513
  screenshotPaths,
634
514
  task: tasks[0]
635
515
  });
516
+ if (tasks[0].type === "test" && tasks[0].annotations.length) {
517
+ const test = this.ctx.state.getReportedEntity(tasks[0]);
518
+ this.printAnnotations(test, "error", 1);
519
+ this.error();
520
+ }
636
521
  errorDivider();
637
522
  }
638
523
  }
639
524
  }
525
+ function deepEqual(a, b) {
526
+ if (a === b) return true;
527
+ if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
528
+ const keysA = Object.keys(a);
529
+ const keysB = Object.keys(b);
530
+ if (keysA.length !== keysB.length) return false;
531
+ for (const key of keysA) if (!keysB.includes(key) || !deepEqual(a[key], b[key])) return false;
532
+ return true;
533
+ }
640
534
  function sum(items, cb) {
641
535
  return items.reduce((total, next) => {
642
536
  return total + Math.max(cb(next) || 0, 0);
@@ -650,7 +544,7 @@ class BasicReporter extends BaseReporter {
650
544
  }
651
545
  onInit(ctx) {
652
546
  super.onInit(ctx);
653
- ctx.logger.deprecate(`'basic' reporter is deprecated and will be removed in Vitest v3.\n` + `Remove 'basic' from 'reporters' option. To match 'basic' reporter 100%, use configuration:\n${JSON.stringify({ test: { reporters: [["default", { summary: false }]] } }, null, 2)}`);
547
+ ctx.logger.deprecate(`'basic' reporter is deprecated and will be removed in Vitest v3.\nRemove 'basic' from 'reporters' option. To match 'basic' reporter 100%, use configuration:\n${JSON.stringify({ test: { reporters: [["default", { summary: false }]] } }, null, 2)}`);
654
548
  }
655
549
  reportSummary(files, errors) {
656
550
  // non-tty mode doesn't add a new line
@@ -774,9 +668,7 @@ class BlobReporter {
774
668
  this.options = options;
775
669
  }
776
670
  onInit(ctx) {
777
- if (ctx.config.watch) {
778
- throw new Error("Blob reporter is not supported in watch mode");
779
- }
671
+ if (ctx.config.watch) throw new Error("Blob reporter is not supported in watch mode");
780
672
  this.ctx = ctx;
781
673
  this.start = performance.now();
782
674
  }
@@ -789,9 +681,7 @@ class BlobReporter {
789
681
  }
790
682
  const modules = this.ctx.projects.map((project) => {
791
683
  return [project.name, [...project.vite.moduleGraph.idToModuleMap.entries()].map((mod) => {
792
- if (!mod[1].file) {
793
- return null;
794
- }
684
+ if (!mod[1].file) return null;
795
685
  return [
796
686
  mod[0],
797
687
  mod[1].file,
@@ -815,9 +705,7 @@ class BlobReporter {
815
705
  async function writeBlob(content, filename) {
816
706
  const report = stringify(content);
817
707
  const dir = dirname(filename);
818
- if (!existsSync(dir)) {
819
- await mkdir(dir, { recursive: true });
820
- }
708
+ if (!existsSync(dir)) await mkdir(dir, { recursive: true });
821
709
  await writeFile(filename, report, "utf-8");
822
710
  }
823
711
  async function readBlobs(currentVersion, blobsDirectory, projectsArray) {
@@ -827,14 +715,10 @@ async function readBlobs(currentVersion, blobsDirectory, projectsArray) {
827
715
  const promises = blobsFiles.map(async (filename) => {
828
716
  const fullPath = resolve(resolvedDir, filename);
829
717
  const stats = await stat(fullPath);
830
- if (!stats.isFile()) {
831
- throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a file`);
832
- }
718
+ if (!stats.isFile()) throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a file`);
833
719
  const content = await readFile(fullPath, "utf-8");
834
720
  const [version, files, errors, moduleKeys, coverage, executionTime] = parse(content);
835
- if (!version) {
836
- throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a valid blob file`);
837
- }
721
+ if (!version) throw new TypeError(`vitest.mergeReports() expects all paths in "${blobsDirectory}" to be files generated by the blob reporter, but "${filename}" is not a valid blob file`);
838
722
  return {
839
723
  version,
840
724
  files,
@@ -846,24 +730,16 @@ async function readBlobs(currentVersion, blobsDirectory, projectsArray) {
846
730
  };
847
731
  });
848
732
  const blobs = await Promise.all(promises);
849
- if (!blobs.length) {
850
- throw new Error(`vitest.mergeReports() requires at least one blob file in "${blobsDirectory}" directory, but none were found`);
851
- }
733
+ if (!blobs.length) throw new Error(`vitest.mergeReports() requires at least one blob file in "${blobsDirectory}" directory, but none were found`);
852
734
  const versions = new Set(blobs.map((blob) => blob.version));
853
- if (versions.size > 1) {
854
- throw new Error(`vitest.mergeReports() requires all blob files to be generated by the same Vitest version, received\n\n${blobs.map((b) => `- "${b.file}" uses v${b.version}`).join("\n")}`);
855
- }
856
- if (!versions.has(currentVersion)) {
857
- throw new Error(`the blobs in "${blobsDirectory}" were generated by a different version of Vitest. Expected v${currentVersion}, but received v${blobs[0].version}`);
858
- }
735
+ if (versions.size > 1) throw new Error(`vitest.mergeReports() requires all blob files to be generated by the same Vitest version, received\n\n${blobs.map((b) => `- "${b.file}" uses v${b.version}`).join("\n")}`);
736
+ if (!versions.has(currentVersion)) throw new Error(`the blobs in "${blobsDirectory}" were generated by a different version of Vitest. Expected v${currentVersion}, but received v${blobs[0].version}`);
859
737
  // fake module graph - it is used to check if module is imported, but we don't use values inside
860
738
  const projects = Object.fromEntries(projectsArray.map((p) => [p.name, p]));
861
739
  blobs.forEach((blob) => {
862
740
  blob.moduleKeys.forEach(([projectName, moduleIds]) => {
863
741
  const project = projects[projectName];
864
- if (!project) {
865
- return;
866
- }
742
+ if (!project) return;
867
743
  moduleIds.forEach(([moduleId, file, url]) => {
868
744
  const moduleNode = project.vite.moduleGraph.createFileOnlyEntry(file);
869
745
  moduleNode.url = url;
@@ -902,7 +778,7 @@ class WindowRenderer {
902
778
  options;
903
779
  streams;
904
780
  buffer = [];
905
- renderInterval = undefined;
781
+ renderInterval = void 0;
906
782
  renderScheduled = false;
907
783
  windowHeight = 0;
908
784
  finished = false;
@@ -954,9 +830,7 @@ class WindowRenderer {
954
830
  }
955
831
  }
956
832
  flushBuffer() {
957
- if (this.buffer.length === 0) {
958
- return this.render();
959
- }
833
+ if (this.buffer.length === 0) return this.render();
960
834
  let current;
961
835
  // Concatenate same types into a single render
962
836
  for (const next of this.buffer.splice(0)) {
@@ -971,9 +845,7 @@ class WindowRenderer {
971
845
  }
972
846
  current.message += next.message;
973
847
  }
974
- if (current) {
975
- this.render(current?.message, current?.type);
976
- }
848
+ if (current) this.render(current?.message, current?.type);
977
849
  }
978
850
  render(message, type = "output") {
979
851
  if (this.finished) {
@@ -983,45 +855,30 @@ class WindowRenderer {
983
855
  const windowContent = this.options.getWindow();
984
856
  const rowCount = getRenderedRowCount(windowContent, this.options.logger.getColumns());
985
857
  let padding = this.windowHeight - rowCount;
986
- if (padding > 0 && message) {
987
- padding -= getRenderedRowCount([message], this.options.logger.getColumns());
988
- }
858
+ if (padding > 0 && message) padding -= getRenderedRowCount([message], this.options.logger.getColumns());
989
859
  this.write(SYNC_START);
990
860
  this.clearWindow();
991
- if (message) {
992
- this.write(message, type);
993
- }
994
- if (padding > 0) {
995
- this.write("\n".repeat(padding));
996
- }
861
+ if (message) this.write(message, type);
862
+ if (padding > 0) this.write("\n".repeat(padding));
997
863
  this.write(windowContent.join("\n"));
998
864
  this.write(SYNC_END);
999
865
  this.windowHeight = rowCount + Math.max(0, padding);
1000
866
  }
1001
867
  clearWindow() {
1002
- if (this.windowHeight === 0) {
1003
- return;
1004
- }
868
+ if (this.windowHeight === 0) return;
1005
869
  this.write(CLEAR_LINE);
1006
- for (let i = 1; i < this.windowHeight; i++) {
1007
- this.write(`${MOVE_CURSOR_ONE_ROW_UP}${CLEAR_LINE}`);
1008
- }
870
+ for (let i = 1; i < this.windowHeight; i++) this.write(`${MOVE_CURSOR_ONE_ROW_UP}${CLEAR_LINE}`);
1009
871
  this.windowHeight = 0;
1010
872
  }
1011
873
  interceptStream(stream, type) {
1012
874
  const original = stream.write;
1013
875
  // @ts-expect-error -- not sure how 2 overloads should be typed
1014
876
  stream.write = (chunk, _, callback) => {
1015
- if (chunk) {
1016
- if (this.finished) {
1017
- this.write(chunk.toString(), type);
1018
- } else {
1019
- this.buffer.push({
1020
- type,
1021
- message: chunk.toString()
1022
- });
1023
- }
1024
- }
877
+ if (chunk) if (this.finished) this.write(chunk.toString(), type);
878
+ else this.buffer.push({
879
+ type,
880
+ message: chunk.toString()
881
+ });
1025
882
  callback?.();
1026
883
  };
1027
884
  return function restore() {
@@ -1056,13 +913,13 @@ class SummaryReporter {
1056
913
  tests = emptyCounters();
1057
914
  maxParallelTests = 0;
1058
915
  /** Currently running test modules, may include finished test modules too */
1059
- runningModules = new Map();
916
+ runningModules = /* @__PURE__ */ new Map();
1060
917
  /** ID of finished `this.runningModules` that are currently being shown */
1061
- finishedModules = new Map();
918
+ finishedModules = /* @__PURE__ */ new Map();
1062
919
  startTime = "";
1063
920
  currentTime = 0;
1064
921
  duration = 0;
1065
- durationInterval = undefined;
922
+ durationInterval = void 0;
1066
923
  onInit(ctx, options = {}) {
1067
924
  this.ctx = ctx;
1068
925
  this.options = {
@@ -1116,9 +973,7 @@ class SummaryReporter {
1116
973
  }
1117
974
  onHookStart(options) {
1118
975
  const stats = this.getHookStats(options);
1119
- if (!stats) {
1120
- return;
1121
- }
976
+ if (!stats) return;
1122
977
  const hook = {
1123
978
  name: options.name,
1124
979
  visible: false,
@@ -1134,21 +989,15 @@ class SummaryReporter {
1134
989
  }
1135
990
  onHookEnd(options) {
1136
991
  const stats = this.getHookStats(options);
1137
- if (stats?.hook?.name !== options.name) {
1138
- return;
1139
- }
992
+ if (stats?.hook?.name !== options.name) return;
1140
993
  stats.hook.onFinish();
1141
994
  stats.hook.visible = false;
1142
995
  }
1143
996
  onTestCaseReady(test) {
1144
997
  // Track slow running tests only on verbose mode
1145
- if (!this.options.verbose) {
1146
- return;
1147
- }
998
+ if (!this.options.verbose) return;
1148
999
  const stats = this.runningModules.get(test.module.id);
1149
- if (!stats || stats.tests.has(test.id)) {
1150
- return;
1151
- }
1000
+ if (!stats || stats.tests.has(test.id)) return;
1152
1001
  const slowTest = {
1153
1002
  name: test.name,
1154
1003
  visible: false,
@@ -1166,59 +1015,42 @@ class SummaryReporter {
1166
1015
  }
1167
1016
  onTestCaseResult(test) {
1168
1017
  const stats = this.runningModules.get(test.module.id);
1169
- if (!stats) {
1170
- return;
1171
- }
1018
+ if (!stats) return;
1172
1019
  stats.tests.get(test.id)?.onFinish();
1173
1020
  stats.tests.delete(test.id);
1174
1021
  stats.completed++;
1175
1022
  const result = test.result();
1176
- if (result?.state === "passed") {
1177
- this.tests.passed++;
1178
- } else if (result?.state === "failed") {
1179
- this.tests.failed++;
1180
- } else if (!result?.state || result?.state === "skipped") {
1181
- this.tests.skipped++;
1182
- }
1023
+ if (result?.state === "passed") this.tests.passed++;
1024
+ else if (result?.state === "failed") this.tests.failed++;
1025
+ else if (!result?.state || result?.state === "skipped") this.tests.skipped++;
1183
1026
  this.renderer.schedule();
1184
1027
  }
1185
1028
  onTestModuleEnd(module) {
1186
1029
  const state = module.state();
1187
1030
  this.modules.completed++;
1188
- if (state === "passed") {
1189
- this.modules.passed++;
1190
- } else if (state === "failed") {
1191
- this.modules.failed++;
1192
- } else if (module.task.mode === "todo" && state === "skipped") {
1193
- this.modules.todo++;
1194
- } else if (state === "skipped") {
1195
- this.modules.skipped++;
1196
- }
1031
+ if (state === "passed") this.modules.passed++;
1032
+ else if (state === "failed") this.modules.failed++;
1033
+ else if (module.task.mode === "todo" && state === "skipped") this.modules.todo++;
1034
+ else if (state === "skipped") this.modules.skipped++;
1197
1035
  const left = this.modules.total - this.modules.completed;
1198
1036
  // Keep finished tests visible in summary for a while if there are more tests left.
1199
1037
  // When a new test starts in onTestModuleQueued it will take this ones place.
1200
1038
  // This reduces flickering by making summary more stable.
1201
- if (left > this.maxParallelTests) {
1202
- this.finishedModules.set(module.id, setTimeout(() => {
1203
- this.removeTestModule(module.id);
1204
- }, FINISHED_TEST_CLEANUP_TIME_MS).unref());
1205
- } else {
1206
- // Run is about to end as there are less tests left than whole run had parallel at max.
1207
- // Remove finished test immediately.
1039
+ if (left > this.maxParallelTests) this.finishedModules.set(module.id, setTimeout(() => {
1208
1040
  this.removeTestModule(module.id);
1209
- }
1041
+ }, FINISHED_TEST_CLEANUP_TIME_MS).unref());
1042
+ else
1043
+ // Run is about to end as there are less tests left than whole run had parallel at max.
1044
+ // Remove finished test immediately.
1045
+ this.removeTestModule(module.id);
1210
1046
  this.renderer.schedule();
1211
1047
  }
1212
1048
  getHookStats({ entity }) {
1213
1049
  // Track slow running hooks only on verbose mode
1214
- if (!this.options.verbose) {
1215
- return;
1216
- }
1050
+ if (!this.options.verbose) return;
1217
1051
  const module = entity.type === "module" ? entity : entity.module;
1218
1052
  const stats = this.runningModules.get(module.id);
1219
- if (!stats) {
1220
- return;
1221
- }
1053
+ if (!stats) return;
1222
1054
  return entity.type === "test" ? stats.tests.get(entity.id) : stats;
1223
1055
  }
1224
1056
  createSummary() {
@@ -1234,14 +1066,10 @@ class SummaryReporter {
1234
1066
  const elapsed = this.currentTime - task.startTime;
1235
1067
  const icon = index === slowTasks.length - 1 ? F_TREE_NODE_END : F_TREE_NODE_MIDDLE;
1236
1068
  summary.push(c.bold(c.yellow(` ${icon} `)) + task.name + c.bold(c.yellow(` ${formatTime(Math.max(0, elapsed))}`)));
1237
- if (task.hook?.visible) {
1238
- summary.push(c.bold(c.yellow(` ${F_TREE_NODE_END} `)) + task.hook.name);
1239
- }
1069
+ if (task.hook?.visible) summary.push(c.bold(c.yellow(` ${F_TREE_NODE_END} `)) + task.hook.name);
1240
1070
  }
1241
1071
  }
1242
- if (this.runningModules.size > 0) {
1243
- summary.push("");
1244
- }
1072
+ if (this.runningModules.size > 0) summary.push("");
1245
1073
  summary.push(padSummaryTitle("Test Files") + getStateString(this.modules));
1246
1074
  summary.push(padSummaryTitle("Tests") + getStateString(this.tests));
1247
1075
  summary.push(padSummaryTitle("Start at") + this.startTime);
@@ -1251,16 +1079,14 @@ class SummaryReporter {
1251
1079
  }
1252
1080
  startTimers() {
1253
1081
  const start = performance.now();
1254
- this.startTime = formatTimeString(new Date());
1082
+ this.startTime = formatTimeString(/* @__PURE__ */ new Date());
1255
1083
  this.durationInterval = setInterval(() => {
1256
1084
  this.currentTime = performance.now();
1257
1085
  this.duration = this.currentTime - start;
1258
1086
  }, DURATION_UPDATE_INTERVAL_MS).unref();
1259
1087
  }
1260
1088
  removeTestModule(id) {
1261
- if (!id) {
1262
- return;
1263
- }
1089
+ if (!id) return;
1264
1090
  const testFile = this.runningModules.get(id);
1265
1091
  testFile?.hook?.onFinish();
1266
1092
  testFile?.tests?.forEach((test) => test.onFinish());
@@ -1288,12 +1114,8 @@ function getStateString(entry) {
1288
1114
  ].filter(Boolean).join(c.dim(" | ")) + c.gray(` (${entry.total})`);
1289
1115
  }
1290
1116
  function sortRunningModules(a, b) {
1291
- if ((a.projectName || "") > (b.projectName || "")) {
1292
- return 1;
1293
- }
1294
- if ((a.projectName || "") < (b.projectName || "")) {
1295
- return -1;
1296
- }
1117
+ if ((a.projectName || "") > (b.projectName || "")) return 1;
1118
+ if ((a.projectName || "") < (b.projectName || "")) return -1;
1297
1119
  return a.filename.localeCompare(b.filename);
1298
1120
  }
1299
1121
  function initializeStats(module) {
@@ -1303,7 +1125,7 @@ function initializeStats(module) {
1303
1125
  filename: module.task.name,
1304
1126
  projectName: module.project.name,
1305
1127
  projectColor: module.project.color,
1306
- tests: new Map(),
1128
+ tests: /* @__PURE__ */ new Map(),
1307
1129
  typecheck: !!module.task.meta.typecheck
1308
1130
  };
1309
1131
  }
@@ -1317,21 +1139,13 @@ class DefaultReporter extends BaseReporter {
1317
1139
  summary: true,
1318
1140
  ...options
1319
1141
  };
1320
- if (!this.isTTY) {
1321
- this.options.summary = false;
1322
- }
1323
- if (this.options.summary) {
1324
- this.summary = new SummaryReporter();
1325
- }
1142
+ if (!this.isTTY) this.options.summary = false;
1143
+ if (this.options.summary) this.summary = new SummaryReporter();
1326
1144
  }
1327
1145
  onTestRunStart(specifications) {
1328
1146
  if (this.isTTY) {
1329
- if (this.renderSucceed === undefined) {
1330
- this.renderSucceed = !!this.renderSucceed;
1331
- }
1332
- if (this.renderSucceed !== true) {
1333
- this.renderSucceed = specifications.length <= 1;
1334
- }
1147
+ if (this.renderSucceed === void 0) this.renderSucceed = !!this.renderSucceed;
1148
+ if (this.renderSucceed !== true) this.renderSucceed = specifications.length <= 1;
1335
1149
  }
1336
1150
  this.summary?.onTestRunStart(specifications);
1337
1151
  }
@@ -1369,8 +1183,8 @@ class DefaultReporter extends BaseReporter {
1369
1183
 
1370
1184
  class DotReporter extends BaseReporter {
1371
1185
  renderer;
1372
- tests = new Map();
1373
- finishedTests = new Set();
1186
+ tests = /* @__PURE__ */ new Map();
1187
+ finishedTests = /* @__PURE__ */ new Set();
1374
1188
  onInit(ctx) {
1375
1189
  super.onInit(ctx);
1376
1190
  if (this.isTTY) {
@@ -1382,9 +1196,7 @@ class DotReporter extends BaseReporter {
1382
1196
  }
1383
1197
  }
1384
1198
  printTestModule(testModule) {
1385
- if (!this.isTTY) {
1386
- super.printTestModule(testModule);
1387
- }
1199
+ if (!this.isTTY) super.printTestModule(testModule);
1388
1200
  }
1389
1201
  onWatcherRerun(files, trigger) {
1390
1202
  this.tests.clear();
@@ -1401,15 +1213,12 @@ class DotReporter extends BaseReporter {
1401
1213
  super.onFinished(files, errors);
1402
1214
  }
1403
1215
  onTestModuleCollected(module) {
1404
- for (const test of module.children.allTests()) {
1405
- // Dot reporter marks pending tests as running
1406
- this.onTestCaseReady(test);
1407
- }
1216
+ for (const test of module.children.allTests())
1217
+ // Dot reporter marks pending tests as running
1218
+ this.onTestCaseReady(test);
1408
1219
  }
1409
1220
  onTestCaseReady(test) {
1410
- if (this.finishedTests.has(test.id)) {
1411
- return;
1412
- }
1221
+ if (this.finishedTests.has(test.id)) return;
1413
1222
  this.tests.set(test.id, test.result().state || "run");
1414
1223
  this.renderer?.schedule();
1415
1224
  }
@@ -1421,24 +1230,16 @@ class DotReporter extends BaseReporter {
1421
1230
  }
1422
1231
  onTestModuleEnd(testModule) {
1423
1232
  super.onTestModuleEnd(testModule);
1424
- if (!this.isTTY) {
1425
- return;
1426
- }
1233
+ if (!this.isTTY) return;
1427
1234
  const columns = this.ctx.logger.getColumns();
1428
- if (this.tests.size < columns) {
1429
- return;
1430
- }
1235
+ if (this.tests.size < columns) return;
1431
1236
  const finishedTests = Array.from(this.tests).filter((entry) => entry[1] !== "pending");
1432
- if (finishedTests.length < columns) {
1433
- return;
1434
- }
1237
+ if (finishedTests.length < columns) return;
1435
1238
  // Remove finished tests from state and render them in static output
1436
1239
  const states = [];
1437
1240
  let count = 0;
1438
1241
  for (const [id, state] of finishedTests) {
1439
- if (count++ >= columns) {
1440
- break;
1441
- }
1242
+ if (count++ >= columns) break;
1442
1243
  this.tests.delete(id);
1443
1244
  states.push(state);
1444
1245
  }
@@ -1529,13 +1330,11 @@ function printError(error, ctx, logger, options) {
1529
1330
  parseErrorStacktrace(error) {
1530
1331
  // browser stack trace needs to be processed differently,
1531
1332
  // so there is a separate method for that
1532
- if (options.task?.file.pool === "browser" && project.browser) {
1533
- return project.browser.parseErrorStacktrace(error, { ignoreStackEntries: options.fullStack ? [] : undefined });
1534
- }
1333
+ if (options.task?.file.pool === "browser" && project.browser) return project.browser.parseErrorStacktrace(error, { ignoreStackEntries: options.fullStack ? [] : void 0 });
1535
1334
  // node.js stack trace already has correct source map locations
1536
1335
  return parseErrorStacktrace(error, {
1537
1336
  frameFilter: project.config.onStackTrace,
1538
- ignoreStackEntries: options.fullStack ? [] : undefined
1337
+ ignoreStackEntries: options.fullStack ? [] : void 0
1539
1338
  });
1540
1339
  }
1541
1340
  });
@@ -1544,12 +1343,10 @@ function printErrorInner(error, project, options) {
1544
1343
  const { showCodeFrame = true, type, printProperties = true } = options;
1545
1344
  const logger = options.logger;
1546
1345
  let e = error;
1547
- if (isPrimitive(e)) {
1548
- e = {
1549
- message: String(error).split(/\n/g)[0],
1550
- stack: String(error)
1551
- };
1552
- }
1346
+ if (isPrimitive(e)) e = {
1347
+ message: String(error).split(/\n/g)[0],
1348
+ stack: String(error)
1349
+ };
1553
1350
  if (!e) {
1554
1351
  const error = new Error("unknown error");
1555
1352
  e = {
@@ -1570,21 +1367,15 @@ function printErrorInner(error, project, options) {
1570
1367
  return false;
1571
1368
  }
1572
1369
  });
1573
- if (type) {
1574
- printErrorType(type, project.vitest);
1575
- }
1370
+ if (type) printErrorType(type, project.vitest);
1576
1371
  printErrorMessage(e, logger);
1577
1372
  if (options.screenshotPaths?.length) {
1578
1373
  const length = options.screenshotPaths.length;
1579
1374
  logger.error(`\nFailure screenshot${length > 1 ? "s" : ""}:`);
1580
1375
  logger.error(options.screenshotPaths.map((p) => ` - ${c.dim(relative(process.cwd(), p))}`).join("\n"));
1581
- if (!e.diff) {
1582
- logger.error();
1583
- }
1584
- }
1585
- if (e.codeFrame) {
1586
- logger.error(`${e.codeFrame}\n`);
1376
+ if (!e.diff) logger.error();
1587
1377
  }
1378
+ if (e.codeFrame) logger.error(`${e.codeFrame}\n`);
1588
1379
  if ("__vitest_rollup_error__" in e) {
1589
1380
  // https://github.com/vitejs/vite/blob/95020ab49e12d143262859e095025cf02423c1d9/packages/vite/src/node/server/middlewares/error.ts#L25-L36
1590
1381
  const err = e.__vitest_rollup_error__;
@@ -1595,13 +1386,10 @@ function printErrorInner(error, project, options) {
1595
1386
  ].filter(Boolean).join("\n"));
1596
1387
  }
1597
1388
  // E.g. AssertionError from assert does not set showDiff but has both actual and expected properties
1598
- if (e.diff) {
1599
- logger.error(`\n${e.diff}\n`);
1600
- }
1389
+ if (e.diff) logger.error(`\n${e.diff}\n`);
1601
1390
  // if the error provide the frame
1602
- if (e.frame) {
1603
- logger.error(c.yellow(e.frame));
1604
- } else {
1391
+ if (e.frame) logger.error(c.yellow(e.frame));
1392
+ else {
1605
1393
  const errorProperties = printProperties ? getErrorProperties(e) : {};
1606
1394
  printStack(logger, project, stacks, nearest, errorProperties, (s) => {
1607
1395
  if (showCodeFrame && s === nearest && nearest) {
@@ -1614,15 +1402,11 @@ function printErrorInner(error, project, options) {
1614
1402
  const testName = e.VITEST_TEST_NAME;
1615
1403
  const afterEnvTeardown = e.VITEST_AFTER_ENV_TEARDOWN;
1616
1404
  // testName has testPath inside
1617
- if (testPath) {
1618
- logger.error(c.red(`This error originated in "${c.bold(relative(project.config.root, testPath))}" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.`));
1619
- }
1620
- if (testName) {
1621
- logger.error(c.red(`The latest test that might've caused the error is "${c.bold(testName)}". It might mean one of the following:` + "\n- The error was thrown, while Vitest was running this test." + "\n- If the error occurred after the test had been completed, this was the last documented test before it was thrown."));
1622
- }
1623
- if (afterEnvTeardown) {
1624
- logger.error(c.red("This error was caught after test environment was torn down. Make sure to cancel any running tasks before test finishes:" + "\n- cancel timeouts using clearTimeout and clearInterval" + "\n- wait for promises to resolve using the await keyword"));
1625
- }
1405
+ if (testPath) logger.error(c.red(`This error originated in "${c.bold(relative(project.config.root, testPath))}" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.`));
1406
+ if (testName) logger.error(c.red(`The latest test that might've caused the error is "${c.bold(testName)}". It might mean one of the following:
1407
+ - The error was thrown, while Vitest was running this test.
1408
+ - If the error occurred after the test had been completed, this was the last documented test before it was thrown.`));
1409
+ if (afterEnvTeardown) logger.error(c.red("This error was caught after test environment was torn down. Make sure to cancel any running tasks before test finishes:\n- cancel timeouts using clearTimeout and clearInterval\n- wait for promises to resolve using the await keyword"));
1626
1410
  if (typeof e.cause === "object" && e.cause && "name" in e.cause) {
1627
1411
  e.cause.name = `Caused by: ${e.cause.name}`;
1628
1412
  printErrorInner(e.cause, project, {
@@ -1631,17 +1415,15 @@ function printErrorInner(error, project, options) {
1631
1415
  parseErrorStacktrace: options.parseErrorStacktrace
1632
1416
  });
1633
1417
  }
1634
- handleImportOutsideModuleError(e.stack || e.stackStr || "", logger);
1418
+ handleImportOutsideModuleError(e.stack || "", logger);
1635
1419
  return { nearest };
1636
1420
  }
1637
1421
  function printErrorType(type, ctx) {
1638
1422
  ctx.logger.error(`\n${errorBanner(type)}`);
1639
1423
  }
1640
1424
  const skipErrorProperties = new Set([
1641
- "nameStr",
1642
1425
  "cause",
1643
1426
  "stacks",
1644
- "stackStr",
1645
1427
  "type",
1646
1428
  "showDiff",
1647
1429
  "ok",
@@ -1660,44 +1442,35 @@ const skipErrorProperties = new Set([
1660
1442
  "VITEST_TEST_NAME",
1661
1443
  "VITEST_TEST_PATH",
1662
1444
  "VITEST_AFTER_ENV_TEARDOWN",
1445
+ "__vitest_rollup_error__",
1663
1446
  ...Object.getOwnPropertyNames(Error.prototype),
1664
1447
  ...Object.getOwnPropertyNames(Object.prototype)
1665
1448
  ]);
1666
1449
  function getErrorProperties(e) {
1667
1450
  const errorObject = Object.create(null);
1668
- if (e.name === "AssertionError") {
1669
- return errorObject;
1670
- }
1671
- for (const key of Object.getOwnPropertyNames(e)) {
1672
- // print the original stack if it was ever changed manually by the user
1673
- if (key === "stack" && e[key] != null && typeof e[key] !== "string") {
1674
- errorObject[key] = e[key];
1675
- } else if (key !== "stack" && !skipErrorProperties.has(key)) {
1676
- errorObject[key] = e[key];
1677
- }
1678
- }
1451
+ if (e.name === "AssertionError") return errorObject;
1452
+ for (const key of Object.getOwnPropertyNames(e))
1453
+ // print the original stack if it was ever changed manually by the user
1454
+ if (key === "stack" && e[key] != null && typeof e[key] !== "string") errorObject[key] = e[key];
1455
+ else if (key !== "stack" && !skipErrorProperties.has(key)) errorObject[key] = e[key];
1679
1456
  return errorObject;
1680
1457
  }
1681
1458
  const esmErrors = ["Cannot use import statement outside a module", "Unexpected token 'export'"];
1682
1459
  function handleImportOutsideModuleError(stack, logger) {
1683
- if (!esmErrors.some((e) => stack.includes(e))) {
1684
- return;
1685
- }
1460
+ if (!esmErrors.some((e) => stack.includes(e))) return;
1686
1461
  const path = normalize(stack.split("\n")[0].trim());
1687
1462
  let name = path.split("/node_modules/").pop() || "";
1688
- if (name?.startsWith("@")) {
1689
- name = name.split("/").slice(0, 2).join("/");
1690
- } else {
1691
- name = name.split("/")[0];
1692
- }
1693
- if (name) {
1694
- printModuleWarningForPackage(logger, path, name);
1695
- } else {
1696
- printModuleWarningForSourceCode(logger, path);
1697
- }
1463
+ if (name?.startsWith("@")) name = name.split("/").slice(0, 2).join("/");
1464
+ else name = name.split("/")[0];
1465
+ if (name) printModuleWarningForPackage(logger, path, name);
1466
+ else printModuleWarningForSourceCode(logger, path);
1698
1467
  }
1699
1468
  function printModuleWarningForPackage(logger, path, name) {
1700
- logger.error(c.yellow(`Module ${path} seems to be an ES Module but shipped in a CommonJS package. ` + `You might want to create an issue to the package ${c.bold(`"${name}"`)} asking ` + "them to ship the file in .mjs extension or add \"type\": \"module\" in their package.json." + "\n\n" + "As a temporary workaround you can try to inline the package by updating your config:" + "\n\n" + c.gray(c.dim("// vitest.config.js")) + "\n" + c.green(`export default {
1469
+ logger.error(c.yellow(`Module ${path} seems to be an ES Module but shipped in a CommonJS package. You might want to create an issue to the package ${c.bold(`"${name}"`)} asking them to ship the file in .mjs extension or add "type": "module" in their package.json.
1470
+
1471
+ As a temporary workaround you can try to inline the package by updating your config:
1472
+
1473
+ ` + c.gray(c.dim("// vitest.config.js")) + "\n" + c.green(`export default {
1701
1474
  test: {
1702
1475
  server: {
1703
1476
  deps: {
@@ -1710,20 +1483,18 @@ function printModuleWarningForPackage(logger, path, name) {
1710
1483
  }\n`)));
1711
1484
  }
1712
1485
  function printModuleWarningForSourceCode(logger, path) {
1713
- logger.error(c.yellow(`Module ${path} seems to be an ES Module but shipped in a CommonJS package. ` + "To fix this issue, change the file extension to .mjs or add \"type\": \"module\" in your package.json."));
1486
+ logger.error(c.yellow(`Module ${path} seems to be an ES Module but shipped in a CommonJS package. To fix this issue, change the file extension to .mjs or add "type": "module" in your package.json.`));
1714
1487
  }
1715
1488
  function printErrorMessage(error, logger) {
1716
- const errorName = error.name || error.nameStr || "Unknown Error";
1489
+ const errorName = error.name || "Unknown Error";
1717
1490
  if (!error.message) {
1718
1491
  logger.error(error);
1719
1492
  return;
1720
1493
  }
1721
- if (error.message.length > 5e3) {
1722
- // Protect against infinite stack trace in tinyrainbow
1723
- logger.error(`${c.red(c.bold(errorName))}: ${error.message}`);
1724
- } else {
1725
- logger.error(c.red(`${c.bold(errorName)}: ${error.message}`));
1726
- }
1494
+ if (error.message.length > 5e3)
1495
+ // Protect against infinite stack trace in tinyrainbow
1496
+ logger.error(`${c.red(c.bold(errorName))}: ${error.message}`);
1497
+ else logger.error(c.red(`${c.bold(errorName)}: ${error.message}`));
1727
1498
  }
1728
1499
  function printStack(logger, project, stack, highlight, errorProperties, onStack) {
1729
1500
  for (const frame of stack) {
@@ -1732,9 +1503,7 @@ function printStack(logger, project, stack, highlight, errorProperties, onStack)
1732
1503
  logger.error(color(` ${c.dim(F_POINTER)} ${[frame.method, `${path}:${c.dim(`${frame.line}:${frame.column}`)}`].filter(Boolean).join(" ")}`));
1733
1504
  onStack?.(frame);
1734
1505
  }
1735
- if (stack.length) {
1736
- logger.error();
1737
- }
1506
+ if (stack.length) logger.error();
1738
1507
  if (hasProperties(errorProperties)) {
1739
1508
  logger.error(c.red(c.dim(divider())));
1740
1509
  const propertiesString = inspect(errorProperties);
@@ -1743,9 +1512,7 @@ function printStack(logger, project, stack, highlight, errorProperties, onStack)
1743
1512
  }
1744
1513
  function hasProperties(obj) {
1745
1514
  // eslint-disable-next-line no-unreachable-loop
1746
- for (const _key in obj) {
1747
- return true;
1748
- }
1515
+ for (const _key in obj) return true;
1749
1516
  return false;
1750
1517
  }
1751
1518
  function generateCodeFrame(source, indent = 0, loc, range = 2) {
@@ -1760,14 +1527,10 @@ function generateCodeFrame(source, indent = 0, loc, range = 2) {
1760
1527
  count += lines[i].length + nl;
1761
1528
  if (count >= start) {
1762
1529
  for (let j = i - range; j <= i + range || end > count; j++) {
1763
- if (j < 0 || j >= lines.length) {
1764
- continue;
1765
- }
1530
+ if (j < 0 || j >= lines.length) continue;
1766
1531
  const lineLength = lines[j].length;
1767
1532
  // too long, maybe it's a minified file, skip for codeframe
1768
- if (stripVTControlCharacters(lines[j]).length > 200) {
1769
- return "";
1770
- }
1533
+ if (stripVTControlCharacters(lines[j]).length > 200) return "";
1771
1534
  res.push(lineNo(j + 1) + truncateString(lines[j].replace(/\t/g, " "), columns - 5 - indent));
1772
1535
  if (j === i) {
1773
1536
  // push underline
@@ -1785,9 +1548,7 @@ function generateCodeFrame(source, indent = 0, loc, range = 2) {
1785
1548
  break;
1786
1549
  }
1787
1550
  }
1788
- if (indent) {
1789
- res = res.map((line) => " ".repeat(indent) + line);
1790
- }
1551
+ if (indent) res = res.map((line) => " ".repeat(indent) + line);
1791
1552
  return res.join("\n");
1792
1553
  }
1793
1554
  function lineNo(no = "") {
@@ -1795,7 +1556,7 @@ function lineNo(no = "") {
1795
1556
  }
1796
1557
 
1797
1558
  class GithubActionsReporter {
1798
- ctx = undefined;
1559
+ ctx = void 0;
1799
1560
  options;
1800
1561
  constructor(options = {}) {
1801
1562
  this.options = options;
@@ -1803,32 +1564,41 @@ class GithubActionsReporter {
1803
1564
  onInit(ctx) {
1804
1565
  this.ctx = ctx;
1805
1566
  }
1567
+ onTestCaseAnnotate(testCase, annotation) {
1568
+ if (!annotation.location) return;
1569
+ const type = getTitle(annotation.type);
1570
+ const formatted = formatMessage({
1571
+ command: getType(annotation.type),
1572
+ properties: {
1573
+ file: annotation.location.file,
1574
+ line: String(annotation.location.line),
1575
+ column: String(annotation.location.column),
1576
+ ...type && { title: type }
1577
+ },
1578
+ message: stripVTControlCharacters(annotation.message)
1579
+ });
1580
+ this.ctx.logger.log(`\n${formatted}`);
1581
+ }
1806
1582
  onFinished(files = [], errors = []) {
1807
1583
  // collect all errors and associate them with projects
1808
1584
  const projectErrors = new Array();
1809
- for (const error of errors) {
1810
- projectErrors.push({
1811
- project: this.ctx.getRootProject(),
1812
- title: "Unhandled error",
1813
- error
1814
- });
1815
- }
1585
+ for (const error of errors) projectErrors.push({
1586
+ project: this.ctx.getRootProject(),
1587
+ title: "Unhandled error",
1588
+ error
1589
+ });
1816
1590
  for (const file of files) {
1817
1591
  const tasks = getTasks(file);
1818
1592
  const project = this.ctx.getProjectByName(file.projectName || "");
1819
1593
  for (const task of tasks) {
1820
- if (task.result?.state !== "fail") {
1821
- continue;
1822
- }
1594
+ if (task.result?.state !== "fail") continue;
1823
1595
  const title = getFullName(task, " > ");
1824
- for (const error of task.result?.errors ?? []) {
1825
- projectErrors.push({
1826
- project,
1827
- title,
1828
- error,
1829
- file
1830
- });
1831
- }
1596
+ for (const error of task.result?.errors ?? []) projectErrors.push({
1597
+ project,
1598
+ title,
1599
+ error,
1600
+ file
1601
+ });
1832
1602
  }
1833
1603
  }
1834
1604
  const onWritePath = this.options.onWritePath ?? defaultOnWritePath;
@@ -1839,9 +1609,7 @@ class GithubActionsReporter {
1839
1609
  task: file
1840
1610
  });
1841
1611
  const stack = result?.nearest;
1842
- if (!stack) {
1843
- continue;
1844
- }
1612
+ if (!stack) continue;
1845
1613
  const formatted = formatMessage({
1846
1614
  command: "error",
1847
1615
  properties: {
@@ -1856,6 +1624,19 @@ class GithubActionsReporter {
1856
1624
  }
1857
1625
  }
1858
1626
  }
1627
+ const BUILT_IN_TYPES = [
1628
+ "notice",
1629
+ "error",
1630
+ "warning"
1631
+ ];
1632
+ function getTitle(type) {
1633
+ if (BUILT_IN_TYPES.includes(type)) return void 0;
1634
+ return type;
1635
+ }
1636
+ function getType(type) {
1637
+ if (BUILT_IN_TYPES.includes(type)) return type;
1638
+ return "notice";
1639
+ }
1859
1640
  function defaultOnWritePath(path) {
1860
1641
  return path;
1861
1642
  }
@@ -1926,9 +1707,7 @@ class JsonReporter {
1926
1707
  for (const file of files) {
1927
1708
  const tests = getTests([file]);
1928
1709
  let startTime = tests.reduce((prev, next) => Math.min(prev, next.result?.startTime ?? Number.POSITIVE_INFINITY), Number.POSITIVE_INFINITY);
1929
- if (startTime === Number.POSITIVE_INFINITY) {
1930
- startTime = this.start;
1931
- }
1710
+ if (startTime === Number.POSITIVE_INFINITY) startTime = this.start;
1932
1711
  const endTime = tests.reduce((prev, next) => Math.max(prev, (next.result?.startTime ?? 0) + (next.result?.duration ?? 0)), startTime);
1933
1712
  const assertionResults = tests.map((t) => {
1934
1713
  const ancestorTitles = [];
@@ -1949,9 +1728,7 @@ class JsonReporter {
1949
1728
  meta: t.meta
1950
1729
  };
1951
1730
  });
1952
- if (tests.some((t) => t.result?.state === "run" || t.result?.state === "queued")) {
1953
- this.ctx.logger.warn("WARNING: Some tests are still running when generating the JSON report." + "This is likely an internal bug in Vitest." + "Please report it to https://github.com/vitest-dev/vitest/issues");
1954
- }
1731
+ if (tests.some((t) => t.result?.state === "run" || t.result?.state === "queued")) this.ctx.logger.warn("WARNING: Some tests are still running when generating the JSON report.This is likely an internal bug in Vitest.Please report it to https://github.com/vitest-dev/vitest/issues");
1955
1732
  const hasFailedTests = tests.some((t) => t.result?.state === "fail");
1956
1733
  testResults.push({
1957
1734
  assertionResults,
@@ -1993,14 +1770,10 @@ class JsonReporter {
1993
1770
  if (outputFile) {
1994
1771
  const reportFile = resolve(this.ctx.config.root, outputFile);
1995
1772
  const outputDirectory = dirname(reportFile);
1996
- if (!existsSync(outputDirectory)) {
1997
- await promises.mkdir(outputDirectory, { recursive: true });
1998
- }
1773
+ if (!existsSync(outputDirectory)) await promises.mkdir(outputDirectory, { recursive: true });
1999
1774
  await promises.writeFile(reportFile, report, "utf-8");
2000
1775
  this.ctx.logger.log(`JSON report written to ${reportFile}`);
2001
- } else {
2002
- this.ctx.logger.log(report);
2003
- }
1776
+ } else this.ctx.logger.log(report);
2004
1777
  }
2005
1778
  }
2006
1779
 
@@ -2022,14 +1795,11 @@ class IndentedLogger {
2022
1795
 
2023
1796
  function flattenTasks$1(task, baseName = "") {
2024
1797
  const base = baseName ? `${baseName} > ` : "";
2025
- if (task.type === "suite") {
2026
- return task.tasks.flatMap((child) => flattenTasks$1(child, `${base}${task.name}`));
2027
- } else {
2028
- return [{
2029
- ...task,
2030
- name: `${base}${task.name}`
2031
- }];
2032
- }
1798
+ if (task.type === "suite") return task.tasks.flatMap((child) => flattenTasks$1(child, `${base}${task.name}`));
1799
+ else return [{
1800
+ ...task,
1801
+ name: `${base}${task.name}`
1802
+ }];
2033
1803
  }
2034
1804
  // https://gist.github.com/john-doherty/b9195065884cdbfd2017a4756e6409cc
2035
1805
  function removeInvalidXMLCharacters(value, removeDiscouragedChars) {
@@ -2039,7 +1809,7 @@ function removeInvalidXMLCharacters(value, removeDiscouragedChars) {
2039
1809
  // remove everything discouraged by XML 1.0 specifications
2040
1810
  regex = new RegExp(
2041
1811
  /* eslint-disable regexp/prefer-character-class, regexp/no-obscure-range, regexp/no-useless-non-capturing-group */
2042
- "([\\x7F-\\x84]|[\\x86-\\x9F]|[\\uFDD0-\\uFDEF]|\\uD83F[\\uDFFE\\uDFFF]|(?:\\uD87F[\\uDF" + "FE\\uDFFF])|\\uD8BF[\\uDFFE\\uDFFF]|\\uD8FF[\\uDFFE\\uDFFF]|(?:\\uD93F[\\uDFFE\\uD" + "FFF])|\\uD97F[\\uDFFE\\uDFFF]|\\uD9BF[\\uDFFE\\uDFFF]|\\uD9FF[\\uDFFE\\uDFFF]" + "|\\uDA3F[\\uDFFE\\uDFFF]|\\uDA7F[\\uDFFE\\uDFFF]|\\uDABF[\\uDFFE\\uDFFF]|(?:\\" + "uDAFF[\\uDFFE\\uDFFF])|\\uDB3F[\\uDFFE\\uDFFF]|\\uDB7F[\\uDFFE\\uDFFF]|(?:\\uDBBF" + "[\\uDFFE\\uDFFF])|\\uDBFF[\\uDFFE\\uDFFF](?:[\\0-\\t\\v\\f\\x0E-\\u2027\\u202A-\\uD7FF\\" + "uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|" + "(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))",
1812
+ "([\\x7F-\\x84]|[\\x86-\\x9F]|[\\uFDD0-\\uFDEF]|\\uD83F[\\uDFFE\\uDFFF]|(?:\\uD87F[\\uDFFE\\uDFFF])|\\uD8BF[\\uDFFE\\uDFFF]|\\uD8FF[\\uDFFE\\uDFFF]|(?:\\uD93F[\\uDFFE\\uDFFF])|\\uD97F[\\uDFFE\\uDFFF]|\\uD9BF[\\uDFFE\\uDFFF]|\\uD9FF[\\uDFFE\\uDFFF]|\\uDA3F[\\uDFFE\\uDFFF]|\\uDA7F[\\uDFFE\\uDFFF]|\\uDABF[\\uDFFE\\uDFFF]|(?:\\uDAFF[\\uDFFE\\uDFFF])|\\uDB3F[\\uDFFE\\uDFFF]|\\uDB7F[\\uDFFE\\uDFFF]|(?:\\uDBBF[\\uDFFE\\uDFFF])|\\uDBFF[\\uDFFE\\uDFFF](?:[\\0-\\t\\v\\f\\x0E-\\u2027\\u202A-\\uD7FF\\uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))",
2043
1813
  "g"
2044
1814
  /* eslint-enable */
2045
1815
  );
@@ -2065,7 +1835,7 @@ class JUnitReporter {
2065
1835
  reportFile;
2066
1836
  baseLog;
2067
1837
  logger;
2068
- _timeStart = new Date();
1838
+ _timeStart = /* @__PURE__ */ new Date();
2069
1839
  fileFd;
2070
1840
  options;
2071
1841
  constructor(options) {
@@ -2078,30 +1848,22 @@ class JUnitReporter {
2078
1848
  if (outputFile) {
2079
1849
  this.reportFile = resolve(this.ctx.config.root, outputFile);
2080
1850
  const outputDirectory = dirname(this.reportFile);
2081
- if (!existsSync(outputDirectory)) {
2082
- await promises.mkdir(outputDirectory, { recursive: true });
2083
- }
1851
+ if (!existsSync(outputDirectory)) await promises.mkdir(outputDirectory, { recursive: true });
2084
1852
  const fileFd = await promises.open(this.reportFile, "w+");
2085
1853
  this.fileFd = fileFd;
2086
1854
  this.baseLog = async (text) => {
2087
- if (!this.fileFd) {
2088
- this.fileFd = await promises.open(this.reportFile, "w+");
2089
- }
1855
+ if (!this.fileFd) this.fileFd = await promises.open(this.reportFile, "w+");
2090
1856
  await promises.writeFile(this.fileFd, `${text}\n`);
2091
1857
  };
2092
- } else {
2093
- this.baseLog = async (text) => this.ctx.logger.log(text);
2094
- }
2095
- this._timeStart = new Date();
1858
+ } else this.baseLog = async (text) => this.ctx.logger.log(text);
1859
+ this._timeStart = /* @__PURE__ */ new Date();
2096
1860
  this.logger = new IndentedLogger(this.baseLog);
2097
1861
  }
2098
1862
  async writeElement(name, attrs, children) {
2099
1863
  const pairs = [];
2100
1864
  for (const key in attrs) {
2101
1865
  const attr = attrs[key];
2102
- if (attr === undefined) {
2103
- continue;
2104
- }
1866
+ if (attr === void 0) continue;
2105
1867
  pairs.push(`${key}="${escapeXML(attr)}"`);
2106
1868
  }
2107
1869
  await this.logger.log(`<${name}${pairs.length ? ` ${pairs.join(" ")}` : ""}>`);
@@ -2111,18 +1873,12 @@ class JUnitReporter {
2111
1873
  await this.logger.log(`</${name}>`);
2112
1874
  }
2113
1875
  async writeLogs(task, type) {
2114
- if (task.logs == null || task.logs.length === 0) {
2115
- return;
2116
- }
1876
+ if (task.logs == null || task.logs.length === 0) return;
2117
1877
  const logType = type === "err" ? "stderr" : "stdout";
2118
1878
  const logs = task.logs.filter((log) => log.type === logType);
2119
- if (logs.length === 0) {
2120
- return;
2121
- }
1879
+ if (logs.length === 0) return;
2122
1880
  await this.writeElement(`system-${type}`, {}, async () => {
2123
- for (const log of logs) {
2124
- await this.baseLog(escapeXML(log.content));
2125
- }
1881
+ for (const log of logs) await this.baseLog(escapeXML(log.content));
2126
1882
  });
2127
1883
  }
2128
1884
  async writeTasks(tasks, filename) {
@@ -2132,16 +1888,12 @@ class JUnitReporter {
2132
1888
  filename: task.file.name,
2133
1889
  filepath: task.file.filepath
2134
1890
  };
2135
- if (typeof this.options.classnameTemplate === "function") {
2136
- classname = this.options.classnameTemplate(templateVars);
2137
- } else if (typeof this.options.classnameTemplate === "string") {
2138
- classname = this.options.classnameTemplate.replace(/\{filename\}/g, templateVars.filename).replace(/\{filepath\}/g, templateVars.filepath);
2139
- } else if (typeof this.options.classname === "string") {
2140
- classname = this.options.classname;
2141
- }
1891
+ if (typeof this.options.classnameTemplate === "function") classname = this.options.classnameTemplate(templateVars);
1892
+ else if (typeof this.options.classnameTemplate === "string") classname = this.options.classnameTemplate.replace(/\{filename\}/g, templateVars.filename).replace(/\{filepath\}/g, templateVars.filepath);
1893
+ else if (typeof this.options.classname === "string") classname = this.options.classname;
2142
1894
  await this.writeElement("testcase", {
2143
1895
  classname,
2144
- file: this.options.addFileAttribute ? filename : undefined,
1896
+ file: this.options.addFileAttribute ? filename : void 0,
2145
1897
  name: task.name,
2146
1898
  time: getDuration(task)
2147
1899
  }, async () => {
@@ -2149,26 +1901,30 @@ class JUnitReporter {
2149
1901
  await this.writeLogs(task, "out");
2150
1902
  await this.writeLogs(task, "err");
2151
1903
  }
2152
- if (task.mode === "skip" || task.mode === "todo") {
2153
- await this.logger.log("<skipped/>");
1904
+ if (task.mode === "skip" || task.mode === "todo") await this.logger.log("<skipped/>");
1905
+ if (task.type === "test" && task.annotations.length) {
1906
+ await this.logger.log("<properties>");
1907
+ this.logger.indent();
1908
+ for (const annotation of task.annotations) {
1909
+ await this.logger.log(`<property name="${escapeXML(annotation.type)}" value="${escapeXML(annotation.message)}">`);
1910
+ await this.logger.log("</property>");
1911
+ }
1912
+ this.logger.unindent();
1913
+ await this.logger.log("</properties>");
2154
1914
  }
2155
1915
  if (task.result?.state === "fail") {
2156
1916
  const errors = task.result.errors || [];
2157
- for (const error of errors) {
2158
- await this.writeElement("failure", {
2159
- message: error?.message,
2160
- type: error?.name ?? error?.nameStr
2161
- }, async () => {
2162
- if (!error) {
2163
- return;
2164
- }
2165
- const result = capturePrintError(error, this.ctx, {
2166
- project: this.ctx.getProjectByName(task.file.projectName || ""),
2167
- task
2168
- });
2169
- await this.baseLog(escapeXML(stripVTControlCharacters(result.output.trim())));
1917
+ for (const error of errors) await this.writeElement("failure", {
1918
+ message: error?.message,
1919
+ type: error?.name
1920
+ }, async () => {
1921
+ if (!error) return;
1922
+ const result = capturePrintError(error, this.ctx, {
1923
+ project: this.ctx.getProjectByName(task.file.projectName || ""),
1924
+ task
2170
1925
  });
2171
- }
1926
+ await this.baseLog(escapeXML(stripVTControlCharacters(result.output.trim())));
1927
+ });
2172
1928
  }
2173
1929
  });
2174
1930
  }
@@ -2190,11 +1946,9 @@ class JUnitReporter {
2190
1946
  });
2191
1947
  // inject failed suites to surface errors during beforeAll/afterAll
2192
1948
  const suites = getSuites(file);
2193
- for (const suite of suites) {
2194
- if (suite.result?.errors) {
2195
- tasks.push(suite);
2196
- stats.failures += 1;
2197
- }
1949
+ for (const suite of suites) if (suite.result?.errors) {
1950
+ tasks.push(suite);
1951
+ stats.failures += 1;
2198
1952
  }
2199
1953
  // If there are no tests, but the file failed to load, we still want to report it as a failure
2200
1954
  if (tasks.length === 0 && file.result?.state === "fail") {
@@ -2209,7 +1963,8 @@ class JUnitReporter {
2209
1963
  timeout: 0,
2210
1964
  context: null,
2211
1965
  suite: null,
2212
- file: null
1966
+ file: null,
1967
+ annotations: []
2213
1968
  });
2214
1969
  }
2215
1970
  return {
@@ -2238,7 +1993,7 @@ class JUnitReporter {
2238
1993
  const filename = relative(this.ctx.config.root, file.filepath);
2239
1994
  await this.writeElement("testsuite", {
2240
1995
  name: filename,
2241
- timestamp: new Date().toISOString(),
1996
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2242
1997
  hostname: hostname(),
2243
1998
  tests: file.tasks.length,
2244
1999
  failures: file.stats.failures,
@@ -2250,11 +2005,9 @@ class JUnitReporter {
2250
2005
  });
2251
2006
  }
2252
2007
  });
2253
- if (this.reportFile) {
2254
- this.ctx.logger.log(`JUNIT report written to ${this.reportFile}`);
2255
- }
2008
+ if (this.reportFile) this.ctx.logger.log(`JUNIT report written to ${this.reportFile}`);
2256
2009
  await this.fileFd?.close();
2257
- this.fileFd = undefined;
2010
+ this.fileFd = void 0;
2258
2011
  }
2259
2012
  }
2260
2013
 
@@ -2272,24 +2025,18 @@ class TapReporter {
2272
2025
  this.logger = new IndentedLogger(ctx.logger.log.bind(ctx.logger));
2273
2026
  }
2274
2027
  static getComment(task) {
2275
- if (task.mode === "skip") {
2276
- return " # SKIP";
2277
- } else if (task.mode === "todo") {
2278
- return " # TODO";
2279
- } else if (task.result?.duration != null) {
2280
- return ` # time=${task.result.duration.toFixed(2)}ms`;
2281
- } else {
2282
- return "";
2283
- }
2028
+ if (task.mode === "skip") return " # SKIP";
2029
+ else if (task.mode === "todo") return " # TODO";
2030
+ else if (task.result?.duration != null) return ` # time=${task.result.duration.toFixed(2)}ms`;
2031
+ else return "";
2284
2032
  }
2285
2033
  logErrorDetails(error, stack) {
2286
- const errorName = error.name || error.nameStr || "Unknown Error";
2034
+ const errorName = error.name || "Unknown Error";
2287
2035
  this.logger.log(`name: ${yamlString(String(errorName))}`);
2288
2036
  this.logger.log(`message: ${yamlString(String(error.message))}`);
2289
- if (stack) {
2290
- // For compatibility with tap-mocha-reporter
2291
- this.logger.log(`stack: ${yamlString(`${stack.file}:${stack.line}:${stack.column}`)}`);
2292
- }
2037
+ if (stack)
2038
+ // For compatibility with tap-mocha-reporter
2039
+ this.logger.log(`stack: ${yamlString(`${stack.file}:${stack.line}:${stack.column}`)}`);
2293
2040
  }
2294
2041
  logTasks(tasks) {
2295
2042
  this.logger.log(`1..${tasks.length}`);
@@ -2306,6 +2053,13 @@ class TapReporter {
2306
2053
  } else {
2307
2054
  this.logger.log(`${ok} ${id} - ${tapString(task.name)}${comment}`);
2308
2055
  const project = this.ctx.getProjectByName(task.file.projectName || "");
2056
+ if (task.type === "test" && task.annotations) {
2057
+ this.logger.indent();
2058
+ task.annotations.forEach(({ type, message }) => {
2059
+ this.logger.log(`# ${type}: ${message}`);
2060
+ });
2061
+ this.logger.unindent();
2062
+ }
2309
2063
  if (task.result?.state === "fail" && task.result.errors) {
2310
2064
  this.logger.indent();
2311
2065
  task.result.errors.forEach((error) => {
@@ -2316,9 +2070,7 @@ class TapReporter {
2316
2070
  this.logger.indent();
2317
2071
  this.logErrorDetails(error);
2318
2072
  this.logger.unindent();
2319
- if (stack) {
2320
- this.logger.log(`at: ${yamlString(`${stack.file}:${stack.line}:${stack.column}`)}`);
2321
- }
2073
+ if (stack) this.logger.log(`at: ${yamlString(`${stack.file}:${stack.line}:${stack.column}`)}`);
2322
2074
  if (error.showDiff) {
2323
2075
  this.logger.log(`actual: ${yamlString(error.actual)}`);
2324
2076
  this.logger.log(`expected: ${yamlString(error.expected)}`);
@@ -2338,14 +2090,11 @@ class TapReporter {
2338
2090
 
2339
2091
  function flattenTasks(task, baseName = "") {
2340
2092
  const base = baseName ? `${baseName} > ` : "";
2341
- if (task.type === "suite" && task.tasks.length > 0) {
2342
- return task.tasks.flatMap((child) => flattenTasks(child, `${base}${task.name}`));
2343
- } else {
2344
- return [{
2345
- ...task,
2346
- name: `${base}${task.name}`
2347
- }];
2348
- }
2093
+ if (task.type === "suite" && task.tasks.length > 0) return task.tasks.flatMap((child) => flattenTasks(child, `${base}${task.name}`));
2094
+ else return [{
2095
+ ...task,
2096
+ name: `${base}${task.name}`
2097
+ }];
2349
2098
  }
2350
2099
  class TapFlatReporter extends TapReporter {
2351
2100
  onInit(ctx) {
@@ -2366,37 +2115,28 @@ class VerboseReporter extends DefaultReporter {
2366
2115
  // but don't print it in the CLI because we
2367
2116
  // print all the tests when they finish
2368
2117
  // instead of printing them when the test file finishes
2369
- if (this.isTTY) {
2370
- return super.printTestModule(module);
2371
- }
2118
+ if (this.isTTY) return super.printTestModule(module);
2372
2119
  }
2373
2120
  onTestCaseResult(test) {
2374
2121
  super.onTestCaseResult(test);
2375
2122
  // don't print tests in TTY as they go, only print them
2376
2123
  // in the CLI when they finish
2377
- if (this.isTTY) {
2378
- return;
2379
- }
2124
+ if (this.isTTY) return;
2380
2125
  const testResult = test.result();
2381
- if (this.ctx.config.hideSkippedTests && testResult.state === "skipped") {
2382
- return;
2383
- }
2126
+ if (this.ctx.config.hideSkippedTests && testResult.state === "skipped") return;
2384
2127
  let title = ` ${getStateSymbol(test.task)} `;
2385
- if (test.project.name) {
2386
- title += formatProjectName(test.project);
2387
- }
2128
+ if (test.project.name) title += formatProjectName(test.project);
2388
2129
  title += getFullName(test.task, c.dim(" > "));
2389
2130
  title += this.getDurationPrefix(test.task);
2390
2131
  const diagnostic = test.diagnostic();
2391
- if (diagnostic?.heap != null) {
2392
- title += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`);
2393
- }
2394
- if (testResult.state === "skipped" && testResult.note) {
2395
- title += c.dim(c.gray(` [${testResult.note}]`));
2396
- }
2132
+ if (diagnostic?.heap != null) title += c.magenta(` ${Math.floor(diagnostic.heap / 1024 / 1024)} MB heap used`);
2133
+ if (testResult.state === "skipped" && testResult.note) title += c.dim(c.gray(` [${testResult.note}]`));
2397
2134
  this.log(title);
2398
- if (testResult.state === "failed") {
2399
- testResult.errors.forEach((error) => this.log(c.red(` ${F_RIGHT} ${error?.message}`)));
2135
+ if (testResult.state === "failed") testResult.errors.forEach((error) => this.log(c.red(` ${F_RIGHT} ${error?.message}`)));
2136
+ if (test.annotations().length) {
2137
+ this.log();
2138
+ this.printAnnotations(test, "log", 3);
2139
+ this.log();
2400
2140
  }
2401
2141
  }
2402
2142
  printTestSuite(testSuite) {
@@ -2417,9 +2157,7 @@ class VerboseReporter extends DefaultReporter {
2417
2157
  }
2418
2158
  }
2419
2159
  function getIndentation(suite, level = 1) {
2420
- if (suite.suite && !("filepath" in suite.suite)) {
2421
- return getIndentation(suite.suite, level + 1);
2422
- }
2160
+ if (suite.suite && !("filepath" in suite.suite)) return getIndentation(suite.suite, level + 1);
2423
2161
  return level;
2424
2162
  }
2425
2163