vitest 2.1.4 → 2.2.0-beta.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 (46) hide show
  1. package/dist/browser.d.ts +11 -11
  2. package/dist/browser.js +1 -1
  3. package/dist/chunks/{base.C3xNdjV6.js → base.BS0HhLXd.js} +1 -1
  4. package/dist/chunks/{cac.DrfPaMvZ.js → cac.Z91LBqmg.js} +56 -7
  5. package/dist/chunks/{cli-api.CKrRYkw8.js → cli-api.DVJJMJHj.js} +123 -80
  6. package/dist/chunks/{config.Crbj2GAb.d.ts → config.CPguQ7J1.d.ts} +2 -2
  7. package/dist/chunks/{environment.LoooBwUu.d.ts → environment.CT0jpO-1.d.ts} +2 -1
  8. package/dist/chunks/{globals.Bp645TTJ.js → globals.BCGEw6ON.js} +2 -2
  9. package/dist/chunks/{index.D3d79vc8.js → index.BjjsHdBb.js} +1 -1
  10. package/dist/chunks/{index.Dqe5k2Rk.js → index.DD5eTY2y.js} +2 -8
  11. package/dist/chunks/{index.Bn81VaWg.js → index.DLRzErGF.js} +240 -318
  12. package/dist/chunks/{index.BMoXz_-n.js → index.K90BXFOx.js} +1 -1
  13. package/dist/chunks/{reporters.anwo7Y6a.d.ts → reporters.B_9uUTGW.d.ts} +148 -22
  14. package/dist/chunks/{resolveConfig.DPmbhVlP.js → resolveConfig.CQIc6fe7.js} +8 -4
  15. package/dist/chunks/{runBaseTests.Dm-659zB.js → runBaseTests.B7hcVT-s.js} +4 -4
  16. package/dist/chunks/{setup-common.DDmVKp6O.js → setup-common.BfGt8K-K.js} +4 -1
  17. package/dist/chunks/{utils.BB4zjzR8.js → utils.DNoFbBUZ.js} +6 -2
  18. package/dist/chunks/{vi.JMQoNY_Z.js → vi.BlPttogV.js} +91 -4
  19. package/dist/chunks/{vite.BdBj-UWY.d.ts → vite.Bvms8Xir.d.ts} +1 -1
  20. package/dist/chunks/{vm.jpyrB0xy.js → vm.Zr4qWzDJ.js} +3 -0
  21. package/dist/chunks/{worker.BAlI9hII.d.ts → worker.9VY11NZs.d.ts} +3 -2
  22. package/dist/chunks/{worker.DHnGaO2M.d.ts → worker.Qz1UB4Fv.d.ts} +1 -1
  23. package/dist/cli.js +1 -1
  24. package/dist/config.d.ts +10 -9
  25. package/dist/coverage.d.ts +9 -112
  26. package/dist/coverage.js +1 -1
  27. package/dist/environments.d.ts +2 -2
  28. package/dist/environments.js +1 -1
  29. package/dist/execute.d.ts +4 -3
  30. package/dist/index.d.ts +39 -10
  31. package/dist/index.js +2 -2
  32. package/dist/node.d.ts +13 -11
  33. package/dist/node.js +7 -7
  34. package/dist/reporters.d.ts +10 -9
  35. package/dist/reporters.js +2 -2
  36. package/dist/runners.d.ts +3 -1
  37. package/dist/runners.js +4 -1
  38. package/dist/worker.js +6 -2
  39. package/dist/workers/forks.js +1 -1
  40. package/dist/workers/runVmTests.js +4 -4
  41. package/dist/workers/threads.js +1 -1
  42. package/dist/workers/vmForks.js +1 -1
  43. package/dist/workers/vmThreads.js +1 -1
  44. package/dist/workers.d.ts +5 -4
  45. package/dist/workers.js +4 -3
  46. package/package.json +15 -15
@@ -3,7 +3,7 @@ import { getTests, getTestName, hasFailed, getFullName, getSuites, getTasks } fr
3
3
  import * as pathe from 'pathe';
4
4
  import { extname, relative, normalize, resolve, dirname } from 'pathe';
5
5
  import c from 'tinyrainbow';
6
- import { d as divider, F as F_POINTER, g as getStateSymbol, f as formatProjectName, t as taskFail, a as F_RIGHT, b as F_CHECK, r as renderSnapshotSummary, c as getStateString, e as formatTimeString, h as countTestErrors, i as getCols, j as getHookStateSymbol } from './utils.BB4zjzR8.js';
6
+ import { d as divider, F as F_POINTER, w as withLabel, f as formatProjectName, a as formatTimeString, g as getStateSymbol, t as taskFail, b as F_RIGHT, c as F_CHECK, r as renderSnapshotSummary, e as getStateString, h as countTestErrors, i as getCols, j as getHookStateSymbol } from './utils.DNoFbBUZ.js';
7
7
  import { stripVTControlCharacters } from 'node:util';
8
8
  import { highlight, isPrimitive, inspect, positionToOffset, lineSplitRE, toArray, notNullish } from '@vitest/utils';
9
9
  import { performance } from 'node:perf_hooks';
@@ -31,6 +31,10 @@ class TestProject {
31
31
  * @experimental The public Vitest API is experimental and does not follow semver.
32
32
  */
33
33
  workspaceProject;
34
+ /**
35
+ * Vite's dev server instance. Every workspace project has its own server.
36
+ */
37
+ vite;
34
38
  /**
35
39
  * Resolved project configuration.
36
40
  */
@@ -46,6 +50,7 @@ class TestProject {
46
50
  constructor(workspaceProject) {
47
51
  this.workspaceProject = workspaceProject;
48
52
  this.vitest = workspaceProject.ctx;
53
+ this.vite = workspaceProject.server;
49
54
  this.globalConfig = workspaceProject.ctx.config;
50
55
  this.config = workspaceProject.config;
51
56
  this.name = workspaceProject.getName();
@@ -165,9 +170,22 @@ class TestCase extends ReportedTaskImplementation {
165
170
  return void 0;
166
171
  }
167
172
  const state = result.state === "fail" ? "failed" : result.state === "pass" ? "passed" : "skipped";
173
+ if (state === "skipped") {
174
+ return {
175
+ state,
176
+ note: result.note,
177
+ errors: void 0
178
+ };
179
+ }
180
+ if (state === "passed") {
181
+ return {
182
+ state,
183
+ errors: result.errors
184
+ };
185
+ }
168
186
  return {
169
187
  state,
170
- errors: result.errors
188
+ errors: result.errors || []
171
189
  };
172
190
  }
173
191
  /**
@@ -2398,8 +2416,10 @@ function isWide(x) {
2398
2416
  || x === 0x25FE
2399
2417
  || x === 0x2614
2400
2418
  || x === 0x2615
2419
+ || x >= 0x2630 && x <= 0x2637
2401
2420
  || x >= 0x2648 && x <= 0x2653
2402
2421
  || x === 0x267F
2422
+ || x >= 0x268A && x <= 0x268F
2403
2423
  || x === 0x2693
2404
2424
  || x === 0x26A1
2405
2425
  || x === 0x26AA
@@ -2440,11 +2460,10 @@ function isWide(x) {
2440
2460
  || x >= 0x3099 && x <= 0x30FF
2441
2461
  || x >= 0x3105 && x <= 0x312F
2442
2462
  || x >= 0x3131 && x <= 0x318E
2443
- || x >= 0x3190 && x <= 0x31E3
2463
+ || x >= 0x3190 && x <= 0x31E5
2444
2464
  || x >= 0x31EF && x <= 0x321E
2445
2465
  || x >= 0x3220 && x <= 0x3247
2446
- || x >= 0x3250 && x <= 0x4DBF
2447
- || x >= 0x4E00 && x <= 0xA48C
2466
+ || x >= 0x3250 && x <= 0xA48C
2448
2467
  || x >= 0xA490 && x <= 0xA4C6
2449
2468
  || x >= 0xA960 && x <= 0xA97C
2450
2469
  || x >= 0xAC00 && x <= 0xD7A3
@@ -2458,7 +2477,7 @@ function isWide(x) {
2458
2477
  || x === 0x16FF1
2459
2478
  || x >= 0x17000 && x <= 0x187F7
2460
2479
  || x >= 0x18800 && x <= 0x18CD5
2461
- || x >= 0x18D00 && x <= 0x18D08
2480
+ || x >= 0x18CFF && x <= 0x18D08
2462
2481
  || x >= 0x1AFF0 && x <= 0x1AFF3
2463
2482
  || x >= 0x1AFF5 && x <= 0x1AFFB
2464
2483
  || x === 0x1AFFD
@@ -2469,6 +2488,8 @@ function isWide(x) {
2469
2488
  || x === 0x1B155
2470
2489
  || x >= 0x1B164 && x <= 0x1B167
2471
2490
  || x >= 0x1B170 && x <= 0x1B2FB
2491
+ || x >= 0x1D300 && x <= 0x1D356
2492
+ || x >= 0x1D360 && x <= 0x1D376
2472
2493
  || x === 0x1F004
2473
2494
  || x === 0x1F0CF
2474
2495
  || x === 0x1F18E
@@ -2512,11 +2533,10 @@ function isWide(x) {
2512
2533
  || x >= 0x1F93C && x <= 0x1F945
2513
2534
  || x >= 0x1F947 && x <= 0x1F9FF
2514
2535
  || x >= 0x1FA70 && x <= 0x1FA7C
2515
- || x >= 0x1FA80 && x <= 0x1FA88
2516
- || x >= 0x1FA90 && x <= 0x1FABD
2517
- || x >= 0x1FABF && x <= 0x1FAC5
2518
- || x >= 0x1FACE && x <= 0x1FADB
2519
- || x >= 0x1FAE0 && x <= 0x1FAE8
2536
+ || x >= 0x1FA80 && x <= 0x1FA89
2537
+ || x >= 0x1FA8F && x <= 0x1FAC6
2538
+ || x >= 0x1FACE && x <= 0x1FADC
2539
+ || x >= 0x1FADF && x <= 0x1FAE9
2520
2540
  || x >= 0x1FAF0 && x <= 0x1FAF8
2521
2541
  || x >= 0x20000 && x <= 0x2FFFD
2522
2542
  || x >= 0x30000 && x <= 0x3FFFD;
@@ -3005,6 +3025,7 @@ function lineNo(no = "") {
3005
3025
  return c.gray(`${String(no).padStart(3, " ")}| `);
3006
3026
  }
3007
3027
 
3028
+ const PAD = " ";
3008
3029
  const ESC = "\x1B[";
3009
3030
  const ERASE_DOWN = `${ESC}J`;
3010
3031
  const ERASE_SCROLLBACK = `${ESC}3J`;
@@ -3018,6 +3039,7 @@ class Logger {
3018
3039
  this.console = new Console({ stdout: outputStream, stderr: errorStream });
3019
3040
  this.logUpdate = createLogUpdate(this.outputStream);
3020
3041
  this._highlights.clear();
3042
+ this.registerUnhandledRejection();
3021
3043
  }
3022
3044
  logUpdate;
3023
3045
  _clearScreenPending;
@@ -3035,12 +3057,16 @@ class Logger {
3035
3057
  this._clearScreen();
3036
3058
  this.console.warn(...args);
3037
3059
  }
3038
- clearFullScreen(message) {
3060
+ clearFullScreen(message = "") {
3039
3061
  if (!this.ctx.config.clearScreen) {
3040
3062
  this.console.log(message);
3041
3063
  return;
3042
3064
  }
3043
- this.console.log(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}${message}`);
3065
+ if (message) {
3066
+ this.console.log(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}${message}`);
3067
+ } else {
3068
+ this.outputStream.write(`${CLEAR_SCREEN}${ERASE_SCROLLBACK}`);
3069
+ }
3044
3070
  }
3045
3071
  clearScreen(message, force = false) {
3046
3072
  if (!this.ctx.config.clearScreen) {
@@ -3152,68 +3178,53 @@ No ${config.mode} files found, exiting with code 1`)
3152
3178
  }
3153
3179
  printBanner() {
3154
3180
  this.log();
3155
- const versionTest = this.ctx.config.watch ? c.blue(`v${this.ctx.version}`) : c.cyan(`v${this.ctx.version}`);
3156
- const mode = this.ctx.config.watch ? c.blue(" DEV ") : c.cyan(" RUN ");
3157
- this.log(
3158
- `${c.inverse(c.bold(mode))} ${versionTest} ${c.gray(
3159
- this.ctx.config.root
3160
- )}`
3161
- );
3181
+ const color = this.ctx.config.watch ? "blue" : "cyan";
3182
+ const mode = this.ctx.config.watch ? "DEV" : "RUN";
3183
+ this.log(withLabel(color, mode, `v${this.ctx.version} `) + c.gray(this.ctx.config.root));
3162
3184
  if (this.ctx.config.sequence.sequencer === RandomSequencer) {
3163
- this.log(
3164
- c.gray(
3165
- ` Running tests with seed "${this.ctx.config.sequence.seed}"`
3166
- )
3167
- );
3185
+ this.log(PAD + c.gray(`Running tests with seed "${this.ctx.config.sequence.seed}"`));
3168
3186
  }
3169
- this.ctx.projects.forEach((project) => {
3170
- if (!project.browser) {
3171
- return;
3172
- }
3173
- const name = project.getName();
3174
- const output = project.isCore() ? "" : ` [${name}]`;
3175
- const resolvedUrls = project.browser.vite.resolvedUrls;
3176
- const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
3177
- const provider = project.browser.provider.name;
3178
- const providerString = provider === "preview" ? "" : ` by ${provider}`;
3179
- this.log(
3180
- c.dim(
3181
- c.green(
3182
- ` ${output} Browser runner started${providerString} at ${new URL("/", origin)}`
3183
- )
3184
- )
3185
- );
3186
- });
3187
3187
  if (this.ctx.config.ui) {
3188
- this.log(
3189
- c.dim(
3190
- c.green(
3191
- ` UI started at http://${this.ctx.config.api?.host || "localhost"}:${c.bold(`${this.ctx.server.config.server.port}`)}${this.ctx.config.uiBase}`
3192
- )
3193
- )
3194
- );
3188
+ const host = this.ctx.config.api?.host || "localhost";
3189
+ const port = this.ctx.server.config.server.port;
3190
+ const base = this.ctx.config.uiBase;
3191
+ this.log(PAD + c.dim(c.green(`UI started at http://${host}:${c.bold(port)}${base}`)));
3195
3192
  } else if (this.ctx.config.api?.port) {
3196
3193
  const resolvedUrls = this.ctx.server.resolvedUrls;
3197
3194
  const fallbackUrl = `http://${this.ctx.config.api.host || "localhost"}:${this.ctx.config.api.port}`;
3198
3195
  const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0] ?? fallbackUrl;
3199
- this.log(c.dim(c.green(` API started at ${new URL("/", origin)}`)));
3196
+ this.log(PAD + c.dim(c.green(`API started at ${new URL("/", origin)}`)));
3200
3197
  }
3201
3198
  if (this.ctx.coverageProvider) {
3202
- this.log(
3203
- c.dim(" Coverage enabled with ") + c.yellow(this.ctx.coverageProvider.name)
3204
- );
3199
+ this.log(PAD + c.dim("Coverage enabled with ") + c.yellow(this.ctx.coverageProvider.name));
3205
3200
  }
3206
3201
  if (this.ctx.config.standalone) {
3207
- this.log(
3208
- c.yellow(
3209
- `
3210
- Vitest is running in standalone mode. Edit a test file to rerun tests.`
3211
- )
3212
- );
3202
+ this.log(c.yellow(`
3203
+ Vitest is running in standalone mode. Edit a test file to rerun tests.`));
3213
3204
  } else {
3214
3205
  this.log();
3215
3206
  }
3216
3207
  }
3208
+ printBrowserBanner(project) {
3209
+ if (!project.browser) {
3210
+ return;
3211
+ }
3212
+ const resolvedUrls = project.browser.vite.resolvedUrls;
3213
+ const origin = resolvedUrls?.local[0] ?? resolvedUrls?.network[0];
3214
+ if (!origin) {
3215
+ return;
3216
+ }
3217
+ const name = project.getName();
3218
+ const output = project.isCore() ? "" : formatProjectName(name);
3219
+ const provider = project.browser.provider.name;
3220
+ const providerString = provider === "preview" ? "" : ` by ${c.reset(c.bold(provider))}`;
3221
+ this.log(
3222
+ c.dim(
3223
+ `${output}Browser runner started${providerString} ${c.dim("at")} ${c.blue(new URL("/", origin))}
3224
+ `
3225
+ )
3226
+ );
3227
+ }
3217
3228
  printUnhandledErrors(errors) {
3218
3229
  const errorMessage = c.red(
3219
3230
  c.bold(
@@ -3246,6 +3257,21 @@ Vitest found ${errors.length} error${errors.length > 1 ? "s" : ""} not related t
3246
3257
  });
3247
3258
  this.log(c.red(divider()));
3248
3259
  }
3260
+ registerUnhandledRejection() {
3261
+ const onUnhandledRejection = (err) => {
3262
+ process.exitCode = 1;
3263
+ this.printError(err, {
3264
+ fullStack: true,
3265
+ type: "Unhandled Rejection"
3266
+ });
3267
+ this.error("\n\n");
3268
+ process.exit();
3269
+ };
3270
+ process.on("unhandledRejection", onUnhandledRejection);
3271
+ this.ctx.onClose(() => {
3272
+ process.off("unhandledRejection", onUnhandledRejection);
3273
+ });
3274
+ }
3249
3275
  }
3250
3276
 
3251
3277
  class BlobReporter {
@@ -3376,21 +3402,6 @@ function hasFailedSnapshot(suite) {
3376
3402
  }
3377
3403
 
3378
3404
  const BADGE_PADDING = " ";
3379
- const HELP_HINT = `${c.dim("press ")}${c.bold("h")}${c.dim(" to show help")}`;
3380
- const HELP_UPDATE_SNAP = c.dim("press ") + c.bold(c.yellow("u")) + c.dim(" to update snapshot");
3381
- const HELP_QUITE = `${c.dim("press ")}${c.bold("q")}${c.dim(" to quit")}`;
3382
- const WAIT_FOR_CHANGE_PASS = `
3383
- ${c.bold(
3384
- c.inverse(c.green(" PASS "))
3385
- )}${c.green(" Waiting for file changes...")}`;
3386
- const WAIT_FOR_CHANGE_FAIL = `
3387
- ${c.bold(c.inverse(c.red(" FAIL ")))}${c.red(
3388
- " Tests failed. Watching for file changes..."
3389
- )}`;
3390
- const WAIT_FOR_CHANGE_CANCELLED = `
3391
- ${c.bold(
3392
- c.inverse(c.red(" CANCELLED "))
3393
- )}${c.red(" Test run cancelled. Watching for file changes...")}`;
3394
3405
  const LAST_RUN_LOG_TIMEOUT = 1500;
3395
3406
  class BaseReporter {
3396
3407
  start = 0;
@@ -3401,37 +3412,30 @@ class BaseReporter {
3401
3412
  ctx = void 0;
3402
3413
  verbose = false;
3403
3414
  _filesInWatchMode = /* @__PURE__ */ new Map();
3415
+ _timeStart = formatTimeString(/* @__PURE__ */ new Date());
3404
3416
  _lastRunTimeout = 0;
3405
3417
  _lastRunTimer;
3406
3418
  _lastRunCount = 0;
3407
- _timeStart = /* @__PURE__ */ new Date();
3408
- _offUnhandledRejection;
3409
3419
  constructor(options = {}) {
3410
3420
  this.isTTY = options.isTTY ?? ((isNode || isDeno) && process.stdout?.isTTY && !isCI);
3411
- this.registerUnhandledRejection();
3412
- }
3413
- get mode() {
3414
- return this.ctx.config.mode;
3415
3421
  }
3416
3422
  onInit(ctx) {
3417
3423
  this.ctx = ctx;
3418
- ctx.onClose(() => {
3419
- this._offUnhandledRejection?.();
3420
- });
3421
- ctx.logger.printBanner();
3424
+ this.ctx.logger.printBanner();
3422
3425
  this.start = performance.now();
3423
3426
  }
3427
+ log(...messages) {
3428
+ this.ctx.logger.log(...messages);
3429
+ }
3430
+ error(...messages) {
3431
+ this.ctx.logger.error(...messages);
3432
+ }
3424
3433
  relative(path) {
3425
3434
  return relative(this.ctx.config.root, path);
3426
3435
  }
3427
3436
  onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
3428
3437
  this.end = performance.now();
3429
3438
  this.reportSummary(files, errors);
3430
- if (errors.length) {
3431
- if (!this.ctx.config.dangerouslyIgnoreUnhandledErrors) {
3432
- process.exitCode = 1;
3433
- }
3434
- }
3435
3439
  }
3436
3440
  onTaskUpdate(packs) {
3437
3441
  if (this.isTTY) {
@@ -3448,48 +3452,39 @@ class BaseReporter {
3448
3452
  if (!("filepath" in task) || !task.result?.state || task.result?.state === "run") {
3449
3453
  return;
3450
3454
  }
3451
- const logger = this.ctx.logger;
3452
3455
  const tests = getTests(task);
3453
3456
  const failed = tests.filter((t) => t.result?.state === "fail");
3454
- const skipped = tests.filter(
3455
- (t) => t.mode === "skip" || t.mode === "todo"
3456
- );
3457
+ const skipped = tests.filter((t) => t.mode === "skip" || t.mode === "todo");
3457
3458
  let state = c.dim(`${tests.length} test${tests.length > 1 ? "s" : ""}`);
3458
3459
  if (failed.length) {
3459
- state += ` ${c.dim("|")} ${c.red(`${failed.length} failed`)}`;
3460
+ state += c.dim(" | ") + c.red(`${failed.length} failed`);
3460
3461
  }
3461
3462
  if (skipped.length) {
3462
- state += ` ${c.dim("|")} ${c.yellow(`${skipped.length} skipped`)}`;
3463
+ state += c.dim(" | ") + c.yellow(`${skipped.length} skipped`);
3463
3464
  }
3464
- let suffix = c.dim(" (") + state + c.dim(")");
3465
- suffix += this.getDurationPrefix(task);
3465
+ let suffix = c.dim("(") + state + c.dim(")") + this.getDurationPrefix(task);
3466
3466
  if (this.ctx.config.logHeapUsage && task.result.heap != null) {
3467
- suffix += c.magenta(
3468
- ` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`
3469
- );
3467
+ suffix += c.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`);
3470
3468
  }
3471
- let title = ` ${getStateSymbol(task)} `;
3469
+ let title = getStateSymbol(task);
3472
3470
  if (task.meta.typecheck) {
3473
- title += `${c.bgBlue(c.bold(" TS "))} `;
3471
+ title += ` ${c.bgBlue(c.bold(" TS "))}`;
3474
3472
  }
3475
3473
  if (task.projectName) {
3476
- title += formatProjectName(task.projectName);
3474
+ title += ` ${formatProjectName(task.projectName, "")}`;
3477
3475
  }
3478
- title += `${task.name} ${suffix}`;
3479
- logger.log(title);
3476
+ this.log(` ${title} ${task.name} ${suffix}`);
3480
3477
  for (const test of tests) {
3481
3478
  const duration = test.result?.duration;
3482
3479
  if (test.result?.state === "fail") {
3483
3480
  const suffix2 = this.getDurationPrefix(test);
3484
- logger.log(c.red(` ${taskFail} ${getTestName(test, c.dim(" > "))}${suffix2}`));
3481
+ this.log(c.red(` ${taskFail} ${getTestName(test, c.dim(" > "))}${suffix2}`));
3485
3482
  test.result?.errors?.forEach((e) => {
3486
- logger.log(c.red(` ${F_RIGHT} ${e?.message}`));
3483
+ this.log(c.red(` ${F_RIGHT} ${e?.message}`));
3487
3484
  });
3488
3485
  } else if (duration && duration > this.ctx.config.slowTestThreshold) {
3489
- logger.log(
3490
- ` ${c.yellow(c.dim(F_CHECK))} ${getTestName(test, c.dim(" > "))}${c.yellow(
3491
- ` ${Math.round(duration)}${c.dim("ms")}`
3492
- )}`
3486
+ this.log(
3487
+ ` ${c.yellow(c.dim(F_CHECK))} ${getTestName(test, c.dim(" > "))} ${c.yellow(Math.round(duration) + c.dim("ms"))}`
3493
3488
  );
3494
3489
  }
3495
3490
  }
@@ -3504,23 +3499,20 @@ class BaseReporter {
3504
3499
  onWatcherStart(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
3505
3500
  this.resetLastRunLog();
3506
3501
  const failed = errors.length > 0 || hasFailed(files);
3507
- const failedSnap = hasFailedSnapshot(files);
3508
- const cancelled = this.ctx.isCancelling;
3509
3502
  if (failed) {
3510
- this.ctx.logger.log(WAIT_FOR_CHANGE_FAIL);
3511
- } else if (cancelled) {
3512
- this.ctx.logger.log(WAIT_FOR_CHANGE_CANCELLED);
3503
+ this.log(withLabel("red", "FAIL", "Tests failed. Watching for file changes..."));
3504
+ } else if (this.ctx.isCancelling) {
3505
+ this.log(withLabel("red", "CANCELLED", "Test run cancelled. Watching for file changes..."));
3513
3506
  } else {
3514
- this.ctx.logger.log(WAIT_FOR_CHANGE_PASS);
3507
+ this.log(withLabel("green", "PASS", "Waiting for file changes..."));
3515
3508
  }
3516
- const hints = [];
3517
- hints.push(HELP_HINT);
3518
- if (failedSnap) {
3519
- hints.unshift(HELP_UPDATE_SNAP);
3509
+ const hints = [c.dim("press ") + c.bold("h") + c.dim(" to show help")];
3510
+ if (hasFailedSnapshot(files)) {
3511
+ hints.unshift(c.dim("press ") + c.bold(c.yellow("u")) + c.dim(" to update snapshot"));
3520
3512
  } else {
3521
- hints.push(HELP_QUITE);
3513
+ hints.push(c.dim("press ") + c.bold("q") + c.dim(" to quit"));
3522
3514
  }
3523
- this.ctx.logger.log(BADGE_PADDING + hints.join(c.dim(", ")));
3515
+ this.log(BADGE_PADDING + hints.join(c.dim(", ")));
3524
3516
  if (this._lastRunCount) {
3525
3517
  const LAST_RUN_TEXT = `rerun x${this._lastRunCount}`;
3526
3518
  const LAST_RUN_TEXTS = [
@@ -3550,90 +3542,79 @@ class BaseReporter {
3550
3542
  onWatcherRerun(files, trigger) {
3551
3543
  this.resetLastRunLog();
3552
3544
  this.watchFilters = files;
3553
- this.failedUnwatchedFiles = this.ctx.state.getFiles().filter((file) => {
3554
- return !files.includes(file.filepath) && hasFailed(file);
3555
- });
3545
+ this.failedUnwatchedFiles = this.ctx.state.getFiles().filter(
3546
+ (file) => !files.includes(file.filepath) && hasFailed(file)
3547
+ );
3556
3548
  files.forEach((filepath) => {
3557
3549
  let reruns = this._filesInWatchMode.get(filepath) ?? 0;
3558
3550
  this._filesInWatchMode.set(filepath, ++reruns);
3559
3551
  });
3560
- const BADGE = c.inverse(c.bold(c.blue(" RERUN ")));
3561
- const TRIGGER = trigger ? c.dim(` ${this.relative(trigger)}`) : "";
3562
- const FILENAME_PATTERN = this.ctx.filenamePattern ? `${BADGE_PADDING} ${c.dim("Filename pattern: ")}${c.blue(
3563
- this.ctx.filenamePattern
3564
- )}
3565
- ` : "";
3566
- const TESTNAME_PATTERN = this.ctx.configOverride.testNamePattern ? `${BADGE_PADDING} ${c.dim("Test name pattern: ")}${c.blue(
3567
- String(this.ctx.configOverride.testNamePattern)
3568
- )}
3569
- ` : "";
3570
- const PROJECT_FILTER = this.ctx.configOverride.project ? `${BADGE_PADDING} ${c.dim("Project name: ")}${c.blue(
3571
- toArray(this.ctx.configOverride.project).join(", ")
3572
- )}
3573
- ` : "";
3552
+ let banner = trigger ? c.dim(`${this.relative(trigger)} `) : "";
3574
3553
  if (files.length > 1 || !files.length) {
3575
- this.ctx.logger.clearFullScreen(
3576
- `
3577
- ${BADGE}${TRIGGER}
3578
- ${PROJECT_FILTER}${FILENAME_PATTERN}${TESTNAME_PATTERN}`
3579
- );
3580
3554
  this._lastRunCount = 0;
3581
3555
  } else if (files.length === 1) {
3582
3556
  const rerun = this._filesInWatchMode.get(files[0]) ?? 1;
3583
- this._lastRunCount = rerun;
3584
- this.ctx.logger.clearFullScreen(
3585
- `
3586
- ${BADGE}${TRIGGER} ${c.blue(
3587
- `x${rerun}`
3588
- )}
3589
- ${PROJECT_FILTER}${FILENAME_PATTERN}${TESTNAME_PATTERN}`
3590
- );
3557
+ banner += c.blue(`x${rerun} `);
3591
3558
  }
3559
+ this.ctx.logger.clearFullScreen();
3560
+ this.log(withLabel("blue", "RERUN", banner));
3561
+ if (this.ctx.configOverride.project) {
3562
+ this.log(BADGE_PADDING + c.dim(" Project name: ") + c.blue(toArray(this.ctx.configOverride.project).join(", ")));
3563
+ }
3564
+ if (this.ctx.filenamePattern) {
3565
+ this.log(BADGE_PADDING + c.dim(" Filename pattern: ") + c.blue(this.ctx.filenamePattern));
3566
+ }
3567
+ if (this.ctx.configOverride.testNamePattern) {
3568
+ this.log(BADGE_PADDING + c.dim(" Test name pattern: ") + c.blue(String(this.ctx.configOverride.testNamePattern)));
3569
+ }
3570
+ this.log("");
3592
3571
  if (!this.isTTY) {
3593
3572
  for (const task of this.failedUnwatchedFiles) {
3594
3573
  this.printTask(task);
3595
3574
  }
3596
3575
  }
3597
- this._timeStart = /* @__PURE__ */ new Date();
3576
+ this._timeStart = formatTimeString(/* @__PURE__ */ new Date());
3598
3577
  this.start = performance.now();
3599
3578
  }
3600
3579
  onUserConsoleLog(log) {
3601
3580
  if (!this.shouldLog(log)) {
3602
3581
  return;
3603
3582
  }
3604
- const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0;
3605
- const header = c.gray(
3606
- log.type + c.dim(
3607
- ` | ${task ? getFullName(task, c.dim(" > ")) : log.taskId !== "__vitest__unknown_test__" ? log.taskId : "unknown test"}`
3608
- )
3609
- );
3610
3583
  const output = log.type === "stdout" ? this.ctx.logger.outputStream : this.ctx.logger.errorStream;
3611
3584
  const write = (msg) => output.write(msg);
3612
- write(`${header}
3613
- ${log.content}`);
3585
+ let headerText = "unknown test";
3586
+ const task = log.taskId ? this.ctx.state.idMap.get(log.taskId) : void 0;
3587
+ if (task) {
3588
+ headerText = getFullName(task, c.dim(" > "));
3589
+ } else if (log.taskId && log.taskId !== "__vitest__unknown_test__") {
3590
+ headerText = log.taskId;
3591
+ }
3592
+ write(c.gray(log.type + c.dim(` | ${headerText}
3593
+ `)) + log.content);
3614
3594
  if (log.origin) {
3615
3595
  if (log.browser) {
3616
3596
  write("\n");
3617
3597
  }
3618
3598
  const project = log.taskId ? this.ctx.getProjectByTaskId(log.taskId) : this.ctx.getCoreWorkspaceProject();
3619
3599
  const stack = log.browser ? project.browser?.parseStacktrace(log.origin) || [] : parseStacktrace(log.origin);
3620
- const highlight = task ? stack.find((i) => i.file === task.file.filepath) : null;
3600
+ const highlight = task && stack.find((i) => i.file === task.file.filepath);
3621
3601
  for (const frame of stack) {
3622
3602
  const color = frame === highlight ? c.cyan : c.gray;
3623
3603
  const path = relative(project.config.root, frame.file);
3624
- write(
3625
- color(
3626
- ` ${c.dim(F_POINTER)} ${[
3627
- frame.method,
3628
- `${path}:${c.dim(`${frame.line}:${frame.column}`)}`
3629
- ].filter(Boolean).join(" ")}
3630
- `
3631
- )
3632
- );
3604
+ const positions = [
3605
+ frame.method,
3606
+ `${path}:${c.dim(`${frame.line}:${frame.column}`)}`
3607
+ ].filter(Boolean).join(" ");
3608
+ write(color(` ${c.dim(F_POINTER)} ${positions}
3609
+ `));
3633
3610
  }
3634
3611
  }
3635
3612
  write("\n");
3636
3613
  }
3614
+ onTestRemoved(trigger) {
3615
+ this.log(c.yellow("Test removed...") + (trigger ? c.dim(` [ ${this.relative(trigger)} ]
3616
+ `) : ""));
3617
+ }
3637
3618
  shouldLog(log) {
3638
3619
  if (this.ctx.config.silent) {
3639
3620
  return false;
@@ -3645,17 +3626,13 @@ ${log.content}`);
3645
3626
  return true;
3646
3627
  }
3647
3628
  onServerRestart(reason) {
3648
- this.ctx.logger.log(
3649
- c.bold(
3650
- c.magenta(
3651
- reason === "config" ? "\nRestarting due to config changes..." : "\nRestarting Vitest..."
3652
- )
3653
- )
3654
- );
3629
+ this.log(c.bold(c.magenta(
3630
+ reason === "config" ? "\nRestarting due to config changes..." : "\nRestarting Vitest..."
3631
+ )));
3655
3632
  }
3656
3633
  reportSummary(files, errors) {
3657
3634
  this.printErrorsSummary(files, errors);
3658
- if (this.mode === "benchmark") {
3635
+ if (this.ctx.config.mode === "benchmark") {
3659
3636
  this.reportBenchmarkSummary(files);
3660
3637
  } else {
3661
3638
  this.reportTestSummary(files, errors);
@@ -3667,167 +3644,117 @@ ${log.content}`);
3667
3644
  ...files
3668
3645
  ];
3669
3646
  const tests = getTests(affectedFiles);
3670
- const logger = this.ctx.logger;
3671
- const executionTime = this.end - this.start;
3672
- const collectTime = files.reduce(
3673
- (acc, test) => acc + Math.max(0, test.collectDuration || 0),
3674
- 0
3675
- );
3676
- const setupTime = files.reduce(
3677
- (acc, test) => acc + Math.max(0, test.setupDuration || 0),
3678
- 0
3679
- );
3680
- const testsTime = files.reduce(
3681
- (acc, test) => acc + Math.max(0, test.result?.duration || 0),
3682
- 0
3683
- );
3684
- const transformTime = this.ctx.projects.flatMap((w) => w.vitenode.getTotalDuration()).reduce((a, b) => a + b, 0);
3685
- const environmentTime = files.reduce(
3686
- (acc, file) => acc + Math.max(0, file.environmentLoad || 0),
3687
- 0
3688
- );
3689
- const prepareTime = files.reduce(
3690
- (acc, file) => acc + Math.max(0, file.prepareDuration || 0),
3691
- 0
3692
- );
3693
- const threadTime = collectTime + testsTime + setupTime;
3694
3647
  const snapshotOutput = renderSnapshotSummary(
3695
3648
  this.ctx.config.root,
3696
3649
  this.ctx.snapshot.summary
3697
3650
  );
3698
- if (snapshotOutput.length) {
3699
- logger.log(
3700
- snapshotOutput.map(
3701
- (t, i) => i === 0 ? `${padTitle("Snapshots")} ${t}` : `${padTitle("")} ${t}`
3702
- ).join("\n")
3703
- );
3704
- if (snapshotOutput.length > 1) {
3705
- logger.log();
3706
- }
3651
+ for (const [index, snapshot] of snapshotOutput.entries()) {
3652
+ const title = index === 0 ? "Snapshots" : "";
3653
+ this.log(`${padTitle(title)} ${snapshot}`);
3654
+ }
3655
+ if (snapshotOutput.length > 1) {
3656
+ this.log();
3707
3657
  }
3708
- logger.log(padTitle("Test Files"), getStateString(affectedFiles));
3709
- logger.log(padTitle("Tests"), getStateString(tests));
3658
+ this.log(padTitle("Test Files"), getStateString(affectedFiles));
3659
+ this.log(padTitle("Tests"), getStateString(tests));
3710
3660
  if (this.ctx.projects.some((c2) => c2.config.typecheck.enabled)) {
3711
- const failed = tests.filter(
3712
- (t) => t.meta?.typecheck && t.result?.errors?.length
3713
- );
3714
- logger.log(
3661
+ const failed = tests.filter((t) => t.meta?.typecheck && t.result?.errors?.length);
3662
+ this.log(
3715
3663
  padTitle("Type Errors"),
3716
3664
  failed.length ? c.bold(c.red(`${failed.length} failed`)) : c.dim("no errors")
3717
3665
  );
3718
3666
  }
3719
3667
  if (errors.length) {
3720
- logger.log(
3668
+ this.log(
3721
3669
  padTitle("Errors"),
3722
3670
  c.bold(c.red(`${errors.length} error${errors.length > 1 ? "s" : ""}`))
3723
3671
  );
3724
3672
  }
3725
- logger.log(padTitle("Start at"), formatTimeString(this._timeStart));
3673
+ this.log(padTitle("Start at"), this._timeStart);
3674
+ const collectTime = sum(files, (file) => file.collectDuration);
3675
+ const testsTime = sum(files, (file) => file.result?.duration);
3676
+ const setupTime = sum(files, (file) => file.setupDuration);
3726
3677
  if (this.watchFilters) {
3727
- logger.log(padTitle("Duration"), time(threadTime));
3678
+ this.log(padTitle("Duration"), time(collectTime + testsTime + setupTime));
3728
3679
  } else {
3729
- let timers = `transform ${time(transformTime)}, setup ${time(
3730
- setupTime
3731
- )}, collect ${time(collectTime)}, tests ${time(
3732
- testsTime
3733
- )}, environment ${time(environmentTime)}, prepare ${time(prepareTime)}`;
3734
- const typecheck = this.ctx.projects.reduce(
3735
- (acc, c2) => acc + (c2.typechecker?.getResult().time || 0),
3736
- 0
3737
- );
3738
- if (typecheck) {
3739
- timers += `, typecheck ${time(typecheck)}`;
3740
- }
3741
- logger.log(
3742
- padTitle("Duration"),
3743
- time(executionTime) + c.dim(` (${timers})`)
3744
- );
3680
+ const executionTime = this.end - this.start;
3681
+ const environmentTime = sum(files, (file) => file.environmentLoad);
3682
+ const prepareTime = sum(files, (file) => file.prepareDuration);
3683
+ const transformTime = sum(this.ctx.projects, (project) => project.vitenode.getTotalDuration());
3684
+ const typecheck = sum(this.ctx.projects, (project) => project.typechecker?.getResult().time);
3685
+ const timers = [
3686
+ `transform ${time(transformTime)}`,
3687
+ `setup ${time(setupTime)}`,
3688
+ `collect ${time(collectTime)}`,
3689
+ `tests ${time(testsTime)}`,
3690
+ `environment ${time(environmentTime)}`,
3691
+ `prepare ${time(prepareTime)}`,
3692
+ typecheck && `typecheck ${time(typecheck)}`
3693
+ ].filter(Boolean).join(", ");
3694
+ this.log(padTitle("Duration"), time(executionTime) + c.dim(` (${timers})`));
3745
3695
  }
3746
- logger.log();
3696
+ this.log();
3747
3697
  }
3748
3698
  printErrorsSummary(files, errors) {
3749
- const logger = this.ctx.logger;
3750
3699
  const suites = getSuites(files);
3751
3700
  const tests = getTests(files);
3752
3701
  const failedSuites = suites.filter((i) => i.result?.errors);
3753
3702
  const failedTests = tests.filter((i) => i.result?.state === "fail");
3754
3703
  const failedTotal = countTestErrors(failedSuites) + countTestErrors(failedTests);
3755
3704
  let current = 1;
3756
- const errorDivider = () => logger.error(
3757
- `${c.red(
3758
- c.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1))
3759
- )}
3760
- `
3761
- );
3705
+ const errorDivider = () => this.error(`${c.red(c.dim(divider(`[${current++}/${failedTotal}]`, void 0, 1)))}
3706
+ `);
3762
3707
  if (failedSuites.length) {
3763
- logger.error(
3764
- c.red(
3765
- divider(c.bold(c.inverse(` Failed Suites ${failedSuites.length} `)))
3766
- )
3767
- );
3768
- logger.error();
3708
+ this.error(`${errorBanner(`Failed Suites ${failedSuites.length}`)}
3709
+ `);
3769
3710
  this.printTaskErrors(failedSuites, errorDivider);
3770
3711
  }
3771
3712
  if (failedTests.length) {
3772
- logger.error(
3773
- c.red(
3774
- divider(c.bold(c.inverse(` Failed Tests ${failedTests.length} `)))
3775
- )
3776
- );
3777
- logger.error();
3713
+ this.error(`${errorBanner(`Failed Tests ${failedTests.length}`)}
3714
+ `);
3778
3715
  this.printTaskErrors(failedTests, errorDivider);
3779
3716
  }
3780
3717
  if (errors.length) {
3781
- logger.printUnhandledErrors(errors);
3782
- logger.error();
3718
+ this.ctx.logger.printUnhandledErrors(errors);
3719
+ this.error();
3783
3720
  }
3784
- return tests;
3785
3721
  }
3786
3722
  reportBenchmarkSummary(files) {
3787
- const logger = this.ctx.logger;
3788
3723
  const benches = getTests(files);
3789
3724
  const topBenches = benches.filter((i) => i.result?.benchmark?.rank === 1);
3790
- logger.log(
3791
- `
3792
- ${c.cyan(c.inverse(c.bold(" BENCH ")))} ${c.cyan("Summary")}
3793
- `
3794
- );
3725
+ this.log(withLabel("cyan", "BENCH", "Summary\n"));
3795
3726
  for (const bench of topBenches) {
3796
3727
  const group = bench.suite || bench.file;
3797
3728
  if (!group) {
3798
3729
  continue;
3799
3730
  }
3800
3731
  const groupName = getFullName(group, c.dim(" > "));
3801
- logger.log(` ${bench.name}${c.dim(` - ${groupName}`)}`);
3732
+ this.log(` ${bench.name}${c.dim(` - ${groupName}`)}`);
3802
3733
  const siblings = group.tasks.filter((i) => i.meta.benchmark && i.result?.benchmark && i !== bench).sort((a, b) => a.result.benchmark.rank - b.result.benchmark.rank);
3803
- if (siblings.length === 0) {
3804
- logger.log("");
3805
- continue;
3806
- }
3807
3734
  for (const sibling of siblings) {
3808
- const number = `${(sibling.result.benchmark.mean / bench.result.benchmark.mean).toFixed(2)}x`;
3809
- logger.log(
3810
- ` ${c.green(number)} ${c.gray("faster than")} ${sibling.name}`
3811
- );
3735
+ const number = (sibling.result.benchmark.mean / bench.result.benchmark.mean).toFixed(2);
3736
+ this.log(c.green(` ${number}x `) + c.gray("faster than ") + sibling.name);
3812
3737
  }
3813
- logger.log("");
3738
+ this.log("");
3814
3739
  }
3815
3740
  }
3816
3741
  printTaskErrors(tasks, errorDivider) {
3817
3742
  const errorsQueue = [];
3818
3743
  for (const task of tasks) {
3819
3744
  task.result?.errors?.forEach((error) => {
3820
- const errorItem = error?.stackStr && errorsQueue.find((i) => {
3821
- const hasStr = i[0]?.stackStr === error.stackStr;
3822
- if (!hasStr) {
3823
- return false;
3824
- }
3825
- const currentProjectName = task?.projectName || task.file?.projectName || "";
3826
- const projectName = i[1][0]?.projectName || i[1][0].file?.projectName || "";
3827
- return projectName === currentProjectName;
3828
- });
3829
- if (errorItem) {
3830
- errorItem[1].push(task);
3745
+ let previous;
3746
+ if (error?.stackStr) {
3747
+ previous = errorsQueue.find((i) => {
3748
+ if (i[0]?.stackStr !== error.stackStr) {
3749
+ return false;
3750
+ }
3751
+ const currentProjectName = task?.projectName || task.file?.projectName || "";
3752
+ const projectName = i[1][0]?.projectName || i[1][0].file?.projectName || "";
3753
+ return projectName === currentProjectName;
3754
+ });
3755
+ }
3756
+ if (previous) {
3757
+ previous[1].push(task);
3831
3758
  } else {
3832
3759
  errorsQueue.push([error, [task]]);
3833
3760
  }
@@ -3839,40 +3766,25 @@ ${c.cyan(c.inverse(c.bold(" BENCH ")))} ${c.cyan("Summary")}
3839
3766
  const projectName = task?.projectName || task.file?.projectName || "";
3840
3767
  let name = getFullName(task, c.dim(" > "));
3841
3768
  if (filepath) {
3842
- name = `${name} ${c.dim(`[ ${this.relative(filepath)} ]`)}`;
3769
+ name += c.dim(` [ ${this.relative(filepath)} ]`);
3843
3770
  }
3844
3771
  this.ctx.logger.error(
3845
- `${c.red(c.bold(c.inverse(" FAIL ")))} ${formatProjectName(
3846
- projectName
3847
- )}${name}`
3772
+ `${c.red(c.bold(c.inverse(" FAIL ")))}${formatProjectName(projectName)} ${name}`
3848
3773
  );
3849
3774
  }
3850
- const screenshots = tasks2.filter((t) => t.meta?.failScreenshotPath).map((t) => t.meta?.failScreenshotPath);
3851
- const project = this.ctx.getProjectByTaskId(tasks2[0].id);
3775
+ const screenshotPaths = tasks2.map((t) => t.meta?.failScreenshotPath).filter((screenshot) => screenshot != null);
3852
3776
  this.ctx.logger.printError(error, {
3853
- project,
3777
+ project: this.ctx.getProjectByTaskId(tasks2[0].id),
3854
3778
  verbose: this.verbose,
3855
- screenshotPaths: screenshots,
3779
+ screenshotPaths,
3856
3780
  task: tasks2[0]
3857
3781
  });
3858
3782
  errorDivider();
3859
3783
  }
3860
3784
  }
3861
- registerUnhandledRejection() {
3862
- const onUnhandledRejection = async (err) => {
3863
- process.exitCode = 1;
3864
- this.ctx.logger.printError(err, {
3865
- fullStack: true,
3866
- type: "Unhandled Rejection"
3867
- });
3868
- this.ctx.logger.error("\n\n");
3869
- process.exit();
3870
- };
3871
- process.on("unhandledRejection", onUnhandledRejection);
3872
- this._offUnhandledRejection = () => {
3873
- process.off("unhandledRejection", onUnhandledRejection);
3874
- };
3875
- }
3785
+ }
3786
+ function errorBanner(message) {
3787
+ return c.red(divider(c.bold(c.inverse(` ${message} `))));
3876
3788
  }
3877
3789
  function padTitle(str) {
3878
3790
  return c.dim(`${str.padStart(11)} `);
@@ -3883,6 +3795,11 @@ function time(time2) {
3883
3795
  }
3884
3796
  return `${Math.round(time2)}ms`;
3885
3797
  }
3798
+ function sum(items, cb) {
3799
+ return items.reduce((total, next) => {
3800
+ return total + Math.max(cb(next) || 0, 0);
3801
+ }, 0);
3802
+ }
3886
3803
 
3887
3804
  class BasicReporter extends BaseReporter {
3888
3805
  constructor() {
@@ -3973,7 +3890,8 @@ function renderTree$1(tasks, options, level = 0, maxRows) {
3973
3890
  suffix += c.dim(` (${tests.length})`);
3974
3891
  }
3975
3892
  if (task.mode === "skip" || task.mode === "todo") {
3976
- suffix += ` ${c.dim(c.gray("[skipped]"))}`;
3893
+ const note = task.result?.note || "skipped";
3894
+ suffix += ` ${c.dim(c.gray(`[${note}]`))}`;
3977
3895
  }
3978
3896
  if (task.type === "test" && task.result?.repeatCount && task.result.repeatCount > 0) {
3979
3897
  suffix += c.yellow(` (repeat x${task.result.repeatCount})`);
@@ -4135,7 +4053,7 @@ class DefaultReporter extends BaseReporter {
4135
4053
  this.rendererOptions.logger = this.ctx.logger;
4136
4054
  this.rendererOptions.showHeap = this.ctx.config.logHeapUsage;
4137
4055
  this.rendererOptions.slowTestThreshold = this.ctx.config.slowTestThreshold;
4138
- this.rendererOptions.mode = this.mode;
4056
+ this.rendererOptions.mode = this.ctx.config.mode;
4139
4057
  const files = this.ctx.state.getFiles(this.watchFilters);
4140
4058
  if (!this.renderer) {
4141
4059
  this.renderer = createListRenderer(files, this.rendererOptions).start();
@@ -4409,7 +4327,7 @@ class JsonReporter {
4409
4327
  this.ctx = ctx;
4410
4328
  this.start = Date.now();
4411
4329
  }
4412
- async logTasks(files) {
4330
+ async logTasks(files, coverageMap) {
4413
4331
  const suites = getSuites(files);
4414
4332
  const numTotalTestSuites = suites.length;
4415
4333
  const tests = getTests(files);
@@ -4492,12 +4410,13 @@ class JsonReporter {
4492
4410
  snapshot: this.ctx.snapshot.summary,
4493
4411
  startTime: this.start,
4494
4412
  success,
4495
- testResults
4413
+ testResults,
4414
+ coverageMap
4496
4415
  };
4497
4416
  await this.writeReport(JSON.stringify(result));
4498
4417
  }
4499
- async onFinished(files = this.ctx.state.getFiles()) {
4500
- await this.logTasks(files);
4418
+ async onFinished(files = this.ctx.state.getFiles(), _errors = [], coverageMap) {
4419
+ await this.logTasks(files, coverageMap);
4501
4420
  }
4502
4421
  /**
4503
4422
  * Writes the report to an output file if specified in the config,
@@ -4927,6 +4846,9 @@ class VerboseReporter extends DefaultReporter {
4927
4846
  ` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`
4928
4847
  );
4929
4848
  }
4849
+ if (task.result?.note) {
4850
+ title += c.dim(c.gray(` [${task.result.note}]`));
4851
+ }
4930
4852
  this.ctx.logger.log(title);
4931
4853
  if (task.result.state === "fail") {
4932
4854
  task.result.errors?.forEach((error) => {