vitest 0.10.0 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,25 +5,25 @@ import process$1 from 'process';
5
5
  import { s as signalExit, m as mergeStream, g as getStream, c as crossSpawn, o as onetime$1 } from './vendor-index.40be925a.js';
6
6
  import url, { fileURLToPath, pathToFileURL } from 'url';
7
7
  import require$$0, { constants as constants$5, cpus, hostname } from 'os';
8
- import { j as join, f as basename, h as dirname, k as resolve, p as picocolors, s as slash$2, l as isAbsolute, m as relative, o as getTests, q as getFullName, u as hasFailed, v as hasFailedSnapshot, w as getSuites, t as toArray, n as noop$1, x as deepMerge, y as toNamespacedPath, g as getCallLastIndex, e as notNullish, z as ensurePackageInstalled } from './chunk-utils-global.37a7c822.js';
8
+ import { j as join, f as basename, h as dirname, k as resolve, p as picocolors, s as slash$2, l as isAbsolute, m as relative, o as getTests, q as getFullName, u as hasFailed, v as hasFailedSnapshot, w as getSuites, t as toArray, x as normalize, n as noop$1, y as deepMerge, z as toNamespacedPath, g as getCallLastIndex, e as notNullish, A as ensurePackageInstalled, B as stdout } from './chunk-utils-global.eb31f3da.js';
9
9
  import { createServer, mergeConfig } from 'vite';
10
- import fs$8, { promises, existsSync } from 'fs';
11
- import { d as distDir, a as defaultPort, c as configFiles } from './chunk-constants.d540b1d1.js';
10
+ import fs$8, { promises, existsSync, readFileSync } from 'fs';
11
+ import { d as distDir, a as defaultPort, c as configFiles } from './chunk-constants.54c46a47.js';
12
12
  import readline from 'readline';
13
13
  import require$$0$1 from 'util';
14
14
  import require$$0$2 from 'stream';
15
15
  import require$$2 from 'events';
16
16
  import { c as commonjsGlobal } from './vendor-_commonjsHelpers.addc3445.js';
17
- import { i as isNodeBuiltin, a as isValidNodeImport, s as slash$1, t as toFilePath, w as withInlineSourcemap, c as createBirpc, V as ViteNodeRunner } from './chunk-vite-node-utils.33447cc0.js';
18
- import { c as configDefaults, r as resolveC8Options, a as cleanCoverage, b as reportCoverage } from './chunk-defaults.04d5d90b.js';
17
+ import { i as isNodeBuiltin, a as isValidNodeImport, s as slash$1, t as toFilePath, w as withInlineSourcemap, c as createBirpc, V as ViteNodeRunner } from './chunk-vite-node-utils.3cb38009.js';
18
+ import { c as configDefaults, r as resolveC8Options, a as cleanCoverage, b as reportCoverage } from './chunk-defaults.c143550b.js';
19
19
  import { MessageChannel } from 'worker_threads';
20
20
  import { Tinypool } from 'tinypool';
21
21
  import { performance } from 'perf_hooks';
22
- import { e as stripAnsi, h as stringWidth, i as ansiStyles, j as sliceAnsi, k as setInterval, o as clearInterval, q as cliTruncate, c as setTimeout$1, b as parseStacktrace, r as interpretSourcePos, s as stringify$5, u as unifiedDiff, a as posToNumber, l as lineSplitRE, d as clearTimeout$1 } from './chunk-utils-timers.12bc05d1.js';
22
+ import { e as stripAnsi, h as stringWidth, i as ansiStyles, j as sliceAnsi, k as setInterval, o as clearInterval, q as cliTruncate, c as setTimeout$1, b as parseStacktrace, r as interpretSourcePos, s as stringify$5, u as unifiedDiff, a as posToNumber, l as lineSplitRE, d as clearTimeout$1 } from './chunk-utils-timers.8a5e7cd5.js';
23
23
  import MagicString from './chunk-magic-string.d5e0e473.js';
24
24
  import { p as prompts } from './vendor-index.405e58ef.js';
25
25
 
26
- var version = "0.10.0";
26
+ var version = "0.10.3";
27
27
 
28
28
  function stripFinalNewline(input) {
29
29
  const LF = typeof input === 'string' ? '\n' : '\n'.charCodeAt();
@@ -8285,8 +8285,11 @@ function createChannel(ctx) {
8285
8285
  ctx.state.updateUserLog(log);
8286
8286
  ctx.report("onUserConsoleLog", log);
8287
8287
  },
8288
+ onUnhandledRejection(err) {
8289
+ ctx.state.catchError(err, "Unhandled Rejection");
8290
+ },
8288
8291
  onFinished(files) {
8289
- ctx.report("onFinished", files);
8292
+ ctx.report("onFinished", files, ctx.state.getUnhandledErrors());
8290
8293
  }
8291
8294
  }, {
8292
8295
  post(v) {
@@ -8452,6 +8455,7 @@ const WAIT_FOR_CHANGE_PASS = `
8452
8455
  ${picocolors.exports.bold(picocolors.exports.inverse(picocolors.exports.green(" PASS ")))}${picocolors.exports.green(" Waiting for file changes...")}`;
8453
8456
  const WAIT_FOR_CHANGE_FAIL = `
8454
8457
  ${picocolors.exports.bold(picocolors.exports.inverse(picocolors.exports.red(" FAIL ")))}${picocolors.exports.red(" Tests failed. Watching for file changes...")}`;
8458
+ const DURATION_LONG$1 = 300;
8455
8459
  class BaseReporter {
8456
8460
  constructor() {
8457
8461
  this.start = 0;
@@ -8477,9 +8481,21 @@ class BaseReporter {
8477
8481
  relative(path) {
8478
8482
  return relative(this.ctx.config.root, path);
8479
8483
  }
8480
- async onFinished(files = this.ctx.state.getFiles()) {
8484
+ async onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
8481
8485
  this.end = performance.now();
8482
8486
  await this.reportSummary(files);
8487
+ if (errors.length) {
8488
+ process.exitCode = 1;
8489
+ const errorMessage = picocolors.exports.red(picocolors.exports.bold(`
8490
+ Vitest catched ${errors.length} unhandled error${errors.length > 1 ? "s" : ""} during the test run. This might cause false positive tests.
8491
+ Please, resolve all the errors to make sure your tests are not affected.`));
8492
+ this.ctx.log(picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(" Unhandled Errors ")))));
8493
+ this.ctx.log(errorMessage);
8494
+ await Promise.all(errors.map(async (err) => {
8495
+ await this.ctx.printError(err, true, err.type || "Unhandled Error");
8496
+ }));
8497
+ this.ctx.log(picocolors.exports.red(divider()));
8498
+ }
8483
8499
  }
8484
8500
  onTaskUpdate(packs) {
8485
8501
  var _a, _b, _c;
@@ -8500,8 +8516,12 @@ class BaseReporter {
8500
8516
  if (skipped.length)
8501
8517
  state += ` ${picocolors.exports.dim("|")} ${picocolors.exports.yellow(`${skipped.length} skipped`)}`;
8502
8518
  let suffix = picocolors.exports.dim(" (") + state + picocolors.exports.dim(")");
8503
- if (task.result.duration)
8504
- suffix += picocolors.exports.yellow(` ${Math.round(task.result.duration)}${picocolors.exports.dim("ms")}`);
8519
+ if (task.result.duration) {
8520
+ const color = task.result.duration > DURATION_LONG$1 ? picocolors.exports.yellow : picocolors.exports.gray;
8521
+ suffix += color(` ${Math.round(task.result.duration)}${picocolors.exports.dim("ms")}`);
8522
+ }
8523
+ if (this.ctx.config.logHeapUsage && task.result.heap != null)
8524
+ suffix += picocolors.exports.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`);
8505
8525
  this.ctx.log(` ${getStateSymbol(task)} ${task.name} ${suffix}`);
8506
8526
  for (const test of failed) {
8507
8527
  this.ctx.log(picocolors.exports.red(` ${pointer} ${getFullName(test)}`));
@@ -8512,7 +8532,8 @@ class BaseReporter {
8512
8532
  }
8513
8533
  async onWatcherStart() {
8514
8534
  const files = this.ctx.state.getFiles();
8515
- const failed = hasFailed(files);
8535
+ const errors = this.ctx.state.getUnhandledErrors();
8536
+ const failed = errors.length > 0 || hasFailed(files);
8516
8537
  const failedSnap = hasFailedSnapshot(files);
8517
8538
  if (failed)
8518
8539
  this.ctx.log(WAIT_FOR_CHANGE_FAIL);
@@ -8623,9 +8644,7 @@ ${picocolors.exports.inverse(picocolors.exports.bold(picocolors.exports.blue(" R
8623
8644
  registerUnhandledRejection() {
8624
8645
  process.on("unhandledRejection", async (err) => {
8625
8646
  process.exitCode = 1;
8626
- this.ctx.error(`
8627
- ${picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(" Unhandled Rejection "))))}`);
8628
- await this.ctx.printError(err);
8647
+ await this.ctx.printError(err, true, "Unhandled Rejection");
8629
8648
  this.ctx.error("\n\n");
8630
8649
  process.exit(1);
8631
8650
  });
@@ -9137,7 +9156,7 @@ function renderHookState(task, hookName, level = 0) {
9137
9156
  return "";
9138
9157
  }
9139
9158
  function renderTree(tasks, options, level = 0) {
9140
- var _a, _b, _c, _d;
9159
+ var _a, _b, _c, _d, _e;
9141
9160
  let output = [];
9142
9161
  for (const task of tasks) {
9143
9162
  let suffix = "";
@@ -9150,11 +9169,13 @@ function renderTree(tasks, options, level = 0) {
9150
9169
  if (task.result.duration > DURATION_LONG)
9151
9170
  suffix += picocolors.exports.yellow(` ${Math.round(task.result.duration)}${picocolors.exports.dim("ms")}`);
9152
9171
  }
9172
+ if (options.showHeap && ((_b = task.result) == null ? void 0 : _b.heap) != null)
9173
+ suffix += picocolors.exports.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`);
9153
9174
  let name = task.name;
9154
9175
  if (level === 0)
9155
9176
  name = formatFilepath(name);
9156
9177
  output.push(" ".repeat(level) + prefix + name + suffix);
9157
- if (((_b = task.result) == null ? void 0 : _b.state) !== "pass" && outputMap.get(task) != null) {
9178
+ if (((_c = task.result) == null ? void 0 : _c.state) !== "pass" && outputMap.get(task) != null) {
9158
9179
  let data = outputMap.get(task);
9159
9180
  if (typeof data === "string") {
9160
9181
  data = stripAnsi(data.trim().split("\n").filter(Boolean).pop());
@@ -9169,7 +9190,7 @@ function renderTree(tasks, options, level = 0) {
9169
9190
  output = output.concat(renderHookState(task, "beforeAll", level + 1));
9170
9191
  output = output.concat(renderHookState(task, "beforeEach", level + 1));
9171
9192
  if (task.type === "suite" && task.tasks.length > 0) {
9172
- if (((_c = task.result) == null ? void 0 : _c.state) === "fail" || ((_d = task.result) == null ? void 0 : _d.state) === "run" || options.renderSucceed)
9193
+ if (((_d = task.result) == null ? void 0 : _d.state) === "fail" || ((_e = task.result) == null ? void 0 : _e.state) === "run" || options.renderSucceed)
9173
9194
  output = output.concat(renderTree(task.tasks, options, level + 1));
9174
9195
  }
9175
9196
  output = output.concat(renderHookState(task, "afterAll", level + 1));
@@ -9231,6 +9252,7 @@ class DefaultReporter extends BaseReporter {
9231
9252
  onCollected() {
9232
9253
  if (this.isTTY) {
9233
9254
  this.rendererOptions.outputStream = this.ctx.outputStream;
9255
+ this.rendererOptions.showHeap = this.ctx.config.logHeapUsage;
9234
9256
  const files = this.ctx.state.getFiles(this.watchFilters);
9235
9257
  if (!this.renderer)
9236
9258
  this.renderer = createListRenderer(files, this.rendererOptions).start();
@@ -9238,10 +9260,10 @@ class DefaultReporter extends BaseReporter {
9238
9260
  this.renderer.update(files);
9239
9261
  }
9240
9262
  }
9241
- async onFinished(files = this.ctx.state.getFiles()) {
9263
+ async onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
9242
9264
  await this.stopListRender();
9243
9265
  this.ctx.log();
9244
- await super.onFinished(files);
9266
+ await super.onFinished(files, errors);
9245
9267
  }
9246
9268
  async onWatcherStart() {
9247
9269
  await this.stopListRender();
@@ -9328,10 +9350,10 @@ class DotReporter extends BaseReporter {
9328
9350
  this.renderer.update(files);
9329
9351
  }
9330
9352
  }
9331
- async onFinished(files = this.ctx.state.getFiles()) {
9353
+ async onFinished(files = this.ctx.state.getFiles(), errors = this.ctx.state.getUnhandledErrors()) {
9332
9354
  await this.stopListRender();
9333
9355
  this.ctx.log();
9334
- await super.onFinished(files);
9356
+ await super.onFinished(files, errors);
9335
9357
  }
9336
9358
  async onWatcherStart() {
9337
9359
  await this.stopListRender();
@@ -9418,7 +9440,7 @@ class JsonReporter {
9418
9440
  return Math.max(prev, (((_a2 = next.result) == null ? void 0 : _a2.startTime) ?? 0) + (((_b2 = next.result) == null ? void 0 : _b2.duration) ?? 0));
9419
9441
  }, startTime);
9420
9442
  const assertionResults = tests2.map((t) => {
9421
- var _a2, _b2, _c;
9443
+ var _a2, _b2, _c, _d;
9422
9444
  const ancestorTitles = [];
9423
9445
  let iter = t.suite;
9424
9446
  while (iter) {
@@ -9429,10 +9451,10 @@ class JsonReporter {
9429
9451
  return {
9430
9452
  ancestorTitles,
9431
9453
  fullName: ancestorTitles.length > 0 ? `${ancestorTitles.join(" ")} ${t.name}` : t.name,
9432
- status: t.result != null ? StatusMap[t.result.state] : "skipped",
9454
+ status: StatusMap[((_a2 = t.result) == null ? void 0 : _a2.state) || t.mode] || "skipped",
9433
9455
  title: t.name,
9434
- duration: (_a2 = t.result) == null ? void 0 : _a2.duration,
9435
- failureMessages: ((_c = (_b2 = t.result) == null ? void 0 : _b2.error) == null ? void 0 : _c.message) == null ? [] : [t.result.error.message]
9456
+ duration: (_b2 = t.result) == null ? void 0 : _b2.duration,
9457
+ failureMessages: ((_d = (_c = t.result) == null ? void 0 : _c.error) == null ? void 0 : _d.message) == null ? [] : [t.result.error.message]
9436
9458
  };
9437
9459
  });
9438
9460
  if (tests2.some((t) => {
@@ -9499,7 +9521,10 @@ class VerboseReporter extends DefaultReporter {
9499
9521
  for (const pack of packs) {
9500
9522
  const task = this.ctx.state.idMap.get(pack[0]);
9501
9523
  if (task && task.type === "test" && ((_a = task.result) == null ? void 0 : _a.state) && ((_b = task.result) == null ? void 0 : _b.state) !== "run") {
9502
- this.ctx.log(` ${getStateSymbol(task)} ${getFullName(task)}`);
9524
+ let title = ` ${getStateSymbol(task)} ${getFullName(task)}`;
9525
+ if (this.ctx.config.logHeapUsage && task.result.heap != null)
9526
+ title += picocolors.exports.magenta(` ${Math.floor(task.result.heap / 1024 / 1024)} MB heap used`);
9527
+ this.ctx.log(title);
9503
9528
  if (task.result.state === "fail")
9504
9529
  this.ctx.log(picocolors.exports.red(` ${F_RIGHT} ${(_c = task.result.error) == null ? void 0 : _c.message}`));
9505
9530
  }
@@ -9845,6 +9870,17 @@ class StateManager {
9845
9870
  this.filesMap = /* @__PURE__ */ new Map();
9846
9871
  this.idMap = /* @__PURE__ */ new Map();
9847
9872
  this.taskFileMap = /* @__PURE__ */ new WeakMap();
9873
+ this.errorsSet = /* @__PURE__ */ new Set();
9874
+ }
9875
+ catchError(err, type) {
9876
+ err.type = type;
9877
+ this.errorsSet.add(err);
9878
+ }
9879
+ clearErrors() {
9880
+ this.errorsSet.clear();
9881
+ }
9882
+ getUnhandledErrors() {
9883
+ return Array.from(this.errorsSet.values());
9848
9884
  }
9849
9885
  getFiles(keys) {
9850
9886
  if (keys)
@@ -9997,7 +10033,8 @@ function fileFromParsedStack(stack) {
9997
10033
  return join(stack.file, "../", stack.sourcePos.source);
9998
10034
  return stack.file;
9999
10035
  }
10000
- async function printError(error, ctx) {
10036
+ async function printError(error, ctx, options = {}) {
10037
+ const { showCodeFrame = true, fullStack = false, type } = options;
10001
10038
  let e = error;
10002
10039
  if (typeof error === "string") {
10003
10040
  e = {
@@ -10005,20 +10042,56 @@ async function printError(error, ctx) {
10005
10042
  stack: error
10006
10043
  };
10007
10044
  }
10008
- const stacks = parseStacktrace(e);
10045
+ const stacks = parseStacktrace(e, fullStack);
10009
10046
  await interpretSourcePos(stacks, ctx);
10010
10047
  const nearest = stacks.find((stack) => ctx.server.moduleGraph.getModuleById(stack.file) && existsSync(stack.file));
10048
+ const errorProperties = getErrorProperties(e);
10049
+ if (type)
10050
+ printErrorType(type, ctx);
10011
10051
  printErrorMessage(e, ctx.console);
10012
- await printStack(ctx, stacks, nearest, async (s, pos) => {
10013
- if (s === nearest && nearest) {
10014
- const sourceCode = await promises.readFile(fileFromParsedStack(nearest), "utf-8");
10052
+ printStack(ctx, stacks, nearest, errorProperties, (s, pos) => {
10053
+ if (showCodeFrame && s === nearest && nearest) {
10054
+ const sourceCode = readFileSync(fileFromParsedStack(nearest), "utf-8");
10015
10055
  ctx.log(picocolors.exports.yellow(generateCodeFrame(sourceCode, 4, pos)));
10016
10056
  }
10017
10057
  });
10058
+ if (e.cause) {
10059
+ e.cause.name = `Caused by: ${e.cause.name}`;
10060
+ await printError(e.cause, ctx, { fullStack, showCodeFrame: false });
10061
+ }
10018
10062
  handleImportOutsideModuleError(e.stack || e.stackStr || "", ctx);
10019
10063
  if (e.showDiff)
10020
10064
  displayDiff(stringify$5(e.actual), stringify$5(e.expected), ctx.console, ctx.config.outputTruncateLength);
10021
10065
  }
10066
+ function printErrorType(type, ctx) {
10067
+ ctx.error(`
10068
+ ${picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(` ${type} `))))}`);
10069
+ }
10070
+ function getErrorProperties(e) {
10071
+ const errorObject = /* @__PURE__ */ Object.create(null);
10072
+ if (e.name === "AssertionError")
10073
+ return errorObject;
10074
+ const skip = [
10075
+ "message",
10076
+ "name",
10077
+ "nameStr",
10078
+ "stack",
10079
+ "cause",
10080
+ "stacks",
10081
+ "stackStr",
10082
+ "type",
10083
+ "showDiff",
10084
+ "actual",
10085
+ "expected",
10086
+ "constructor",
10087
+ "toString"
10088
+ ];
10089
+ for (const key of Object.getOwnPropertyNames(e)) {
10090
+ if (!skip.includes(key))
10091
+ errorObject[key] = e[key];
10092
+ }
10093
+ return errorObject;
10094
+ }
10022
10095
  const esmErrors = [
10023
10096
  "Cannot use import statement outside a module",
10024
10097
  "Unexpected token 'export'"
@@ -10026,7 +10099,7 @@ const esmErrors = [
10026
10099
  function handleImportOutsideModuleError(stack, ctx) {
10027
10100
  if (!esmErrors.some((e) => stack.includes(e)))
10028
10101
  return;
10029
- const path = stack.split("\n")[0].trim();
10102
+ const path = normalize(stack.split("\n")[0].trim());
10030
10103
  let name = path.split("/node_modules/").pop() || "";
10031
10104
  if (name == null ? void 0 : name.startsWith("@"))
10032
10105
  name = name.split("/").slice(0, 2).join("/");
@@ -10054,7 +10127,7 @@ function printErrorMessage(error, console) {
10054
10127
  const errorName = error.name || error.nameStr || "Unknown Error";
10055
10128
  console.error(picocolors.exports.red(`${picocolors.exports.bold(errorName)}: ${error.message}`));
10056
10129
  }
10057
- async function printStack(ctx, stack, highlight, onStack) {
10130
+ function printStack(ctx, stack, highlight, errorProperties, onStack) {
10058
10131
  if (!stack.length)
10059
10132
  return;
10060
10133
  for (const frame of stack) {
@@ -10063,11 +10136,17 @@ async function printStack(ctx, stack, highlight, onStack) {
10063
10136
  const file = fileFromParsedStack(frame);
10064
10137
  const path = relative(ctx.config.root, file);
10065
10138
  ctx.log(color(` ${picocolors.exports.dim(F_POINTER)} ${[frame.method, picocolors.exports.dim(`${path}:${pos.line}:${pos.column}`)].filter(Boolean).join(" ")}`));
10066
- await (onStack == null ? void 0 : onStack(frame, pos));
10139
+ onStack == null ? void 0 : onStack(frame, pos);
10067
10140
  if (frame.file in ctx.state.filesMap)
10068
10141
  break;
10069
10142
  }
10070
10143
  ctx.log();
10144
+ const hasProperties = Object.keys(errorProperties).length > 0;
10145
+ if (hasProperties) {
10146
+ ctx.log(picocolors.exports.red(picocolors.exports.dim(divider())));
10147
+ const propertiesString = stringify$5(errorProperties, 10, { printBasicPrototype: false });
10148
+ ctx.log(picocolors.exports.red(picocolors.exports.bold("Serialized Error:")), picocolors.exports.gray(propertiesString));
10149
+ }
10071
10150
  }
10072
10151
  function generateCodeFrame(source, indent = 0, start = 0, end, range = 2) {
10073
10152
  start = posToNumber(source, start);
@@ -10329,10 +10408,15 @@ class Vitest {
10329
10408
  const invalidates = Array.from(this.invalidates);
10330
10409
  this.invalidates.clear();
10331
10410
  this.snapshot.clear();
10332
- await this.pool.runTests(files, invalidates);
10411
+ this.state.clearErrors();
10412
+ try {
10413
+ await this.pool.runTests(files, invalidates);
10414
+ } catch (err) {
10415
+ this.state.catchError(err, "Unhandled Error");
10416
+ }
10333
10417
  if (hasFailed(this.state.getFiles()))
10334
10418
  process.exitCode = 1;
10335
- await this.report("onFinished", this.state.getFiles());
10419
+ await this.report("onFinished", this.state.getFiles(), this.state.getUnhandledErrors());
10336
10420
  })().finally(() => {
10337
10421
  this.runningPromise = void 0;
10338
10422
  });
@@ -10351,7 +10435,10 @@ class Vitest {
10351
10435
  await this.rerunFiles(this.state.getFailedFilepaths(), "rerun failed");
10352
10436
  }
10353
10437
  async updateSnapshot(files) {
10354
- files = files || this.state.getFailedFilepaths();
10438
+ files = files || [
10439
+ ...this.state.getFailedFilepaths(),
10440
+ ...this.snapshot.summary.uncheckedKeysByFile.map((s) => s.filePath)
10441
+ ];
10355
10442
  this.configOverride = {
10356
10443
  snapshotOptions: {
10357
10444
  updateSnapshot: "all"
@@ -10532,8 +10619,12 @@ class Vitest {
10532
10619
  isInSourceTestFile(code) {
10533
10620
  return code.includes("import.meta.vitest");
10534
10621
  }
10535
- printError(err) {
10536
- return printError(err, this);
10622
+ printError(err, fullStack = false, type) {
10623
+ return printError(err, this, {
10624
+ fullStack,
10625
+ type,
10626
+ showCodeFrame: true
10627
+ });
10537
10628
  }
10538
10629
  onServerRestarted(fn) {
10539
10630
  this._onRestartListeners.push(fn);
@@ -10847,7 +10938,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest()) {
10847
10938
  await ctx.setServer(options, server);
10848
10939
  haveStarted = true;
10849
10940
  if (options.api && options.watch)
10850
- (await import('./chunk-api-setup.d70fc960.js')).setup(ctx);
10941
+ (await import('./chunk-api-setup.0baa5b9c.js')).setup(ctx);
10851
10942
  if (!options.watch)
10852
10943
  await server.watcher.close();
10853
10944
  }
@@ -10886,7 +10977,7 @@ const keys = [
10886
10977
  ["q", "quit"]
10887
10978
  ];
10888
10979
  function printShortcutsHelp() {
10889
- process.stdout.write(`
10980
+ stdout().write(`
10890
10981
  ${picocolors.exports.bold(" Watch Usage")}
10891
10982
  ${keys.map((i) => picocolors.exports.dim(" press ") + picocolors.exports.reset(picocolors.exports.bold(i[0])) + picocolors.exports.dim(` to ${i[1]}`)).join("\n")}
10892
10983
  `);
@@ -10988,9 +11079,7 @@ async function startVitest(cliFilters, options, viteOverrides) {
10988
11079
  await ctx.start(cliFilters);
10989
11080
  } catch (e) {
10990
11081
  process.exitCode = 1;
10991
- ctx.error(`
10992
- ${picocolors.exports.red(divider(picocolors.exports.bold(picocolors.exports.inverse(" Unhandled Error "))))}`);
10993
- await ctx.printError(e);
11082
+ await ctx.printError(e, true, "Unhandled Error");
10994
11083
  ctx.error("\n\n");
10995
11084
  return false;
10996
11085
  }
@@ -1,7 +1,7 @@
1
1
  import { builtinModules, createRequire } from 'module';
2
2
  import { pathToFileURL, fileURLToPath as fileURLToPath$2, URL as URL$1 } from 'url';
3
3
  import vm from 'vm';
4
- import { l as isAbsolute$2, k as resolve, j as join$2, A as extname$2, h as dirname$2 } from './chunk-utils-global.37a7c822.js';
4
+ import { l as isAbsolute$2, k as resolve, j as join$2, C as extname$2, h as dirname$2 } from './chunk-utils-global.eb31f3da.js';
5
5
  import path from 'path';
6
6
  import fs, { realpathSync, statSync, Stats, promises, existsSync } from 'fs';
7
7
  import assert from 'assert';
@@ -9063,6 +9063,8 @@ function proxyMethod(name, tryDefault) {
9063
9063
  };
9064
9064
  }
9065
9065
  function exportAll(exports, sourceModule) {
9066
+ if (exports === sourceModule)
9067
+ return;
9066
9068
  for (const key in sourceModule) {
9067
9069
  if (key !== "default") {
9068
9070
  try {
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { EventEmitter } from 'events';
2
- import { p as picocolors } from './chunk-utils-global.37a7c822.js';
3
- import { v as version, s as startVitest, d as divider } from './chunk-vite-node-externalize.5c678054.js';
2
+ import { p as picocolors } from './chunk-utils-global.eb31f3da.js';
3
+ import { v as version, s as startVitest, d as divider } from './chunk-vite-node-externalize.f88b9527.js';
4
4
  import 'tty';
5
5
  import 'local-pkg';
6
6
  import 'path';
@@ -16,16 +16,16 @@ import 'util';
16
16
  import 'url';
17
17
  import 'os';
18
18
  import 'vite';
19
- import './chunk-constants.d540b1d1.js';
19
+ import './chunk-constants.54c46a47.js';
20
20
  import 'readline';
21
- import './chunk-vite-node-utils.33447cc0.js';
21
+ import './chunk-vite-node-utils.3cb38009.js';
22
22
  import 'module';
23
23
  import 'vm';
24
- import './chunk-defaults.04d5d90b.js';
24
+ import './chunk-defaults.c143550b.js';
25
25
  import 'worker_threads';
26
26
  import 'tinypool';
27
27
  import 'perf_hooks';
28
- import './chunk-utils-timers.12bc05d1.js';
28
+ import './chunk-utils-timers.8a5e7cd5.js';
29
29
  import './chunk-magic-string.d5e0e473.js';
30
30
  import './vendor-index.405e58ef.js';
31
31
 
package/dist/entry.js CHANGED
@@ -1,20 +1,20 @@
1
- export { r as run } from './vendor-entry.369fd6c9.js';
1
+ export { r as run } from './vendor-entry.2f0617df.js';
2
2
  import 'fs';
3
- import './chunk-utils-global.37a7c822.js';
3
+ import './chunk-utils-global.eb31f3da.js';
4
4
  import 'tty';
5
5
  import 'local-pkg';
6
6
  import 'path';
7
7
  import 'console';
8
8
  import 'stream';
9
- import './chunk-runtime-chain.f863f182.js';
9
+ import './chunk-runtime-chain.0ac0691b.js';
10
10
  import 'chai';
11
11
  import './vendor-_commonjsHelpers.addc3445.js';
12
- import './chunk-runtime-rpc.8f648236.js';
13
- import './chunk-utils-timers.12bc05d1.js';
12
+ import './chunk-runtime-rpc.710f6f7f.js';
13
+ import './chunk-utils-timers.8a5e7cd5.js';
14
14
  import './chunk-integrations-spy.f036df6f.js';
15
15
  import 'tinyspy';
16
16
  import 'util';
17
- import './chunk-defaults.04d5d90b.js';
17
+ import './chunk-defaults.c143550b.js';
18
18
  import 'module';
19
19
  import 'url';
20
20
  import 'crypto';
package/dist/index.d.ts CHANGED
@@ -341,6 +341,10 @@ declare class StateManager {
341
341
  filesMap: Map<string, File>;
342
342
  idMap: Map<string, Task>;
343
343
  taskFileMap: WeakMap<Task, File>;
344
+ errorsSet: Set<unknown>;
345
+ catchError(err: unknown, type: string): void;
346
+ clearErrors(): void;
347
+ getUnhandledErrors(): unknown[];
344
348
  getFiles(keys?: string[]): File[];
345
349
  getFilepaths(): string[];
346
350
  getFailedFilepaths(): string[];
@@ -402,7 +406,7 @@ declare class Vitest {
402
406
  globTestFiles(filters?: string[]): Promise<string[]>;
403
407
  isTargetFile(id: string, source?: string): Promise<boolean>;
404
408
  isInSourceTestFile(code: string): boolean;
405
- printError(err: unknown): Promise<void>;
409
+ printError(err: unknown, fullStack?: boolean, type?: string): Promise<void>;
406
410
  onServerRestarted(fn: () => void): void;
407
411
  }
408
412
 
@@ -417,7 +421,7 @@ declare abstract class BaseReporter implements Reporter {
417
421
  constructor();
418
422
  onInit(ctx: Vitest): void;
419
423
  relative(path: string): string;
420
- onFinished(files?: File[]): Promise<void>;
424
+ onFinished(files?: File[], errors?: unknown[]): Promise<void>;
421
425
  onTaskUpdate(packs: TaskResultPack[]): void;
422
426
  onWatcherStart(): Promise<void>;
423
427
  onWatcherRerun(files: string[], trigger?: string): Promise<void>;
@@ -431,6 +435,7 @@ declare abstract class BaseReporter implements Reporter {
431
435
  interface ListRendererOptions {
432
436
  renderSucceed?: boolean;
433
437
  outputStream: NodeJS.WritableStream;
438
+ showHeap: boolean;
434
439
  }
435
440
  declare const createListRenderer: (_tasks: Task[], options: ListRendererOptions) => {
436
441
  start(): any;
@@ -444,7 +449,7 @@ declare class DefaultReporter extends BaseReporter {
444
449
  rendererOptions: ListRendererOptions;
445
450
  onTestRemoved(trigger?: string): Promise<void>;
446
451
  onCollected(): void;
447
- onFinished(files?: File[]): Promise<void>;
452
+ onFinished(files?: File[], errors?: unknown[]): Promise<void>;
448
453
  onWatcherStart(): Promise<void>;
449
454
  stopListRender(): Promise<void>;
450
455
  onWatcherRerun(files: string[], trigger?: string): Promise<void>;
@@ -454,7 +459,7 @@ declare class DefaultReporter extends BaseReporter {
454
459
  declare class DotReporter extends BaseReporter {
455
460
  renderer?: ReturnType<typeof createListRenderer>;
456
461
  onCollected(): void;
457
- onFinished(files?: File[]): Promise<void>;
462
+ onFinished(files?: File[], errors?: unknown[]): Promise<void>;
458
463
  onWatcherStart(): Promise<void>;
459
464
  stopListRender(): Promise<void>;
460
465
  onWatcherRerun(files: string[], trigger?: string): Promise<void>;
@@ -576,6 +581,7 @@ interface ErrorWithDiff extends Error {
576
581
  actual?: any;
577
582
  expected?: any;
578
583
  operator?: string;
584
+ type?: string;
579
585
  }
580
586
  interface ModuleGraphData {
581
587
  graph: Record<string, string[]>;
@@ -742,6 +748,7 @@ interface TaskResult {
742
748
  state: TaskState;
743
749
  duration?: number;
744
750
  startTime?: number;
751
+ heap?: number;
745
752
  error?: ErrorWithDiff;
746
753
  htmlError?: string;
747
754
  hooks?: Partial<Record<keyof SuiteHooks, TaskState>>;
@@ -789,12 +796,16 @@ declare type TestAPI<ExtraContext = {}> = ChainableFunction<'concurrent' | 'only
789
796
  timeout?: number
790
797
  ], void> & {
791
798
  each: EachFunction;
799
+ skipIf(condition: any): TestAPI<ExtraContext>;
800
+ runIf(condition: any): TestAPI<ExtraContext>;
792
801
  };
793
802
  declare type SuiteAPI<ExtraContext = {}> = ChainableFunction<'concurrent' | 'only' | 'skip' | 'todo', [
794
803
  name: string,
795
804
  factory?: SuiteFactory
796
805
  ], SuiteCollector<ExtraContext>> & {
797
806
  each: EachFunction;
807
+ skipIf(condition: any): SuiteAPI<ExtraContext>;
808
+ runIf(condition: any): SuiteAPI<ExtraContext>;
798
809
  };
799
810
  declare type HookListener<T extends any[], Return = void> = (...args: T) => Awaitable<Return | void>;
800
811
  interface SuiteHooks {
@@ -837,7 +848,7 @@ interface TestContext {
837
848
  interface Reporter {
838
849
  onInit?(ctx: Vitest): void;
839
850
  onCollected?: (files?: File[]) => Awaitable<void>;
840
- onFinished?: (files?: File[]) => Awaitable<void>;
851
+ onFinished?: (files?: File[], errors?: unknown[]) => Awaitable<void>;
841
852
  onTaskUpdate?: (packs: TaskResultPack[]) => Awaitable<void>;
842
853
  onTestRemoved?: (trigger?: string) => Awaitable<void>;
843
854
  onWatcherStart?: () => Awaitable<void>;
@@ -1000,7 +1011,7 @@ interface InlineConfig {
1000
1011
  * Custom reporter for output. Can contain one or more built-in report names, reporter instances,
1001
1012
  * and/or paths to custom reporters
1002
1013
  */
1003
- reporters?: Arrayable<BuiltinReporters | Reporter | string>;
1014
+ reporters?: Arrayable<BuiltinReporters | Reporter | Omit<string, BuiltinReporters>>;
1004
1015
  /**
1005
1016
  * diff output length
1006
1017
  */
@@ -1142,6 +1153,10 @@ interface InlineConfig {
1142
1153
  * Resolve custom snapshot path
1143
1154
  */
1144
1155
  resolveSnapshotPath?: (path: string, extension: string) => string;
1156
+ /**
1157
+ * Show heap usage after each test. Usefull for debugging memory leaks.
1158
+ */
1159
+ logHeapUsage?: boolean;
1145
1160
  }
1146
1161
  interface UserConfig extends InlineConfig {
1147
1162
  /**
@@ -1223,9 +1238,10 @@ interface WorkerRPC {
1223
1238
  fetch: FetchFunction;
1224
1239
  resolveId: ResolveIdFunction;
1225
1240
  getSourceMap: (id: string, force?: boolean) => Promise<RawSourceMap | undefined>;
1226
- onFinished: (files: File[]) => void;
1241
+ onFinished: (files: File[], errors?: unknown[]) => void;
1227
1242
  onWorkerExit: (code?: number) => void;
1228
1243
  onUserConsoleLog: (log: UserConsoleLog) => void;
1244
+ onUnhandledRejection: (err: unknown) => void;
1229
1245
  onCollected: (files: File[]) => void;
1230
1246
  onTaskUpdate: (pack: TaskResultPack[]) => void;
1231
1247
  snapshotSaved: (snapshot: SnapshotResult) => void;
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
- export { c as afterAll, f as afterEach, b as beforeAll, e as beforeEach, g as createExpect, d as describe, h as expect, k as getRunningMode, a as isFirstRun, l as isWatchMode, i as it, r as runOnce, s as suite, t as test, j as vi, v as vitest, w as withCallback } from './chunk-runtime-chain.f863f182.js';
1
+ export { c as afterAll, f as afterEach, b as beforeAll, e as beforeEach, g as createExpect, d as describe, h as expect, k as getRunningMode, a as isFirstRun, l as isWatchMode, i as it, r as runOnce, s as suite, t as test, j as vi, v as vitest, w as withCallback } from './chunk-runtime-chain.0ac0691b.js';
2
2
  export { assert, default as chai, should } from 'chai';
3
3
  import './vendor-_commonjsHelpers.addc3445.js';
4
- import './chunk-runtime-rpc.8f648236.js';
5
- import './chunk-utils-global.37a7c822.js';
4
+ import './chunk-runtime-rpc.710f6f7f.js';
5
+ import './chunk-utils-global.eb31f3da.js';
6
6
  import 'tty';
7
7
  import 'local-pkg';
8
8
  import 'path';
9
9
  import 'fs';
10
- import './chunk-utils-timers.12bc05d1.js';
10
+ import './chunk-utils-timers.8a5e7cd5.js';
11
11
  import './chunk-integrations-spy.f036df6f.js';
12
12
  import 'tinyspy';
13
13
  import 'util';