vitest 0.31.0 → 0.31.2

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.
@@ -25,7 +25,7 @@ import { ViteNodeServer } from 'vite-node/server';
25
25
  import { d as distDir, r as rootDir } from './vendor-paths.84fc7a99.js';
26
26
  import v8 from 'node:v8';
27
27
  import { fork } from 'node:child_process';
28
- import { g as groupBy, a as getEnvironmentTransformMode, c as createBirpc, A as AggregateErrorPonyfill, s as slash$1, t as toArray, i as isPrimitive, d as deepMerge, n as noop$1, b as stdout } from './vendor-index.7dcbfa46.js';
28
+ import { g as groupBy, a as getEnvironmentTransformMode, c as createBirpc, A as AggregateErrorPonyfill, s as slash$1, t as toArray, i as isPrimitive, d as deepMerge, n as noop$1, b as stdout } from './vendor-index.5037f2c0.js';
29
29
  import { MessageChannel } from 'node:worker_threads';
30
30
  import { cpus, hostname } from 'node:os';
31
31
  import Tinypool from 'tinypool';
@@ -60,7 +60,7 @@ function _mergeNamespaces(n, m) {
60
60
  return Object.freeze(n);
61
61
  }
62
62
 
63
- var version$1 = "0.31.0";
63
+ var version$1 = "0.31.2";
64
64
 
65
65
  const __dirname$1 = url.fileURLToPath(new URL(".", import.meta.url));
66
66
  async function ensurePackageInstalled(dependency, root) {
@@ -79,7 +79,7 @@ async function ensurePackageInstalled(dependency, root) {
79
79
  message: c.reset(`Do you want to install ${c.green(dependency)}?`)
80
80
  });
81
81
  if (install) {
82
- await (await import('./chunk-install-pkg.e0e70dba.js')).installPackage(dependency, { dev: true });
82
+ await (await import('./chunk-install-pkg.4207d842.js')).installPackage(dependency, { dev: true });
83
83
  process.stderr.write(c.yellow(`
84
84
  Package ${dependency} installed, re-run the command to start.
85
85
  `));
@@ -7301,10 +7301,22 @@ function createThreadsPool(ctx, { execArgv, env }) {
7301
7301
 
7302
7302
  function createBrowserPool(ctx) {
7303
7303
  const providers = /* @__PURE__ */ new Set();
7304
- const waitForTest = (id) => {
7304
+ const waitForTest = async (provider, id) => {
7305
7305
  const defer = createDefer();
7306
7306
  ctx.state.browserTestPromises.set(id, defer);
7307
- return defer;
7307
+ const off = provider.catchError((error) => {
7308
+ if (id !== "no-isolate") {
7309
+ Object.defineProperty(error, "VITEST_TEST_PATH", {
7310
+ value: id
7311
+ });
7312
+ }
7313
+ defer.reject(error);
7314
+ });
7315
+ try {
7316
+ return await defer;
7317
+ } finally {
7318
+ off();
7319
+ }
7308
7320
  };
7309
7321
  const runTests = async (project, files) => {
7310
7322
  var _a;
@@ -7328,14 +7340,14 @@ function createBrowserPool(ctx) {
7328
7340
  url.searchParams.append("path", path);
7329
7341
  url.searchParams.set("id", path);
7330
7342
  await provider.openPage(url.toString());
7331
- await waitForTest(path);
7343
+ await waitForTest(provider, path);
7332
7344
  }
7333
7345
  } else {
7334
7346
  const url = new URL("/", origin);
7335
7347
  url.searchParams.set("id", "no-isolate");
7336
7348
  paths.forEach((path) => url.searchParams.append("path", path));
7337
7349
  await provider.openPage(url.toString());
7338
- await waitForTest("no-isolate");
7350
+ await waitForTest(provider, "no-isolate");
7339
7351
  }
7340
7352
  };
7341
7353
  const runWorkspaceTests = async (specs) => {
@@ -9056,35 +9068,54 @@ function getIcon(task) {
9056
9068
  return pending;
9057
9069
  }
9058
9070
  }
9059
- function render(tasks) {
9071
+ function render(tasks, width) {
9060
9072
  const all = getTests(tasks);
9061
- const output = [];
9062
9073
  let currentIcon = pending;
9063
9074
  let currentTasks = 0;
9064
- const addOutput = () => output.push(currentIcon.color(currentIcon.char.repeat(currentTasks)));
9075
+ let previousLineWidth = 0;
9076
+ let output = "";
9077
+ const addOutput = () => {
9078
+ const { char, color } = currentIcon;
9079
+ const availableWidth = width - previousLineWidth;
9080
+ if (availableWidth > currentTasks) {
9081
+ output += color(char.repeat(currentTasks));
9082
+ previousLineWidth += currentTasks;
9083
+ } else {
9084
+ let buf = `${char.repeat(availableWidth)}
9085
+ `;
9086
+ const remaining = currentTasks - availableWidth;
9087
+ const fullRows = Math.floor(remaining / width);
9088
+ buf += `${char.repeat(width)}
9089
+ `.repeat(fullRows);
9090
+ const partialRow = remaining % width;
9091
+ if (partialRow > 0) {
9092
+ buf += char.repeat(partialRow);
9093
+ previousLineWidth = partialRow;
9094
+ } else {
9095
+ previousLineWidth = 0;
9096
+ }
9097
+ output += color(buf);
9098
+ }
9099
+ };
9065
9100
  for (const task of all) {
9066
9101
  const icon = getIcon(task);
9067
- const isLast = all.indexOf(task) === all.length - 1;
9068
9102
  if (icon === currentIcon) {
9069
9103
  currentTasks++;
9070
- if (isLast)
9071
- addOutput();
9072
9104
  continue;
9073
9105
  }
9074
9106
  addOutput();
9075
9107
  currentTasks = 1;
9076
9108
  currentIcon = icon;
9077
- if (isLast)
9078
- addOutput();
9079
9109
  }
9080
- return output.join("");
9110
+ addOutput();
9111
+ return output;
9081
9112
  }
9082
9113
  function createDotRenderer(_tasks, options) {
9083
9114
  let tasks = _tasks;
9084
9115
  let timer;
9085
- const log = options.logger.logUpdate;
9116
+ const { logUpdate: log, outputStream } = options.logger;
9086
9117
  function update() {
9087
- log(render(tasks));
9118
+ log(render(tasks, outputStream.columns));
9088
9119
  }
9089
9120
  return {
9090
9121
  start() {
@@ -9103,7 +9134,7 @@ function createDotRenderer(_tasks, options) {
9103
9134
  timer = void 0;
9104
9135
  }
9105
9136
  log.clear();
9106
- options.logger.log(render(tasks));
9137
+ options.logger.log(render(tasks, outputStream.columns));
9107
9138
  return this;
9108
9139
  },
9109
9140
  clear() {
@@ -9466,6 +9497,7 @@ class JUnitReporter {
9466
9497
  if (!existsSync(outputDirectory))
9467
9498
  await promises.mkdir(outputDirectory, { recursive: true });
9468
9499
  const fileFd = await promises.open(this.reportFile, "w+");
9500
+ this.fileFd = fileFd;
9469
9501
  this.baseLog = async (text) => await promises.writeFile(fileFd, `${text}
9470
9502
  `);
9471
9503
  } else {
@@ -9541,14 +9573,15 @@ class JUnitReporter {
9541
9573
  }
9542
9574
  }
9543
9575
  async onFinished(files = this.ctx.state.getFiles()) {
9576
+ var _a;
9544
9577
  await this.logger.log('<?xml version="1.0" encoding="UTF-8" ?>');
9545
9578
  const transformed = files.map((file) => {
9546
9579
  const tasks = file.tasks.flatMap((task) => flattenTasks$1(task));
9547
9580
  const stats2 = tasks.reduce(
9548
9581
  (stats3, task) => {
9549
- var _a, _b;
9582
+ var _a2, _b;
9550
9583
  return {
9551
- passed: stats3.passed + Number(((_a = task.result) == null ? void 0 : _a.state) === "pass"),
9584
+ passed: stats3.passed + Number(((_a2 = task.result) == null ? void 0 : _a2.state) === "pass"),
9552
9585
  failures: stats3.failures + Number(((_b = task.result) == null ? void 0 : _b.state) === "fail"),
9553
9586
  skipped: stats3.skipped + Number(task.mode === "skip" || task.mode === "todo")
9554
9587
  };
@@ -9596,6 +9629,7 @@ class JUnitReporter {
9596
9629
  });
9597
9630
  if (this.reportFile)
9598
9631
  this.ctx.logger.log(`JUNIT report written to ${this.reportFile}`);
9632
+ await ((_a = this.fileFd) == null ? void 0 : _a.close());
9599
9633
  }
9600
9634
  }
9601
9635
 
@@ -9994,7 +10028,10 @@ class StateManager {
9994
10028
  catchError(err, type) {
9995
10029
  if (isAggregateError(err))
9996
10030
  return err.errors.forEach((error) => this.catchError(error, type));
9997
- err.type = type;
10031
+ if (err === Object(err))
10032
+ err.type = type;
10033
+ else
10034
+ err = { type, message: err };
9998
10035
  this.errorsSet.add(err);
9999
10036
  }
10000
10037
  clearErrors() {
@@ -10063,9 +10100,12 @@ class StateManager {
10063
10100
  }
10064
10101
  }
10065
10102
  updateTasks(packs) {
10066
- for (const [id, result] of packs) {
10067
- if (this.idMap.has(id))
10068
- this.idMap.get(id).result = result;
10103
+ for (const [id, result, meta] of packs) {
10104
+ const task = this.idMap.get(id);
10105
+ if (task) {
10106
+ task.result = result;
10107
+ task.meta = meta;
10108
+ }
10069
10109
  }
10070
10110
  }
10071
10111
  updateUserLog(log) {
@@ -10092,6 +10132,7 @@ class StateManager {
10092
10132
  result: {
10093
10133
  state: "skip"
10094
10134
  },
10135
+ meta: {},
10095
10136
  // Cancelled files have not yet collected tests
10096
10137
  tasks: []
10097
10138
  })));
@@ -10127,6 +10168,7 @@ const coverageConfigDefaults = {
10127
10168
  cleanOnRerun: true,
10128
10169
  reportsDirectory: "./coverage",
10129
10170
  exclude: defaultCoverageExcludes,
10171
+ reportOnFailure: true,
10130
10172
  reporter: [["text", {}], ["html", {}], ["clover", {}], ["json", {}]],
10131
10173
  // default extensions used by c8, plus '.vue' and '.svelte'
10132
10174
  // see https://github.com/istanbuljs/schema/blob/master/default-extension.js
@@ -10406,7 +10448,7 @@ function resolveApiServerConfig(options) {
10406
10448
  return api;
10407
10449
  }
10408
10450
  function resolveConfig(mode, options, viteConfig) {
10409
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
10451
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
10410
10452
  if (options.dom) {
10411
10453
  if (((_a = viteConfig.test) == null ? void 0 : _a.environment) != null && viteConfig.test.environment !== "happy-dom") {
10412
10454
  console.warn(
@@ -10458,10 +10500,18 @@ function resolveConfig(mode, options, viteConfig) {
10458
10500
  resolved.deps.inline.push(...extraInlineDeps);
10459
10501
  }
10460
10502
  }
10503
+ (_c = resolved.deps).moduleDirectories ?? (_c.moduleDirectories = ["/node_modules/"]);
10504
+ resolved.deps.moduleDirectories = resolved.deps.moduleDirectories.map((dir) => {
10505
+ if (!dir.startsWith("/"))
10506
+ dir = `/${dir}`;
10507
+ if (!dir.endsWith("/"))
10508
+ dir += "/";
10509
+ return normalize(dir);
10510
+ });
10461
10511
  if (resolved.runner) {
10462
10512
  resolved.runner = resolveModule(resolved.runner, { paths: [resolved.root] }) ?? resolve$2(resolved.root, resolved.runner);
10463
10513
  }
10464
- (_c = resolved.deps).registerNodeLoader ?? (_c.registerNodeLoader = false);
10514
+ (_d = resolved.deps).registerNodeLoader ?? (_d.registerNodeLoader = false);
10465
10515
  resolved.testNamePattern = resolved.testNamePattern ? resolved.testNamePattern instanceof RegExp ? resolved.testNamePattern : new RegExp(resolved.testNamePattern) : void 0;
10466
10516
  const UPDATE_SNAPSHOT = resolved.update || process.env.UPDATE_SNAPSHOT;
10467
10517
  resolved.snapshotOptions = {
@@ -10526,19 +10576,19 @@ function resolveConfig(mode, options, viteConfig) {
10526
10576
  resolved.passWithNoTests ?? (resolved.passWithNoTests = true);
10527
10577
  resolved.css ?? (resolved.css = {});
10528
10578
  if (typeof resolved.css === "object") {
10529
- (_d = resolved.css).modules ?? (_d.modules = {});
10530
- (_e = resolved.css.modules).classNameStrategy ?? (_e.classNameStrategy = "stable");
10579
+ (_e = resolved.css).modules ?? (_e.modules = {});
10580
+ (_f = resolved.css.modules).classNameStrategy ?? (_f.classNameStrategy = "stable");
10531
10581
  }
10532
10582
  resolved.cache ?? (resolved.cache = { dir: "" });
10533
10583
  if (resolved.cache)
10534
10584
  resolved.cache.dir = VitestCache.resolveCacheDir(resolved.root, resolved.cache.dir);
10535
10585
  resolved.sequence ?? (resolved.sequence = {});
10536
- if (!((_f = resolved.sequence) == null ? void 0 : _f.sequencer)) {
10586
+ if (!((_g = resolved.sequence) == null ? void 0 : _g.sequencer)) {
10537
10587
  resolved.sequence.sequencer = resolved.sequence.shuffle ? RandomSequencer : BaseSequencer;
10538
10588
  }
10539
- (_g = resolved.sequence).hooks ?? (_g.hooks = "parallel");
10589
+ (_h = resolved.sequence).hooks ?? (_h.hooks = "parallel");
10540
10590
  if (resolved.sequence.sequencer === RandomSequencer)
10541
- (_h = resolved.sequence).seed ?? (_h.seed = Date.now());
10591
+ (_i = resolved.sequence).seed ?? (_i.seed = Date.now());
10542
10592
  resolved.typecheck = {
10543
10593
  ...configDefaults.typecheck,
10544
10594
  ...resolved.typecheck
@@ -10549,9 +10599,9 @@ function resolveConfig(mode, options, viteConfig) {
10549
10599
  resolved.exclude = resolved.typecheck.exclude;
10550
10600
  }
10551
10601
  resolved.browser ?? (resolved.browser = {});
10552
- (_i = resolved.browser).enabled ?? (_i.enabled = false);
10553
- (_j = resolved.browser).headless ?? (_j.headless = isCI);
10554
- (_k = resolved.browser).slowHijackESM ?? (_k.slowHijackESM = true);
10602
+ (_j = resolved.browser).enabled ?? (_j.enabled = false);
10603
+ (_k = resolved.browser).headless ?? (_k.headless = isCI);
10604
+ (_l = resolved.browser).slowHijackESM ?? (_l.slowHijackESM = true);
10555
10605
  resolved.browser.api = resolveApiServerConfig(resolved.browser) || {
10556
10606
  port: defaultBrowserPort
10557
10607
  };
@@ -11110,7 +11160,7 @@ createLogUpdate(process$1.stdout);
11110
11160
 
11111
11161
  createLogUpdate(process$1.stderr);
11112
11162
 
11113
- var version = "0.31.0";
11163
+ var version = "0.31.2";
11114
11164
 
11115
11165
  const comma = ','.charCodeAt(0);
11116
11166
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
@@ -11778,9 +11828,9 @@ async function makeTscErrorInfo(errInfo) {
11778
11828
  ];
11779
11829
  }
11780
11830
  async function getTsconfig(root, config) {
11781
- var _a;
11782
- const configName = ((_a = config.tsconfig) == null ? void 0 : _a.includes("jsconfig.json")) ? "jsconfig.json" : void 0;
11783
- const tsconfig = kn(config.tsconfig || root, configName);
11831
+ const configName = config.tsconfig ? basename(config.tsconfig) : void 0;
11832
+ const configSearchPath = config.tsconfig ? dirname(resolve$2(root, config.tsconfig)) : root;
11833
+ const tsconfig = kn(configSearchPath, configName);
11784
11834
  if (!tsconfig)
11785
11835
  throw new Error("no tsconfig.json found");
11786
11836
  const tempConfigPath = join(dirname(tsconfig.path), "tsconfig.vitest-temp.json");
@@ -11980,6 +12030,7 @@ class Typechecker {
11980
12030
  files: [],
11981
12031
  sourceErrors: []
11982
12032
  };
12033
+ this._output = "";
11983
12034
  this._tests = {};
11984
12035
  }
11985
12036
  onParseStart(fn) {
@@ -12139,6 +12190,13 @@ class Typechecker {
12139
12190
  this.tempConfigPath = path;
12140
12191
  this.allowJs = typecheck.allowJs || config.allowJs || false;
12141
12192
  }
12193
+ getExitCode() {
12194
+ var _a;
12195
+ return ((_a = this.process) == null ? void 0 : _a.exitCode) != null && this.process.exitCode;
12196
+ }
12197
+ getOutput() {
12198
+ return this._output;
12199
+ }
12142
12200
  async start() {
12143
12201
  var _a, _b, _c;
12144
12202
  if (!this.tempConfigPath)
@@ -12149,7 +12207,7 @@ class Typechecker {
12149
12207
  args.push("--watch");
12150
12208
  if (typecheck.allowJs)
12151
12209
  args.push("--allowJs", "--checkJs");
12152
- let output = "";
12210
+ this._output = "";
12153
12211
  const child = execa(typecheck.checker, args, {
12154
12212
  cwd: root,
12155
12213
  stdout: "pipe",
@@ -12160,29 +12218,29 @@ class Typechecker {
12160
12218
  let rerunTriggered = false;
12161
12219
  (_b = child.stdout) == null ? void 0 : _b.on("data", (chunk) => {
12162
12220
  var _a2;
12163
- output += chunk;
12221
+ this._output += chunk;
12164
12222
  if (!watch)
12165
12223
  return;
12166
- if (output.includes("File change detected") && !rerunTriggered) {
12224
+ if (this._output.includes("File change detected") && !rerunTriggered) {
12167
12225
  (_a2 = this._onWatcherRerun) == null ? void 0 : _a2.call(this);
12168
12226
  this._result.sourceErrors = [];
12169
12227
  this._result.files = [];
12170
12228
  this._tests = null;
12171
12229
  rerunTriggered = true;
12172
12230
  }
12173
- if (/Found \w+ errors*. Watching for/.test(output)) {
12231
+ if (/Found \w+ errors*. Watching for/.test(this._output)) {
12174
12232
  rerunTriggered = false;
12175
- this.prepareResults(output).then((result) => {
12233
+ this.prepareResults(this._output).then((result) => {
12176
12234
  var _a3;
12177
12235
  this._result = result;
12178
12236
  (_a3 = this._onParseEnd) == null ? void 0 : _a3.call(this, result);
12179
12237
  });
12180
- output = "";
12238
+ this._output = "";
12181
12239
  }
12182
12240
  });
12183
12241
  if (!watch) {
12184
12242
  await child;
12185
- this._result = await this.prepareResults(output);
12243
+ this._result = await this.prepareResults(this._output);
12186
12244
  await ((_c = this._onParseEnd) == null ? void 0 : _c.call(this, this._result));
12187
12245
  }
12188
12246
  }
@@ -12193,7 +12251,7 @@ class Typechecker {
12193
12251
  return Object.values(this._tests || {}).map((i) => i.file);
12194
12252
  }
12195
12253
  getTestPacks() {
12196
- return Object.values(this._tests || {}).map(({ file }) => getTasks(file)).flat().map((i) => [i.id, void 0]);
12254
+ return Object.values(this._tests || {}).map(({ file }) => getTasks(file)).flat().map((i) => [i.id, void 0, { typecheck: true }]);
12197
12255
  }
12198
12256
  }
12199
12257
 
@@ -12223,13 +12281,15 @@ async function printError(error, ctx, options = {}) {
12223
12281
  if (type)
12224
12282
  printErrorType(type, ctx);
12225
12283
  printErrorMessage(e, ctx.logger);
12284
+ if (e.diff)
12285
+ displayDiff(e.diff, ctx.logger.console);
12226
12286
  if (e.frame) {
12227
12287
  ctx.logger.error(c.yellow(e.frame));
12228
12288
  } else {
12229
12289
  printStack(ctx, stacks, nearest, errorProperties, (s) => {
12230
12290
  if (showCodeFrame && s === nearest && nearest) {
12231
12291
  const sourceCode = readFileSync(nearest.file, "utf-8");
12232
- ctx.logger.error(c.yellow(generateCodeFrame(sourceCode, 4, s.line, s.column)));
12292
+ ctx.logger.error(generateCodeFrame(sourceCode, 4, s.line, s.column));
12233
12293
  }
12234
12294
  });
12235
12295
  }
@@ -12251,8 +12311,6 @@ async function printError(error, ctx, options = {}) {
12251
12311
  await printError(e.cause, ctx, { fullStack, showCodeFrame: false });
12252
12312
  }
12253
12313
  handleImportOutsideModuleError(e.stack || e.stackStr || "", ctx);
12254
- if (e.diff)
12255
- displayDiff(e.diff, ctx.logger.console);
12256
12314
  }
12257
12315
  function printErrorType(type, ctx) {
12258
12316
  ctx.logger.error(`
@@ -12327,7 +12385,9 @@ function printModuleWarningForSourceCode(logger, path) {
12327
12385
  ));
12328
12386
  }
12329
12387
  function displayDiff(diff, console) {
12330
- console.error(diff);
12388
+ console.error(`
12389
+ ${diff}
12390
+ `);
12331
12391
  }
12332
12392
  function printErrorMessage(error, logger) {
12333
12393
  const errorName = error.name || error.nameStr || "Unknown Error";
@@ -12336,9 +12396,9 @@ function printErrorMessage(error, logger) {
12336
12396
  function printStack(ctx, stack, highlight, errorProperties, onStack) {
12337
12397
  const logger = ctx.logger;
12338
12398
  for (const frame of stack) {
12339
- const color = frame === highlight ? c.yellow : c.gray;
12399
+ const color = frame === highlight ? c.cyan : c.gray;
12340
12400
  const path = relative(ctx.config.root, frame.file);
12341
- logger.error(color(` ${c.dim(F_POINTER)} ${[frame.method, c.dim(`${path}:${frame.line}:${frame.column}`)].filter(Boolean).join(" ")}`));
12401
+ logger.error(color(` ${c.dim(F_POINTER)} ${[frame.method, `${path}:${c.dim(`${frame.line}:${frame.column}`)}`].filter(Boolean).join(" ")}`));
12342
12402
  onStack == null ? void 0 : onStack(frame);
12343
12403
  }
12344
12404
  if (stack.length)
@@ -12691,7 +12751,7 @@ async function createBrowserServer(project, options) {
12691
12751
  });
12692
12752
  await server.listen();
12693
12753
  await server.watcher.close();
12694
- (await import('./chunk-api-setup.df3106cd.js')).setup(project, server);
12754
+ (await import('./chunk-api-setup.3854747a.js')).setup(project, server);
12695
12755
  return server;
12696
12756
  }
12697
12757
 
@@ -12723,6 +12783,14 @@ class PlaywrightBrowserProvider {
12723
12783
  });
12724
12784
  return this.cachedBrowser;
12725
12785
  }
12786
+ catchError(cb) {
12787
+ var _a;
12788
+ (_a = this.cachedBrowser) == null ? void 0 : _a.on("pageerror", cb);
12789
+ return () => {
12790
+ var _a2;
12791
+ (_a2 = this.cachedBrowser) == null ? void 0 : _a2.off("pageerror", cb);
12792
+ };
12793
+ }
12726
12794
  async openPage(url) {
12727
12795
  const browserInstance = await this.openBrowser();
12728
12796
  await browserInstance.goto(url);
@@ -12780,6 +12848,11 @@ class WebdriverBrowserProvider {
12780
12848
  const browserInstance = await this.openBrowser();
12781
12849
  await browserInstance.url(url);
12782
12850
  }
12851
+ // TODO
12852
+ catchError(_cb) {
12853
+ return () => {
12854
+ };
12855
+ }
12783
12856
  async close() {
12784
12857
  var _a, _b, _c;
12785
12858
  await Promise.all([
@@ -13132,9 +13205,9 @@ class WorkspaceProject {
13132
13205
  return this.ctx.reporters;
13133
13206
  }
13134
13207
  async globTestFiles(filters = []) {
13135
- const { dir, root } = this.config;
13136
- const testFiles = await this.globAllTestFiles(this.config, dir || root);
13137
- return this.filterFiles(testFiles, filters);
13208
+ const dir = this.config.dir || this.config.root;
13209
+ const testFiles = await this.globAllTestFiles(this.config, dir);
13210
+ return this.filterFiles(testFiles, filters, dir);
13138
13211
  }
13139
13212
  async globAllTestFiles(config, cwd) {
13140
13213
  const { include, exclude, includeSource } = config;
@@ -13178,11 +13251,17 @@ class WorkspaceProject {
13178
13251
  isInSourceTestFile(code) {
13179
13252
  return code.includes("import.meta.vitest");
13180
13253
  }
13181
- filterFiles(testFiles, filters = []) {
13254
+ filterFiles(testFiles, filters = [], dir) {
13182
13255
  if (filters.length && process.platform === "win32")
13183
13256
  filters = filters.map((f) => toNamespacedPath(f));
13184
- if (filters.length)
13185
- return testFiles.filter((i) => filters.some((f) => i.includes(f)));
13257
+ if (filters.length) {
13258
+ return testFiles.filter((t) => {
13259
+ const testFile = relative(dir, t);
13260
+ return filters.some((f) => {
13261
+ return testFile.includes(f) || testFile.includes(relative(dir, f));
13262
+ });
13263
+ });
13264
+ }
13186
13265
  return testFiles;
13187
13266
  }
13188
13267
  async initBrowserServer(options) {
@@ -13213,19 +13292,27 @@ class WorkspaceProject {
13213
13292
  return this.ctx.report(name, ...args);
13214
13293
  }
13215
13294
  async typecheck(filters = []) {
13216
- const { dir, root } = this.config;
13295
+ const dir = this.config.dir || this.config.root;
13217
13296
  const { include, exclude } = this.config.typecheck;
13218
- const testsFilesList = this.filterFiles(await this.globFiles(include, exclude, dir || root), filters);
13297
+ const testFiles = await this.globFiles(include, exclude, dir);
13298
+ const testsFilesList = this.filterFiles(testFiles, filters, dir);
13219
13299
  const checker = new Typechecker(this, testsFilesList);
13220
13300
  this.typechecker = checker;
13221
13301
  checker.onParseEnd(async ({ files, sourceErrors }) => {
13222
13302
  this.ctx.state.collectFiles(checker.getTestFiles());
13223
13303
  await this.report("onTaskUpdate", checker.getTestPacks());
13224
13304
  await this.report("onCollected");
13305
+ const failedTests = hasFailed(files);
13306
+ const exitCode = !failedTests && checker.getExitCode();
13307
+ if (exitCode) {
13308
+ const error = new Error(checker.getOutput());
13309
+ error.stack = "";
13310
+ this.ctx.state.catchError(error, "Typecheck Error");
13311
+ }
13225
13312
  if (!files.length) {
13226
13313
  this.ctx.logger.printNoTestFound();
13227
13314
  } else {
13228
- if (hasFailed(files))
13315
+ if (failedTests)
13229
13316
  process.exitCode = 1;
13230
13317
  await this.report("onFinished", files);
13231
13318
  }
@@ -13234,8 +13321,9 @@ class WorkspaceProject {
13234
13321
  await this.ctx.logger.printSourceTypeErrors(sourceErrors);
13235
13322
  }
13236
13323
  if (!files.length) {
13237
- const exitCode = this.config.passWithNoTests ? process.exitCode ?? 0 : 1;
13238
- process.exit(exitCode);
13324
+ const exitCode2 = this.config.passWithNoTests ? process.exitCode ?? 0 : 1;
13325
+ await this.close();
13326
+ process.exit(exitCode2);
13239
13327
  }
13240
13328
  if (this.config.watch) {
13241
13329
  await this.report("onWatcherStart", files, [
@@ -13521,10 +13609,13 @@ class Vitest {
13521
13609
  await this.typecheck(filters);
13522
13610
  return;
13523
13611
  }
13524
- await this.report("onInit", this);
13525
- await this.initCoverageProvider();
13526
- await ((_a = this.coverageProvider) == null ? void 0 : _a.clean(this.config.coverage.clean));
13527
- await this.initBrowserProviders();
13612
+ try {
13613
+ await this.initCoverageProvider();
13614
+ await ((_a = this.coverageProvider) == null ? void 0 : _a.clean(this.config.coverage.clean));
13615
+ await this.initBrowserProviders();
13616
+ } finally {
13617
+ await this.report("onInit", this);
13618
+ }
13528
13619
  const files = await this.filterTestsBySource(
13529
13620
  await this.globTestFiles(filters)
13530
13621
  );
@@ -13822,21 +13913,21 @@ class Vitest {
13822
13913
  return files;
13823
13914
  }
13824
13915
  async reportCoverage(allTestsRun) {
13916
+ if (!this.config.coverage.reportOnFailure && this.state.getCountOfFailedTests() > 0)
13917
+ return;
13825
13918
  if (this.coverageProvider) {
13826
13919
  this.logger.log(c.blue(" % ") + c.dim("Coverage report from ") + c.yellow(this.coverageProvider.name));
13827
13920
  await this.coverageProvider.reportCoverage({ allTestsRun });
13828
13921
  }
13829
13922
  }
13830
13923
  async close() {
13831
- var _a;
13832
13924
  if (!this.closingPromise) {
13833
- const closePromises = this.projects.map((w) => w.close());
13925
+ const closePromises = this.projects.map((w) => w.close().then(() => w.server = void 0));
13834
13926
  if (this.coreWorkspace && !this.projects.includes(this.coreWorkspace))
13835
- closePromises.push(this.server.close());
13836
- this.closingPromise = Promise.allSettled([
13837
- (_a = this.pool) == null ? void 0 : _a.close(),
13838
- ...closePromises
13839
- ].filter(Boolean)).then((results) => {
13927
+ closePromises.push(this.server.close().then(() => this.server = void 0));
13928
+ if (this.pool)
13929
+ closePromises.push(this.pool.close().then(() => this.pool = void 0));
13930
+ this.closingPromise = Promise.allSettled(closePromises).then((results) => {
13840
13931
  results.filter((r) => r.status === "rejected").forEach((err) => {
13841
13932
  this.logger.error("error during close", err.reason);
13842
13933
  });
@@ -13852,6 +13943,16 @@ class Vitest {
13852
13943
  this.report("onProcessTimeout").then(() => {
13853
13944
  console.warn(`close timed out after ${this.config.teardownTimeout}ms`);
13854
13945
  this.state.getProcessTimeoutCauses().forEach((cause) => console.warn(cause));
13946
+ if (!this.pool) {
13947
+ const runningServers = [this.server, ...this.projects.map((p) => p.server)].filter(Boolean).length;
13948
+ if (runningServers === 1)
13949
+ console.warn("Tests closed successfully but something prevents Vite server from exiting");
13950
+ else if (runningServers > 1)
13951
+ console.warn(`Tests closed successfully but something prevents ${runningServers} Vite servers from exiting`);
13952
+ else
13953
+ console.warn("Tests closed successfully but something prevents the main process from exiting");
13954
+ console.warn('You can try to identify the cause by enabling "hanging-process" reporter. See https://vitest.dev/config/#reporters');
13955
+ }
13855
13956
  process.exit();
13856
13957
  });
13857
13958
  }, this.config.teardownTimeout).unref();
@@ -14036,7 +14137,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
14036
14137
  try {
14037
14138
  await ctx.setServer(options, server, userConfig);
14038
14139
  if (options.api && options.watch)
14039
- (await import('./chunk-api-setup.df3106cd.js')).setup(ctx);
14140
+ (await import('./chunk-api-setup.3854747a.js')).setup(ctx);
14040
14141
  } catch (err) {
14041
14142
  await ctx.logger.printError(err, true);
14042
14143
  process.exit(1);
@@ -20347,27 +20448,33 @@ var index = /*#__PURE__*/_mergeNamespaces({
20347
20448
  }, [prompts]);
20348
20449
 
20349
20450
  const keys = [
20350
- ["a", "rerun all tests"],
20451
+ [["a", "return"], "rerun all tests"],
20452
+ ["r", "rerun current pattern tests"],
20351
20453
  ["f", "rerun only failed tests"],
20352
20454
  ["u", "update snapshot"],
20353
20455
  ["p", "filter by a filename"],
20354
20456
  ["t", "filter by a test name regex pattern"],
20355
20457
  ["q", "quit"]
20356
20458
  ];
20357
- const cancelKeys = ["space", "c", ...keys.map((key) => key[0])];
20459
+ const cancelKeys = ["space", "c", ...keys.map((key) => key[0]).flat()];
20358
20460
  function printShortcutsHelp() {
20359
20461
  stdout().write(
20360
20462
  `
20361
20463
  ${c.bold(" Watch Usage")}
20362
- ${keys.map((i) => c.dim(" press ") + c.reset(c.bold(i[0])) + c.dim(` to ${i[1]}`)).join("\n")}
20464
+ ${keys.map((i) => c.dim(" press ") + c.reset([i[0]].flat().map(c.bold).join(", ")) + c.dim(` to ${i[1]}`)).join("\n")}
20363
20465
  `
20364
20466
  );
20365
20467
  }
20366
20468
  function registerConsoleShortcuts(ctx) {
20367
20469
  let latestFilename = "";
20368
20470
  async function _keypressHandler(str, key) {
20369
- if (str === "" || str === "\x1B" || key && key.ctrl && key.name === "c")
20471
+ if (str === "" || str === "\x1B" || key && key.ctrl && key.name === "c") {
20472
+ if (!ctx.isCancelling) {
20473
+ await ctx.cancelCurrentRun("keyboard-input");
20474
+ await ctx.runningPromise;
20475
+ }
20370
20476
  return ctx.exit(true);
20477
+ }
20371
20478
  if (!isWindows && key && key.ctrl && key.name === "z") {
20372
20479
  process.kill(process.ppid, "SIGTSTP");
20373
20480
  process.kill(process.pid, "SIGTSTP");
@@ -20389,6 +20496,8 @@ function registerConsoleShortcuts(ctx) {
20389
20496
  return ctx.updateSnapshot();
20390
20497
  if (name === "a" || name === "return")
20391
20498
  return ctx.changeNamePattern("");
20499
+ if (name === "r")
20500
+ return ctx.rerunFiles();
20392
20501
  if (name === "f")
20393
20502
  return ctx.rerunFailed();
20394
20503
  if (name === "t")
@@ -20442,7 +20551,7 @@ function registerConsoleShortcuts(ctx) {
20442
20551
  on();
20443
20552
  }
20444
20553
 
20445
- async function startVitest(mode, cliFilters, options, viteOverrides) {
20554
+ async function startVitest(mode, cliFilters = [], options = {}, viteOverrides) {
20446
20555
  var _a;
20447
20556
  process.env.TEST = "true";
20448
20557
  process.env.VITEST = "true";
@@ -20480,6 +20589,8 @@ async function startVitest(mode, cliFilters, options, viteOverrides) {
20480
20589
  }
20481
20590
  if (process.stdin.isTTY && ctx.config.watch)
20482
20591
  registerConsoleShortcuts(ctx);
20592
+ else
20593
+ process.on("SIGINT", () => ctx.cancelCurrentRun("keyboard-input"));
20483
20594
  ctx.onServerRestart((reason) => {
20484
20595
  ctx.report("onServerRestart", reason);
20485
20596
  if (process.env.VITEST_CLI_WRAPPER)