vitest 3.0.3 → 3.0.5

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 (31) hide show
  1. package/dist/browser.d.ts +1 -1
  2. package/dist/chunks/{base.gZAre3Yy.js → base.wKnmhRYd.js} +1 -1
  3. package/dist/chunks/{cac.Cfe6a4o8.js → cac.B_eDEFh6.js} +4 -4
  4. package/dist/chunks/{cli-api.BaY17YBo.js → cli-api.az_rB_xZ.js} +207 -78
  5. package/dist/chunks/{creator.B8v1wNyQ.js → creator.fUJbheb8.js} +2 -2
  6. package/dist/chunks/{execute.4vt3NSmG.js → execute.PoofJYS5.js} +2 -1
  7. package/dist/chunks/{index.Bh7wTRhh.js → index.B57_6XMC.js} +7 -7
  8. package/dist/chunks/{index.DfqWks-F.js → index.NxxmQyK2.js} +7 -7
  9. package/dist/chunks/{index.CvtAP0DU.js → index.vId0fl99.js} +1 -1
  10. package/dist/chunks/{reporters.Y8BYiXBN.d.ts → reporters.6vxQttCV.d.ts} +7 -4
  11. package/dist/chunks/{resolveConfig.9CnFfuqj.js → resolveConfig.BT-MMQUD.js} +24 -14
  12. package/dist/chunks/{typechecker.ChNaIV36.js → typechecker.CdcjdhoT.js} +17 -11
  13. package/dist/chunks/{vite.CQ0dHgkN.d.ts → vite.Cu7NWuBa.d.ts} +1 -1
  14. package/dist/chunks/{vm.CUw7ChSp.js → vm.DXDoSHPT.js} +1 -1
  15. package/dist/cli.js +1 -1
  16. package/dist/config.d.ts +3 -3
  17. package/dist/coverage.d.ts +1 -1
  18. package/dist/coverage.js +3 -3
  19. package/dist/execute.d.ts +1 -1
  20. package/dist/execute.js +1 -1
  21. package/dist/index.d.ts +3 -3
  22. package/dist/node.d.ts +9 -6
  23. package/dist/node.js +11 -12
  24. package/dist/reporters.d.ts +1 -1
  25. package/dist/reporters.js +2 -2
  26. package/dist/workers/forks.js +2 -2
  27. package/dist/workers/threads.js +2 -2
  28. package/dist/workers/vmForks.js +2 -2
  29. package/dist/workers/vmThreads.js +2 -2
  30. package/dist/workers.js +3 -3
  31. package/package.json +19 -15
package/dist/browser.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { b as CoverageProvider, c as CoverageProviderModule } from './chunks/reporters.Y8BYiXBN.js';
1
+ import { b as CoverageProvider, c as CoverageProviderModule } from './chunks/reporters.6vxQttCV.js';
2
2
  import { a as SerializedCoverageConfig, S as SerializedConfig } from './chunks/config.BRtC-JeT.js';
3
3
  import * as spy$1 from '@vitest/spy';
4
4
  import * as _vitest_utils_diff from '@vitest/utils/diff';
@@ -1,5 +1,5 @@
1
1
  import { ModuleCacheMap } from 'vite-node/client';
2
- import { g as getDefaultRequestStubs, s as startVitestExecutor } from './execute.4vt3NSmG.js';
2
+ import { g as getDefaultRequestStubs, s as startVitestExecutor } from './execute.PoofJYS5.js';
3
3
  import { p as provideWorkerState } from './utils.C8RiOc4B.js';
4
4
 
5
5
  let _viteNode;
@@ -618,7 +618,7 @@ class CAC extends EventEmitter {
618
618
 
619
619
  const cac = (name = "") => new CAC(name);
620
620
 
621
- var version = "3.0.3";
621
+ var version = "3.0.5";
622
622
 
623
623
  const apiConfig = (port) => ({
624
624
  port: {
@@ -1567,7 +1567,7 @@ async function start(mode, cliFilters, options) {
1567
1567
  } catch {
1568
1568
  }
1569
1569
  try {
1570
- const { startVitest } = await import('./cli-api.BaY17YBo.js').then(function (n) { return n.f; });
1570
+ const { startVitest } = await import('./cli-api.az_rB_xZ.js').then(function (n) { return n.f; });
1571
1571
  const ctx = await startVitest(mode, cliFilters.map(normalize), normalizeCliOptions(cliFilters, options));
1572
1572
  if (!ctx.shouldKeepServer()) {
1573
1573
  await ctx.exit();
@@ -1589,7 +1589,7 @@ async function init(project) {
1589
1589
  console.error(new Error('Only the "browser" project is supported. Use "vitest init browser" to create a new project.'));
1590
1590
  process.exit(1);
1591
1591
  }
1592
- const { create } = await import('./creator.B8v1wNyQ.js');
1592
+ const { create } = await import('./creator.fUJbheb8.js');
1593
1593
  await create();
1594
1594
  }
1595
1595
  async function collect(mode, cliFilters, options) {
@@ -1598,7 +1598,7 @@ async function collect(mode, cliFilters, options) {
1598
1598
  } catch {
1599
1599
  }
1600
1600
  try {
1601
- const { prepareVitest, processCollected, outputFileList } = await import('./cli-api.BaY17YBo.js').then(function (n) { return n.f; });
1601
+ const { prepareVitest, processCollected, outputFileList } = await import('./cli-api.az_rB_xZ.js').then(function (n) { return n.f; });
1602
1602
  const ctx = await prepareVitest(mode, {
1603
1603
  ...normalizeCliOptions(cliFilters, options),
1604
1604
  watch: false,
@@ -1,18 +1,19 @@
1
1
  import { existsSync, promises, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
2
2
  import { extname, normalize, relative, dirname, resolve, join, basename, isAbsolute } from 'pathe';
3
3
  import { g as getCoverageProvider, C as CoverageProviderMap } from './coverage.BWeNbfBa.js';
4
- import a, { resolve as resolve$1 } from 'node:path';
4
+ import p, { resolve as resolve$1 } from 'node:path';
5
5
  import { noop, isPrimitive, createDefer, highlight, toArray, deepMerge, nanoid, slash, deepClone, notNullish } from '@vitest/utils';
6
- import { f as findUp, p as prompt } from './index.Bh7wTRhh.js';
6
+ import { f as findUp, p as prompt } from './index.B57_6XMC.js';
7
+ import * as vite from 'vite';
7
8
  import { searchForWorkspaceRoot, version, createServer, mergeConfig } from 'vite';
8
9
  import { A as API_PATH, c as configFiles, a as defaultBrowserPort, w as workspacesFiles, d as defaultPort } from './constants.fzPh7AOq.js';
9
10
  import { generateFileHash, createFileTask, limitConcurrency, hasFailed, getTasks, getTests } from '@vitest/runner/utils';
10
11
  import { SnapshotManager } from '@vitest/snapshot/manager';
11
12
  import { ViteNodeRunner } from 'vite-node/client';
12
13
  import { ViteNodeServer } from 'vite-node/server';
13
- import { v as version$1 } from './cac.Cfe6a4o8.js';
14
+ import { v as version$1 } from './cac.B_eDEFh6.js';
14
15
  import { c as createBirpc } from './index.TH3f4LSA.js';
15
- import { s as stringify, p as parse, g as printError, h as generateCodeFrame, R as ReportersMap, b as BenchmarkReportsMap, i as BlobReporter, r as readBlobs, H as HangingProcessReporter } from './index.CvtAP0DU.js';
16
+ import { s as stringify, p as parse, g as printError, h as generateCodeFrame, R as ReportersMap, b as BenchmarkReportsMap, i as BlobReporter, r as readBlobs, H as HangingProcessReporter } from './index.vId0fl99.js';
16
17
  import require$$0$2 from 'stream';
17
18
  import require$$0 from 'zlib';
18
19
  import require$$0$1 from 'buffer';
@@ -25,9 +26,10 @@ import require$$4 from 'tls';
25
26
  import require$$7 from 'url';
26
27
  import { g as getDefaultExportFromCjs, c as commonjsGlobal } from './_commonjsHelpers.BFTU3MAI.js';
27
28
  import { parseErrorStacktrace } from '@vitest/utils/source-map';
29
+ import crypto from 'node:crypto';
28
30
  import { distDir, rootDir } from '../path.js';
29
- import { R as RandomSequencer, i as isPackageExists, e as requireMicromatch, h as hash, V as VitestCache, f as configDefaults, g as getFilePoolName, j as isBrowserEnabled, m as mm, a as resolveConfig, k as groupBy, w as wildcardPatternToRegExp, l as createPool, b as resolveApiServerConfig, s as stdout } from './resolveConfig.9CnFfuqj.js';
30
- import { i as isTTY, b as isWindows, c as convertTasksToEvents } from './typechecker.ChNaIV36.js';
31
+ import { R as RandomSequencer, i as isPackageExists, e as requireMicromatch, h as hash, V as VitestCache, f as configDefaults, g as getFilePoolName, j as isBrowserEnabled, m as mm, a as resolveConfig, k as groupBy, w as wildcardPatternToRegExp, l as createPool, b as resolveApiServerConfig, s as stdout } from './resolveConfig.BT-MMQUD.js';
32
+ import { i as isTTY, b as isWindows, c as convertTasksToEvents } from './typechecker.CdcjdhoT.js';
31
33
  import { Console } from 'node:console';
32
34
  import c from 'tinyrainbow';
33
35
  import { a as formatProjectName, w as withLabel, d as divider } from './utils.DJWL04yX.js';
@@ -4883,6 +4885,21 @@ function stringifyReplace(key, value) {
4883
4885
  }
4884
4886
  }
4885
4887
 
4888
+ function isValidApiRequest(config, req) {
4889
+ const url = new URL(req.url ?? "", "http://localhost");
4890
+ try {
4891
+ const token = url.searchParams.get("token");
4892
+ if (token && crypto.timingSafeEqual(
4893
+ Buffer.from(token),
4894
+ Buffer.from(config.api.token)
4895
+ )) {
4896
+ return true;
4897
+ }
4898
+ } catch {
4899
+ }
4900
+ return false;
4901
+ }
4902
+
4886
4903
  function setup(ctx, _server) {
4887
4904
  const wss = new WebSocketServer({ noServer: true });
4888
4905
  const clients = /* @__PURE__ */ new Map();
@@ -4895,6 +4912,10 @@ function setup(ctx, _server) {
4895
4912
  if (pathname !== API_PATH) {
4896
4913
  return;
4897
4914
  }
4915
+ if (!isValidApiRequest(ctx.config, request)) {
4916
+ socket.destroy();
4917
+ return;
4918
+ }
4898
4919
  wss.handleUpgrade(request, socket, head, (ws) => {
4899
4920
  wss.emit("connection", ws, request);
4900
4921
  setupClient(ws);
@@ -5123,6 +5144,12 @@ class RangeLocationFilterProvidedError extends Error {
5123
5144
  super(`Found "-" in location filter ${filter}. Note that range location filters are not supported. Consider specifying the exact line numbers of your tests.`);
5124
5145
  }
5125
5146
  }
5147
+ class VitestFilteredOutProjectError extends Error {
5148
+ code = "VITEST_FILTERED_OUT_PROJECT";
5149
+ constructor() {
5150
+ super("VITEST_FILTERED_OUT_PROJECT");
5151
+ }
5152
+ }
5126
5153
 
5127
5154
  const HIGHLIGHT_SUPPORTED_EXTS = new Set(
5128
5155
  ["js", "ts"].flatMap((lang) => [
@@ -5160,7 +5187,9 @@ class Logger {
5160
5187
  this._highlights.clear();
5161
5188
  this.addCleanupListeners();
5162
5189
  this.registerUnhandledRejection();
5163
- this.outputStream.write(HIDE_CURSOR);
5190
+ if (this.outputStream.isTTY) {
5191
+ this.outputStream.write(HIDE_CURSOR);
5192
+ }
5164
5193
  }
5165
5194
  _clearScreenPending;
5166
5195
  _highlights = /* @__PURE__ */ new Map();
@@ -5374,7 +5403,9 @@ Vitest found ${errors.length} error${errors.length > 1 ? "s" : ""} not related t
5374
5403
  addCleanupListeners() {
5375
5404
  const cleanup = () => {
5376
5405
  this.cleanupListeners.forEach((fn) => fn());
5377
- this.outputStream.write(SHOW_CURSOR);
5406
+ if (this.outputStream.isTTY) {
5407
+ this.outputStream.write(SHOW_CURSOR);
5408
+ }
5378
5409
  };
5379
5410
  const onExit = (signal, exitCode) => {
5380
5411
  cleanup();
@@ -5442,7 +5473,7 @@ class VitestPackageInstaller {
5442
5473
  if (!isTTY) {
5443
5474
  return false;
5444
5475
  }
5445
- const prompts = await import('./index.Bh7wTRhh.js').then(function (n) { return n.i; });
5476
+ const prompts = await import('./index.B57_6XMC.js').then(function (n) { return n.i; });
5446
5477
  const { install } = await prompts.default({
5447
5478
  type: "confirm",
5448
5479
  name: "install",
@@ -5450,7 +5481,7 @@ class VitestPackageInstaller {
5450
5481
  });
5451
5482
  if (install) {
5452
5483
  const packageName = version ? `${dependency}@${version}` : dependency;
5453
- await (await import('./index.DfqWks-F.js')).installPackage(packageName, { dev: true });
5484
+ await (await import('./index.NxxmQyK2.js')).installPackage(packageName, { dev: true });
5454
5485
  process.stderr.write(
5455
5486
  c.yellow(
5456
5487
  `
@@ -9693,6 +9724,24 @@ function resolveFsAllow(projectRoot, rootConfigFile) {
9693
9724
  rootDir
9694
9725
  ];
9695
9726
  }
9727
+ function getDefaultResolveOptions() {
9728
+ return {
9729
+ // by default Vite resolves `module` field, which is not always a native ESM module
9730
+ // setting this option can bypass that and fallback to cjs version
9731
+ mainFields: [],
9732
+ // same for `module` condition and Vite 5 doesn't even allow excluding it,
9733
+ // but now it's possible since Vite 6.
9734
+ conditions: getDefaultServerConditions()
9735
+ };
9736
+ }
9737
+ function getDefaultServerConditions() {
9738
+ const viteMajor = Number(version.split(".")[0]);
9739
+ if (viteMajor >= 6) {
9740
+ const conditions = vite.defaultServerConditions;
9741
+ return conditions.filter((c) => c !== "module");
9742
+ }
9743
+ return ["node"];
9744
+ }
9696
9745
 
9697
9746
  function VitestOptimizer() {
9698
9747
  return {
@@ -9813,14 +9862,32 @@ function WorkspaceVitestPlugin(project, options) {
9813
9862
  name = options.workspacePath.toString();
9814
9863
  }
9815
9864
  }
9865
+ const workspaceNames = [name];
9866
+ if (viteConfig.test?.browser?.enabled) {
9867
+ if (viteConfig.test.browser.name) {
9868
+ const browser = viteConfig.test.browser.name;
9869
+ workspaceNames.push(name ? `${name} (${browser})` : browser);
9870
+ }
9871
+ viteConfig.test.browser.instances?.forEach((instance) => {
9872
+ instance.name ??= name ? `${name} (${instance.browser})` : instance.browser;
9873
+ workspaceNames.push(instance.name);
9874
+ });
9875
+ }
9876
+ const filters = project.vitest.config.project;
9877
+ if (filters.length) {
9878
+ const hasProject = workspaceNames.some((name2) => {
9879
+ return project.vitest._matchesProjectFilter(name2);
9880
+ });
9881
+ if (!hasProject) {
9882
+ throw new VitestFilteredOutProjectError();
9883
+ }
9884
+ }
9885
+ const resolveOptions = getDefaultResolveOptions();
9816
9886
  const config = {
9817
9887
  root,
9818
9888
  resolve: {
9819
- // by default Vite resolves `module` field, which not always a native ESM module
9820
- // setting this option can bypass that and fallback to cjs version
9821
- mainFields: [],
9822
- alias: testConfig.alias,
9823
- conditions: ["node"]
9889
+ ...resolveOptions,
9890
+ alias: testConfig.alias
9824
9891
  },
9825
9892
  esbuild: viteConfig.esbuild === false ? false : {
9826
9893
  // Lowest target Vitest supports is Node18
@@ -9841,7 +9908,7 @@ function WorkspaceVitestPlugin(project, options) {
9841
9908
  fs: {
9842
9909
  allow: resolveFsAllow(
9843
9910
  project.vitest.config.root,
9844
- project.vitest.server.config.configFile
9911
+ project.vitest.vite.config.configFile
9845
9912
  )
9846
9913
  }
9847
9914
  },
@@ -9849,12 +9916,7 @@ function WorkspaceVitestPlugin(project, options) {
9849
9916
  // @ts-ignore Vite 6 compat
9850
9917
  environments: {
9851
9918
  ssr: {
9852
- resolve: {
9853
- // by default Vite resolves `module` field, which not always a native ESM module
9854
- // setting this option can bypass that and fallback to cjs version
9855
- mainFields: [],
9856
- conditions: ["node"]
9857
- }
9919
+ resolve: resolveOptions
9858
9920
  }
9859
9921
  },
9860
9922
  test: {
@@ -9878,7 +9940,7 @@ function WorkspaceVitestPlugin(project, options) {
9878
9940
  }
9879
9941
  }
9880
9942
  config.customLogger = createViteLogger(
9881
- project.logger,
9943
+ project.vitest.logger,
9882
9944
  viteConfig.logLevel || "warn",
9883
9945
  {
9884
9946
  allowClearScreen: false
@@ -10288,7 +10350,7 @@ class TestProject {
10288
10350
  ignore: exclude
10289
10351
  };
10290
10352
  const files = await fg(include, globOptions);
10291
- return files.map((file) => slash(a.resolve(cwd, file)));
10353
+ return files.map((file) => slash(p.resolve(cwd, file)));
10292
10354
  }
10293
10355
  /**
10294
10356
  * Test if a file matches the test globs. This does the actual glob matching if the test is not cached, unlike `isCachedTestFile`.
@@ -10418,13 +10480,12 @@ class TestProject {
10418
10480
  /** @internal */
10419
10481
  async _configureServer(options, server) {
10420
10482
  this._config = resolveConfig(
10421
- this.vitest.mode,
10483
+ this.vitest,
10422
10484
  {
10423
10485
  ...options,
10424
10486
  coverage: this.vitest.config.coverage
10425
10487
  },
10426
- server.config,
10427
- this.vitest.logger
10488
+ server.config
10428
10489
  );
10429
10490
  for (const _providedKey in this.config.provide) {
10430
10491
  const providedKey = _providedKey;
@@ -11726,7 +11787,10 @@ async function resolveWorkspace(vitest, cliOptions, workspaceConfigPath, workspa
11726
11787
  });
11727
11788
  for (const path of fileProjects) {
11728
11789
  if (vitest.vite.config.configFile === path) {
11729
- projectPromises.push(Promise.resolve(vitest._ensureRootProject()));
11790
+ const project = getDefaultTestProject(vitest);
11791
+ if (project) {
11792
+ projectPromises.push(Promise.resolve(project));
11793
+ }
11730
11794
  continue;
11731
11795
  }
11732
11796
  const configFile = path.endsWith("/") ? false : path;
@@ -11740,10 +11804,34 @@ async function resolveWorkspace(vitest, cliOptions, workspaceConfigPath, workspa
11740
11804
  );
11741
11805
  }
11742
11806
  if (!projectPromises.length) {
11743
- return resolveBrowserWorkspace(vitest, /* @__PURE__ */ new Set(), [vitest._ensureRootProject()]);
11807
+ throw new Error(
11808
+ [
11809
+ "No projects were found. Make sure your configuration is correct. ",
11810
+ vitest.config.project.length ? `The filter matched no projects: ${vitest.config.project.join(", ")}. ` : "",
11811
+ `The workspace: ${JSON.stringify(workspaceDefinition, null, 4)}.`
11812
+ ].join("")
11813
+ );
11744
11814
  }
11745
- const resolvedProjects = await Promise.all(projectPromises);
11815
+ const resolvedProjectsPromises = await Promise.allSettled(projectPromises);
11746
11816
  const names = /* @__PURE__ */ new Set();
11817
+ const errors = [];
11818
+ const resolvedProjects = [];
11819
+ for (const result of resolvedProjectsPromises) {
11820
+ if (result.status === "rejected") {
11821
+ if (result.reason instanceof VitestFilteredOutProjectError) {
11822
+ continue;
11823
+ }
11824
+ errors.push(result.reason);
11825
+ } else {
11826
+ resolvedProjects.push(result.value);
11827
+ }
11828
+ }
11829
+ if (errors.length) {
11830
+ throw new AggregateError(
11831
+ errors,
11832
+ "Failed to initialize projects. There were errors during workspace setup. See below for more details."
11833
+ );
11834
+ }
11747
11835
  for (const project of resolvedProjects) {
11748
11836
  const name = project.name;
11749
11837
  if (names.has(name)) {
@@ -11767,15 +11855,18 @@ async function resolveWorkspace(vitest, cliOptions, workspaceConfigPath, workspa
11767
11855
  return resolveBrowserWorkspace(vitest, names, resolvedProjects);
11768
11856
  }
11769
11857
  async function resolveBrowserWorkspace(vitest, names, resolvedProjects) {
11770
- const filters = toArray(vitest.config.project).map((s) => wildcardPatternToRegExp(s));
11771
11858
  const removeProjects = /* @__PURE__ */ new Set();
11772
11859
  resolvedProjects.forEach((project) => {
11773
11860
  if (!project.config.browser.enabled) {
11774
11861
  return;
11775
11862
  }
11776
- const configs = project.config.browser.instances || [];
11777
- if (configs.length === 0) {
11778
- configs.push({ browser: project.config.browser.name });
11863
+ const instances = project.config.browser.instances || [];
11864
+ if (instances.length === 0) {
11865
+ const browser = project.config.browser.name;
11866
+ instances.push({
11867
+ browser,
11868
+ name: project.name ? `${project.name} (${browser})` : browser
11869
+ });
11779
11870
  console.warn(
11780
11871
  withLabel(
11781
11872
  "yellow",
@@ -11791,12 +11882,12 @@ async function resolveBrowserWorkspace(vitest, names, resolvedProjects) {
11791
11882
  );
11792
11883
  }
11793
11884
  const originalName = project.config.name;
11794
- const filteredConfigs = !filters.length ? configs : configs.filter((config) => {
11795
- const browser = config.browser;
11796
- const newName = config.name || (originalName ? `${originalName} (${browser})` : browser);
11797
- return filters.some((pattern) => pattern.test(newName));
11885
+ const filteredInstances = !vitest._projectFilters.length || vitest._matchesProjectFilter(originalName) ? instances : instances.filter((instance) => {
11886
+ const newName = instance.name;
11887
+ return vitest._matchesProjectFilter(newName);
11798
11888
  });
11799
- if (!filteredConfigs.length) {
11889
+ if (!filteredInstances.length) {
11890
+ removeProjects.add(project);
11800
11891
  return;
11801
11892
  }
11802
11893
  if (project.config.browser.providerOptions) {
@@ -11804,7 +11895,7 @@ async function resolveBrowserWorkspace(vitest, names, resolvedProjects) {
11804
11895
  withLabel("yellow", "Vitest", `"providerOptions"${originalName ? ` in "${originalName}" project` : ""} is ignored because it's overriden by the configs. To hide this warning, remove the "providerOptions" property from the browser configuration.`)
11805
11896
  );
11806
11897
  }
11807
- filteredConfigs.forEach((config, index) => {
11898
+ filteredInstances.forEach((config, index) => {
11808
11899
  const browser = config.browser;
11809
11900
  if (!browser) {
11810
11901
  const nth = index + 1;
@@ -11812,19 +11903,21 @@ async function resolveBrowserWorkspace(vitest, names, resolvedProjects) {
11812
11903
  throw new Error(`The browser configuration must have a "browser" property. The ${nth}${ending} item in "browser.instances" doesn't have it. Make sure your${originalName ? ` "${originalName}"` : ""} configuration is correct.`);
11813
11904
  }
11814
11905
  const name = config.name;
11815
- const newName = name || (originalName ? `${originalName} (${browser})` : browser);
11816
- if (names.has(newName)) {
11906
+ if (name == null) {
11907
+ throw new Error(`The browser configuration must have a "name" property. This is a bug in Vitest. Please, open a new issue with reproduction`);
11908
+ }
11909
+ if (names.has(name)) {
11817
11910
  throw new Error(
11818
11911
  [
11819
- `Cannot define a nested project for a ${browser} browser. The project name "${newName}" was already defined. `,
11912
+ `Cannot define a nested project for a ${browser} browser. The project name "${name}" was already defined. `,
11820
11913
  'If you have multiple instances for the same browser, make sure to define a custom "name". ',
11821
11914
  "All projects in a workspace should have unique names. Make sure your configuration is correct."
11822
11915
  ].join("")
11823
11916
  );
11824
11917
  }
11825
- names.add(newName);
11918
+ names.add(name);
11826
11919
  const clonedConfig = cloneConfig(project, config);
11827
- clonedConfig.name = newName;
11920
+ clonedConfig.name = name;
11828
11921
  const clone = TestProject._cloneBrowserProject(project, clonedConfig);
11829
11922
  resolvedProjects.push(clone);
11830
11923
  });
@@ -11842,7 +11935,7 @@ async function resolveBrowserWorkspace(vitest, names, resolvedProjects) {
11842
11935
  if (!isTTY) {
11843
11936
  throw new Error(`${message} Please, filter projects with --browser=name or --project=name flag or run tests with "headless: true" option.`);
11844
11937
  }
11845
- const prompts = await import('./index.Bh7wTRhh.js').then(function (n) { return n.i; });
11938
+ const prompts = await import('./index.B57_6XMC.js').then(function (n) { return n.i; });
11846
11939
  const { projectName } = await prompts.default({
11847
11940
  type: "select",
11848
11941
  name: "projectName",
@@ -11983,6 +12076,29 @@ async function resolveDirectoryConfig(directory) {
11983
12076
  }
11984
12077
  return null;
11985
12078
  }
12079
+ function getDefaultTestProject(vitest) {
12080
+ const filter = vitest.config.project;
12081
+ const project = vitest._ensureRootProject();
12082
+ if (!filter.length) {
12083
+ return project;
12084
+ }
12085
+ const hasProjects = getPotentialProjectNames(project).some(
12086
+ (p) => vitest._matchesProjectFilter(p)
12087
+ );
12088
+ if (hasProjects) {
12089
+ return project;
12090
+ }
12091
+ return null;
12092
+ }
12093
+ function getPotentialProjectNames(project) {
12094
+ const names = [project.name];
12095
+ if (project.config.browser.instances) {
12096
+ names.push(...project.config.browser.instances.map((i) => i.name));
12097
+ } else if (project.config.browser.name) {
12098
+ names.push(project.config.browser.name);
12099
+ }
12100
+ return names;
12101
+ }
11986
12102
 
11987
12103
  const WATCHER_DEBOUNCE = 100;
11988
12104
  class Vitest {
@@ -12040,7 +12156,10 @@ class Vitest {
12040
12156
  isCancelling = false;
12041
12157
  /** @internal */
12042
12158
  coreWorkspaceProject;
12043
- /** @internal */
12159
+ /**
12160
+ * @internal
12161
+ * @deprecated
12162
+ */
12044
12163
  resolvedProjects = [];
12045
12164
  /** @internal */
12046
12165
  _browserLastPort = defaultBrowserPort;
@@ -12056,6 +12175,8 @@ class Vitest {
12056
12175
  runner = undefined;
12057
12176
  /** @internal */
12058
12177
  _testRun = undefined;
12178
+ /** @internal */
12179
+ _projectFilters = [];
12059
12180
  isFirstRun = true;
12060
12181
  restartsCount = 0;
12061
12182
  specifications;
@@ -12143,8 +12264,9 @@ class Vitest {
12143
12264
  this.coreWorkspaceProject = undefined;
12144
12265
  this.specifications.clearCache();
12145
12266
  this._onUserTestsRerun = [];
12146
- const resolved = resolveConfig(this.mode, options, server.config, this.logger);
12267
+ this._projectFilters = toArray(options.project || []).map((project) => wildcardPatternToRegExp(project));
12147
12268
  this._vite = server;
12269
+ const resolved = resolveConfig(this, options, server.config);
12148
12270
  this._config = resolved;
12149
12271
  this._state = new StateManager();
12150
12272
  this._cache = new VitestCache(this.version);
@@ -12192,14 +12314,8 @@ class Vitest {
12192
12314
  const projects = await this.resolveWorkspace(cliOptions);
12193
12315
  this.resolvedProjects = projects;
12194
12316
  this.projects = projects;
12195
- const filters = toArray(resolved.project).map((s) => wildcardPatternToRegExp(s));
12196
- if (filters.length > 0) {
12197
- this.projects = this.projects.filter(
12198
- (p) => filters.some((pattern) => pattern.test(p.name))
12199
- );
12200
- if (!this.projects.length) {
12201
- throw new Error(`No projects matched the filter "${toArray(resolved.project).join('", "')}".`);
12202
- }
12317
+ if (!this.projects.length) {
12318
+ throw new Error(`No projects matched the filter "${toArray(resolved.project).join('", "')}".`);
12203
12319
  }
12204
12320
  if (!this.coreWorkspaceProject) {
12205
12321
  this.coreWorkspaceProject = TestProject._createBasicProject(this);
@@ -12291,7 +12407,11 @@ class Vitest {
12291
12407
  const workspaceConfigPath = await this.resolveWorkspaceConfigPath();
12292
12408
  this._workspaceConfigPath = workspaceConfigPath;
12293
12409
  if (!workspaceConfigPath) {
12294
- return resolveBrowserWorkspace(this, /* @__PURE__ */ new Set(), [this._ensureRootProject()]);
12410
+ const project = getDefaultTestProject(this);
12411
+ if (!project) {
12412
+ return [];
12413
+ }
12414
+ return resolveBrowserWorkspace(this, /* @__PURE__ */ new Set(), [project]);
12295
12415
  }
12296
12416
  const workspaceModule = await this.import(workspaceConfigPath);
12297
12417
  if (!workspaceModule.default || !Array.isArray(workspaceModule.default)) {
@@ -12372,7 +12492,6 @@ class Vitest {
12372
12492
  };
12373
12493
  }
12374
12494
  async collect(filters) {
12375
- this._onClose = [];
12376
12495
  const files = await this.specifications.getRelevantTestSpecifications(filters);
12377
12496
  if (!files.length) {
12378
12497
  return { testModules: [], unhandledErrors: [] };
@@ -12399,7 +12518,6 @@ class Vitest {
12399
12518
  * @param filters String filters to match the test files
12400
12519
  */
12401
12520
  async start(filters) {
12402
- this._onClose = [];
12403
12521
  try {
12404
12522
  await this.initCoverageProvider();
12405
12523
  await this.coverageProvider?.clean(this.config.coverage.clean);
@@ -12440,7 +12558,6 @@ class Vitest {
12440
12558
  * If the `--watch` flag is provided, Vitest will still run changed tests even if this method was not called.
12441
12559
  */
12442
12560
  async init() {
12443
- this._onClose = [];
12444
12561
  try {
12445
12562
  await this.initCoverageProvider();
12446
12563
  await this.coverageProvider?.clean(this.config.coverage.clean);
@@ -12644,13 +12761,13 @@ class Vitest {
12644
12761
  /** @internal */
12645
12762
  async changeProjectName(pattern) {
12646
12763
  if (pattern === "") {
12647
- delete this.configOverride.project;
12764
+ this.configOverride.project = undefined;
12765
+ this._projectFilters = [];
12648
12766
  } else {
12649
- this.configOverride.project = pattern;
12767
+ this.configOverride.project = [pattern];
12768
+ this._projectFilters = [wildcardPatternToRegExp(pattern)];
12650
12769
  }
12651
- this.projects = this.resolvedProjects.filter((p) => p.name === pattern);
12652
- const files = (await this.globTestSpecifications()).map((spec) => spec.moduleId);
12653
- await this.rerunFiles(files, "change project filter", pattern === "");
12770
+ await this.vite.restart();
12654
12771
  }
12655
12772
  /** @internal */
12656
12773
  async changeNamePattern(pattern, files = this.state.getFilepaths(), trigger) {
@@ -12958,6 +13075,16 @@ class Vitest {
12958
13075
  onAfterSetServer(fn) {
12959
13076
  this._onSetServer.push(fn);
12960
13077
  }
13078
+ /**
13079
+ * Check if the project with a given name should be included.
13080
+ * @internal
13081
+ */
13082
+ _matchesProjectFilter(name) {
13083
+ if (!this._projectFilters.length) {
13084
+ return true;
13085
+ }
13086
+ return this._projectFilters.some((filter) => filter.test(name));
13087
+ }
12961
13088
  }
12962
13089
  function assert(condition, property, name = property) {
12963
13090
  if (!condition) {
@@ -12995,6 +13122,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
12995
13122
  if (testConfig.ui && testConfig.open) {
12996
13123
  open = testConfig.uiBase ?? "/__vitest__/";
12997
13124
  }
13125
+ const resolveOptions = getDefaultResolveOptions();
12998
13126
  const config = {
12999
13127
  root: viteConfig.test?.root || options.root,
13000
13128
  esbuild: viteConfig.esbuild === false ? false : {
@@ -13005,11 +13133,8 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
13005
13133
  legalComments: "inline"
13006
13134
  },
13007
13135
  resolve: {
13008
- // by default Vite resolves `module` field, which not always a native ESM module
13009
- // setting this option can bypass that and fallback to cjs version
13010
- mainFields: [],
13011
- alias: testConfig.alias,
13012
- conditions: ["node"]
13136
+ ...resolveOptions,
13137
+ alias: testConfig.alias
13013
13138
  },
13014
13139
  server: {
13015
13140
  ...testConfig.api,
@@ -13034,12 +13159,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
13034
13159
  // @ts-ignore Vite 6 compat
13035
13160
  environments: {
13036
13161
  ssr: {
13037
- resolve: {
13038
- // by default Vite resolves `module` field, which not always a native ESM module
13039
- // setting this option can bypass that and fallback to cjs version
13040
- mainFields: [],
13041
- conditions: ["node"]
13042
- }
13162
+ resolve: resolveOptions
13043
13163
  }
13044
13164
  },
13045
13165
  test: {
@@ -13055,6 +13175,9 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
13055
13175
  deps: testConfig.deps ?? viteConfig.test?.deps
13056
13176
  }
13057
13177
  };
13178
+ if (ctx.configOverride.project) {
13179
+ options.project = ctx.configOverride.project;
13180
+ }
13058
13181
  config.customLogger = createViteLogger(
13059
13182
  ctx.logger,
13060
13183
  viteConfig.logLevel || "warn",
@@ -13125,6 +13248,12 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
13125
13248
  enumerable: false,
13126
13249
  configurable: true
13127
13250
  });
13251
+ const originalName = options.name;
13252
+ if (options.browser?.enabled && options.browser?.instances) {
13253
+ options.browser.instances.forEach((instance) => {
13254
+ instance.name ??= originalName ? `${originalName} (${instance.browser})` : instance.browser;
13255
+ });
13256
+ }
13128
13257
  },
13129
13258
  configureServer: {
13130
13259
  // runs after vite:import-analysis as it relies on `server` instance on Vite 5
@@ -13471,7 +13600,7 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout2) {
13471
13600
  name: "filter",
13472
13601
  type: "text",
13473
13602
  message: "Input a single project name",
13474
- initial: toArray(ctx.configOverride.project)[0] || ""
13603
+ initial: ctx.config.project[0] || ""
13475
13604
  }
13476
13605
  ]);
13477
13606
  on();
@@ -13739,4 +13868,4 @@ var cliApi = /*#__PURE__*/Object.freeze({
13739
13868
  startVitest: startVitest
13740
13869
  });
13741
13870
 
13742
- export { FilesNotFoundError as F, GitNotFoundError as G, TestModule as T, Vitest as V, VitestPlugin as a, VitestPackageInstaller as b, createVitest as c, registerConsoleShortcuts as d, createViteLogger as e, cliApi as f, resolveFsAllow as r, startVitest as s };
13871
+ export { FilesNotFoundError as F, GitNotFoundError as G, TestModule as T, Vitest as V, VitestPlugin as a, VitestPackageInstaller as b, createVitest as c, registerConsoleShortcuts as d, createViteLogger as e, cliApi as f, isValidApiRequest as i, resolveFsAllow as r, startVitest as s };
@@ -1,8 +1,8 @@
1
1
  import { existsSync, writeFileSync, readFileSync } from 'node:fs';
2
2
  import { mkdir, writeFile } from 'node:fs/promises';
3
3
  import { resolve, dirname, relative } from 'node:path';
4
- import { detectPackageManager, installPackage } from './index.DfqWks-F.js';
5
- import { p as prompt, f as findUp } from './index.Bh7wTRhh.js';
4
+ import { detectPackageManager, installPackage } from './index.NxxmQyK2.js';
5
+ import { p as prompt, f as findUp } from './index.B57_6XMC.js';
6
6
  import { x } from 'tinyexec';
7
7
  import c from 'tinyrainbow';
8
8
  import { c as configFiles } from './constants.fzPh7AOq.js';
@@ -21,7 +21,7 @@ function normalizeWindowsPath(input = "") {
21
21
  const _UNC_REGEX = /^[/\\]{2}/;
22
22
  const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
23
23
  const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
24
- const _EXTNAME_RE = /.(\.[^./]+)$/;
24
+ const _EXTNAME_RE = /.(\.[^./]+|\.)$/;
25
25
  const normalize = function(path) {
26
26
  if (path.length === 0) {
27
27
  return ".";
@@ -160,6 +160,7 @@ const isAbsolute = function(p) {
160
160
  return _IS_ABSOLUTE_RE.test(p);
161
161
  };
162
162
  const extname = function(p) {
163
+ if (p === "..") return "";
163
164
  const match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
164
165
  return match && match[1] || "";
165
166
  };