vitest 2.2.0-beta.1 → 2.2.0-beta.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.
@@ -8,12 +8,12 @@ import { f as findUp, p as prompt } from './index.BJDntFik.js';
8
8
  import { searchForWorkspaceRoot, version, createServer, mergeConfig } from 'vite';
9
9
  import { A as API_PATH, c as configFiles, a as defaultBrowserPort, w as workspacesFiles, d as defaultPort } from './constants.fzPh7AOq.js';
10
10
  import { SnapshotManager } from '@vitest/snapshot/manager';
11
- import { i as isPackageExists, e as requireMicromatch, V as VitestCache, f as configDefaults, m as mm, b as resolveConfig, h as isBrowserEnabled, w as wildcardPatternToRegExp, g as getFilePoolName, j as createPool, a as resolveApiServerConfig, c as coverageConfigDefaults, s as stdout } from './resolveConfig.CQIc6fe7.js';
11
+ import { i as isPackageExists, e as requireMicromatch, V as VitestCache, f as configDefaults, g as getFilePoolName, h as isBrowserEnabled, m as mm, b as resolveConfig, w as wildcardPatternToRegExp, j as createPool, a as resolveApiServerConfig, c as coverageConfigDefaults, s as stdout } from './resolveConfig.CLnvCvEs.js';
12
12
  import { ViteNodeRunner } from 'vite-node/client';
13
13
  import { ViteNodeServer } from 'vite-node/server';
14
- import { v as version$1 } from './cac.Z91LBqmg.js';
14
+ import { v as version$1 } from './cac.Cs06pOqp.js';
15
15
  import { c as createBirpc } from './index.68735LiX.js';
16
- import { s as stringify, p as parse, R as ReportersMap, h as BenchmarkReportsMap, f as TestModule, g as TestSuite, e as TestCase, j as generateCodeFrame, i as TestProject, L as Logger, k as BlobReporter, r as readBlobs } from './index.DLRzErGF.js';
16
+ import { s as stringify, p as parse, i as generateCodeFrame, R as ReportersMap, h as BenchmarkReportsMap, f as TestModule, g as TestSuite, e as TestCase, L as Logger, j as BlobReporter, r as readBlobs } from './index.bzFpKeaq.js';
17
17
  import require$$0$2 from 'stream';
18
18
  import require$$0 from 'zlib';
19
19
  import require$$0$1 from 'buffer';
@@ -30,7 +30,7 @@ import { distDir, rootDir } from '../path.js';
30
30
  import { createRequire } from 'node:module';
31
31
  import url from 'node:url';
32
32
  import c from 'tinyrainbow';
33
- import { h as hash, i as isWindows } from './RandomSequencer.CMRlh2v4.js';
33
+ import { h as hash, i as isWindows } from './RandomSequencer.BPedXEug.js';
34
34
  import { isCI } from 'std-env';
35
35
  import { rm } from 'node:fs/promises';
36
36
  import nodeos__default, { tmpdir } from 'node:os';
@@ -4845,7 +4845,7 @@ async function getModuleGraph(ctx, projectName, id, browser = false) {
4845
4845
  if (browser && project.browser) {
4846
4846
  await get(project.browser.vite.moduleGraph.getModuleById(id));
4847
4847
  } else {
4848
- await get(project.server.moduleGraph.getModuleById(id));
4848
+ await get(project.vite.moduleGraph.getModuleById(id));
4849
4849
  }
4850
4850
  return {
4851
4851
  graph,
@@ -4924,11 +4924,14 @@ function setup(ctx, _server) {
4924
4924
  }
4925
4925
  return promises.writeFile(id, content, "utf-8");
4926
4926
  },
4927
- async rerun(files) {
4928
- await ctx.rerunFiles(files);
4927
+ async rerun(files, resetTestNamePattern) {
4928
+ await ctx.rerunFiles(files, void 0, true, resetTestNamePattern);
4929
+ },
4930
+ async rerunTask(id) {
4931
+ await ctx.rerunTask(id);
4929
4932
  },
4930
4933
  getConfig() {
4931
- return ctx.getCoreWorkspaceProject().getSerializableConfig();
4934
+ return ctx.getRootTestProject().serializedConfig;
4932
4935
  },
4933
4936
  async getTransformResult(projectName, id, browser = false) {
4934
4937
  const project = ctx.getProjectByName(projectName);
@@ -5123,250 +5126,6 @@ Package ${packageName} installed, re-run the command to start.
5123
5126
  }
5124
5127
  }
5125
5128
 
5126
- async function loadCustomReporterModule(path, runner) {
5127
- let customReporterModule;
5128
- try {
5129
- customReporterModule = await runner.executeId(path);
5130
- } catch (customReporterModuleError) {
5131
- throw new Error(`Failed to load custom Reporter from ${path}`, {
5132
- cause: customReporterModuleError
5133
- });
5134
- }
5135
- if (customReporterModule.default === null || customReporterModule.default === void 0) {
5136
- throw new Error(
5137
- `Custom reporter loaded from ${path} was not the default export`
5138
- );
5139
- }
5140
- return customReporterModule.default;
5141
- }
5142
- function createReporters(reporterReferences, ctx) {
5143
- const runner = ctx.runner;
5144
- const promisedReporters = reporterReferences.map(
5145
- async (referenceOrInstance) => {
5146
- if (Array.isArray(referenceOrInstance)) {
5147
- const [reporterName, reporterOptions] = referenceOrInstance;
5148
- if (reporterName === "html") {
5149
- await ctx.packageInstaller.ensureInstalled("@vitest/ui", runner.root, ctx.version);
5150
- const CustomReporter = await loadCustomReporterModule(
5151
- "@vitest/ui/reporter",
5152
- runner
5153
- );
5154
- return new CustomReporter(reporterOptions);
5155
- } else if (reporterName in ReportersMap) {
5156
- const BuiltinReporter = ReportersMap[reporterName];
5157
- return new BuiltinReporter(reporterOptions);
5158
- } else {
5159
- const CustomReporter = await loadCustomReporterModule(
5160
- reporterName,
5161
- runner
5162
- );
5163
- return new CustomReporter(reporterOptions);
5164
- }
5165
- }
5166
- return referenceOrInstance;
5167
- }
5168
- );
5169
- return Promise.all(promisedReporters);
5170
- }
5171
- function createBenchmarkReporters(reporterReferences, runner) {
5172
- const promisedReporters = reporterReferences.map(
5173
- async (referenceOrInstance) => {
5174
- if (typeof referenceOrInstance === "string") {
5175
- if (referenceOrInstance in BenchmarkReportsMap) {
5176
- const BuiltinReporter = BenchmarkReportsMap[referenceOrInstance];
5177
- return new BuiltinReporter();
5178
- } else {
5179
- const CustomReporter = await loadCustomReporterModule(
5180
- referenceOrInstance,
5181
- runner
5182
- );
5183
- return new CustomReporter();
5184
- }
5185
- }
5186
- return referenceOrInstance;
5187
- }
5188
- );
5189
- return Promise.all(promisedReporters);
5190
- }
5191
-
5192
- function isAggregateError(err) {
5193
- if (typeof AggregateError !== "undefined" && err instanceof AggregateError) {
5194
- return true;
5195
- }
5196
- return err instanceof Error && "errors" in err;
5197
- }
5198
- class StateManager {
5199
- filesMap = /* @__PURE__ */ new Map();
5200
- pathsSet = /* @__PURE__ */ new Set();
5201
- idMap = /* @__PURE__ */ new Map();
5202
- taskFileMap = /* @__PURE__ */ new WeakMap();
5203
- errorsSet = /* @__PURE__ */ new Set();
5204
- processTimeoutCauses = /* @__PURE__ */ new Set();
5205
- reportedTasksMap = /* @__PURE__ */ new WeakMap();
5206
- catchError(err, type) {
5207
- if (isAggregateError(err)) {
5208
- return err.errors.forEach((error) => this.catchError(error, type));
5209
- }
5210
- if (err === Object(err)) {
5211
- err.type = type;
5212
- } else {
5213
- err = { type, message: err };
5214
- }
5215
- const _err = err;
5216
- if (_err && typeof _err === "object" && _err.code === "VITEST_PENDING") {
5217
- const task = this.idMap.get(_err.taskId);
5218
- if (task) {
5219
- task.mode = "skip";
5220
- task.result ??= { state: "skip" };
5221
- task.result.state = "skip";
5222
- task.result.note = _err.note;
5223
- }
5224
- return;
5225
- }
5226
- this.errorsSet.add(err);
5227
- }
5228
- clearErrors() {
5229
- this.errorsSet.clear();
5230
- }
5231
- getUnhandledErrors() {
5232
- return Array.from(this.errorsSet.values());
5233
- }
5234
- addProcessTimeoutCause(cause) {
5235
- this.processTimeoutCauses.add(cause);
5236
- }
5237
- getProcessTimeoutCauses() {
5238
- return Array.from(this.processTimeoutCauses.values());
5239
- }
5240
- getPaths() {
5241
- return Array.from(this.pathsSet);
5242
- }
5243
- /**
5244
- * Return files that were running or collected.
5245
- */
5246
- getFiles(keys) {
5247
- if (keys) {
5248
- return keys.map((key) => this.filesMap.get(key)).flat().filter((file) => file && !file.local);
5249
- }
5250
- return Array.from(this.filesMap.values()).flat().filter((file) => !file.local).sort((f1, f2) => {
5251
- if (f1.meta?.typecheck && f2.meta?.typecheck) {
5252
- return 0;
5253
- }
5254
- if (f1.meta?.typecheck) {
5255
- return -1;
5256
- }
5257
- return 1;
5258
- });
5259
- }
5260
- getFilepaths() {
5261
- return Array.from(this.filesMap.keys());
5262
- }
5263
- getFailedFilepaths() {
5264
- return this.getFiles().filter((i) => i.result?.state === "fail").map((i) => i.filepath);
5265
- }
5266
- collectPaths(paths = []) {
5267
- paths.forEach((path) => {
5268
- this.pathsSet.add(path);
5269
- });
5270
- }
5271
- collectFiles(project, files = []) {
5272
- files.forEach((file) => {
5273
- const existing = this.filesMap.get(file.filepath) || [];
5274
- const otherFiles = existing.filter(
5275
- (i) => i.projectName !== file.projectName || i.meta.typecheck !== file.meta.typecheck
5276
- );
5277
- const currentFile = existing.find(
5278
- (i) => i.projectName === file.projectName
5279
- );
5280
- if (currentFile) {
5281
- file.logs = currentFile.logs;
5282
- }
5283
- otherFiles.push(file);
5284
- this.filesMap.set(file.filepath, otherFiles);
5285
- this.updateId(file, project);
5286
- });
5287
- }
5288
- clearFiles(project, paths = []) {
5289
- paths.forEach((path) => {
5290
- const files = this.filesMap.get(path);
5291
- const fileTask = createFileTask(
5292
- path,
5293
- project.config.root,
5294
- project.config.name
5295
- );
5296
- fileTask.local = true;
5297
- TestModule.register(fileTask, project);
5298
- this.idMap.set(fileTask.id, fileTask);
5299
- if (!files) {
5300
- this.filesMap.set(path, [fileTask]);
5301
- return;
5302
- }
5303
- const filtered = files.filter(
5304
- (file) => file.projectName !== project.config.name
5305
- );
5306
- if (!filtered.length) {
5307
- this.filesMap.set(path, [fileTask]);
5308
- } else {
5309
- this.filesMap.set(path, [...filtered, fileTask]);
5310
- }
5311
- });
5312
- }
5313
- updateId(task, project) {
5314
- if (this.idMap.get(task.id) === task) {
5315
- return;
5316
- }
5317
- if (task.type === "suite" && "filepath" in task) {
5318
- TestModule.register(task, project);
5319
- } else if (task.type === "suite") {
5320
- TestSuite.register(task, project);
5321
- } else {
5322
- TestCase.register(task, project);
5323
- }
5324
- this.idMap.set(task.id, task);
5325
- if (task.type === "suite") {
5326
- task.tasks.forEach((task2) => {
5327
- this.updateId(task2, project);
5328
- });
5329
- }
5330
- }
5331
- getReportedEntity(task) {
5332
- return this.reportedTasksMap.get(task);
5333
- }
5334
- updateTasks(packs) {
5335
- for (const [id, result, meta] of packs) {
5336
- const task = this.idMap.get(id);
5337
- if (task) {
5338
- task.result = result;
5339
- task.meta = meta;
5340
- if (result?.state === "skip") {
5341
- task.mode = "skip";
5342
- }
5343
- }
5344
- }
5345
- }
5346
- updateUserLog(log) {
5347
- const task = log.taskId && this.idMap.get(log.taskId);
5348
- if (task) {
5349
- if (!task.logs) {
5350
- task.logs = [];
5351
- }
5352
- task.logs.push(log);
5353
- }
5354
- }
5355
- getCountOfFailedTests() {
5356
- return Array.from(this.idMap.values()).filter(
5357
- (t) => t.result?.state === "fail"
5358
- ).length;
5359
- }
5360
- cancelFiles(files, project) {
5361
- this.collectFiles(
5362
- project,
5363
- files.map(
5364
- (filepath) => createFileTask(filepath, project.config.root, project.config.name)
5365
- )
5366
- );
5367
- }
5368
- }
5369
-
5370
5129
  var tasks = {};
5371
5130
 
5372
5131
  var utils$1 = {};
@@ -9447,7 +9206,7 @@ function NormalizeURLPlugin() {
9447
9206
  };
9448
9207
  }
9449
9208
 
9450
- function resolveOptimizerConfig(_testOptions, viteOptions, testConfig) {
9209
+ function resolveOptimizerConfig(_testOptions, viteOptions, testConfig, viteCacheDir) {
9451
9210
  const testOptions = _testOptions || {};
9452
9211
  const newConfig = {};
9453
9212
  const [major, minor, fix] = version.split(".").map(Number);
@@ -9468,7 +9227,6 @@ function resolveOptimizerConfig(_testOptions, viteOptions, testConfig) {
9468
9227
  };
9469
9228
  } else {
9470
9229
  const root = testConfig.root ?? process.cwd();
9471
- const cacheDir = testConfig.cache !== false ? testConfig.cache?.dir : void 0;
9472
9230
  const currentInclude = testOptions.include || viteOptions?.include || [];
9473
9231
  const exclude = [
9474
9232
  "vitest",
@@ -9484,7 +9242,7 @@ function resolveOptimizerConfig(_testOptions, viteOptions, testConfig) {
9484
9242
  const include = (testOptions.include || viteOptions?.include || []).filter(
9485
9243
  (n) => !exclude.includes(n)
9486
9244
  );
9487
- newConfig.cacheDir = cacheDir ?? VitestCache.resolveCacheDir(root, cacheDir, testConfig.name);
9245
+ newConfig.cacheDir = testConfig.cache !== false && testConfig.cache?.dir || VitestCache.resolveCacheDir(root, viteCacheDir, testConfig.name);
9488
9246
  newConfig.optimizeDeps = {
9489
9247
  ...viteOptions,
9490
9248
  ...testOptions,
@@ -9567,12 +9325,14 @@ function VitestOptimizer() {
9567
9325
  const webOptimizer = resolveOptimizerConfig(
9568
9326
  testConfig.deps?.optimizer?.web,
9569
9327
  viteConfig.optimizeDeps,
9570
- testConfig
9328
+ testConfig,
9329
+ viteConfig.cacheDir
9571
9330
  );
9572
9331
  const ssrOptimizer = resolveOptimizerConfig(
9573
9332
  testConfig.deps?.optimizer?.ssr,
9574
9333
  viteConfig.ssr?.optimizeDeps,
9575
- testConfig
9334
+ testConfig,
9335
+ viteConfig.cacheDir
9576
9336
  );
9577
9337
  viteConfig.cacheDir = webOptimizer.cacheDir || ssrOptimizer.cacheDir || viteConfig.cacheDir;
9578
9338
  viteConfig.optimizeDeps = webOptimizer.optimizeDeps;
@@ -9753,7 +9513,7 @@ function WorkspaceVitestPlugin(project, options) {
9753
9513
  },
9754
9514
  async configureServer(server) {
9755
9515
  const options2 = deepMerge({}, configDefaults, server.config.test || {});
9756
- await project.setServer(options2, server);
9516
+ await project._configureServer(options2, server);
9757
9517
  await server.watcher.close();
9758
9518
  }
9759
9519
  },
@@ -9784,11 +9544,11 @@ class TestSpecification {
9784
9544
  moduleId;
9785
9545
  pool;
9786
9546
  // public readonly location: WorkspaceSpecLocation | undefined
9787
- constructor(workspaceProject, moduleId, pool) {
9788
- this[0] = workspaceProject;
9547
+ constructor(project, moduleId, pool) {
9548
+ this[0] = project;
9789
9549
  this[1] = moduleId;
9790
9550
  this[2] = { pool };
9791
- this.project = workspaceProject.testProject;
9551
+ this.project = project;
9792
9552
  this.moduleId = moduleId;
9793
9553
  this.pool = pool;
9794
9554
  }
@@ -9807,7 +9567,7 @@ class TestSpecification {
9807
9567
  * @deprecated
9808
9568
  */
9809
9569
  *[Symbol.iterator]() {
9810
- yield this.project.workspaceProject;
9570
+ yield this.project;
9811
9571
  yield this.moduleId;
9812
9572
  yield this.pool;
9813
9573
  }
@@ -9826,51 +9586,46 @@ async function createViteServer(inlineConfig) {
9826
9586
  return server;
9827
9587
  }
9828
9588
 
9829
- async function initializeProject(workspacePath, ctx, options) {
9830
- const project = new WorkspaceProject(workspacePath, ctx, options);
9831
- const root = options.root || (typeof workspacePath === "number" ? void 0 : workspacePath.endsWith("/") ? workspacePath : dirname(workspacePath));
9832
- const configFile = options.extends ? resolve(dirname(options.workspaceConfigPath), options.extends) : typeof workspacePath === "number" || workspacePath.endsWith("/") ? false : workspacePath;
9833
- const config = {
9834
- ...options,
9835
- root,
9836
- configFile,
9837
- // this will make "mode": "test" | "benchmark" inside defineConfig
9838
- mode: options.test?.mode || options.mode || ctx.config.mode,
9839
- plugins: [
9840
- ...options.plugins || [],
9841
- WorkspaceVitestPlugin(project, { ...options, root, workspacePath })
9842
- ]
9843
- };
9844
- await createViteServer(config);
9845
- return project;
9846
- }
9847
- class WorkspaceProject {
9848
- constructor(path2, ctx, options) {
9589
+ class TestProject {
9590
+ constructor(path2, vitest, options) {
9849
9591
  this.path = path2;
9850
- this.ctx = ctx;
9851
9592
  this.options = options;
9593
+ this.vitest = vitest;
9594
+ this.ctx = vitest;
9595
+ this.globalConfig = vitest.config;
9852
9596
  }
9853
- configOverride;
9854
- config;
9855
- server;
9597
+ /**
9598
+ * The global Vitest instance.
9599
+ * @experimental The public Vitest API is experimental and does not follow semver.
9600
+ */
9601
+ vitest;
9602
+ /**
9603
+ * Resolved global configuration. If there are no workspace projects, this will be the same as `config`.
9604
+ */
9605
+ globalConfig;
9606
+ /**
9607
+ * Browser instance if the browser is enabled. This is initialized when the tests run for the first time.
9608
+ */
9609
+ browser;
9610
+ /** @deprecated use `vitest` instead */
9611
+ ctx;
9612
+ /**
9613
+ * Temporary directory for the project. This is unique for each project. Vitest stores transformed content here.
9614
+ */
9615
+ tmpDir = join(tmpdir(), nanoid());
9856
9616
  vitenode;
9857
9617
  runner;
9858
- browser;
9859
9618
  typechecker;
9860
9619
  closingPromise;
9861
9620
  testFilesList = null;
9862
9621
  typecheckFilesList = null;
9863
- testProject;
9864
- id = nanoid();
9865
- tmpDir = join(tmpdir(), this.id);
9866
9622
  _globalSetups;
9867
9623
  _provided = {};
9868
- getName() {
9869
- return this.config.name || "";
9870
- }
9871
- isCore() {
9872
- return this.ctx.getCoreWorkspaceProject() === this;
9873
- }
9624
+ _config;
9625
+ _vite;
9626
+ /**
9627
+ * Provide a value to the test context. This value will be available to all tests with `inject`.
9628
+ */
9874
9629
  provide(key, value) {
9875
9630
  try {
9876
9631
  structuredClone(value);
@@ -9884,19 +9639,90 @@ class WorkspaceProject {
9884
9639
  }
9885
9640
  this._provided[key] = value;
9886
9641
  }
9642
+ /**
9643
+ * Get the provided context. The project context is merged with the global context.
9644
+ */
9887
9645
  getProvidedContext() {
9888
- if (this.isCore()) {
9646
+ if (this.isRootProject()) {
9889
9647
  return this._provided;
9890
9648
  }
9891
9649
  return {
9892
- ...this.ctx.getCoreWorkspaceProject().getProvidedContext(),
9650
+ ...this.vitest.getRootTestProject().getProvidedContext(),
9893
9651
  ...this._provided
9894
9652
  };
9895
9653
  }
9654
+ /**
9655
+ * Creates a new test specification. Specifications describe how to run tests.
9656
+ * @param moduleId The file path
9657
+ */
9658
+ createSpecification(moduleId, pool) {
9659
+ return new TestSpecification(
9660
+ this,
9661
+ moduleId,
9662
+ pool || getFilePoolName(this, moduleId)
9663
+ );
9664
+ }
9665
+ toJSON() {
9666
+ return {
9667
+ name: this.name,
9668
+ serializedConfig: this.serializedConfig,
9669
+ context: this.getProvidedContext()
9670
+ };
9671
+ }
9672
+ /**
9673
+ * Vite's dev server instance. Every workspace project has its own server.
9674
+ */
9675
+ get vite() {
9676
+ if (!this._vite) {
9677
+ throw new Error("The server was not set. It means that `project.vite` was called before the Vite server was established.");
9678
+ }
9679
+ return this._vite;
9680
+ }
9681
+ /**
9682
+ * Resolved project configuration.
9683
+ */
9684
+ get config() {
9685
+ if (!this._config) {
9686
+ throw new Error("The config was not set. It means that `project.config` was called before the Vite server was established.");
9687
+ }
9688
+ return this._config;
9689
+ }
9690
+ /**
9691
+ * The name of the project or an empty string if not set.
9692
+ */
9693
+ get name() {
9694
+ return this.config.name || "";
9695
+ }
9696
+ /**
9697
+ * Serialized project configuration. This is the config that tests receive.
9698
+ */
9699
+ get serializedConfig() {
9700
+ return this._serializeOverridenConfig();
9701
+ }
9702
+ /** @deprecated use `vite` instead */
9703
+ get server() {
9704
+ return this._vite;
9705
+ }
9706
+ /**
9707
+ * Check if this is the root project. The root project is the one that has the root config.
9708
+ */
9709
+ isRootProject() {
9710
+ return this.vitest.getRootTestProject() === this;
9711
+ }
9712
+ /** @deprecated use `isRootProject` instead */
9713
+ isCore() {
9714
+ return this.isRootProject();
9715
+ }
9716
+ /** @deprecated use `createSpecification` instead */
9896
9717
  createSpec(moduleId, pool) {
9897
9718
  return new TestSpecification(this, moduleId, pool);
9898
9719
  }
9899
- async initializeGlobalSetup() {
9720
+ /** @deprecated */
9721
+ initializeGlobalSetup() {
9722
+ return this._initializeGlobalSetup();
9723
+ }
9724
+ /** @internal */
9725
+ async _initializeGlobalSetup() {
9900
9726
  if (this._globalSetups) {
9901
9727
  return;
9902
9728
  }
@@ -9908,7 +9734,7 @@ class WorkspaceProject {
9908
9734
  const teardown = await globalSetupFile.setup?.({
9909
9735
  provide: (key, value) => this.provide(key, value),
9910
9736
  config: this.config,
9911
- onTestsRerun: (cb) => this.ctx.onTestsRerun(cb)
9737
+ onTestsRerun: (cb) => this.vitest.onTestsRerun(cb)
9912
9738
  });
9913
9739
  if (teardown == null || !!globalSetupFile.teardown) {
9914
9740
  continue;
@@ -9921,7 +9747,12 @@ class WorkspaceProject {
9921
9747
  globalSetupFile.teardown = teardown;
9922
9748
  }
9923
9749
  }
9924
- async teardownGlobalSetup() {
9750
+ /** @deprecated */
9751
+ teardownGlobalSetup() {
9752
+ return this._teardownGlobalSetup();
9753
+ }
9754
+ /** @internal */
9755
+ async _teardownGlobalSetup() {
9925
9756
  if (!this._globalSetups) {
9926
9757
  return;
9927
9758
  }
@@ -9929,24 +9760,33 @@ class WorkspaceProject {
9929
9760
  await globalSetupFile.teardown?.();
9930
9761
  }
9931
9762
  }
9763
+ /** @deprecated use `vitest.logger` instead */
9932
9764
  get logger() {
9933
- return this.ctx.logger;
9765
+ return this.vitest.logger;
9934
9766
  }
9935
9767
  // it's possible that file path was imported with different queries (?raw, ?url, etc)
9768
+ /** @deprecated use `.vite` or `.browser.vite` directly */
9936
9769
  getModulesByFilepath(file) {
9937
9770
  const set = this.server.moduleGraph.getModulesByFile(file) || this.browser?.vite.moduleGraph.getModulesByFile(file);
9938
9771
  return set || /* @__PURE__ */ new Set();
9939
9772
  }
9773
+ /** @deprecated use `.vite` or `.browser.vite` directly */
9940
9774
  getModuleById(id) {
9941
9775
  return this.server.moduleGraph.getModuleById(id) || this.browser?.vite.moduleGraph.getModuleById(id);
9942
9776
  }
9777
+ /** @deprecated use `.vite` or `.browser.vite` directly */
9943
9778
  getSourceMapModuleById(id) {
9944
9779
  const mod = this.server.moduleGraph.getModuleById(id);
9945
9780
  return mod?.ssrTransformResult?.map || mod?.transformResult?.map;
9946
9781
  }
9782
+ /** @deprecated use `vitest.reporters` instead */
9947
9783
  get reporters() {
9948
9784
  return this.ctx.reporters;
9949
9785
  }
9786
+ /**
9787
+ * Get all files in the project that match the globs in the config and the filters.
9788
+ * @param filters String filters to match the test files.
9789
+ */
9950
9790
  async globTestFiles(filters = []) {
9951
9791
  const dir = this.config.dir || this.config.root;
9952
9792
  const { include, exclude, includeSource } = this.config;
@@ -9980,7 +9820,7 @@ class WorkspaceProject {
9980
9820
  files.map(async (file) => {
9981
9821
  try {
9982
9822
  const code = await promises.readFile(file, "utf-8");
9983
- if (this.isInSourceTestFile(code)) {
9823
+ if (this.isInSourceTestCode(code)) {
9984
9824
  testFiles.push(file);
9985
9825
  }
9986
9826
  } catch {
@@ -9992,12 +9832,32 @@ class WorkspaceProject {
9992
9832
  this.testFilesList = testFiles;
9993
9833
  return testFiles;
9994
9834
  }
9995
- isTestFile(id) {
9996
- return this.testFilesList && this.testFilesList.includes(id);
9835
+ isBrowserEnabled() {
9836
+ return isBrowserEnabled(this.config);
9997
9837
  }
9998
- isTypecheckFile(id) {
9999
- return this.typecheckFilesList && this.typecheckFilesList.includes(id);
9838
+ /** @internal */
9839
+ _markTestFile(testPath) {
9840
+ this.testFilesList?.push(testPath);
10000
9841
  }
9842
+ /**
9843
+ * Returns if the file is a test file. Requires `.globTestFiles()` to be called first.
9844
+ * @internal
9845
+ */
9846
+ isTestFile(testPath) {
9847
+ return !!this.testFilesList && this.testFilesList.includes(testPath);
9848
+ }
9849
+ /**
9850
+ * Returns if the file is a typecheck test file. Requires `.globTestFiles()` to be called first.
9851
+ * @internal
9852
+ */
9853
+ isTypecheckFile(testPath) {
9854
+ return !!this.typecheckFilesList && this.typecheckFilesList.includes(testPath);
9855
+ }
9856
+ /** @deprecated use `serializedConfig` instead */
9857
+ getSerializableConfig() {
9858
+ return this._serializeOverridenConfig();
9859
+ }
9860
+ /** @internal */
10001
9861
  async globFiles(include, exclude, cwd) {
10002
9862
  const globOptions = {
10003
9863
  dot: true,
@@ -10007,8 +9867,11 @@ class WorkspaceProject {
10007
9867
  const files = await fg(include, globOptions);
10008
9868
  return files.map((file) => slash(a.resolve(cwd, file)));
10009
9869
  }
10010
- async isTargetFile(id, source) {
10011
- const relativeId = relative(this.config.dir || this.config.root, id);
9870
+ /**
9871
+ * Test if a file matches the test globs. This does the actual glob matching unlike `isTestFile`.
9872
+ */
9873
+ matchesTestGlob(filepath, source) {
9874
+ const relativeId = relative(this.config.dir || this.config.root, filepath);
10012
9875
  if (mm.isMatch(relativeId, this.config.exclude)) {
10013
9876
  return false;
10014
9877
  }
@@ -10016,12 +9879,16 @@ class WorkspaceProject {
10016
9879
  return true;
10017
9880
  }
10018
9881
  if (this.config.includeSource?.length && mm.isMatch(relativeId, this.config.includeSource)) {
10019
- source = source || await promises.readFile(id, "utf-8");
10020
- return this.isInSourceTestFile(source);
9882
+ const code = source || readFileSync(filepath, "utf-8");
9883
+ return this.isInSourceTestCode(code);
10021
9884
  }
10022
9885
  return false;
10023
9886
  }
10024
- isInSourceTestFile(code) {
9887
+ /** @deprecated use `matchesTestGlob` instead */
9888
+ async isTargetFile(id, source) {
9889
+ return this.matchesTestGlob(id, source);
9890
+ }
9891
+ isInSourceTestCode(code) {
10025
9892
  return code.includes("import.meta.vitest");
10026
9893
  }
10027
9894
  filterFiles(testFiles, filters, dir) {
@@ -10042,15 +9909,16 @@ class WorkspaceProject {
10042
9909
  }
10043
9910
  return testFiles;
10044
9911
  }
10045
- async initBrowserServer() {
9912
+ /** @internal */
9913
+ async _initBrowserServer() {
10046
9914
  if (!this.isBrowserEnabled() || this.browser) {
10047
9915
  return;
10048
9916
  }
10049
- await this.ctx.packageInstaller.ensureInstalled("@vitest/browser", this.config.root, this.ctx.version);
9917
+ await this.vitest.packageInstaller.ensureInstalled("@vitest/browser", this.config.root, this.ctx.version);
10050
9918
  const { createBrowserServer, distRoot } = await import('@vitest/browser');
10051
9919
  const browser = await createBrowserServer(
10052
9920
  this,
10053
- this.server.config.configFile,
9921
+ this.vite.config.configFile,
10054
9922
  [
10055
9923
  ...MocksPlugins({
10056
9924
  filter(id) {
@@ -10065,40 +9933,47 @@ class WorkspaceProject {
10065
9933
  );
10066
9934
  this.browser = browser;
10067
9935
  if (this.config.browser.ui) {
10068
- setup(this.ctx, browser.vite);
9936
+ setup(this.vitest, browser.vite);
10069
9937
  }
10070
9938
  }
10071
- static createBasicProject(ctx) {
10072
- const project = new WorkspaceProject(
10073
- ctx.config.name || ctx.config.root,
10074
- ctx
10075
- );
10076
- project.vitenode = ctx.vitenode;
10077
- project.server = ctx.server;
10078
- project.runner = ctx.runner;
10079
- project.config = ctx.config;
10080
- for (const _providedKey in ctx.config.provide) {
10081
- const providedKey = _providedKey;
10082
- project.provide(
10083
- providedKey,
10084
- ctx.config.provide[providedKey]
10085
- );
9939
+ /**
9940
+ * Closes the project and all associated resources. This can only be called once; the closing promise is cached until the server restarts.
9941
+ * If the resources are needed again, create a new project.
9942
+ */
9943
+ close() {
9944
+ if (!this.closingPromise) {
9945
+ this.closingPromise = Promise.all(
9946
+ [
9947
+ this.vite?.close(),
9948
+ this.typechecker?.stop(),
9949
+ this.browser?.close(),
9950
+ this.clearTmpDir()
9951
+ ].filter(Boolean)
9952
+ ).then(() => {
9953
+ this._provided = {};
9954
+ this._vite = void 0;
9955
+ });
10086
9956
  }
10087
- project.testProject = new TestProject(project);
10088
- return project;
9957
+ return this.closingPromise;
10089
9958
  }
10090
- static async createCoreProject(ctx) {
10091
- return WorkspaceProject.createBasicProject(ctx);
9959
+ /** @deprecated use `name` instead */
9960
+ getName() {
9961
+ return this.config.name || "";
9962
+ }
9963
+ /** @deprecated internal */
9964
+ setServer(options, server) {
9965
+ return this._configureServer(options, server);
10092
9966
  }
10093
- async setServer(options, server) {
10094
- this.config = resolveConfig(
10095
- this.ctx.mode,
9967
+ /** @internal */
9968
+ async _configureServer(options, server) {
9969
+ this._config = resolveConfig(
9970
+ this.vitest.mode,
10096
9971
  {
10097
9972
  ...options,
10098
- coverage: this.ctx.config.coverage
9973
+ coverage: this.vitest.config.coverage
10099
9974
  },
10100
9975
  server.config,
10101
- this.ctx.logger
9976
+ this.vitest.logger
10102
9977
  );
10103
9978
  for (const _providedKey in this.config.provide) {
10104
9979
  const providedKey = _providedKey;
@@ -10108,8 +9983,7 @@ class WorkspaceProject {
10108
9983
  );
10109
9984
  }
10110
9985
  this.closingPromise = void 0;
10111
- this.testProject = new TestProject(this);
10112
- this.server = server;
9986
+ this._vite = server;
10113
9987
  this.vitenode = new ViteNodeServer(server, this.config.server);
10114
9988
  const node = this.vitenode;
10115
9989
  this.runner = new ViteNodeRunner({
@@ -10123,51 +9997,325 @@ class WorkspaceProject {
10123
9997
  }
10124
9998
  });
10125
9999
  }
10126
- isBrowserEnabled() {
10127
- return isBrowserEnabled(this.config);
10128
- }
10129
- getSerializableConfig() {
10000
+ _serializeOverridenConfig() {
10130
10001
  const config = serializeConfig(
10131
10002
  this.config,
10132
- this.ctx.config,
10133
- this.server.config
10003
+ this.vitest.config,
10004
+ this.vite.config
10134
10005
  );
10135
- if (!this.ctx.configOverride) {
10006
+ if (!this.vitest.configOverride) {
10136
10007
  return config;
10137
10008
  }
10138
10009
  return deepMerge(
10139
10010
  config,
10140
- this.ctx.configOverride
10011
+ this.vitest.configOverride
10141
10012
  );
10142
10013
  }
10143
- close() {
10144
- if (!this.closingPromise) {
10145
- this.closingPromise = Promise.all(
10146
- [
10147
- this.server?.close(),
10148
- this.typechecker?.stop(),
10149
- this.browser?.close(),
10150
- this.clearTmpDir()
10151
- ].filter(Boolean)
10152
- ).then(() => this._provided = {});
10153
- }
10154
- return this.closingPromise;
10155
- }
10156
10014
  async clearTmpDir() {
10157
10015
  try {
10158
10016
  await rm(this.tmpDir, { recursive: true });
10159
10017
  } catch {
10160
10018
  }
10161
10019
  }
10162
- async initBrowserProvider() {
10020
+ /** @deprecated */
10021
+ initBrowserProvider() {
10022
+ return this._initBrowserProvider();
10023
+ }
10024
+ /** @internal */
10025
+ async _initBrowserProvider() {
10163
10026
  if (!this.isBrowserEnabled() || this.browser?.provider) {
10164
10027
  return;
10165
10028
  }
10166
10029
  if (!this.browser) {
10167
- await this.initBrowserServer();
10030
+ await this._initBrowserServer();
10168
10031
  }
10169
10032
  await this.browser?.initBrowserProvider();
10170
10033
  }
10034
+ /** @internal */
10035
+ static _createBasicProject(vitest) {
10036
+ const project = new TestProject(
10037
+ vitest.config.name || vitest.config.root,
10038
+ vitest
10039
+ );
10040
+ project.vitenode = vitest.vitenode;
10041
+ project.runner = vitest.runner;
10042
+ project._vite = vitest.server;
10043
+ project._config = vitest.config;
10044
+ for (const _providedKey in vitest.config.provide) {
10045
+ const providedKey = _providedKey;
10046
+ project.provide(
10047
+ providedKey,
10048
+ vitest.config.provide[providedKey]
10049
+ );
10050
+ }
10051
+ return project;
10052
+ }
10053
+ }
10054
+ async function initializeProject(workspacePath, ctx, options) {
10055
+ const project = new TestProject(workspacePath, ctx, options);
10056
+ const { extends: extendsConfig, workspaceConfigPath, ...restOptions } = options;
10057
+ const root = options.root || (typeof workspacePath === "number" ? void 0 : workspacePath.endsWith("/") ? workspacePath : dirname(workspacePath));
10058
+ const configFile = extendsConfig ? resolve(dirname(workspaceConfigPath), extendsConfig) : typeof workspacePath === "number" || workspacePath.endsWith("/") ? false : workspacePath;
10059
+ const config = {
10060
+ ...restOptions,
10061
+ root,
10062
+ configFile,
10063
+ // this will make "mode": "test" | "benchmark" inside defineConfig
10064
+ mode: options.test?.mode || options.mode || ctx.config.mode,
10065
+ plugins: [
10066
+ ...options.plugins || [],
10067
+ WorkspaceVitestPlugin(project, { ...options, root, workspacePath })
10068
+ ]
10069
+ };
10070
+ await createViteServer(config);
10071
+ return project;
10072
+ }
10073
+
10074
+ async function loadCustomReporterModule(path, runner) {
10075
+ let customReporterModule;
10076
+ try {
10077
+ customReporterModule = await runner.executeId(path);
10078
+ } catch (customReporterModuleError) {
10079
+ throw new Error(`Failed to load custom Reporter from ${path}`, {
10080
+ cause: customReporterModuleError
10081
+ });
10082
+ }
10083
+ if (customReporterModule.default === null || customReporterModule.default === void 0) {
10084
+ throw new Error(
10085
+ `Custom reporter loaded from ${path} was not the default export`
10086
+ );
10087
+ }
10088
+ return customReporterModule.default;
10089
+ }
10090
+ function createReporters(reporterReferences, ctx) {
10091
+ const runner = ctx.runner;
10092
+ const promisedReporters = reporterReferences.map(
10093
+ async (referenceOrInstance) => {
10094
+ if (Array.isArray(referenceOrInstance)) {
10095
+ const [reporterName, reporterOptions] = referenceOrInstance;
10096
+ if (reporterName === "html") {
10097
+ await ctx.packageInstaller.ensureInstalled("@vitest/ui", runner.root, ctx.version);
10098
+ const CustomReporter = await loadCustomReporterModule(
10099
+ "@vitest/ui/reporter",
10100
+ runner
10101
+ );
10102
+ return new CustomReporter(reporterOptions);
10103
+ } else if (reporterName in ReportersMap) {
10104
+ const BuiltinReporter = ReportersMap[reporterName];
10105
+ return new BuiltinReporter(reporterOptions);
10106
+ } else {
10107
+ const CustomReporter = await loadCustomReporterModule(
10108
+ reporterName,
10109
+ runner
10110
+ );
10111
+ return new CustomReporter(reporterOptions);
10112
+ }
10113
+ }
10114
+ return referenceOrInstance;
10115
+ }
10116
+ );
10117
+ return Promise.all(promisedReporters);
10118
+ }
10119
+ function createBenchmarkReporters(reporterReferences, runner) {
10120
+ const promisedReporters = reporterReferences.map(
10121
+ async (referenceOrInstance) => {
10122
+ if (typeof referenceOrInstance === "string") {
10123
+ if (referenceOrInstance in BenchmarkReportsMap) {
10124
+ const BuiltinReporter = BenchmarkReportsMap[referenceOrInstance];
10125
+ return new BuiltinReporter();
10126
+ } else {
10127
+ const CustomReporter = await loadCustomReporterModule(
10128
+ referenceOrInstance,
10129
+ runner
10130
+ );
10131
+ return new CustomReporter();
10132
+ }
10133
+ }
10134
+ return referenceOrInstance;
10135
+ }
10136
+ );
10137
+ return Promise.all(promisedReporters);
10138
+ }
10139
+
10140
+ function isAggregateError(err) {
10141
+ if (typeof AggregateError !== "undefined" && err instanceof AggregateError) {
10142
+ return true;
10143
+ }
10144
+ return err instanceof Error && "errors" in err;
10145
+ }
10146
+ class StateManager {
10147
+ filesMap = /* @__PURE__ */ new Map();
10148
+ pathsSet = /* @__PURE__ */ new Set();
10149
+ idMap = /* @__PURE__ */ new Map();
10150
+ taskFileMap = /* @__PURE__ */ new WeakMap();
10151
+ errorsSet = /* @__PURE__ */ new Set();
10152
+ processTimeoutCauses = /* @__PURE__ */ new Set();
10153
+ reportedTasksMap = /* @__PURE__ */ new WeakMap();
10154
+ catchError(err, type) {
10155
+ if (isAggregateError(err)) {
10156
+ return err.errors.forEach((error) => this.catchError(error, type));
10157
+ }
10158
+ if (err === Object(err)) {
10159
+ err.type = type;
10160
+ } else {
10161
+ err = { type, message: err };
10162
+ }
10163
+ const _err = err;
10164
+ if (_err && typeof _err === "object" && _err.code === "VITEST_PENDING") {
10165
+ const task = this.idMap.get(_err.taskId);
10166
+ if (task) {
10167
+ task.mode = "skip";
10168
+ task.result ??= { state: "skip" };
10169
+ task.result.state = "skip";
10170
+ task.result.note = _err.note;
10171
+ }
10172
+ return;
10173
+ }
10174
+ this.errorsSet.add(err);
10175
+ }
10176
+ clearErrors() {
10177
+ this.errorsSet.clear();
10178
+ }
10179
+ getUnhandledErrors() {
10180
+ return Array.from(this.errorsSet.values());
10181
+ }
10182
+ addProcessTimeoutCause(cause) {
10183
+ this.processTimeoutCauses.add(cause);
10184
+ }
10185
+ getProcessTimeoutCauses() {
10186
+ return Array.from(this.processTimeoutCauses.values());
10187
+ }
10188
+ getPaths() {
10189
+ return Array.from(this.pathsSet);
10190
+ }
10191
+ /**
10192
+ * Return files that were running or collected.
10193
+ */
10194
+ getFiles(keys) {
10195
+ if (keys) {
10196
+ return keys.map((key) => this.filesMap.get(key)).flat().filter((file) => file && !file.local);
10197
+ }
10198
+ return Array.from(this.filesMap.values()).flat().filter((file) => !file.local).sort((f1, f2) => {
10199
+ if (f1.meta?.typecheck && f2.meta?.typecheck) {
10200
+ return 0;
10201
+ }
10202
+ if (f1.meta?.typecheck) {
10203
+ return -1;
10204
+ }
10205
+ return 1;
10206
+ });
10207
+ }
10208
+ getTestModules(keys) {
10209
+ return this.getFiles(keys).map((file) => this.getReportedEntity(file));
10210
+ }
10211
+ getFilepaths() {
10212
+ return Array.from(this.filesMap.keys());
10213
+ }
10214
+ getFailedFilepaths() {
10215
+ return this.getFiles().filter((i) => i.result?.state === "fail").map((i) => i.filepath);
10216
+ }
10217
+ collectPaths(paths = []) {
10218
+ paths.forEach((path) => {
10219
+ this.pathsSet.add(path);
10220
+ });
10221
+ }
10222
+ collectFiles(project, files = []) {
10223
+ files.forEach((file) => {
10224
+ const existing = this.filesMap.get(file.filepath) || [];
10225
+ const otherFiles = existing.filter(
10226
+ (i) => i.projectName !== file.projectName || i.meta.typecheck !== file.meta.typecheck
10227
+ );
10228
+ const currentFile = existing.find(
10229
+ (i) => i.projectName === file.projectName
10230
+ );
10231
+ if (currentFile) {
10232
+ file.logs = currentFile.logs;
10233
+ }
10234
+ otherFiles.push(file);
10235
+ this.filesMap.set(file.filepath, otherFiles);
10236
+ this.updateId(file, project);
10237
+ });
10238
+ }
10239
+ clearFiles(project, paths = []) {
10240
+ paths.forEach((path) => {
10241
+ const files = this.filesMap.get(path);
10242
+ const fileTask = createFileTask(
10243
+ path,
10244
+ project.config.root,
10245
+ project.config.name
10246
+ );
10247
+ fileTask.local = true;
10248
+ TestModule.register(fileTask, project);
10249
+ this.idMap.set(fileTask.id, fileTask);
10250
+ if (!files) {
10251
+ this.filesMap.set(path, [fileTask]);
10252
+ return;
10253
+ }
10254
+ const filtered = files.filter(
10255
+ (file) => file.projectName !== project.config.name
10256
+ );
10257
+ if (!filtered.length) {
10258
+ this.filesMap.set(path, [fileTask]);
10259
+ } else {
10260
+ this.filesMap.set(path, [...filtered, fileTask]);
10261
+ }
10262
+ });
10263
+ }
10264
+ updateId(task, project) {
10265
+ if (this.idMap.get(task.id) === task) {
10266
+ return;
10267
+ }
10268
+ if (task.type === "suite" && "filepath" in task) {
10269
+ TestModule.register(task, project);
10270
+ } else if (task.type === "suite") {
10271
+ TestSuite.register(task, project);
10272
+ } else {
10273
+ TestCase.register(task, project);
10274
+ }
10275
+ this.idMap.set(task.id, task);
10276
+ if (task.type === "suite") {
10277
+ task.tasks.forEach((task2) => {
10278
+ this.updateId(task2, project);
10279
+ });
10280
+ }
10281
+ }
10282
+ getReportedEntity(task) {
10283
+ return this.reportedTasksMap.get(task);
10284
+ }
10285
+ updateTasks(packs) {
10286
+ for (const [id, result, meta] of packs) {
10287
+ const task = this.idMap.get(id);
10288
+ if (task) {
10289
+ task.result = result;
10290
+ task.meta = meta;
10291
+ if (result?.state === "skip") {
10292
+ task.mode = "skip";
10293
+ }
10294
+ }
10295
+ }
10296
+ }
10297
+ updateUserLog(log) {
10298
+ const task = log.taskId && this.idMap.get(log.taskId);
10299
+ if (task) {
10300
+ if (!task.logs) {
10301
+ task.logs = [];
10302
+ }
10303
+ task.logs.push(log);
10304
+ }
10305
+ }
10306
+ getCountOfFailedTests() {
10307
+ return Array.from(this.idMap.values()).filter(
10308
+ (t) => t.result?.state === "fail"
10309
+ ).length;
10310
+ }
10311
+ cancelFiles(files, project) {
10312
+ this.collectFiles(
10313
+ project,
10314
+ files.map(
10315
+ (filepath) => createFileTask(filepath, project.config.root, project.config.name)
10316
+ )
10317
+ );
10318
+ }
10171
10319
  }
10172
10320
 
10173
10321
  const ESCAPE_SYMBOL = "\\";
@@ -10208,7 +10356,7 @@ function hasBraceExpansion(pattern) {
10208
10356
  }
10209
10357
 
10210
10358
  async function resolveWorkspace(vitest, cliOptions, workspaceConfigPath, workspaceDefinition) {
10211
- const { configFiles, projectConfigs, nonConfigDirectories } = await resolveWorkspaceProjectConfigs(
10359
+ const { configFiles, projectConfigs, nonConfigDirectories } = await resolveTestProjectConfigs(
10212
10360
  vitest,
10213
10361
  workspaceConfigPath,
10214
10362
  workspaceDefinition
@@ -10275,9 +10423,9 @@ async function resolveWorkspace(vitest, cliOptions, workspaceConfigPath, workspa
10275
10423
  ].join("") : [" "];
10276
10424
  throw new Error([
10277
10425
  `Project name "${name}"`,
10278
- project.server.config.configFile ? ` from "${relative(vitest.config.root, project.server.config.configFile)}"` : "",
10426
+ project.vite.config.configFile ? ` from "${relative(vitest.config.root, project.vite.config.configFile)}"` : "",
10279
10427
  " is not unique.",
10280
- duplicate?.server.config.configFile ? ` The project is already defined by "${relative(vitest.config.root, duplicate.server.config.configFile)}".` : "",
10428
+ duplicate?.vite.config.configFile ? ` The project is already defined by "${relative(vitest.config.root, duplicate.vite.config.configFile)}".` : "",
10281
10429
  filesError,
10282
10430
  "All projects in a workspace should have unique names. Make sure your configuration is correct."
10283
10431
  ].join(""));
@@ -10286,7 +10434,7 @@ async function resolveWorkspace(vitest, cliOptions, workspaceConfigPath, workspa
10286
10434
  }
10287
10435
  return resolvedProjects;
10288
10436
  }
10289
- async function resolveWorkspaceProjectConfigs(vitest, workspaceConfigPath, workspaceDefinition) {
10437
+ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, workspaceDefinition) {
10290
10438
  const projectsOptions = [];
10291
10439
  const workspaceConfigFiles = [];
10292
10440
  const workspaceGlobMatches = [];
@@ -10405,6 +10553,7 @@ class Vitest {
10405
10553
  restartsCount = 0;
10406
10554
  runner = void 0;
10407
10555
  packageInstaller;
10556
+ /** @internal */
10408
10557
  coreWorkspaceProject;
10409
10558
  /** @private */
10410
10559
  resolvedProjects = [];
@@ -10492,7 +10641,7 @@ class Vitest {
10492
10641
  );
10493
10642
  }
10494
10643
  if (!this.coreWorkspaceProject) {
10495
- this.coreWorkspaceProject = WorkspaceProject.createBasicProject(this);
10644
+ this.coreWorkspaceProject = TestProject._createBasicProject(this);
10496
10645
  }
10497
10646
  if (this.config.testNamePattern) {
10498
10647
  this.configOverride.testNamePattern = this.config.testNamePattern;
@@ -10500,22 +10649,19 @@ class Vitest {
10500
10649
  await Promise.all(this._onSetServer.map((fn) => fn()));
10501
10650
  }
10502
10651
  provide(key, value) {
10503
- this.getCoreWorkspaceProject().provide(key, value);
10504
- }
10505
- /**
10506
- * @deprecated internal, use `_createCoreProject` instead
10507
- */
10508
- createCoreProject() {
10509
- return this._createCoreProject();
10652
+ this.getRootTestProject().provide(key, value);
10510
10653
  }
10511
10654
  /**
10512
10655
  * @internal
10513
10656
  */
10514
- async _createCoreProject() {
10515
- this.coreWorkspaceProject = await WorkspaceProject.createCoreProject(this);
10657
+ _createCoreProject() {
10658
+ this.coreWorkspaceProject = TestProject._createBasicProject(this);
10516
10659
  return this.coreWorkspaceProject;
10517
10660
  }
10518
- getCoreWorkspaceProject() {
10661
+ getRootTestProject() {
10662
+ if (!this.coreWorkspaceProject) {
10663
+ throw new Error(`Root project is not initialized. This means that the Vite server was not established yet and the the workspace config is not resolved.`);
10664
+ }
10519
10665
  return this.coreWorkspaceProject;
10520
10666
  }
10521
10667
  /**
@@ -10524,10 +10670,10 @@ class Vitest {
10524
10670
  getProjectByTaskId(taskId) {
10525
10671
  const task = this.state.idMap.get(taskId);
10526
10672
  const projectName = task.projectName || task?.file?.projectName || "";
10527
- return this.projects.find((p) => p.getName() === projectName) || this.getCoreWorkspaceProject() || this.projects[0];
10673
+ return this.projects.find((p) => p.name === projectName) || this.getRootTestProject() || this.projects[0];
10528
10674
  }
10529
10675
  getProjectByName(name = "") {
10530
- return this.projects.find((p) => p.getName() === name) || this.getCoreWorkspaceProject() || this.projects[0];
10676
+ return this.projects.find((p) => p.name === name) || this.coreWorkspaceProject || this.projects[0];
10531
10677
  }
10532
10678
  async getWorkspaceConfigPath() {
10533
10679
  if (this.config.workspace) {
@@ -10547,7 +10693,7 @@ class Vitest {
10547
10693
  const workspaceConfigPath = await this.getWorkspaceConfigPath();
10548
10694
  this._workspaceConfigPath = workspaceConfigPath;
10549
10695
  if (!workspaceConfigPath) {
10550
- return [await this._createCoreProject()];
10696
+ return [this._createCoreProject()];
10551
10697
  }
10552
10698
  const workspaceModule = await this.runner.executeFile(workspaceConfigPath);
10553
10699
  if (!workspaceModule.default || !Array.isArray(workspaceModule.default)) {
@@ -10689,21 +10835,21 @@ class Vitest {
10689
10835
  return;
10690
10836
  }
10691
10837
  deps.add(filepath);
10692
- const mod = project.server.moduleGraph.getModuleById(filepath);
10838
+ const mod = project.vite.moduleGraph.getModuleById(filepath);
10693
10839
  const transformed = mod?.ssrTransformResult || await project.vitenode.transformRequest(filepath);
10694
10840
  if (!transformed) {
10695
10841
  return;
10696
10842
  }
10697
10843
  const dependencies = [...transformed.deps || [], ...transformed.dynamicDeps || []];
10698
10844
  await Promise.all(dependencies.map(async (dep) => {
10699
- const path = await project.server.pluginContainer.resolveId(dep, filepath, { ssr: true });
10845
+ const path = await project.vite.pluginContainer.resolveId(dep, filepath, { ssr: true });
10700
10846
  const fsPath = path && !path.external && path.id.split("?")[0];
10701
10847
  if (fsPath && !fsPath.includes("node_modules") && !deps.has(fsPath) && existsSync(fsPath)) {
10702
10848
  await addImports(project, fsPath);
10703
10849
  }
10704
10850
  }));
10705
10851
  };
10706
- await addImports(spec.project.workspaceProject, spec.moduleId);
10852
+ await addImports(spec.project, spec.moduleId);
10707
10853
  deps.delete(spec.moduleId);
10708
10854
  return deps;
10709
10855
  }
@@ -10759,24 +10905,23 @@ class Vitest {
10759
10905
  const specs = [];
10760
10906
  for (const project of this.projects) {
10761
10907
  if (project.isTestFile(file)) {
10762
- const pool = getFilePoolName(project, file);
10763
- specs.push(project.createSpec(file, pool));
10908
+ specs.push(project.createSpecification(file));
10764
10909
  }
10765
10910
  if (project.isTypecheckFile(file)) {
10766
- specs.push(project.createSpec(file, "typescript"));
10911
+ specs.push(project.createSpecification(file, "typescript"));
10767
10912
  }
10768
10913
  }
10769
10914
  specs.forEach((spec) => this.ensureSpecCached(spec));
10770
10915
  return specs;
10771
10916
  }
10772
10917
  async initializeGlobalSetup(paths) {
10773
- const projects = new Set(paths.map((spec) => spec.project.workspaceProject));
10774
- const coreProject = this.getCoreWorkspaceProject();
10918
+ const projects = new Set(paths.map((spec) => spec.project));
10919
+ const coreProject = this.getRootTestProject();
10775
10920
  if (!projects.has(coreProject)) {
10776
10921
  projects.add(coreProject);
10777
10922
  }
10778
10923
  for (const project of projects) {
10779
- await project.initializeGlobalSetup();
10924
+ await project._initializeGlobalSetup();
10780
10925
  }
10781
10926
  }
10782
10927
  async runFiles(specs, allTestsRun) {
@@ -10860,9 +11005,12 @@ class Vitest {
10860
11005
  await Promise.all(this._onCancelListeners.splice(0).map((listener) => listener(reason)));
10861
11006
  }
10862
11007
  async initBrowserServers() {
10863
- await Promise.all(this.projects.map((p) => p.initBrowserServer()));
11008
+ await Promise.all(this.projects.map((p) => p._initBrowserServer()));
10864
11009
  }
10865
- async rerunFiles(files = this.state.getFilepaths(), trigger, allTestsRun = true) {
11010
+ async rerunFiles(files = this.state.getFilepaths(), trigger, allTestsRun = true, resetTestNamePattern = false) {
11011
+ if (resetTestNamePattern) {
11012
+ this.configOverride.testNamePattern = void 0;
11013
+ }
10866
11014
  if (this.filenamePattern) {
10867
11015
  const filteredFiles = await this.globTestFiles([this.filenamePattern]);
10868
11016
  files = files.filter((file) => filteredFiles.some((f) => f[1] === file));
@@ -10874,6 +11022,20 @@ class Vitest {
10874
11022
  await this.runFiles(files.flatMap((file) => this.getProjectsByTestFile(file)), allTestsRun);
10875
11023
  await this.report("onWatcherStart", this.state.getFiles(files));
10876
11024
  }
11025
+ isSuite(task) {
11026
+ return Object.hasOwnProperty.call(task, "tasks");
11027
+ }
11028
+ async rerunTask(id) {
11029
+ const task = this.state.idMap.get(id);
11030
+ if (!task) {
11031
+ throw new Error(`Task ${id} was not found`);
11032
+ }
11033
+ await this.changeNamePattern(
11034
+ task.name,
11035
+ [task.file.filepath],
11036
+ this.isSuite(task) ? "rerun suite" : "rerun test"
11037
+ );
11038
+ }
10877
11039
  async changeProjectName(pattern) {
10878
11040
  if (pattern === "") {
10879
11041
  delete this.configOverride.project;
@@ -11018,13 +11180,14 @@ class Vitest {
11018
11180
  onAdd = async (id) => {
11019
11181
  id = slash(id);
11020
11182
  this.updateLastChanged(id);
11183
+ const fileContent = readFileSync(id, "utf-8");
11021
11184
  const matchingProjects = [];
11022
- await Promise.all(this.projects.map(async (project) => {
11023
- if (await project.isTargetFile(id)) {
11185
+ this.projects.forEach((project) => {
11186
+ if (project.matchesTestGlob(id, fileContent)) {
11024
11187
  matchingProjects.push(project);
11025
- project.testFilesList?.push(id);
11188
+ project._markTestFile(id);
11026
11189
  }
11027
- }));
11190
+ });
11028
11191
  if (matchingProjects.length > 0) {
11029
11192
  this.changedTests.add(id);
11030
11193
  this.scheduleRerun([id]);
@@ -11128,10 +11291,10 @@ class Vitest {
11128
11291
  if (!teardownProjects.includes(this.coreWorkspaceProject)) {
11129
11292
  teardownProjects.push(this.coreWorkspaceProject);
11130
11293
  }
11131
- for await (const project of teardownProjects.reverse()) {
11132
- await project.teardownGlobalSetup();
11294
+ for (const project of teardownProjects.reverse()) {
11295
+ await project._teardownGlobalSetup();
11133
11296
  }
11134
- const closePromises = this.resolvedProjects.map((w) => w.close().then(() => w.server = void 0));
11297
+ const closePromises = this.resolvedProjects.map((w) => w.close());
11135
11298
  if (!this.resolvedProjects.includes(this.coreWorkspaceProject)) {
11136
11299
  closePromises.push(this.coreWorkspaceProject.close().then(() => this.server = void 0));
11137
11300
  }
@@ -11194,13 +11357,12 @@ class Vitest {
11194
11357
  await Promise.all(this.projects.map(async (project) => {
11195
11358
  const { testFiles, typecheckTestFiles } = await project.globTestFiles(filters);
11196
11359
  testFiles.forEach((file) => {
11197
- const pool = getFilePoolName(project, file);
11198
- const spec = project.createSpec(file, pool);
11360
+ const spec = project.createSpecification(file);
11199
11361
  this.ensureSpecCached(spec);
11200
11362
  files.push(spec);
11201
11363
  });
11202
11364
  typecheckTestFiles.forEach((file) => {
11203
- const spec = project.createSpec(file, "typescript");
11365
+ const spec = project.createSpecification(file, "typescript");
11204
11366
  this.ensureSpecCached(spec);
11205
11367
  files.push(spec);
11206
11368
  });
@@ -11208,7 +11370,7 @@ class Vitest {
11208
11370
  return files;
11209
11371
  }
11210
11372
  /**
11211
- * @deprecated use globTestSpecs instead
11373
+ * @deprecated use `globTestSpecs` instead
11212
11374
  */
11213
11375
  async globTestFiles(filters = []) {
11214
11376
  return this.globTestSpecs(filters);
@@ -11329,7 +11491,9 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
11329
11491
  forks: {
11330
11492
  isolate: options.poolOptions?.forks?.isolate ?? options.isolate ?? testConfig.poolOptions?.forks?.isolate ?? viteConfig.test?.isolate
11331
11493
  }
11332
- }
11494
+ },
11495
+ root: testConfig.root ?? viteConfig.test?.root,
11496
+ deps: testConfig.deps ?? viteConfig.test?.deps
11333
11497
  }
11334
11498
  };
11335
11499
  config.customLogger = createViteLogger(