vitest 2.2.0-beta.2 → 3.0.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.
- package/LICENSE.md +75 -0
- package/dist/browser.d.ts +13 -10
- package/dist/browser.js +2 -2
- package/dist/chunks/{RandomSequencer.BPedXEug.js → RandomSequencer.gisBJ77r.js} +11 -4
- package/dist/chunks/{base.BS0HhLXd.js → base.CUgXReRN.js} +8 -3
- package/dist/chunks/{cac.Cs06pOqp.js → cac.Xzv7eNWw.js} +22 -17
- package/dist/chunks/{cli-api.CB-jIbYQ.js → cli-api.CETCDGgZ.js} +985 -498
- package/dist/chunks/{config.CPguQ7J1.d.ts → config.BTPBhmK5.d.ts} +1 -1
- package/dist/chunks/{coverage.BoMDb1ip.js → coverage.BWeNbfBa.js} +4 -4
- package/dist/chunks/{creator.IIqd8RWT.js → creator.DcAcUhMD.js} +1 -4
- package/dist/chunks/{environment.CT0jpO-1.d.ts → environment.d8YfPkTm.d.ts} +1 -3
- package/dist/chunks/{globals.BCGEw6ON.js → globals.BFncSRNA.js} +2 -2
- package/dist/chunks/{index.bzFpKeaq.js → index.9ZEBV_TJ.js} +992 -577
- package/dist/chunks/{index.DD5eTY2y.js → index.CkWmZCXU.js} +1 -1
- package/dist/chunks/{index.CqYx2Nsr.js → index.DQboAxJm.js} +23 -14
- package/dist/chunks/{index.BjjsHdBb.js → index.DoV7W5gc.js} +2 -2
- package/dist/chunks/{inspector.70d6emsh.js → inspector.DKLceBVD.js} +1 -1
- package/dist/chunks/{reporters.F9D2idOT.d.ts → reporters.DTtxC3KQ.d.ts} +588 -524
- package/dist/chunks/{resolveConfig.CLnvCvEs.js → resolveConfig.BA-_OKEx.js} +5599 -5570
- package/dist/chunks/{runBaseTests.B7hcVT-s.js → runBaseTests.D0dWpzZV.js} +13 -12
- package/dist/chunks/{setup-common.BfGt8K-K.js → setup-common.Cp_bu5q3.js} +1 -1
- package/dist/chunks/types.BOjykUpq.d.ts +27 -0
- package/dist/chunks/{utils.DJONn5B5.js → utils.CMUTX-p8.js} +5 -2
- package/dist/chunks/{vi.BlPttogV.js → vi.S4Fq8wSo.js} +20 -14
- package/dist/chunks/{vite.DonA4fvH.d.ts → vite.CXaetSK3.d.ts} +1 -1
- package/dist/chunks/{vm.Zr4qWzDJ.js → vm.DGhTouO3.js} +10 -1
- package/dist/chunks/{worker.Qz1UB4Fv.d.ts → worker.ClntunZp.d.ts} +1 -1
- package/dist/chunks/{worker.9VY11NZs.d.ts → worker.o1PBoDdo.d.ts} +4 -4
- package/dist/cli.js +1 -1
- package/dist/config.cjs +1 -10
- package/dist/config.d.ts +7 -10
- package/dist/config.js +1 -10
- package/dist/coverage.d.ts +5 -7
- package/dist/coverage.js +4 -4
- package/dist/environments.d.ts +2 -2
- package/dist/execute.d.ts +4 -4
- package/dist/index.d.ts +27 -22
- package/dist/index.js +2 -2
- package/dist/node.d.ts +25 -33
- package/dist/node.js +66 -32
- package/dist/reporters.d.ts +5 -7
- package/dist/reporters.js +5 -4
- package/dist/runners.d.ts +3 -4
- package/dist/runners.js +9 -14
- package/dist/suite.d.ts +1 -1
- package/dist/worker.js +1 -1
- package/dist/workers/forks.js +1 -1
- package/dist/workers/runVmTests.js +9 -9
- package/dist/workers/threads.js +1 -1
- package/dist/workers/vmForks.js +1 -1
- package/dist/workers/vmThreads.js +1 -1
- package/dist/workers.d.ts +4 -4
- package/dist/workers.js +3 -3
- package/package.json +23 -24
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { existsSync, promises, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { createFileTask, limitConcurrency, getTasks, hasFailed, getTests, getNames } from '@vitest/runner/utils';
|
|
3
2
|
import { normalize, relative, dirname, resolve, join, basename, isAbsolute } from 'pathe';
|
|
4
|
-
import { g as getCoverageProvider, C as CoverageProviderMap } from './coverage.
|
|
3
|
+
import { g as getCoverageProvider, C as CoverageProviderMap } from './coverage.BWeNbfBa.js';
|
|
5
4
|
import a, { resolve as resolve$1 } from 'node:path';
|
|
6
5
|
import { noop, isPrimitive, toArray, deepMerge, nanoid, slash, notNullish, createDefer } from '@vitest/utils';
|
|
7
6
|
import { f as findUp, p as prompt } from './index.BJDntFik.js';
|
|
8
7
|
import { searchForWorkspaceRoot, version, createServer, mergeConfig } from 'vite';
|
|
9
8
|
import { A as API_PATH, c as configFiles, a as defaultBrowserPort, w as workspacesFiles, d as defaultPort } from './constants.fzPh7AOq.js';
|
|
9
|
+
import { createFileTask, limitConcurrency, getTasks, hasFailed, getTests } from '@vitest/runner/utils';
|
|
10
10
|
import { SnapshotManager } from '@vitest/snapshot/manager';
|
|
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
11
|
import { ViteNodeRunner } from 'vite-node/client';
|
|
13
12
|
import { ViteNodeServer } from 'vite-node/server';
|
|
14
|
-
import { v as version$1 } from './cac.
|
|
13
|
+
import { v as version$1 } from './cac.Xzv7eNWw.js';
|
|
15
14
|
import { c as createBirpc } from './index.68735LiX.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.
|
|
15
|
+
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.9ZEBV_TJ.js';
|
|
17
16
|
import require$$0$2 from 'stream';
|
|
18
17
|
import require$$0 from 'zlib';
|
|
19
18
|
import require$$0$1 from 'buffer';
|
|
@@ -27,10 +26,11 @@ import require$$7 from 'url';
|
|
|
27
26
|
import { g as getDefaultExportFromCjs, c as commonjsGlobal } from './_commonjsHelpers.BFTU3MAI.js';
|
|
28
27
|
import { parseErrorStacktrace } from '@vitest/utils/source-map';
|
|
29
28
|
import { distDir, rootDir } from '../path.js';
|
|
29
|
+
import { i as isPackageExists, e as requireMicromatch, V as VitestCache, f as configDefaults, g as getFilePoolName, h as isBrowserEnabled, m as mm, a as resolveConfig, j as groupBy, w as wildcardPatternToRegExp, k as createPool, b as resolveApiServerConfig, c as coverageConfigDefaults, s as stdout } from './resolveConfig.BA-_OKEx.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.
|
|
33
|
+
import { h as hash, i as isWindows } from './RandomSequencer.gisBJ77r.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';
|
|
@@ -4931,7 +4931,7 @@ function setup(ctx, _server) {
|
|
|
4931
4931
|
await ctx.rerunTask(id);
|
|
4932
4932
|
},
|
|
4933
4933
|
getConfig() {
|
|
4934
|
-
return ctx.
|
|
4934
|
+
return ctx.getRootProject().serializedConfig;
|
|
4935
4935
|
},
|
|
4936
4936
|
async getTransformResult(projectName, id, browser = false) {
|
|
4937
4937
|
const project = ctx.getProjectByName(projectName);
|
|
@@ -4957,7 +4957,7 @@ function setup(ctx, _server) {
|
|
|
4957
4957
|
return ctx.state.getUnhandledErrors();
|
|
4958
4958
|
},
|
|
4959
4959
|
async getTestFiles() {
|
|
4960
|
-
const spec = await ctx.
|
|
4960
|
+
const spec = await ctx.globTestSpecifications();
|
|
4961
4961
|
return spec.map((spec2) => [
|
|
4962
4962
|
{
|
|
4963
4963
|
name: spec2.project.config.name,
|
|
@@ -5019,15 +5019,18 @@ class WebSocketReporter {
|
|
|
5019
5019
|
return;
|
|
5020
5020
|
}
|
|
5021
5021
|
packs.forEach(([taskId, result]) => {
|
|
5022
|
-
const project = this.ctx.getProjectByTaskId(taskId);
|
|
5023
5022
|
const task = this.ctx.state.idMap.get(taskId);
|
|
5024
5023
|
const isBrowser = task && task.file.pool === "browser";
|
|
5025
5024
|
result?.errors?.forEach((error) => {
|
|
5026
5025
|
if (isPrimitive(error)) {
|
|
5027
5026
|
return;
|
|
5028
5027
|
}
|
|
5029
|
-
|
|
5030
|
-
|
|
5028
|
+
if (isBrowser) {
|
|
5029
|
+
const project = this.ctx.getProjectByName(task.file.projectName || "");
|
|
5030
|
+
error.stacks = project.browser?.parseErrorStacktrace(error);
|
|
5031
|
+
} else {
|
|
5032
|
+
error.stacks = parseErrorStacktrace(error);
|
|
5033
|
+
}
|
|
5031
5034
|
});
|
|
5032
5035
|
});
|
|
5033
5036
|
this.clients.forEach((client) => {
|
|
@@ -5069,6 +5072,24 @@ class GitNotFoundError extends Error {
|
|
|
5069
5072
|
super("Could not find Git root. Have you initialized git with `git init`?");
|
|
5070
5073
|
}
|
|
5071
5074
|
}
|
|
5075
|
+
class LocationFilterFileNotFoundError extends Error {
|
|
5076
|
+
code = "VITEST_LOCATION_FILTER_FILE_NOT_FOUND";
|
|
5077
|
+
constructor(filename) {
|
|
5078
|
+
super(`Couldn't find file ${filename}. Note when specifying the test location you have to specify the full test filename.`);
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
5081
|
+
class IncludeTaskLocationDisabledError extends Error {
|
|
5082
|
+
code = "VITEST_INCLUDE_TASK_LOCATION_DISABLED";
|
|
5083
|
+
constructor() {
|
|
5084
|
+
super("Recieved line number filters while `includeTaskLocation` option is disabled");
|
|
5085
|
+
}
|
|
5086
|
+
}
|
|
5087
|
+
class RangeLocationFilterProvidedError extends Error {
|
|
5088
|
+
code = "VITEST_RANGE_LOCATION_FILTER_PROVIDED";
|
|
5089
|
+
constructor(filter) {
|
|
5090
|
+
super(`Found "-" in location filter ${filter}. Note that range location filters are not supported. Consider specifying the exact line numbers of your tests.`);
|
|
5091
|
+
}
|
|
5092
|
+
}
|
|
5072
5093
|
|
|
5073
5094
|
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
5074
5095
|
class VitestPackageInstaller {
|
|
@@ -5111,7 +5132,7 @@ class VitestPackageInstaller {
|
|
|
5111
5132
|
});
|
|
5112
5133
|
if (install) {
|
|
5113
5134
|
const packageName = version ? `${dependency}@${version}` : dependency;
|
|
5114
|
-
await (await import('./index.
|
|
5135
|
+
await (await import('./index.DQboAxJm.js')).installPackage(packageName, { dev: true });
|
|
5115
5136
|
process.stderr.write(
|
|
5116
5137
|
c.yellow(
|
|
5117
5138
|
`
|
|
@@ -8703,7 +8724,7 @@ function requireJsTokens () {
|
|
|
8703
8724
|
// Copyright 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Simon Lydell
|
|
8704
8725
|
// License: MIT.
|
|
8705
8726
|
var HashbangComment, Identifier, JSXIdentifier, JSXPunctuator, JSXString, JSXText, KeywordsWithExpressionAfter, KeywordsWithNoLineTerminatorAfter, LineTerminatorSequence, MultiLineComment, Newline, NumericLiteral, Punctuator, RegularExpressionLiteral, SingleLineComment, StringLiteral, Template, TokensNotPrecedingObjectLiteral, TokensPrecedingExpression, WhiteSpace;
|
|
8706
|
-
RegularExpressionLiteral = /\/(?![*\/])(?:\[(?:[^\]\\\n\r\u2028\u2029]+|\\.)*\]
|
|
8727
|
+
RegularExpressionLiteral = /\/(?![*\/])(?:\[(?:[^\]\\\n\r\u2028\u2029]+|\\.)*\]?|[^\/[\\\n\r\u2028\u2029]+|\\.)*(\/[$_\u200C\u200D\p{ID_Continue}]*|\\)?/yu;
|
|
8707
8728
|
Punctuator = /--|\+\+|=>|\.{3}|\??\.(?!\d)|(?:&&|\|\||\?\?|[+\-%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2}|\/(?![\/*]))=?|[?~,:;[\](){}]/y;
|
|
8708
8729
|
Identifier = /(\x23?)(?=[$_\p{ID_Start}\\])(?:[$_\u200C\u200D\p{ID_Continue}]+|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+/yu;
|
|
8709
8730
|
StringLiteral = /(['"])(?:[^'"\\\n\r]+|(?!\1)['"]|\\(?:\r\n|[^]))*(\1)?/y;
|
|
@@ -9461,8 +9482,8 @@ function WorkspaceVitestPlugin(project, options) {
|
|
|
9461
9482
|
middlewareMode: true,
|
|
9462
9483
|
fs: {
|
|
9463
9484
|
allow: resolveFsAllow(
|
|
9464
|
-
project.
|
|
9465
|
-
project.
|
|
9485
|
+
project.vitest.config.root,
|
|
9486
|
+
project.vitest.server.config.configFile
|
|
9466
9487
|
)
|
|
9467
9488
|
}
|
|
9468
9489
|
},
|
|
@@ -9540,17 +9561,31 @@ class TestSpecification {
|
|
|
9540
9561
|
* @deprecated use `pool` instead
|
|
9541
9562
|
*/
|
|
9542
9563
|
2;
|
|
9564
|
+
/**
|
|
9565
|
+
* The test project that the module belongs to.
|
|
9566
|
+
*/
|
|
9543
9567
|
project;
|
|
9568
|
+
/**
|
|
9569
|
+
* The ID of the module in the Vite module graph. It is usually an absolute file path.
|
|
9570
|
+
*/
|
|
9544
9571
|
moduleId;
|
|
9572
|
+
/**
|
|
9573
|
+
* The current test pool. It's possible to have multiple pools in a single test project with `poolMatchGlob` and `typecheck.enabled`.
|
|
9574
|
+
* @experimental In Vitest 4, the project will only support a single pool and this property will be removed.
|
|
9575
|
+
*/
|
|
9545
9576
|
pool;
|
|
9546
|
-
|
|
9547
|
-
|
|
9577
|
+
/**
|
|
9578
|
+
* Line numbers of the test locations to run.
|
|
9579
|
+
*/
|
|
9580
|
+
testLines;
|
|
9581
|
+
constructor(project, moduleId, pool, testLines) {
|
|
9548
9582
|
this[0] = project;
|
|
9549
9583
|
this[1] = moduleId;
|
|
9550
9584
|
this[2] = { pool };
|
|
9551
9585
|
this.project = project;
|
|
9552
9586
|
this.moduleId = moduleId;
|
|
9553
9587
|
this.pool = pool;
|
|
9588
|
+
this.testLines = testLines;
|
|
9554
9589
|
}
|
|
9555
9590
|
toJSON() {
|
|
9556
9591
|
return [
|
|
@@ -9559,7 +9594,7 @@ class TestSpecification {
|
|
|
9559
9594
|
root: this.project.config.root
|
|
9560
9595
|
},
|
|
9561
9596
|
this.moduleId,
|
|
9562
|
-
{ pool: this.pool }
|
|
9597
|
+
{ pool: this.pool, testLines: this.testLines }
|
|
9563
9598
|
];
|
|
9564
9599
|
}
|
|
9565
9600
|
/**
|
|
@@ -9613,9 +9648,11 @@ class TestProject {
|
|
|
9613
9648
|
* Temporary directory for the project. This is unique for each project. Vitest stores transformed content here.
|
|
9614
9649
|
*/
|
|
9615
9650
|
tmpDir = join(tmpdir(), nanoid());
|
|
9651
|
+
/** @internal */
|
|
9616
9652
|
vitenode;
|
|
9617
|
-
|
|
9653
|
+
/** @internal */
|
|
9618
9654
|
typechecker;
|
|
9655
|
+
runner;
|
|
9619
9656
|
closingPromise;
|
|
9620
9657
|
testFilesList = null;
|
|
9621
9658
|
typecheckFilesList = null;
|
|
@@ -9623,10 +9660,12 @@ class TestProject {
|
|
|
9623
9660
|
_provided = {};
|
|
9624
9661
|
_config;
|
|
9625
9662
|
_vite;
|
|
9663
|
+
// "provide" is a property, not a method to keep the context when destructed in the global setup,
|
|
9664
|
+
// making it a method would be a breaking change, and can be done in Vitest 3 at minimum
|
|
9626
9665
|
/**
|
|
9627
9666
|
* Provide a value to the test context. This value will be available to all tests with `inject`.
|
|
9628
9667
|
*/
|
|
9629
|
-
provide(key, value) {
|
|
9668
|
+
provide = (key, value) => {
|
|
9630
9669
|
try {
|
|
9631
9670
|
structuredClone(value);
|
|
9632
9671
|
} catch (err) {
|
|
@@ -9638,7 +9677,7 @@ class TestProject {
|
|
|
9638
9677
|
);
|
|
9639
9678
|
}
|
|
9640
9679
|
this._provided[key] = value;
|
|
9641
|
-
}
|
|
9680
|
+
};
|
|
9642
9681
|
/**
|
|
9643
9682
|
* Get the provided context. The project context is merged with the global context.
|
|
9644
9683
|
*/
|
|
@@ -9647,7 +9686,7 @@ class TestProject {
|
|
|
9647
9686
|
return this._provided;
|
|
9648
9687
|
}
|
|
9649
9688
|
return {
|
|
9650
|
-
...this.vitest.
|
|
9689
|
+
...this.vitest.getRootProject().getProvidedContext(),
|
|
9651
9690
|
...this._provided
|
|
9652
9691
|
};
|
|
9653
9692
|
}
|
|
@@ -9655,11 +9694,12 @@ class TestProject {
|
|
|
9655
9694
|
* Creates a new test specification. Specifications describe how to run tests.
|
|
9656
9695
|
* @param moduleId The file path
|
|
9657
9696
|
*/
|
|
9658
|
-
createSpecification(moduleId, pool) {
|
|
9697
|
+
createSpecification(moduleId, locations, pool) {
|
|
9659
9698
|
return new TestSpecification(
|
|
9660
9699
|
this,
|
|
9661
9700
|
moduleId,
|
|
9662
|
-
pool || getFilePoolName(this, moduleId)
|
|
9701
|
+
pool || getFilePoolName(this, moduleId),
|
|
9702
|
+
locations
|
|
9663
9703
|
);
|
|
9664
9704
|
}
|
|
9665
9705
|
toJSON() {
|
|
@@ -9707,7 +9747,7 @@ class TestProject {
|
|
|
9707
9747
|
* Check if this is the root project. The root project is the one that has the root config.
|
|
9708
9748
|
*/
|
|
9709
9749
|
isRootProject() {
|
|
9710
|
-
return this.vitest.
|
|
9750
|
+
return this.vitest.getRootProject() === this;
|
|
9711
9751
|
}
|
|
9712
9752
|
/** @deprecated use `isRootProject` instead */
|
|
9713
9753
|
isCore() {
|
|
@@ -9731,11 +9771,7 @@ class TestProject {
|
|
|
9731
9771
|
this.config.globalSetup
|
|
9732
9772
|
);
|
|
9733
9773
|
for (const globalSetupFile of this._globalSetups) {
|
|
9734
|
-
const teardown = await globalSetupFile.setup?.(
|
|
9735
|
-
provide: (key, value) => this.provide(key, value),
|
|
9736
|
-
config: this.config,
|
|
9737
|
-
onTestsRerun: (cb) => this.vitest.onTestsRerun(cb)
|
|
9738
|
-
});
|
|
9774
|
+
const teardown = await globalSetupFile.setup?.(this);
|
|
9739
9775
|
if (teardown == null || !!globalSetupFile.teardown) {
|
|
9740
9776
|
continue;
|
|
9741
9777
|
}
|
|
@@ -9747,6 +9783,9 @@ class TestProject {
|
|
|
9747
9783
|
globalSetupFile.teardown = teardown;
|
|
9748
9784
|
}
|
|
9749
9785
|
}
|
|
9786
|
+
onTestsRerun(cb) {
|
|
9787
|
+
this.vitest.onTestsRerun(cb);
|
|
9788
|
+
}
|
|
9750
9789
|
/** @deprecated */
|
|
9751
9790
|
teardownGlobalSetup() {
|
|
9752
9791
|
return this._teardownGlobalSetup();
|
|
@@ -9835,22 +9874,21 @@ class TestProject {
|
|
|
9835
9874
|
isBrowserEnabled() {
|
|
9836
9875
|
return isBrowserEnabled(this.config);
|
|
9837
9876
|
}
|
|
9838
|
-
|
|
9839
|
-
_markTestFile(testPath) {
|
|
9877
|
+
markTestFile(testPath) {
|
|
9840
9878
|
this.testFilesList?.push(testPath);
|
|
9841
9879
|
}
|
|
9842
9880
|
/**
|
|
9843
9881
|
* Returns if the file is a test file. Requires `.globTestFiles()` to be called first.
|
|
9844
9882
|
* @internal
|
|
9845
9883
|
*/
|
|
9846
|
-
|
|
9884
|
+
isCachedTestFile(testPath) {
|
|
9847
9885
|
return !!this.testFilesList && this.testFilesList.includes(testPath);
|
|
9848
9886
|
}
|
|
9849
9887
|
/**
|
|
9850
9888
|
* Returns if the file is a typecheck test file. Requires `.globTestFiles()` to be called first.
|
|
9851
9889
|
* @internal
|
|
9852
9890
|
*/
|
|
9853
|
-
|
|
9891
|
+
isCachedTypecheckFile(testPath) {
|
|
9854
9892
|
return !!this.typecheckFilesList && this.typecheckFilesList.includes(testPath);
|
|
9855
9893
|
}
|
|
9856
9894
|
/** @deprecated use `serializedConfig` instead */
|
|
@@ -9868,25 +9906,32 @@ class TestProject {
|
|
|
9868
9906
|
return files.map((file) => slash(a.resolve(cwd, file)));
|
|
9869
9907
|
}
|
|
9870
9908
|
/**
|
|
9871
|
-
* Test if a file matches the test globs. This does the actual glob matching unlike `
|
|
9909
|
+
* Test if a file matches the test globs. This does the actual glob matching if the test is not cached, unlike `isCachedTestFile`.
|
|
9872
9910
|
*/
|
|
9873
|
-
matchesTestGlob(
|
|
9874
|
-
|
|
9911
|
+
matchesTestGlob(moduleId, source) {
|
|
9912
|
+
if (this.isCachedTestFile(moduleId)) {
|
|
9913
|
+
return true;
|
|
9914
|
+
}
|
|
9915
|
+
const relativeId = relative(this.config.dir || this.config.root, moduleId);
|
|
9875
9916
|
if (mm.isMatch(relativeId, this.config.exclude)) {
|
|
9876
9917
|
return false;
|
|
9877
9918
|
}
|
|
9878
9919
|
if (mm.isMatch(relativeId, this.config.include)) {
|
|
9920
|
+
this.markTestFile(moduleId);
|
|
9879
9921
|
return true;
|
|
9880
9922
|
}
|
|
9881
9923
|
if (this.config.includeSource?.length && mm.isMatch(relativeId, this.config.includeSource)) {
|
|
9882
|
-
const code = source || readFileSync(
|
|
9883
|
-
|
|
9924
|
+
const code = source?.() || readFileSync(moduleId, "utf-8");
|
|
9925
|
+
if (this.isInSourceTestCode(code)) {
|
|
9926
|
+
this.markTestFile(moduleId);
|
|
9927
|
+
return true;
|
|
9928
|
+
}
|
|
9884
9929
|
}
|
|
9885
9930
|
return false;
|
|
9886
9931
|
}
|
|
9887
9932
|
/** @deprecated use `matchesTestGlob` instead */
|
|
9888
9933
|
async isTargetFile(id, source) {
|
|
9889
|
-
return this.matchesTestGlob(id, source);
|
|
9934
|
+
return this.matchesTestGlob(id, source ? () => source : void 0);
|
|
9890
9935
|
}
|
|
9891
9936
|
isInSourceTestCode(code) {
|
|
9892
9937
|
return code.includes("import.meta.vitest");
|
|
@@ -9956,6 +10001,13 @@ class TestProject {
|
|
|
9956
10001
|
}
|
|
9957
10002
|
return this.closingPromise;
|
|
9958
10003
|
}
|
|
10004
|
+
/**
|
|
10005
|
+
* Import a file using Vite module runner.
|
|
10006
|
+
* @param moduleId The ID of the module in Vite module graph
|
|
10007
|
+
*/
|
|
10008
|
+
import(moduleId) {
|
|
10009
|
+
return this.runner.executeId(moduleId);
|
|
10010
|
+
}
|
|
9959
10011
|
/** @deprecated use `name` instead */
|
|
9960
10012
|
getName() {
|
|
9961
10013
|
return this.config.name || "";
|
|
@@ -10053,18 +10105,15 @@ class TestProject {
|
|
|
10053
10105
|
}
|
|
10054
10106
|
async function initializeProject(workspacePath, ctx, options) {
|
|
10055
10107
|
const project = new TestProject(workspacePath, ctx, options);
|
|
10056
|
-
const { extends: extendsConfig,
|
|
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;
|
|
10108
|
+
const { extends: extendsConfig, configFile, ...restOptions } = options;
|
|
10059
10109
|
const config = {
|
|
10060
10110
|
...restOptions,
|
|
10061
|
-
root,
|
|
10062
10111
|
configFile,
|
|
10063
10112
|
// this will make "mode": "test" | "benchmark" inside defineConfig
|
|
10064
10113
|
mode: options.test?.mode || options.mode || ctx.config.mode,
|
|
10065
10114
|
plugins: [
|
|
10066
10115
|
...options.plugins || [],
|
|
10067
|
-
WorkspaceVitestPlugin(project, { ...options,
|
|
10116
|
+
WorkspaceVitestPlugin(project, { ...options, workspacePath })
|
|
10068
10117
|
]
|
|
10069
10118
|
};
|
|
10070
10119
|
await createViteServer(config);
|
|
@@ -10137,6 +10186,192 @@ function createBenchmarkReporters(reporterReferences, runner) {
|
|
|
10137
10186
|
return Promise.all(promisedReporters);
|
|
10138
10187
|
}
|
|
10139
10188
|
|
|
10189
|
+
function parseFilter(filter) {
|
|
10190
|
+
const colonIndex = filter.lastIndexOf(":");
|
|
10191
|
+
if (colonIndex === -1) {
|
|
10192
|
+
return { filename: filter };
|
|
10193
|
+
}
|
|
10194
|
+
const [parsedFilename, lineNumber] = [
|
|
10195
|
+
filter.substring(0, colonIndex),
|
|
10196
|
+
filter.substring(colonIndex + 1)
|
|
10197
|
+
];
|
|
10198
|
+
if (lineNumber.match(/^\d+$/)) {
|
|
10199
|
+
return {
|
|
10200
|
+
filename: parsedFilename,
|
|
10201
|
+
lineNumber: Number.parseInt(lineNumber)
|
|
10202
|
+
};
|
|
10203
|
+
} else if (lineNumber.match(/^\d+-\d+$/)) {
|
|
10204
|
+
throw new RangeLocationFilterProvidedError(filter);
|
|
10205
|
+
} else {
|
|
10206
|
+
return { filename: filter };
|
|
10207
|
+
}
|
|
10208
|
+
}
|
|
10209
|
+
function groupFilters(filters) {
|
|
10210
|
+
const groupedFilters_ = groupBy(filters, (f) => f.filename);
|
|
10211
|
+
const groupedFilters = Object.fromEntries(
|
|
10212
|
+
Object.entries(groupedFilters_).map((entry) => {
|
|
10213
|
+
const [filename, filters2] = entry;
|
|
10214
|
+
const testLocations = filters2.map((f) => f.lineNumber);
|
|
10215
|
+
return [
|
|
10216
|
+
filename,
|
|
10217
|
+
testLocations.filter((l) => l !== void 0)
|
|
10218
|
+
];
|
|
10219
|
+
})
|
|
10220
|
+
);
|
|
10221
|
+
return groupedFilters;
|
|
10222
|
+
}
|
|
10223
|
+
|
|
10224
|
+
class VitestSpecifications {
|
|
10225
|
+
constructor(vitest) {
|
|
10226
|
+
this.vitest = vitest;
|
|
10227
|
+
}
|
|
10228
|
+
_cachedSpecs = /* @__PURE__ */ new Map();
|
|
10229
|
+
getModuleSpecifications(moduleId) {
|
|
10230
|
+
const _cached = this.getCachedSpecifications(moduleId);
|
|
10231
|
+
if (_cached) {
|
|
10232
|
+
return _cached;
|
|
10233
|
+
}
|
|
10234
|
+
const specs = [];
|
|
10235
|
+
for (const project of this.vitest.projects) {
|
|
10236
|
+
if (project.isCachedTestFile(moduleId)) {
|
|
10237
|
+
specs.push(project.createSpecification(moduleId));
|
|
10238
|
+
}
|
|
10239
|
+
if (project.isCachedTypecheckFile(moduleId)) {
|
|
10240
|
+
specs.push(project.createSpecification(moduleId, [], "typescript"));
|
|
10241
|
+
}
|
|
10242
|
+
}
|
|
10243
|
+
specs.forEach((spec) => this.ensureSpecificationCached(spec));
|
|
10244
|
+
return specs;
|
|
10245
|
+
}
|
|
10246
|
+
async getRelevantTestSpecifications(filters = []) {
|
|
10247
|
+
return this.filterTestsBySource(
|
|
10248
|
+
await this.globTestSpecifications(filters)
|
|
10249
|
+
);
|
|
10250
|
+
}
|
|
10251
|
+
async globTestSpecifications(filters = []) {
|
|
10252
|
+
const files = [];
|
|
10253
|
+
const dir = process.cwd();
|
|
10254
|
+
const parsedFilters = filters.map((f) => parseFilter(f));
|
|
10255
|
+
if (!this.vitest.config.includeTaskLocation && parsedFilters.some((f) => f.lineNumber !== void 0)) {
|
|
10256
|
+
throw new IncludeTaskLocationDisabledError();
|
|
10257
|
+
}
|
|
10258
|
+
const testLines = groupFilters(parsedFilters.map(
|
|
10259
|
+
(f) => ({ ...f, filename: resolve(dir, f.filename) })
|
|
10260
|
+
));
|
|
10261
|
+
const testLocHasMatch = {};
|
|
10262
|
+
await Promise.all(this.vitest.projects.map(async (project) => {
|
|
10263
|
+
const { testFiles, typecheckTestFiles } = await project.globTestFiles(
|
|
10264
|
+
parsedFilters.map((f) => f.filename)
|
|
10265
|
+
);
|
|
10266
|
+
testFiles.forEach((file) => {
|
|
10267
|
+
const lines = testLines[file];
|
|
10268
|
+
testLocHasMatch[file] = true;
|
|
10269
|
+
const spec = project.createSpecification(file, lines);
|
|
10270
|
+
this.ensureSpecificationCached(spec);
|
|
10271
|
+
files.push(spec);
|
|
10272
|
+
});
|
|
10273
|
+
typecheckTestFiles.forEach((file) => {
|
|
10274
|
+
const lines = testLines[file];
|
|
10275
|
+
testLocHasMatch[file] = true;
|
|
10276
|
+
const spec = project.createSpecification(file, lines, "typescript");
|
|
10277
|
+
this.ensureSpecificationCached(spec);
|
|
10278
|
+
files.push(spec);
|
|
10279
|
+
});
|
|
10280
|
+
}));
|
|
10281
|
+
Object.entries(testLines).forEach(([filepath, loc]) => {
|
|
10282
|
+
if (loc.length !== 0 && !testLocHasMatch[filepath]) {
|
|
10283
|
+
throw new LocationFilterFileNotFoundError(
|
|
10284
|
+
relative(dir, filepath)
|
|
10285
|
+
);
|
|
10286
|
+
}
|
|
10287
|
+
});
|
|
10288
|
+
return files;
|
|
10289
|
+
}
|
|
10290
|
+
clearCache(moduleId) {
|
|
10291
|
+
if (moduleId) {
|
|
10292
|
+
this._cachedSpecs.delete(moduleId);
|
|
10293
|
+
} else {
|
|
10294
|
+
this._cachedSpecs.clear();
|
|
10295
|
+
}
|
|
10296
|
+
}
|
|
10297
|
+
getCachedSpecifications(moduleId) {
|
|
10298
|
+
return this._cachedSpecs.get(moduleId);
|
|
10299
|
+
}
|
|
10300
|
+
ensureSpecificationCached(spec) {
|
|
10301
|
+
const file = spec.moduleId;
|
|
10302
|
+
const specs = this._cachedSpecs.get(file) || [];
|
|
10303
|
+
const index = specs.findIndex((_s) => _s.project === spec.project && _s.pool === spec.pool);
|
|
10304
|
+
if (index === -1) {
|
|
10305
|
+
specs.push(spec);
|
|
10306
|
+
this._cachedSpecs.set(file, specs);
|
|
10307
|
+
} else {
|
|
10308
|
+
specs.splice(index, 1, spec);
|
|
10309
|
+
}
|
|
10310
|
+
return specs;
|
|
10311
|
+
}
|
|
10312
|
+
async filterTestsBySource(specs) {
|
|
10313
|
+
if (this.vitest.config.changed && !this.vitest.config.related) {
|
|
10314
|
+
const { VitestGit } = await import('./git.B5SDxu-n.js');
|
|
10315
|
+
const vitestGit = new VitestGit(this.vitest.config.root);
|
|
10316
|
+
const related2 = await vitestGit.findChangedFiles({
|
|
10317
|
+
changedSince: this.vitest.config.changed
|
|
10318
|
+
});
|
|
10319
|
+
if (!related2) {
|
|
10320
|
+
process.exitCode = 1;
|
|
10321
|
+
throw new GitNotFoundError();
|
|
10322
|
+
}
|
|
10323
|
+
this.vitest.config.related = Array.from(new Set(related2));
|
|
10324
|
+
}
|
|
10325
|
+
const related = this.vitest.config.related;
|
|
10326
|
+
if (!related) {
|
|
10327
|
+
return specs;
|
|
10328
|
+
}
|
|
10329
|
+
const forceRerunTriggers = this.vitest.config.forceRerunTriggers;
|
|
10330
|
+
if (forceRerunTriggers.length && mm(related, forceRerunTriggers).length) {
|
|
10331
|
+
return specs;
|
|
10332
|
+
}
|
|
10333
|
+
if (!this.vitest.config.watch && !related.length) {
|
|
10334
|
+
return [];
|
|
10335
|
+
}
|
|
10336
|
+
const testGraphs = await Promise.all(
|
|
10337
|
+
specs.map(async (spec) => {
|
|
10338
|
+
const deps = await this.getTestDependencies(spec);
|
|
10339
|
+
return [spec, deps];
|
|
10340
|
+
})
|
|
10341
|
+
);
|
|
10342
|
+
const runningTests = [];
|
|
10343
|
+
for (const [specification, deps] of testGraphs) {
|
|
10344
|
+
if (related.some((path) => path === specification.moduleId || deps.has(path))) {
|
|
10345
|
+
runningTests.push(specification);
|
|
10346
|
+
}
|
|
10347
|
+
}
|
|
10348
|
+
return runningTests;
|
|
10349
|
+
}
|
|
10350
|
+
async getTestDependencies(spec, deps = /* @__PURE__ */ new Set()) {
|
|
10351
|
+
const addImports = async (project, filepath) => {
|
|
10352
|
+
if (deps.has(filepath)) {
|
|
10353
|
+
return;
|
|
10354
|
+
}
|
|
10355
|
+
deps.add(filepath);
|
|
10356
|
+
const mod = project.vite.moduleGraph.getModuleById(filepath);
|
|
10357
|
+
const transformed = mod?.ssrTransformResult || await project.vitenode.transformRequest(filepath);
|
|
10358
|
+
if (!transformed) {
|
|
10359
|
+
return;
|
|
10360
|
+
}
|
|
10361
|
+
const dependencies = [...transformed.deps || [], ...transformed.dynamicDeps || []];
|
|
10362
|
+
await Promise.all(dependencies.map(async (dep) => {
|
|
10363
|
+
const fsPath = dep.startsWith("/@fs/") ? dep.slice(isWindows ? 5 : 4) : join(project.config.root, dep);
|
|
10364
|
+
if (!fsPath.includes("node_modules") && !deps.has(fsPath) && existsSync(fsPath)) {
|
|
10365
|
+
await addImports(project, fsPath);
|
|
10366
|
+
}
|
|
10367
|
+
}));
|
|
10368
|
+
};
|
|
10369
|
+
await addImports(spec.project, spec.moduleId);
|
|
10370
|
+
deps.delete(spec.moduleId);
|
|
10371
|
+
return deps;
|
|
10372
|
+
}
|
|
10373
|
+
}
|
|
10374
|
+
|
|
10140
10375
|
function isAggregateError(err) {
|
|
10141
10376
|
if (typeof AggregateError !== "undefined" && err instanceof AggregateError) {
|
|
10142
10377
|
return true;
|
|
@@ -10318,6 +10553,144 @@ class StateManager {
|
|
|
10318
10553
|
}
|
|
10319
10554
|
}
|
|
10320
10555
|
|
|
10556
|
+
class VitestWatcher {
|
|
10557
|
+
constructor(vitest) {
|
|
10558
|
+
this.vitest = vitest;
|
|
10559
|
+
}
|
|
10560
|
+
/**
|
|
10561
|
+
* Modules that will be invalidated on the next run.
|
|
10562
|
+
*/
|
|
10563
|
+
invalidates = /* @__PURE__ */ new Set();
|
|
10564
|
+
/**
|
|
10565
|
+
* Test files that have changed and need to be rerun.
|
|
10566
|
+
*/
|
|
10567
|
+
changedTests = /* @__PURE__ */ new Set();
|
|
10568
|
+
_onRerun = [];
|
|
10569
|
+
/**
|
|
10570
|
+
* Register a handler that will be called when test files need to be rerun.
|
|
10571
|
+
* The callback can receive several files in case the changed file is imported by several test files.
|
|
10572
|
+
* Several invocations of this method will add multiple handlers.
|
|
10573
|
+
* @internal
|
|
10574
|
+
*/
|
|
10575
|
+
onWatcherRerun(cb) {
|
|
10576
|
+
this._onRerun.push(cb);
|
|
10577
|
+
return this;
|
|
10578
|
+
}
|
|
10579
|
+
unregisterWatcher = noop;
|
|
10580
|
+
registerWatcher() {
|
|
10581
|
+
const watcher = this.vitest.vite.watcher;
|
|
10582
|
+
if (this.vitest.config.forceRerunTriggers.length) {
|
|
10583
|
+
watcher.add(this.vitest.config.forceRerunTriggers);
|
|
10584
|
+
}
|
|
10585
|
+
watcher.on("change", this.onChange);
|
|
10586
|
+
watcher.on("unlink", this.onUnlink);
|
|
10587
|
+
watcher.on("add", this.onAdd);
|
|
10588
|
+
this.unregisterWatcher = () => {
|
|
10589
|
+
watcher.off("change", this.onChange);
|
|
10590
|
+
watcher.off("unlink", this.onUnlink);
|
|
10591
|
+
watcher.off("add", this.onAdd);
|
|
10592
|
+
this.unregisterWatcher = noop;
|
|
10593
|
+
};
|
|
10594
|
+
return this;
|
|
10595
|
+
}
|
|
10596
|
+
scheduleRerun(file) {
|
|
10597
|
+
this._onRerun.forEach((cb) => cb(file));
|
|
10598
|
+
}
|
|
10599
|
+
onChange = (id) => {
|
|
10600
|
+
id = slash(id);
|
|
10601
|
+
this.vitest.logger.clearHighlightCache(id);
|
|
10602
|
+
this.vitest.invalidateFile(id);
|
|
10603
|
+
const needsRerun = this.handleFileChanged(id);
|
|
10604
|
+
if (needsRerun) {
|
|
10605
|
+
this.scheduleRerun(id);
|
|
10606
|
+
}
|
|
10607
|
+
};
|
|
10608
|
+
onUnlink = (id) => {
|
|
10609
|
+
id = slash(id);
|
|
10610
|
+
this.vitest.logger.clearHighlightCache(id);
|
|
10611
|
+
this.invalidates.add(id);
|
|
10612
|
+
if (this.vitest.state.filesMap.has(id)) {
|
|
10613
|
+
this.vitest.state.filesMap.delete(id);
|
|
10614
|
+
this.vitest.cache.results.removeFromCache(id);
|
|
10615
|
+
this.vitest.cache.stats.removeStats(id);
|
|
10616
|
+
this.changedTests.delete(id);
|
|
10617
|
+
this.vitest.report("onTestRemoved", id);
|
|
10618
|
+
}
|
|
10619
|
+
};
|
|
10620
|
+
onAdd = (id) => {
|
|
10621
|
+
id = slash(id);
|
|
10622
|
+
this.vitest.invalidateFile(id);
|
|
10623
|
+
let fileContent;
|
|
10624
|
+
const matchingProjects = [];
|
|
10625
|
+
this.vitest.projects.forEach((project) => {
|
|
10626
|
+
if (project.matchesTestGlob(id, () => fileContent ??= readFileSync(id, "utf-8"))) {
|
|
10627
|
+
matchingProjects.push(project);
|
|
10628
|
+
}
|
|
10629
|
+
});
|
|
10630
|
+
if (matchingProjects.length > 0) {
|
|
10631
|
+
this.changedTests.add(id);
|
|
10632
|
+
this.scheduleRerun(id);
|
|
10633
|
+
} else {
|
|
10634
|
+
const needsRerun = this.handleFileChanged(id);
|
|
10635
|
+
if (needsRerun) {
|
|
10636
|
+
this.scheduleRerun(id);
|
|
10637
|
+
}
|
|
10638
|
+
}
|
|
10639
|
+
};
|
|
10640
|
+
/**
|
|
10641
|
+
* @returns A value indicating whether rerun is needed (changedTests was mutated)
|
|
10642
|
+
*/
|
|
10643
|
+
handleFileChanged(filepath) {
|
|
10644
|
+
if (this.changedTests.has(filepath) || this.invalidates.has(filepath)) {
|
|
10645
|
+
return false;
|
|
10646
|
+
}
|
|
10647
|
+
if (mm.isMatch(filepath, this.vitest.config.forceRerunTriggers)) {
|
|
10648
|
+
this.vitest.state.getFilepaths().forEach((file) => this.changedTests.add(file));
|
|
10649
|
+
return true;
|
|
10650
|
+
}
|
|
10651
|
+
const projects = this.vitest.projects.filter((project) => {
|
|
10652
|
+
const moduleGraph = project.browser?.vite.moduleGraph || project.vite.moduleGraph;
|
|
10653
|
+
return moduleGraph.getModulesByFile(filepath)?.size;
|
|
10654
|
+
});
|
|
10655
|
+
if (!projects.length) {
|
|
10656
|
+
if (this.vitest.state.filesMap.has(filepath) || this.vitest.projects.some((project) => project.isCachedTestFile(filepath))) {
|
|
10657
|
+
this.changedTests.add(filepath);
|
|
10658
|
+
return true;
|
|
10659
|
+
}
|
|
10660
|
+
return false;
|
|
10661
|
+
}
|
|
10662
|
+
const files = [];
|
|
10663
|
+
for (const project of projects) {
|
|
10664
|
+
const mods = project.browser?.vite.moduleGraph.getModulesByFile(filepath) || project.vite.moduleGraph.getModulesByFile(filepath);
|
|
10665
|
+
if (!mods || !mods.size) {
|
|
10666
|
+
continue;
|
|
10667
|
+
}
|
|
10668
|
+
this.invalidates.add(filepath);
|
|
10669
|
+
if (this.vitest.state.filesMap.has(filepath) || project.isCachedTestFile(filepath)) {
|
|
10670
|
+
this.changedTests.add(filepath);
|
|
10671
|
+
files.push(filepath);
|
|
10672
|
+
continue;
|
|
10673
|
+
}
|
|
10674
|
+
let rerun = false;
|
|
10675
|
+
for (const mod of mods) {
|
|
10676
|
+
mod.importers.forEach((i) => {
|
|
10677
|
+
if (!i.file) {
|
|
10678
|
+
return;
|
|
10679
|
+
}
|
|
10680
|
+
const needsRerun = this.handleFileChanged(i.file);
|
|
10681
|
+
if (needsRerun) {
|
|
10682
|
+
rerun = true;
|
|
10683
|
+
}
|
|
10684
|
+
});
|
|
10685
|
+
}
|
|
10686
|
+
if (rerun) {
|
|
10687
|
+
files.push(filepath);
|
|
10688
|
+
}
|
|
10689
|
+
}
|
|
10690
|
+
return !!files.length;
|
|
10691
|
+
}
|
|
10692
|
+
}
|
|
10693
|
+
|
|
10321
10694
|
const ESCAPE_SYMBOL = "\\";
|
|
10322
10695
|
const COMMON_GLOB_SYMBOLS_RE = /[*?]|^!/;
|
|
10323
10696
|
const REGEX_CHARACTER_CLASS_SYMBOLS_RE = /\[[^[]*\]/;
|
|
@@ -10387,35 +10760,41 @@ async function resolveWorkspace(vitest, cliOptions, workspaceConfigPath, workspa
|
|
|
10387
10760
|
const projectPromises = [];
|
|
10388
10761
|
const fileProjects = [...configFiles, ...nonConfigDirectories];
|
|
10389
10762
|
const concurrent = limitConcurrency(nodeos__default.availableParallelism?.() || nodeos__default.cpus().length || 5);
|
|
10390
|
-
|
|
10391
|
-
|
|
10392
|
-
|
|
10763
|
+
projectConfigs.forEach((options, index) => {
|
|
10764
|
+
const configRoot = workspaceConfigPath ? dirname(workspaceConfigPath) : vitest.config.root;
|
|
10765
|
+
const configFile = typeof options.extends === "string" ? resolve(configRoot, options.extends) : false;
|
|
10766
|
+
const rootOptions = options.extends === true ? vitest._options : {};
|
|
10767
|
+
const root = options.root ? resolve(configRoot, options.root) : vitest.config.root;
|
|
10768
|
+
projectPromises.push(concurrent(() => initializeProject(
|
|
10769
|
+
index,
|
|
10770
|
+
vitest,
|
|
10771
|
+
mergeConfig(rootOptions, { ...options, root, configFile })
|
|
10772
|
+
)));
|
|
10773
|
+
});
|
|
10774
|
+
for (const path of fileProjects) {
|
|
10775
|
+
if (vitest.vite.config.configFile === path) {
|
|
10776
|
+
projectPromises.push(Promise.resolve(vitest._ensureRootProject()));
|
|
10393
10777
|
continue;
|
|
10394
10778
|
}
|
|
10779
|
+
const configFile = path.endsWith("/") ? false : path;
|
|
10780
|
+
const root = path.endsWith("/") ? path : dirname(path);
|
|
10395
10781
|
projectPromises.push(
|
|
10396
10782
|
concurrent(() => initializeProject(
|
|
10397
|
-
|
|
10783
|
+
path,
|
|
10398
10784
|
vitest,
|
|
10399
|
-
{
|
|
10785
|
+
{ root, configFile, test: cliOverrides }
|
|
10400
10786
|
))
|
|
10401
10787
|
);
|
|
10402
10788
|
}
|
|
10403
|
-
projectConfigs.forEach((options, index) => {
|
|
10404
|
-
projectPromises.push(concurrent(() => initializeProject(
|
|
10405
|
-
index,
|
|
10406
|
-
vitest,
|
|
10407
|
-
mergeConfig(options, { workspaceConfigPath, test: cliOverrides })
|
|
10408
|
-
)));
|
|
10409
|
-
});
|
|
10410
10789
|
if (!projectPromises.length) {
|
|
10411
|
-
return [
|
|
10790
|
+
return [vitest._ensureRootProject()];
|
|
10412
10791
|
}
|
|
10413
10792
|
const resolvedProjects = await Promise.all(projectPromises);
|
|
10414
10793
|
const names = /* @__PURE__ */ new Set();
|
|
10415
10794
|
for (const project of resolvedProjects) {
|
|
10416
|
-
const name = project.
|
|
10795
|
+
const name = project.name;
|
|
10417
10796
|
if (names.has(name)) {
|
|
10418
|
-
const duplicate = resolvedProjects.find((p) => p.
|
|
10797
|
+
const duplicate = resolvedProjects.find((p) => p.name === name && p !== project);
|
|
10419
10798
|
const filesError = fileProjects.length ? [
|
|
10420
10799
|
"\n\nYour config matched these files:\n",
|
|
10421
10800
|
fileProjects.map((p) => ` - ${relative(vitest.config.root, p)}`).join("\n"),
|
|
@@ -10439,14 +10818,15 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, workspaceD
|
|
|
10439
10818
|
const workspaceConfigFiles = [];
|
|
10440
10819
|
const workspaceGlobMatches = [];
|
|
10441
10820
|
const nonConfigProjectDirectories = [];
|
|
10442
|
-
const relativeWorkpaceConfigPath = relative(vitest.config.root, workspaceConfigPath);
|
|
10443
10821
|
for (const definition of workspaceDefinition) {
|
|
10444
10822
|
if (typeof definition === "string") {
|
|
10445
10823
|
const stringOption = definition.replace("<rootDir>", vitest.config.root);
|
|
10446
10824
|
if (!isDynamicPattern(stringOption)) {
|
|
10447
10825
|
const file = resolve(vitest.config.root, stringOption);
|
|
10448
10826
|
if (!existsSync(file)) {
|
|
10449
|
-
|
|
10827
|
+
const relativeWorkpaceConfigPath = workspaceConfigPath ? relative(vitest.config.root, workspaceConfigPath) : void 0;
|
|
10828
|
+
const note = workspaceConfigPath ? `Workspace config file "${relativeWorkpaceConfigPath}"` : "Inline workspace";
|
|
10829
|
+
throw new Error(`${note} references a non-existing file or a directory: ${file}`);
|
|
10450
10830
|
}
|
|
10451
10831
|
const stats = await promises.stat(file);
|
|
10452
10832
|
if (stats.isFile()) {
|
|
@@ -10467,8 +10847,8 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, workspaceD
|
|
|
10467
10847
|
}
|
|
10468
10848
|
} else if (typeof definition === "function") {
|
|
10469
10849
|
projectsOptions.push(await definition({
|
|
10470
|
-
command: vitest.
|
|
10471
|
-
mode: vitest.
|
|
10850
|
+
command: vitest.vite.config.command,
|
|
10851
|
+
mode: vitest.vite.config.mode,
|
|
10472
10852
|
isPreview: false,
|
|
10473
10853
|
isSsrBuild: false
|
|
10474
10854
|
}));
|
|
@@ -10494,16 +10874,16 @@ async function resolveTestProjectConfigs(vitest, workspaceConfigPath, workspaceD
|
|
|
10494
10874
|
]
|
|
10495
10875
|
};
|
|
10496
10876
|
const workspacesFs = await fg.glob(workspaceGlobMatches, globOptions);
|
|
10497
|
-
await Promise.all(workspacesFs.map(async (
|
|
10498
|
-
if (
|
|
10499
|
-
const configFile = await resolveDirectoryConfig(
|
|
10877
|
+
await Promise.all(workspacesFs.map(async (path) => {
|
|
10878
|
+
if (path.endsWith("/")) {
|
|
10879
|
+
const configFile = await resolveDirectoryConfig(path);
|
|
10500
10880
|
if (configFile) {
|
|
10501
10881
|
workspaceConfigFiles.push(configFile);
|
|
10502
10882
|
} else {
|
|
10503
|
-
nonConfigProjectDirectories.push(
|
|
10883
|
+
nonConfigProjectDirectories.push(path);
|
|
10504
10884
|
}
|
|
10505
10885
|
} else {
|
|
10506
|
-
workspaceConfigFiles.push(
|
|
10886
|
+
workspaceConfigFiles.push(path);
|
|
10507
10887
|
}
|
|
10508
10888
|
}));
|
|
10509
10889
|
}
|
|
@@ -10529,49 +10909,141 @@ class Vitest {
|
|
|
10529
10909
|
this.mode = mode;
|
|
10530
10910
|
this.logger = new Logger(this, options.stdout, options.stderr);
|
|
10531
10911
|
this.packageInstaller = options.packageInstaller || new VitestPackageInstaller();
|
|
10912
|
+
this.specifications = new VitestSpecifications(this);
|
|
10913
|
+
this.watcher = new VitestWatcher(this).onWatcherRerun(
|
|
10914
|
+
(file) => this.scheduleRerun([file])
|
|
10915
|
+
// TODO: error handling
|
|
10916
|
+
);
|
|
10532
10917
|
}
|
|
10918
|
+
/**
|
|
10919
|
+
* Current Vitest version.
|
|
10920
|
+
* @example '2.0.0'
|
|
10921
|
+
*/
|
|
10533
10922
|
version = version$1;
|
|
10534
|
-
|
|
10535
|
-
|
|
10536
|
-
|
|
10537
|
-
|
|
10538
|
-
|
|
10539
|
-
|
|
10540
|
-
|
|
10541
|
-
|
|
10923
|
+
static version = version$1;
|
|
10924
|
+
/**
|
|
10925
|
+
* The logger instance used to log messages. It's recommended to use this logger instead of `console`.
|
|
10926
|
+
* It's possible to override stdout and stderr streams when initiating Vitest.
|
|
10927
|
+
* @example
|
|
10928
|
+
* new Vitest('test', {
|
|
10929
|
+
* stdout: new Writable(),
|
|
10930
|
+
* })
|
|
10931
|
+
*/
|
|
10542
10932
|
logger;
|
|
10543
|
-
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
|
|
10547
|
-
|
|
10548
|
-
filenamePattern;
|
|
10549
|
-
runningPromise;
|
|
10550
|
-
closingPromise;
|
|
10551
|
-
isCancelling = false;
|
|
10552
|
-
isFirstRun = true;
|
|
10553
|
-
restartsCount = 0;
|
|
10554
|
-
runner = void 0;
|
|
10933
|
+
/**
|
|
10934
|
+
* The package installer instance used to install Vitest packages.
|
|
10935
|
+
* @example
|
|
10936
|
+
* await vitest.packageInstaller.ensureInstalled('@vitest/browser', process.cwd())
|
|
10937
|
+
*/
|
|
10555
10938
|
packageInstaller;
|
|
10939
|
+
/**
|
|
10940
|
+
* A path to the built Vitest directory. This is usually a folder in `node_modules`.
|
|
10941
|
+
*/
|
|
10942
|
+
distPath = distDir;
|
|
10943
|
+
/**
|
|
10944
|
+
* A list of projects that are currently running.
|
|
10945
|
+
* If projects were filtered with `--project` flag, they won't appear here.
|
|
10946
|
+
*/
|
|
10947
|
+
projects = [];
|
|
10948
|
+
/** @internal */
|
|
10949
|
+
configOverride = {};
|
|
10950
|
+
/** @internal */
|
|
10951
|
+
coverageProvider;
|
|
10952
|
+
/** @internal */
|
|
10953
|
+
filenamePattern;
|
|
10954
|
+
/** @internal */
|
|
10955
|
+
runningPromise;
|
|
10956
|
+
/** @internal */
|
|
10957
|
+
closingPromise;
|
|
10958
|
+
/** @internal */
|
|
10959
|
+
isCancelling = false;
|
|
10556
10960
|
/** @internal */
|
|
10557
10961
|
coreWorkspaceProject;
|
|
10558
|
-
/** @
|
|
10962
|
+
/** @internal */
|
|
10559
10963
|
resolvedProjects = [];
|
|
10560
|
-
|
|
10561
|
-
distPath = distDir;
|
|
10562
|
-
_cachedSpecs = /* @__PURE__ */ new Map();
|
|
10563
|
-
_workspaceConfigPath;
|
|
10564
|
-
/** @deprecated use `_cachedSpecs` */
|
|
10565
|
-
projectTestFiles = this._cachedSpecs;
|
|
10566
|
-
/** @private */
|
|
10964
|
+
/** @internal */
|
|
10567
10965
|
_browserLastPort = defaultBrowserPort;
|
|
10966
|
+
/** @internal */
|
|
10967
|
+
_options = {};
|
|
10968
|
+
/** @internal */
|
|
10969
|
+
reporters = void 0;
|
|
10970
|
+
/** @internal */
|
|
10971
|
+
vitenode = void 0;
|
|
10972
|
+
/** @internal */
|
|
10973
|
+
runner = void 0;
|
|
10974
|
+
isFirstRun = true;
|
|
10975
|
+
restartsCount = 0;
|
|
10976
|
+
specifications;
|
|
10977
|
+
watcher;
|
|
10978
|
+
pool;
|
|
10979
|
+
_config;
|
|
10980
|
+
_vite;
|
|
10981
|
+
_state;
|
|
10982
|
+
_cache;
|
|
10983
|
+
_snapshot;
|
|
10984
|
+
_workspaceConfigPath;
|
|
10568
10985
|
_onRestartListeners = [];
|
|
10569
10986
|
_onClose = [];
|
|
10570
10987
|
_onSetServer = [];
|
|
10571
10988
|
_onCancelListeners = [];
|
|
10572
10989
|
_onUserTestsRerun = [];
|
|
10573
|
-
|
|
10574
|
-
|
|
10990
|
+
_onFilterWatchedSpecification = [];
|
|
10991
|
+
/** @deprecated will be removed in 4.0, use `onFilterWatchedSpecification` instead */
|
|
10992
|
+
get invalidates() {
|
|
10993
|
+
return this.watcher.invalidates;
|
|
10994
|
+
}
|
|
10995
|
+
/** @deprecated will be removed in 4.0, use `onFilterWatchedSpecification` instead */
|
|
10996
|
+
get changedTests() {
|
|
10997
|
+
return this.watcher.changedTests;
|
|
10998
|
+
}
|
|
10999
|
+
/**
|
|
11000
|
+
* The global config.
|
|
11001
|
+
*/
|
|
11002
|
+
get config() {
|
|
11003
|
+
assert(this._config, "config");
|
|
11004
|
+
return this._config;
|
|
11005
|
+
}
|
|
11006
|
+
/** @deprecated use `vitest.vite` instead */
|
|
11007
|
+
get server() {
|
|
11008
|
+
return this._vite;
|
|
11009
|
+
}
|
|
11010
|
+
/**
|
|
11011
|
+
* Global Vite's dev server instance.
|
|
11012
|
+
*/
|
|
11013
|
+
get vite() {
|
|
11014
|
+
assert(this._vite, "vite", "server");
|
|
11015
|
+
return this._vite;
|
|
11016
|
+
}
|
|
11017
|
+
/**
|
|
11018
|
+
* The global test state manager.
|
|
11019
|
+
* @experimental The State API is experimental and not subject to semver.
|
|
11020
|
+
*/
|
|
11021
|
+
get state() {
|
|
11022
|
+
assert(this._state, "state");
|
|
11023
|
+
return this._state;
|
|
11024
|
+
}
|
|
11025
|
+
/**
|
|
11026
|
+
* The global snapshot manager. You can access the current state on `snapshot.summary`.
|
|
11027
|
+
*/
|
|
11028
|
+
get snapshot() {
|
|
11029
|
+
assert(this._snapshot, "snapshot", "snapshot manager");
|
|
11030
|
+
return this._snapshot;
|
|
11031
|
+
}
|
|
11032
|
+
/**
|
|
11033
|
+
* Test results and test file stats cache. Primarily used by the sequencer to sort tests.
|
|
11034
|
+
*/
|
|
11035
|
+
get cache() {
|
|
11036
|
+
assert(this._cache, "cache");
|
|
11037
|
+
return this._cache;
|
|
11038
|
+
}
|
|
11039
|
+
/** @deprecated internal */
|
|
11040
|
+
setServer(options, server, cliOptions) {
|
|
11041
|
+
return this._setServer(options, server, cliOptions);
|
|
11042
|
+
}
|
|
11043
|
+
/** @internal */
|
|
11044
|
+
async _setServer(options, server, cliOptions) {
|
|
11045
|
+
this._options = options;
|
|
11046
|
+
this.watcher.unregisterWatcher();
|
|
10575
11047
|
clearTimeout(this._rerunTimer);
|
|
10576
11048
|
this.restartsCount += 1;
|
|
10577
11049
|
this._browserLastPort = defaultBrowserPort;
|
|
@@ -10583,16 +11055,16 @@ class Vitest {
|
|
|
10583
11055
|
this._workspaceConfigPath = void 0;
|
|
10584
11056
|
this.coverageProvider = void 0;
|
|
10585
11057
|
this.runningPromise = void 0;
|
|
10586
|
-
this.
|
|
11058
|
+
this.specifications.clearCache();
|
|
10587
11059
|
this._onUserTestsRerun = [];
|
|
10588
11060
|
const resolved = resolveConfig(this.mode, options, server.config, this.logger);
|
|
10589
|
-
this.
|
|
10590
|
-
this.
|
|
10591
|
-
this.
|
|
10592
|
-
this.
|
|
10593
|
-
this.
|
|
11061
|
+
this._vite = server;
|
|
11062
|
+
this._config = resolved;
|
|
11063
|
+
this._state = new StateManager();
|
|
11064
|
+
this._cache = new VitestCache(this.version);
|
|
11065
|
+
this._snapshot = new SnapshotManager({ ...resolved.snapshotOptions });
|
|
10594
11066
|
if (this.config.watch) {
|
|
10595
|
-
this.registerWatcher();
|
|
11067
|
+
this.watcher.registerWatcher();
|
|
10596
11068
|
}
|
|
10597
11069
|
this.vitenode = new ViteNodeServer(server, this.config.server);
|
|
10598
11070
|
const node = this.vitenode;
|
|
@@ -10616,7 +11088,7 @@ class Vitest {
|
|
|
10616
11088
|
};
|
|
10617
11089
|
server.watcher.on("change", async (file) => {
|
|
10618
11090
|
file = normalize(file);
|
|
10619
|
-
const isConfig = file === server.config.configFile || this.resolvedProjects.some((p) => p.
|
|
11091
|
+
const isConfig = file === server.config.configFile || this.resolvedProjects.some((p) => p.vite.config.configFile === file) || file === this._workspaceConfigPath;
|
|
10620
11092
|
if (isConfig) {
|
|
10621
11093
|
await Promise.all(this._onRestartListeners.map((fn) => fn("config")));
|
|
10622
11094
|
this.report("onServerRestart", "config");
|
|
@@ -10625,7 +11097,6 @@ class Vitest {
|
|
|
10625
11097
|
}
|
|
10626
11098
|
});
|
|
10627
11099
|
}
|
|
10628
|
-
this.reporters = resolved.mode === "benchmark" ? await createBenchmarkReporters(toArray(resolved.benchmark?.reporters), this.runner) : await createReporters(resolved.reporters, this);
|
|
10629
11100
|
this.cache.results.setConfig(resolved.root, resolved.cache);
|
|
10630
11101
|
try {
|
|
10631
11102
|
await this.cache.results.readFromCache();
|
|
@@ -10637,8 +11108,11 @@ class Vitest {
|
|
|
10637
11108
|
const filters = toArray(resolved.project).map((s) => wildcardPatternToRegExp(s));
|
|
10638
11109
|
if (filters.length > 0) {
|
|
10639
11110
|
this.projects = this.projects.filter(
|
|
10640
|
-
(p) => filters.some((pattern) => pattern.test(p.
|
|
11111
|
+
(p) => filters.some((pattern) => pattern.test(p.name))
|
|
10641
11112
|
);
|
|
11113
|
+
if (!this.projects.length) {
|
|
11114
|
+
throw new Error(`No projects matched the filter "${toArray(resolved.project).join('", "')}".`);
|
|
11115
|
+
}
|
|
10642
11116
|
}
|
|
10643
11117
|
if (!this.coreWorkspaceProject) {
|
|
10644
11118
|
this.coreWorkspaceProject = TestProject._createBasicProject(this);
|
|
@@ -10646,19 +11120,37 @@ class Vitest {
|
|
|
10646
11120
|
if (this.config.testNamePattern) {
|
|
10647
11121
|
this.configOverride.testNamePattern = this.config.testNamePattern;
|
|
10648
11122
|
}
|
|
11123
|
+
this.reporters = resolved.mode === "benchmark" ? await createBenchmarkReporters(toArray(resolved.benchmark?.reporters), this.runner) : await createReporters(resolved.reporters, this);
|
|
10649
11124
|
await Promise.all(this._onSetServer.map((fn) => fn()));
|
|
10650
11125
|
}
|
|
10651
|
-
provide(key, value) {
|
|
10652
|
-
this.getRootTestProject().provide(key, value);
|
|
10653
|
-
}
|
|
10654
11126
|
/**
|
|
10655
|
-
*
|
|
11127
|
+
* Provide a value to the test context. This value will be available to all tests with `inject`.
|
|
10656
11128
|
*/
|
|
10657
|
-
|
|
11129
|
+
provide = (key, value) => {
|
|
11130
|
+
this.getRootProject().provide(key, value);
|
|
11131
|
+
};
|
|
11132
|
+
/**
|
|
11133
|
+
* Get global provided context.
|
|
11134
|
+
*/
|
|
11135
|
+
getProvidedContext() {
|
|
11136
|
+
return this.getRootProject().getProvidedContext();
|
|
11137
|
+
}
|
|
11138
|
+
/** @internal */
|
|
11139
|
+
_ensureRootProject() {
|
|
11140
|
+
if (this.coreWorkspaceProject) {
|
|
11141
|
+
return this.coreWorkspaceProject;
|
|
11142
|
+
}
|
|
10658
11143
|
this.coreWorkspaceProject = TestProject._createBasicProject(this);
|
|
10659
11144
|
return this.coreWorkspaceProject;
|
|
10660
11145
|
}
|
|
10661
|
-
|
|
11146
|
+
/** @deprecated use `getRootProject` instead */
|
|
11147
|
+
getCoreWorkspaceProject() {
|
|
11148
|
+
return this.getRootProject();
|
|
11149
|
+
}
|
|
11150
|
+
/**
|
|
11151
|
+
* Return project that has the root (or "global") config.
|
|
11152
|
+
*/
|
|
11153
|
+
getRootProject() {
|
|
10662
11154
|
if (!this.coreWorkspaceProject) {
|
|
10663
11155
|
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
11156
|
}
|
|
@@ -10670,16 +11162,27 @@ class Vitest {
|
|
|
10670
11162
|
getProjectByTaskId(taskId) {
|
|
10671
11163
|
const task = this.state.idMap.get(taskId);
|
|
10672
11164
|
const projectName = task.projectName || task?.file?.projectName || "";
|
|
10673
|
-
return this.
|
|
11165
|
+
return this.getProjectByName(projectName);
|
|
10674
11166
|
}
|
|
10675
|
-
getProjectByName(name
|
|
10676
|
-
|
|
11167
|
+
getProjectByName(name) {
|
|
11168
|
+
const project = this.projects.find((p) => p.name === name) || this.coreWorkspaceProject || this.projects[0];
|
|
11169
|
+
if (!project) {
|
|
11170
|
+
throw new Error(`Project "${name}" was not found.`);
|
|
11171
|
+
}
|
|
11172
|
+
return project;
|
|
10677
11173
|
}
|
|
10678
|
-
|
|
10679
|
-
|
|
11174
|
+
/**
|
|
11175
|
+
* Import a file using Vite module runner. The file will be transformed by Vite and executed in a separate context.
|
|
11176
|
+
* @param moduleId The ID of the module in Vite module graph
|
|
11177
|
+
*/
|
|
11178
|
+
import(moduleId) {
|
|
11179
|
+
return this.runner.executeId(moduleId);
|
|
11180
|
+
}
|
|
11181
|
+
async resolveWorkspaceConfigPath() {
|
|
11182
|
+
if (typeof this.config.workspace === "string") {
|
|
10680
11183
|
return this.config.workspace;
|
|
10681
11184
|
}
|
|
10682
|
-
const configDir = this.
|
|
11185
|
+
const configDir = this.vite.config.configFile ? dirname(this.vite.config.configFile) : this.config.root;
|
|
10683
11186
|
const rootFiles = await promises.readdir(configDir);
|
|
10684
11187
|
const workspaceConfigName = workspacesFiles.find((configFile) => {
|
|
10685
11188
|
return rootFiles.includes(configFile);
|
|
@@ -10690,12 +11193,20 @@ class Vitest {
|
|
|
10690
11193
|
return join(configDir, workspaceConfigName);
|
|
10691
11194
|
}
|
|
10692
11195
|
async resolveWorkspace(cliOptions) {
|
|
10693
|
-
|
|
11196
|
+
if (Array.isArray(this.config.workspace)) {
|
|
11197
|
+
return resolveWorkspace(
|
|
11198
|
+
this,
|
|
11199
|
+
cliOptions,
|
|
11200
|
+
void 0,
|
|
11201
|
+
this.config.workspace
|
|
11202
|
+
);
|
|
11203
|
+
}
|
|
11204
|
+
const workspaceConfigPath = await this.resolveWorkspaceConfigPath();
|
|
10694
11205
|
this._workspaceConfigPath = workspaceConfigPath;
|
|
10695
11206
|
if (!workspaceConfigPath) {
|
|
10696
|
-
return [this.
|
|
11207
|
+
return [this._ensureRootProject()];
|
|
10697
11208
|
}
|
|
10698
|
-
const workspaceModule = await this.
|
|
11209
|
+
const workspaceModule = await this.import(workspaceConfigPath);
|
|
10699
11210
|
if (!workspaceModule.default || !Array.isArray(workspaceModule.default)) {
|
|
10700
11211
|
throw new TypeError(`Workspace config file "${workspaceConfigPath}" must export a default array of project paths.`);
|
|
10701
11212
|
}
|
|
@@ -10706,6 +11217,13 @@ class Vitest {
|
|
|
10706
11217
|
workspaceModule.default
|
|
10707
11218
|
);
|
|
10708
11219
|
}
|
|
11220
|
+
/**
|
|
11221
|
+
* Glob test files in every project and create a TestSpecification for each file and pool.
|
|
11222
|
+
* @param filters String filters to match the test files.
|
|
11223
|
+
*/
|
|
11224
|
+
async globTestSpecifications(filters = []) {
|
|
11225
|
+
return this.specifications.globTestSpecifications(filters);
|
|
11226
|
+
}
|
|
10709
11227
|
async initCoverageProvider() {
|
|
10710
11228
|
if (this.coverageProvider !== void 0) {
|
|
10711
11229
|
return;
|
|
@@ -10720,16 +11238,19 @@ class Vitest {
|
|
|
10720
11238
|
}
|
|
10721
11239
|
return this.coverageProvider;
|
|
10722
11240
|
}
|
|
10723
|
-
|
|
11241
|
+
/**
|
|
11242
|
+
* Merge reports from multiple runs located in the specified directory (value from `--merge-reports` if not specified).
|
|
11243
|
+
*/
|
|
11244
|
+
async mergeReports(directory) {
|
|
10724
11245
|
if (this.reporters.some((r) => r instanceof BlobReporter)) {
|
|
10725
11246
|
throw new Error("Cannot merge reports when `--reporter=blob` is used. Remove blob reporter from the config first.");
|
|
10726
11247
|
}
|
|
10727
|
-
const { files, errors, coverages } = await readBlobs(this.version, this.config.mergeReports, this.projects);
|
|
11248
|
+
const { files, errors, coverages } = await readBlobs(this.version, directory || this.config.mergeReports, this.projects);
|
|
10728
11249
|
await this.report("onInit", this);
|
|
10729
11250
|
await this.report("onPathsCollected", files.flatMap((f) => f.filepath));
|
|
10730
11251
|
const workspaceSpecs = /* @__PURE__ */ new Map();
|
|
10731
11252
|
for (const file of files) {
|
|
10732
|
-
const project = this.getProjectByName(file.projectName);
|
|
11253
|
+
const project = this.getProjectByName(file.projectName || "");
|
|
10733
11254
|
const specs = workspaceSpecs.get(project) || [];
|
|
10734
11255
|
specs.push(file);
|
|
10735
11256
|
workspaceSpecs.set(project, specs);
|
|
@@ -10762,31 +11283,42 @@ class Vitest {
|
|
|
10762
11283
|
if (hasFailed(files)) {
|
|
10763
11284
|
process.exitCode = 1;
|
|
10764
11285
|
}
|
|
10765
|
-
this.
|
|
11286
|
+
this._checkUnhandledErrors(errors);
|
|
10766
11287
|
await this.report("onFinished", files, errors);
|
|
10767
11288
|
await this.initCoverageProvider();
|
|
10768
11289
|
await this.coverageProvider?.mergeReports?.(coverages);
|
|
11290
|
+
return {
|
|
11291
|
+
testModules: this.state.getTestModules(),
|
|
11292
|
+
unhandledErrors: this.state.getUnhandledErrors()
|
|
11293
|
+
};
|
|
10769
11294
|
}
|
|
10770
11295
|
async collect(filters) {
|
|
10771
11296
|
this._onClose = [];
|
|
10772
|
-
const files = await this.
|
|
10773
|
-
await this.globTestFiles(filters)
|
|
10774
|
-
);
|
|
11297
|
+
const files = await this.specifications.getRelevantTestSpecifications(filters);
|
|
10775
11298
|
if (!files.length) {
|
|
10776
|
-
return {
|
|
11299
|
+
return { testModules: [], unhandledErrors: [] };
|
|
10777
11300
|
}
|
|
10778
|
-
|
|
10779
|
-
return {
|
|
10780
|
-
tests: this.state.getFiles(),
|
|
10781
|
-
errors: this.state.getUnhandledErrors()
|
|
10782
|
-
};
|
|
11301
|
+
return this.collectTests(files);
|
|
10783
11302
|
}
|
|
10784
|
-
|
|
10785
|
-
|
|
10786
|
-
|
|
10787
|
-
);
|
|
10788
|
-
return files;
|
|
11303
|
+
/** @deprecated use `getRelevantTestSpecifications` instead */
|
|
11304
|
+
listFiles(filters) {
|
|
11305
|
+
return this.getRelevantTestSpecifications(filters);
|
|
10789
11306
|
}
|
|
11307
|
+
/**
|
|
11308
|
+
* Returns the list of test files that match the config and filters.
|
|
11309
|
+
* @param filters String filters to match the test files
|
|
11310
|
+
*/
|
|
11311
|
+
getRelevantTestSpecifications(filters) {
|
|
11312
|
+
return this.specifications.getRelevantTestSpecifications(filters);
|
|
11313
|
+
}
|
|
11314
|
+
/**
|
|
11315
|
+
* Initialize reporters, the coverage provider, and run tests.
|
|
11316
|
+
* This method can throw an error:
|
|
11317
|
+
* - `FilesNotFoundError` if no tests are found
|
|
11318
|
+
* - `GitNotFoundError` if `--related` flag is used, but git repository is not initialized
|
|
11319
|
+
* - `Error` from the user reporters
|
|
11320
|
+
* @param filters String filters to match the test files
|
|
11321
|
+
*/
|
|
10790
11322
|
async start(filters) {
|
|
10791
11323
|
this._onClose = [];
|
|
10792
11324
|
try {
|
|
@@ -10795,9 +11327,8 @@ class Vitest {
|
|
|
10795
11327
|
} finally {
|
|
10796
11328
|
await this.report("onInit", this);
|
|
10797
11329
|
}
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
);
|
|
11330
|
+
this.filenamePattern = filters && filters?.length > 0 ? filters : void 0;
|
|
11331
|
+
const files = await this.specifications.getRelevantTestSpecifications(filters);
|
|
10801
11332
|
if (!files.length) {
|
|
10802
11333
|
const coverage = await this.coverageProvider?.generateCoverage?.({ allTestsRun: true });
|
|
10803
11334
|
await this.reportCoverage(coverage, true);
|
|
@@ -10808,14 +11339,23 @@ class Vitest {
|
|
|
10808
11339
|
throw new FilesNotFoundError(this.mode);
|
|
10809
11340
|
}
|
|
10810
11341
|
}
|
|
11342
|
+
let testModules = {
|
|
11343
|
+
testModules: [],
|
|
11344
|
+
unhandledErrors: []
|
|
11345
|
+
};
|
|
10811
11346
|
if (files.length) {
|
|
10812
11347
|
await this.cache.stats.populateStats(this.config.root, files);
|
|
10813
|
-
await this.runFiles(files, true);
|
|
11348
|
+
testModules = await this.runFiles(files, true);
|
|
10814
11349
|
}
|
|
10815
11350
|
if (this.config.watch) {
|
|
10816
11351
|
await this.report("onWatcherStart");
|
|
10817
11352
|
}
|
|
11353
|
+
return testModules;
|
|
10818
11354
|
}
|
|
11355
|
+
/**
|
|
11356
|
+
* Initialize reporters and the coverage provider. This method doesn't run any tests.
|
|
11357
|
+
* If the `--watch` flag is provided, Vitest will still run changed tests even if this method was not called.
|
|
11358
|
+
*/
|
|
10819
11359
|
async init() {
|
|
10820
11360
|
this._onClose = [];
|
|
10821
11361
|
try {
|
|
@@ -10824,105 +11364,60 @@ class Vitest {
|
|
|
10824
11364
|
} finally {
|
|
10825
11365
|
await this.report("onInit", this);
|
|
10826
11366
|
}
|
|
10827
|
-
await this.
|
|
11367
|
+
await this.globTestSpecifications();
|
|
10828
11368
|
if (this.config.watch) {
|
|
10829
11369
|
await this.report("onWatcherStart");
|
|
10830
11370
|
}
|
|
10831
11371
|
}
|
|
10832
|
-
async getTestDependencies(spec, deps = /* @__PURE__ */ new Set()) {
|
|
10833
|
-
const addImports = async (project, filepath) => {
|
|
10834
|
-
if (deps.has(filepath)) {
|
|
10835
|
-
return;
|
|
10836
|
-
}
|
|
10837
|
-
deps.add(filepath);
|
|
10838
|
-
const mod = project.vite.moduleGraph.getModuleById(filepath);
|
|
10839
|
-
const transformed = mod?.ssrTransformResult || await project.vitenode.transformRequest(filepath);
|
|
10840
|
-
if (!transformed) {
|
|
10841
|
-
return;
|
|
10842
|
-
}
|
|
10843
|
-
const dependencies = [...transformed.deps || [], ...transformed.dynamicDeps || []];
|
|
10844
|
-
await Promise.all(dependencies.map(async (dep) => {
|
|
10845
|
-
const path = await project.vite.pluginContainer.resolveId(dep, filepath, { ssr: true });
|
|
10846
|
-
const fsPath = path && !path.external && path.id.split("?")[0];
|
|
10847
|
-
if (fsPath && !fsPath.includes("node_modules") && !deps.has(fsPath) && existsSync(fsPath)) {
|
|
10848
|
-
await addImports(project, fsPath);
|
|
10849
|
-
}
|
|
10850
|
-
}));
|
|
10851
|
-
};
|
|
10852
|
-
await addImports(spec.project, spec.moduleId);
|
|
10853
|
-
deps.delete(spec.moduleId);
|
|
10854
|
-
return deps;
|
|
10855
|
-
}
|
|
10856
|
-
async filterTestsBySource(specs) {
|
|
10857
|
-
if (this.config.changed && !this.config.related) {
|
|
10858
|
-
const { VitestGit } = await import('./git.B5SDxu-n.js');
|
|
10859
|
-
const vitestGit = new VitestGit(this.config.root);
|
|
10860
|
-
const related2 = await vitestGit.findChangedFiles({
|
|
10861
|
-
changedSince: this.config.changed
|
|
10862
|
-
});
|
|
10863
|
-
if (!related2) {
|
|
10864
|
-
process.exitCode = 1;
|
|
10865
|
-
throw new GitNotFoundError();
|
|
10866
|
-
}
|
|
10867
|
-
this.config.related = Array.from(new Set(related2));
|
|
10868
|
-
}
|
|
10869
|
-
const related = this.config.related;
|
|
10870
|
-
if (!related) {
|
|
10871
|
-
return specs;
|
|
10872
|
-
}
|
|
10873
|
-
const forceRerunTriggers = this.config.forceRerunTriggers;
|
|
10874
|
-
if (forceRerunTriggers.length && mm(related, forceRerunTriggers).length) {
|
|
10875
|
-
return specs;
|
|
10876
|
-
}
|
|
10877
|
-
if (!this.config.watch && !related.length) {
|
|
10878
|
-
return [];
|
|
10879
|
-
}
|
|
10880
|
-
const testGraphs = await Promise.all(
|
|
10881
|
-
specs.map(async (spec) => {
|
|
10882
|
-
const deps = await this.getTestDependencies(spec);
|
|
10883
|
-
return [spec, deps];
|
|
10884
|
-
})
|
|
10885
|
-
);
|
|
10886
|
-
const runningTests = [];
|
|
10887
|
-
for (const [filepath, deps] of testGraphs) {
|
|
10888
|
-
if (related.some((path) => path === filepath[1] || deps.has(path))) {
|
|
10889
|
-
runningTests.push(filepath);
|
|
10890
|
-
}
|
|
10891
|
-
}
|
|
10892
|
-
return runningTests;
|
|
10893
|
-
}
|
|
10894
11372
|
/**
|
|
10895
|
-
* @deprecated remove when vscode extension supports "
|
|
11373
|
+
* @deprecated remove when vscode extension supports "getModuleSpecifications"
|
|
10896
11374
|
*/
|
|
10897
11375
|
getProjectsByTestFile(file) {
|
|
10898
|
-
return this.
|
|
11376
|
+
return this.getModuleSpecifications(file);
|
|
10899
11377
|
}
|
|
11378
|
+
/** @deprecated */
|
|
10900
11379
|
getFileWorkspaceSpecs(file) {
|
|
10901
|
-
|
|
10902
|
-
if (_cached) {
|
|
10903
|
-
return _cached;
|
|
10904
|
-
}
|
|
10905
|
-
const specs = [];
|
|
10906
|
-
for (const project of this.projects) {
|
|
10907
|
-
if (project.isTestFile(file)) {
|
|
10908
|
-
specs.push(project.createSpecification(file));
|
|
10909
|
-
}
|
|
10910
|
-
if (project.isTypecheckFile(file)) {
|
|
10911
|
-
specs.push(project.createSpecification(file, "typescript"));
|
|
10912
|
-
}
|
|
10913
|
-
}
|
|
10914
|
-
specs.forEach((spec) => this.ensureSpecCached(spec));
|
|
10915
|
-
return specs;
|
|
11380
|
+
return this.getModuleSpecifications(file);
|
|
10916
11381
|
}
|
|
10917
|
-
|
|
10918
|
-
|
|
10919
|
-
|
|
10920
|
-
|
|
10921
|
-
|
|
10922
|
-
|
|
10923
|
-
|
|
10924
|
-
|
|
10925
|
-
|
|
11382
|
+
/**
|
|
11383
|
+
* Get test specifications assosiated with the given module. If module is not a test file, an empty array is returned.
|
|
11384
|
+
*
|
|
11385
|
+
* **Note:** this method relies on a cache generated by `globTestSpecifications`. If the file was not processed yet, use `project.matchesGlobPattern` instead.
|
|
11386
|
+
* @param moduleId The module ID to get test specifications for.
|
|
11387
|
+
*/
|
|
11388
|
+
getModuleSpecifications(moduleId) {
|
|
11389
|
+
return this.specifications.getModuleSpecifications(moduleId);
|
|
11390
|
+
}
|
|
11391
|
+
/**
|
|
11392
|
+
* Vitest automatically caches test specifications for each file. This method clears the cache for the given file or the whole cache alltogether.
|
|
11393
|
+
*/
|
|
11394
|
+
clearSpecificationsCache(moduleId) {
|
|
11395
|
+
this.specifications.clearCache(moduleId);
|
|
11396
|
+
}
|
|
11397
|
+
/**
|
|
11398
|
+
* Run tests for the given test specifications. This does not trigger `onWatcher*` events.
|
|
11399
|
+
* @param specifications A list of specifications to run.
|
|
11400
|
+
* @param allTestsRun Indicates whether all tests were run. This only matters for coverage.
|
|
11401
|
+
*/
|
|
11402
|
+
runTestSpecifications(specifications, allTestsRun = false) {
|
|
11403
|
+
specifications.forEach((spec) => this.specifications.ensureSpecificationCached(spec));
|
|
11404
|
+
return this.runFiles(specifications, allTestsRun);
|
|
11405
|
+
}
|
|
11406
|
+
/**
|
|
11407
|
+
* Rerun files and trigger `onWatcherRerun`, `onWatcherStart` and `onTestsRerun` events.
|
|
11408
|
+
* @param specifications A list of specifications to run.
|
|
11409
|
+
* @param allTestsRun Indicates whether all tests were run. This only matters for coverage.
|
|
11410
|
+
*/
|
|
11411
|
+
async rerunTestSpecifications(specifications, allTestsRun = false) {
|
|
11412
|
+
this.configOverride.testNamePattern = void 0;
|
|
11413
|
+
const files = specifications.map((spec) => spec.moduleId);
|
|
11414
|
+
await Promise.all([
|
|
11415
|
+
this.report("onWatcherRerun", files, "rerun test"),
|
|
11416
|
+
...this._onUserTestsRerun.map((fn) => fn(specifications))
|
|
11417
|
+
]);
|
|
11418
|
+
const result = await this.runTestSpecifications(specifications, allTestsRun);
|
|
11419
|
+
await this.report("onWatcherStart", this.state.getFiles(files));
|
|
11420
|
+
return result;
|
|
10926
11421
|
}
|
|
10927
11422
|
async runFiles(specs, allTestsRun) {
|
|
10928
11423
|
const filepaths = specs.map((spec) => spec.moduleId);
|
|
@@ -10933,35 +11428,42 @@ class Vitest {
|
|
|
10933
11428
|
this._onCancelListeners = [];
|
|
10934
11429
|
this.isCancelling = false;
|
|
10935
11430
|
this.runningPromise = (async () => {
|
|
10936
|
-
if (!this.pool) {
|
|
10937
|
-
this.pool = createPool(this);
|
|
10938
|
-
}
|
|
10939
|
-
const invalidates = Array.from(this.invalidates);
|
|
10940
|
-
this.invalidates.clear();
|
|
10941
|
-
this.snapshot.clear();
|
|
10942
|
-
this.state.clearErrors();
|
|
10943
|
-
if (!this.isFirstRun && this.config.coverage.cleanOnRerun) {
|
|
10944
|
-
await this.coverageProvider?.clean();
|
|
10945
|
-
}
|
|
10946
|
-
await this.initializeGlobalSetup(specs);
|
|
10947
11431
|
try {
|
|
10948
|
-
|
|
10949
|
-
|
|
10950
|
-
|
|
10951
|
-
|
|
10952
|
-
|
|
10953
|
-
|
|
10954
|
-
|
|
11432
|
+
if (!this.pool) {
|
|
11433
|
+
this.pool = createPool(this);
|
|
11434
|
+
}
|
|
11435
|
+
const invalidates = Array.from(this.watcher.invalidates);
|
|
11436
|
+
this.watcher.invalidates.clear();
|
|
11437
|
+
this.snapshot.clear();
|
|
11438
|
+
this.state.clearErrors();
|
|
11439
|
+
if (!this.isFirstRun && this.config.coverage.cleanOnRerun) {
|
|
11440
|
+
await this.coverageProvider?.clean();
|
|
11441
|
+
}
|
|
11442
|
+
await this.initializeGlobalSetup(specs);
|
|
11443
|
+
try {
|
|
11444
|
+
await this.pool.runTests(specs, invalidates);
|
|
11445
|
+
} catch (err) {
|
|
11446
|
+
this.state.catchError(err, "Unhandled Error");
|
|
11447
|
+
}
|
|
11448
|
+
const files = this.state.getFiles();
|
|
11449
|
+
if (hasFailed(files)) {
|
|
11450
|
+
process.exitCode = 1;
|
|
11451
|
+
}
|
|
11452
|
+
this.cache.results.updateResults(files);
|
|
11453
|
+
await this.cache.results.writeToCache();
|
|
11454
|
+
return {
|
|
11455
|
+
testModules: this.state.getTestModules(),
|
|
11456
|
+
unhandledErrors: this.state.getUnhandledErrors()
|
|
11457
|
+
};
|
|
11458
|
+
} finally {
|
|
11459
|
+
const files = Array.from(new Set(specs.map((spec) => spec.moduleId)));
|
|
11460
|
+
const errors = this.state.getUnhandledErrors();
|
|
11461
|
+
const coverage = await this.coverageProvider?.generateCoverage({ allTestsRun });
|
|
11462
|
+
this._checkUnhandledErrors(errors);
|
|
11463
|
+
await this.report("onFinished", this.state.getFiles(files), errors, coverage);
|
|
11464
|
+
await this.reportCoverage(coverage, allTestsRun);
|
|
10955
11465
|
}
|
|
10956
|
-
|
|
10957
|
-
await this.cache.results.writeToCache();
|
|
10958
|
-
})().finally(async () => {
|
|
10959
|
-
const files = Array.from(new Set(specs.map((spec) => spec.moduleId)));
|
|
10960
|
-
const errors = this.state.getUnhandledErrors();
|
|
10961
|
-
const coverage = await this.coverageProvider?.generateCoverage({ allTestsRun });
|
|
10962
|
-
this.checkUnhandledErrors(errors);
|
|
10963
|
-
await this.report("onFinished", this.state.getFiles(files), errors, coverage);
|
|
10964
|
-
await this.reportCoverage(coverage, allTestsRun);
|
|
11466
|
+
})().finally(() => {
|
|
10965
11467
|
this.runningPromise = void 0;
|
|
10966
11468
|
this.isFirstRun = false;
|
|
10967
11469
|
this.config.changed = false;
|
|
@@ -10969,8 +11471,12 @@ class Vitest {
|
|
|
10969
11471
|
});
|
|
10970
11472
|
return await this.runningPromise;
|
|
10971
11473
|
}
|
|
10972
|
-
|
|
10973
|
-
|
|
11474
|
+
/**
|
|
11475
|
+
* Collect tests in specified modules. Vitest will run the files to collect tests.
|
|
11476
|
+
* @param specifications A list of specifications to run.
|
|
11477
|
+
*/
|
|
11478
|
+
async collectTests(specifications) {
|
|
11479
|
+
const filepaths = specifications.map((spec) => spec.moduleId);
|
|
10974
11480
|
this.state.collectPaths(filepaths);
|
|
10975
11481
|
await this.runningPromise;
|
|
10976
11482
|
this._onCancelListeners = [];
|
|
@@ -10979,13 +11485,13 @@ class Vitest {
|
|
|
10979
11485
|
if (!this.pool) {
|
|
10980
11486
|
this.pool = createPool(this);
|
|
10981
11487
|
}
|
|
10982
|
-
const invalidates = Array.from(this.invalidates);
|
|
10983
|
-
this.invalidates.clear();
|
|
11488
|
+
const invalidates = Array.from(this.watcher.invalidates);
|
|
11489
|
+
this.watcher.invalidates.clear();
|
|
10984
11490
|
this.snapshot.clear();
|
|
10985
11491
|
this.state.clearErrors();
|
|
10986
|
-
await this.initializeGlobalSetup(
|
|
11492
|
+
await this.initializeGlobalSetup(specifications);
|
|
10987
11493
|
try {
|
|
10988
|
-
await this.pool.collectTests(
|
|
11494
|
+
await this.pool.collectTests(specifications, invalidates);
|
|
10989
11495
|
} catch (err) {
|
|
10990
11496
|
this.state.catchError(err, "Unhandled Error");
|
|
10991
11497
|
}
|
|
@@ -10993,38 +11499,56 @@ class Vitest {
|
|
|
10993
11499
|
if (hasFailed(files)) {
|
|
10994
11500
|
process.exitCode = 1;
|
|
10995
11501
|
}
|
|
10996
|
-
|
|
11502
|
+
return {
|
|
11503
|
+
testModules: this.state.getTestModules(),
|
|
11504
|
+
unhandledErrors: this.state.getUnhandledErrors()
|
|
11505
|
+
};
|
|
11506
|
+
})().finally(() => {
|
|
10997
11507
|
this.runningPromise = void 0;
|
|
10998
11508
|
this.config.changed = false;
|
|
10999
11509
|
this.config.related = void 0;
|
|
11000
11510
|
});
|
|
11001
11511
|
return await this.runningPromise;
|
|
11002
11512
|
}
|
|
11513
|
+
/**
|
|
11514
|
+
* Gracefully cancel the current test run. Vitest will wait until all running tests are finished before cancelling.
|
|
11515
|
+
*/
|
|
11003
11516
|
async cancelCurrentRun(reason) {
|
|
11004
11517
|
this.isCancelling = true;
|
|
11005
11518
|
await Promise.all(this._onCancelListeners.splice(0).map((listener) => listener(reason)));
|
|
11006
11519
|
}
|
|
11007
|
-
|
|
11520
|
+
/** @internal */
|
|
11521
|
+
async _initBrowserServers() {
|
|
11008
11522
|
await Promise.all(this.projects.map((p) => p._initBrowserServer()));
|
|
11009
11523
|
}
|
|
11524
|
+
async initializeGlobalSetup(paths) {
|
|
11525
|
+
const projects = new Set(paths.map((spec) => spec.project));
|
|
11526
|
+
const coreProject = this.getRootProject();
|
|
11527
|
+
if (!projects.has(coreProject)) {
|
|
11528
|
+
projects.add(coreProject);
|
|
11529
|
+
}
|
|
11530
|
+
for (const project of projects) {
|
|
11531
|
+
await project._initializeGlobalSetup();
|
|
11532
|
+
}
|
|
11533
|
+
}
|
|
11534
|
+
/** @internal */
|
|
11010
11535
|
async rerunFiles(files = this.state.getFilepaths(), trigger, allTestsRun = true, resetTestNamePattern = false) {
|
|
11011
11536
|
if (resetTestNamePattern) {
|
|
11012
11537
|
this.configOverride.testNamePattern = void 0;
|
|
11013
11538
|
}
|
|
11014
11539
|
if (this.filenamePattern) {
|
|
11015
|
-
const filteredFiles = await this.
|
|
11016
|
-
files = files.filter((file) => filteredFiles.some((f) => f
|
|
11540
|
+
const filteredFiles = await this.globTestSpecifications(this.filenamePattern);
|
|
11541
|
+
files = files.filter((file) => filteredFiles.some((f) => f.moduleId === file));
|
|
11017
11542
|
}
|
|
11543
|
+
const specifications = files.flatMap((file) => this.getModuleSpecifications(file));
|
|
11018
11544
|
await Promise.all([
|
|
11019
11545
|
this.report("onWatcherRerun", files, trigger),
|
|
11020
|
-
...this._onUserTestsRerun.map((fn) => fn(
|
|
11546
|
+
...this._onUserTestsRerun.map((fn) => fn(specifications))
|
|
11021
11547
|
]);
|
|
11022
|
-
await this.runFiles(
|
|
11548
|
+
await this.runFiles(specifications, allTestsRun);
|
|
11023
11549
|
await this.report("onWatcherStart", this.state.getFiles(files));
|
|
11024
11550
|
}
|
|
11025
|
-
|
|
11026
|
-
return Object.hasOwnProperty.call(task, "tasks");
|
|
11027
|
-
}
|
|
11551
|
+
/** @internal */
|
|
11028
11552
|
async rerunTask(id) {
|
|
11029
11553
|
const task = this.state.idMap.get(id);
|
|
11030
11554
|
if (!task) {
|
|
@@ -11033,19 +11557,21 @@ class Vitest {
|
|
|
11033
11557
|
await this.changeNamePattern(
|
|
11034
11558
|
task.name,
|
|
11035
11559
|
[task.file.filepath],
|
|
11036
|
-
|
|
11560
|
+
"tasks" in task ? "rerun suite" : "rerun test"
|
|
11037
11561
|
);
|
|
11038
11562
|
}
|
|
11563
|
+
/** @internal */
|
|
11039
11564
|
async changeProjectName(pattern) {
|
|
11040
11565
|
if (pattern === "") {
|
|
11041
11566
|
delete this.configOverride.project;
|
|
11042
11567
|
} else {
|
|
11043
11568
|
this.configOverride.project = pattern;
|
|
11044
11569
|
}
|
|
11045
|
-
this.projects = this.resolvedProjects.filter((p) => p.
|
|
11046
|
-
const files = (await this.
|
|
11570
|
+
this.projects = this.resolvedProjects.filter((p) => p.name === pattern);
|
|
11571
|
+
const files = (await this.globTestSpecifications()).map((spec) => spec.moduleId);
|
|
11047
11572
|
await this.rerunFiles(files, "change project filter", pattern === "");
|
|
11048
11573
|
}
|
|
11574
|
+
/** @internal */
|
|
11049
11575
|
async changeNamePattern(pattern, files = this.state.getFilepaths(), trigger) {
|
|
11050
11576
|
if (pattern === "") {
|
|
11051
11577
|
this.filenamePattern = void 0;
|
|
@@ -11063,31 +11589,68 @@ class Vitest {
|
|
|
11063
11589
|
}
|
|
11064
11590
|
await this.rerunFiles(files, trigger, pattern === "");
|
|
11065
11591
|
}
|
|
11592
|
+
/** @internal */
|
|
11066
11593
|
async changeFilenamePattern(pattern, files = this.state.getFilepaths()) {
|
|
11067
|
-
this.filenamePattern = pattern;
|
|
11068
|
-
const trigger = this.filenamePattern ? "change filename pattern" : "reset filename pattern";
|
|
11594
|
+
this.filenamePattern = pattern ? [pattern] : [];
|
|
11595
|
+
const trigger = this.filenamePattern.length ? "change filename pattern" : "reset filename pattern";
|
|
11069
11596
|
await this.rerunFiles(files, trigger, pattern === "");
|
|
11070
11597
|
}
|
|
11598
|
+
/** @internal */
|
|
11071
11599
|
async rerunFailed() {
|
|
11072
11600
|
await this.rerunFiles(this.state.getFailedFilepaths(), "rerun failed", false);
|
|
11073
11601
|
}
|
|
11602
|
+
/** @internal */
|
|
11074
11603
|
async updateSnapshot(files) {
|
|
11075
11604
|
files = files || [
|
|
11076
11605
|
...this.state.getFailedFilepaths(),
|
|
11077
11606
|
...this.snapshot.summary.uncheckedKeysByFile.map((s) => s.filePath)
|
|
11078
11607
|
];
|
|
11608
|
+
this.enableSnapshotUpdate();
|
|
11609
|
+
try {
|
|
11610
|
+
await this.rerunFiles(files, "update snapshot", false);
|
|
11611
|
+
} finally {
|
|
11612
|
+
this.resetSnapshotUpdate();
|
|
11613
|
+
}
|
|
11614
|
+
}
|
|
11615
|
+
/**
|
|
11616
|
+
* Enable the mode that allows updating snapshots when running tests.
|
|
11617
|
+
* This method doesn't run any tests.
|
|
11618
|
+
*
|
|
11619
|
+
* Every test that runs after this method is called will update snapshots.
|
|
11620
|
+
* To disable the mode, call `resetSnapshotUpdate`.
|
|
11621
|
+
*/
|
|
11622
|
+
enableSnapshotUpdate() {
|
|
11079
11623
|
this.configOverride.snapshotOptions = {
|
|
11080
11624
|
updateSnapshot: "all",
|
|
11081
11625
|
// environment is resolved inside a worker thread
|
|
11082
11626
|
snapshotEnvironment: null
|
|
11083
11627
|
};
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11628
|
+
}
|
|
11629
|
+
/**
|
|
11630
|
+
* Disable the mode that allows updating snapshots when running tests.
|
|
11631
|
+
*/
|
|
11632
|
+
resetSnapshotUpdate() {
|
|
11633
|
+
delete this.configOverride.snapshotOptions;
|
|
11634
|
+
}
|
|
11635
|
+
/**
|
|
11636
|
+
* Set the global test name pattern to a regexp.
|
|
11637
|
+
* This method doesn't run any tests.
|
|
11638
|
+
*/
|
|
11639
|
+
setGlobalTestNamePattern(pattern) {
|
|
11640
|
+
if (pattern instanceof RegExp) {
|
|
11641
|
+
this.configOverride.testNamePattern = pattern;
|
|
11642
|
+
} else {
|
|
11643
|
+
this.configOverride.testNamePattern = pattern ? new RegExp(pattern) : void 0;
|
|
11088
11644
|
}
|
|
11089
11645
|
}
|
|
11646
|
+
/**
|
|
11647
|
+
* Resets the global test name pattern. This method doesn't run any tests.
|
|
11648
|
+
*/
|
|
11649
|
+
resetGlobalTestNamePattern() {
|
|
11650
|
+
this.configOverride.testNamePattern = void 0;
|
|
11651
|
+
}
|
|
11090
11652
|
_rerunTimer;
|
|
11653
|
+
// we can't use a single `triggerId` yet because vscode extension relies on this
|
|
11091
11654
|
async scheduleRerun(triggerId) {
|
|
11092
11655
|
const currentCount = this.restartsCount;
|
|
11093
11656
|
clearTimeout(this._rerunTimer);
|
|
@@ -11097,15 +11660,8 @@ class Vitest {
|
|
|
11097
11660
|
return;
|
|
11098
11661
|
}
|
|
11099
11662
|
this._rerunTimer = setTimeout(async () => {
|
|
11100
|
-
if (this.
|
|
11101
|
-
this.
|
|
11102
|
-
if (!this.watchedTests.has(test)) {
|
|
11103
|
-
this.changedTests.delete(test);
|
|
11104
|
-
}
|
|
11105
|
-
});
|
|
11106
|
-
}
|
|
11107
|
-
if (this.changedTests.size === 0) {
|
|
11108
|
-
this.invalidates.clear();
|
|
11663
|
+
if (this.watcher.changedTests.size === 0) {
|
|
11664
|
+
this.watcher.invalidates.clear();
|
|
11109
11665
|
return;
|
|
11110
11666
|
}
|
|
11111
11667
|
if (this.restartsCount !== currentCount) {
|
|
@@ -11113,161 +11669,54 @@ class Vitest {
|
|
|
11113
11669
|
}
|
|
11114
11670
|
this.isFirstRun = false;
|
|
11115
11671
|
this.snapshot.clear();
|
|
11116
|
-
let files = Array.from(this.changedTests);
|
|
11672
|
+
let files = Array.from(this.watcher.changedTests);
|
|
11117
11673
|
if (this.filenamePattern) {
|
|
11118
|
-
const filteredFiles = await this.
|
|
11119
|
-
files = files.filter((file) => filteredFiles.some((f) => f
|
|
11674
|
+
const filteredFiles = await this.globTestSpecifications(this.filenamePattern);
|
|
11675
|
+
files = files.filter((file) => filteredFiles.some((f) => f.moduleId === file));
|
|
11120
11676
|
if (files.length === 0) {
|
|
11121
11677
|
return;
|
|
11122
11678
|
}
|
|
11123
11679
|
}
|
|
11124
|
-
this.changedTests.clear();
|
|
11680
|
+
this.watcher.changedTests.clear();
|
|
11125
11681
|
const triggerIds = new Set(triggerId.map((id) => relative(this.config.root, id)));
|
|
11126
11682
|
const triggerLabel = Array.from(triggerIds).join(", ");
|
|
11683
|
+
const specifications = files.flatMap((file) => this.getModuleSpecifications(file)).filter((specification) => {
|
|
11684
|
+
if (this._onFilterWatchedSpecification.length === 0) {
|
|
11685
|
+
return true;
|
|
11686
|
+
}
|
|
11687
|
+
return this._onFilterWatchedSpecification.every((fn) => fn(specification));
|
|
11688
|
+
});
|
|
11127
11689
|
await Promise.all([
|
|
11128
11690
|
this.report("onWatcherRerun", files, triggerLabel),
|
|
11129
|
-
...this._onUserTestsRerun.map((fn) => fn(
|
|
11691
|
+
...this._onUserTestsRerun.map((fn) => fn(specifications))
|
|
11130
11692
|
]);
|
|
11131
|
-
await this.runFiles(
|
|
11693
|
+
await this.runFiles(specifications, false);
|
|
11132
11694
|
await this.report("onWatcherStart", this.state.getFiles(files));
|
|
11133
11695
|
}, WATCHER_DEBOUNCE);
|
|
11134
11696
|
}
|
|
11135
|
-
getModuleProjects(filepath) {
|
|
11136
|
-
return this.projects.filter((project) => {
|
|
11137
|
-
return project.getModulesByFilepath(filepath).size;
|
|
11138
|
-
});
|
|
11139
|
-
}
|
|
11140
11697
|
/**
|
|
11141
|
-
*
|
|
11698
|
+
* Invalidate a file in all projects.
|
|
11142
11699
|
*/
|
|
11143
|
-
|
|
11144
|
-
this.
|
|
11145
|
-
|
|
11146
|
-
|
|
11147
|
-
}
|
|
11148
|
-
updateLastChanged(filepath) {
|
|
11149
|
-
const projects = this.getModuleProjects(filepath);
|
|
11150
|
-
projects.forEach(({ server, browser }) => {
|
|
11151
|
-
const serverMods = server.moduleGraph.getModulesByFile(filepath);
|
|
11152
|
-
serverMods?.forEach((mod) => server.moduleGraph.invalidateModule(mod));
|
|
11700
|
+
invalidateFile(filepath) {
|
|
11701
|
+
this.projects.forEach(({ vite, browser }) => {
|
|
11702
|
+
const serverMods = vite.moduleGraph.getModulesByFile(filepath);
|
|
11703
|
+
serverMods?.forEach((mod) => vite.moduleGraph.invalidateModule(mod));
|
|
11153
11704
|
if (browser) {
|
|
11154
11705
|
const browserMods = browser.vite.moduleGraph.getModulesByFile(filepath);
|
|
11155
11706
|
browserMods?.forEach((mod) => browser.vite.moduleGraph.invalidateModule(mod));
|
|
11156
11707
|
}
|
|
11157
11708
|
});
|
|
11158
11709
|
}
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
this.
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
this.scheduleRerun(needsRerun);
|
|
11166
|
-
}
|
|
11167
|
-
};
|
|
11168
|
-
onUnlink = (id) => {
|
|
11169
|
-
id = slash(id);
|
|
11170
|
-
this.logger.clearHighlightCache(id);
|
|
11171
|
-
this.invalidates.add(id);
|
|
11172
|
-
if (this.state.filesMap.has(id)) {
|
|
11173
|
-
this.state.filesMap.delete(id);
|
|
11174
|
-
this.cache.results.removeFromCache(id);
|
|
11175
|
-
this.cache.stats.removeStats(id);
|
|
11176
|
-
this.changedTests.delete(id);
|
|
11177
|
-
this.report("onTestRemoved", id);
|
|
11178
|
-
}
|
|
11179
|
-
};
|
|
11180
|
-
onAdd = async (id) => {
|
|
11181
|
-
id = slash(id);
|
|
11182
|
-
this.updateLastChanged(id);
|
|
11183
|
-
const fileContent = readFileSync(id, "utf-8");
|
|
11184
|
-
const matchingProjects = [];
|
|
11185
|
-
this.projects.forEach((project) => {
|
|
11186
|
-
if (project.matchesTestGlob(id, fileContent)) {
|
|
11187
|
-
matchingProjects.push(project);
|
|
11188
|
-
project._markTestFile(id);
|
|
11189
|
-
}
|
|
11190
|
-
});
|
|
11191
|
-
if (matchingProjects.length > 0) {
|
|
11192
|
-
this.changedTests.add(id);
|
|
11193
|
-
this.scheduleRerun([id]);
|
|
11194
|
-
} else {
|
|
11195
|
-
const needsRerun = this.handleFileChanged(id);
|
|
11196
|
-
if (needsRerun.length) {
|
|
11197
|
-
this.scheduleRerun(needsRerun);
|
|
11198
|
-
}
|
|
11199
|
-
}
|
|
11200
|
-
};
|
|
11201
|
-
checkUnhandledErrors(errors) {
|
|
11710
|
+
/** @deprecated use `invalidateFile` */
|
|
11711
|
+
updateLastChanged(filepath) {
|
|
11712
|
+
this.invalidateFile(filepath);
|
|
11713
|
+
}
|
|
11714
|
+
/** @internal */
|
|
11715
|
+
_checkUnhandledErrors(errors) {
|
|
11202
11716
|
if (errors.length && !this.config.dangerouslyIgnoreUnhandledErrors) {
|
|
11203
11717
|
process.exitCode = 1;
|
|
11204
11718
|
}
|
|
11205
11719
|
}
|
|
11206
|
-
unregisterWatcher = noop;
|
|
11207
|
-
registerWatcher() {
|
|
11208
|
-
const watcher = this.server.watcher;
|
|
11209
|
-
if (this.config.forceRerunTriggers.length) {
|
|
11210
|
-
watcher.add(this.config.forceRerunTriggers);
|
|
11211
|
-
}
|
|
11212
|
-
watcher.on("change", this.onChange);
|
|
11213
|
-
watcher.on("unlink", this.onUnlink);
|
|
11214
|
-
watcher.on("add", this.onAdd);
|
|
11215
|
-
this.unregisterWatcher = () => {
|
|
11216
|
-
watcher.off("change", this.onChange);
|
|
11217
|
-
watcher.off("unlink", this.onUnlink);
|
|
11218
|
-
watcher.off("add", this.onAdd);
|
|
11219
|
-
this.unregisterWatcher = noop;
|
|
11220
|
-
};
|
|
11221
|
-
}
|
|
11222
|
-
/**
|
|
11223
|
-
* @returns A value indicating whether rerun is needed (changedTests was mutated)
|
|
11224
|
-
*/
|
|
11225
|
-
handleFileChanged(filepath) {
|
|
11226
|
-
if (this.changedTests.has(filepath) || this.invalidates.has(filepath)) {
|
|
11227
|
-
return [];
|
|
11228
|
-
}
|
|
11229
|
-
if (mm.isMatch(filepath, this.config.forceRerunTriggers)) {
|
|
11230
|
-
this.state.getFilepaths().forEach((file) => this.changedTests.add(file));
|
|
11231
|
-
return [filepath];
|
|
11232
|
-
}
|
|
11233
|
-
const projects = this.getModuleProjects(filepath);
|
|
11234
|
-
if (!projects.length) {
|
|
11235
|
-
if (this.state.filesMap.has(filepath) || this.projects.some((project) => project.isTestFile(filepath))) {
|
|
11236
|
-
this.changedTests.add(filepath);
|
|
11237
|
-
return [filepath];
|
|
11238
|
-
}
|
|
11239
|
-
return [];
|
|
11240
|
-
}
|
|
11241
|
-
const files = [];
|
|
11242
|
-
for (const project of projects) {
|
|
11243
|
-
const mods = project.getModulesByFilepath(filepath);
|
|
11244
|
-
if (!mods.size) {
|
|
11245
|
-
continue;
|
|
11246
|
-
}
|
|
11247
|
-
this.invalidates.add(filepath);
|
|
11248
|
-
if (this.state.filesMap.has(filepath) || project.isTestFile(filepath)) {
|
|
11249
|
-
this.changedTests.add(filepath);
|
|
11250
|
-
files.push(filepath);
|
|
11251
|
-
continue;
|
|
11252
|
-
}
|
|
11253
|
-
let rerun = false;
|
|
11254
|
-
for (const mod of mods) {
|
|
11255
|
-
mod.importers.forEach((i) => {
|
|
11256
|
-
if (!i.file) {
|
|
11257
|
-
return;
|
|
11258
|
-
}
|
|
11259
|
-
const heedsRerun = this.handleFileChanged(i.file);
|
|
11260
|
-
if (heedsRerun.length) {
|
|
11261
|
-
rerun = true;
|
|
11262
|
-
}
|
|
11263
|
-
});
|
|
11264
|
-
}
|
|
11265
|
-
if (rerun) {
|
|
11266
|
-
files.push(filepath);
|
|
11267
|
-
}
|
|
11268
|
-
}
|
|
11269
|
-
return Array.from(new Set(files));
|
|
11270
|
-
}
|
|
11271
11720
|
async reportCoverage(coverage, allTestsRun) {
|
|
11272
11721
|
if (this.state.getCountOfFailedTests() > 0) {
|
|
11273
11722
|
await this.coverageProvider?.onTestFailure?.();
|
|
@@ -11284,19 +11733,23 @@ class Vitest {
|
|
|
11284
11733
|
}
|
|
11285
11734
|
}
|
|
11286
11735
|
}
|
|
11736
|
+
/**
|
|
11737
|
+
* Closes all projects and their associated resources.
|
|
11738
|
+
* This can only be called once; the closing promise is cached until the server restarts.
|
|
11739
|
+
*/
|
|
11287
11740
|
async close() {
|
|
11288
11741
|
if (!this.closingPromise) {
|
|
11289
11742
|
this.closingPromise = (async () => {
|
|
11290
11743
|
const teardownProjects = [...this.projects];
|
|
11291
|
-
if (!teardownProjects.includes(this.coreWorkspaceProject)) {
|
|
11744
|
+
if (this.coreWorkspaceProject && !teardownProjects.includes(this.coreWorkspaceProject)) {
|
|
11292
11745
|
teardownProjects.push(this.coreWorkspaceProject);
|
|
11293
11746
|
}
|
|
11294
11747
|
for (const project of teardownProjects.reverse()) {
|
|
11295
11748
|
await project._teardownGlobalSetup();
|
|
11296
11749
|
}
|
|
11297
11750
|
const closePromises = this.resolvedProjects.map((w) => w.close());
|
|
11298
|
-
if (!this.resolvedProjects.includes(this.coreWorkspaceProject)) {
|
|
11299
|
-
closePromises.push(this.coreWorkspaceProject.close().then(() => this.
|
|
11751
|
+
if (this.coreWorkspaceProject && !this.resolvedProjects.includes(this.coreWorkspaceProject)) {
|
|
11752
|
+
closePromises.push(this.coreWorkspaceProject.close().then(() => this._vite = void 0));
|
|
11300
11753
|
}
|
|
11301
11754
|
if (this.pool) {
|
|
11302
11755
|
closePromises.push((async () => {
|
|
@@ -11318,7 +11771,8 @@ class Vitest {
|
|
|
11318
11771
|
return this.closingPromise;
|
|
11319
11772
|
}
|
|
11320
11773
|
/**
|
|
11321
|
-
*
|
|
11774
|
+
* Closes all projects and exit the process
|
|
11775
|
+
* @param force If true, the process will exit immediately after closing the projects.
|
|
11322
11776
|
*/
|
|
11323
11777
|
async exit(force = false) {
|
|
11324
11778
|
setTimeout(() => {
|
|
@@ -11326,7 +11780,7 @@ class Vitest {
|
|
|
11326
11780
|
console.warn(`close timed out after ${this.config.teardownTimeout}ms`);
|
|
11327
11781
|
this.state.getProcessTimeoutCauses().forEach((cause) => console.warn(cause));
|
|
11328
11782
|
if (!this.pool) {
|
|
11329
|
-
const runningServers = [this.
|
|
11783
|
+
const runningServers = [this.vite, ...this.resolvedProjects.map((p) => p.vite)].filter(Boolean).length;
|
|
11330
11784
|
if (runningServers === 1) {
|
|
11331
11785
|
console.warn("Tests closed successfully but something prevents Vite server from exiting");
|
|
11332
11786
|
} else if (runningServers > 1) {
|
|
@@ -11344,72 +11798,90 @@ class Vitest {
|
|
|
11344
11798
|
process.exit();
|
|
11345
11799
|
}
|
|
11346
11800
|
}
|
|
11801
|
+
/** @internal */
|
|
11347
11802
|
async report(name, ...args) {
|
|
11348
11803
|
await Promise.all(this.reporters.map((r) => r[name]?.(
|
|
11349
11804
|
...args
|
|
11350
11805
|
)));
|
|
11351
11806
|
}
|
|
11352
|
-
|
|
11353
|
-
|
|
11807
|
+
/** @internal */
|
|
11808
|
+
async _globTestFilepaths() {
|
|
11809
|
+
const specifications = await this.globTestSpecifications();
|
|
11810
|
+
return Array.from(new Set(specifications.map((spec) => spec.moduleId)));
|
|
11354
11811
|
}
|
|
11812
|
+
/**
|
|
11813
|
+
* @deprecated use `globTestSpecifications` instead
|
|
11814
|
+
*/
|
|
11355
11815
|
async globTestSpecs(filters = []) {
|
|
11356
|
-
|
|
11357
|
-
await Promise.all(this.projects.map(async (project) => {
|
|
11358
|
-
const { testFiles, typecheckTestFiles } = await project.globTestFiles(filters);
|
|
11359
|
-
testFiles.forEach((file) => {
|
|
11360
|
-
const spec = project.createSpecification(file);
|
|
11361
|
-
this.ensureSpecCached(spec);
|
|
11362
|
-
files.push(spec);
|
|
11363
|
-
});
|
|
11364
|
-
typecheckTestFiles.forEach((file) => {
|
|
11365
|
-
const spec = project.createSpecification(file, "typescript");
|
|
11366
|
-
this.ensureSpecCached(spec);
|
|
11367
|
-
files.push(spec);
|
|
11368
|
-
});
|
|
11369
|
-
}));
|
|
11370
|
-
return files;
|
|
11816
|
+
return this.globTestSpecifications(filters);
|
|
11371
11817
|
}
|
|
11372
11818
|
/**
|
|
11373
|
-
* @deprecated use `
|
|
11819
|
+
* @deprecated use `globTestSpecifications` instead
|
|
11374
11820
|
*/
|
|
11375
11821
|
async globTestFiles(filters = []) {
|
|
11376
|
-
return this.
|
|
11822
|
+
return this.globTestSpecifications(filters);
|
|
11377
11823
|
}
|
|
11378
|
-
|
|
11379
|
-
|
|
11380
|
-
|
|
11381
|
-
|
|
11382
|
-
|
|
11383
|
-
specs.push(spec);
|
|
11384
|
-
this._cachedSpecs.set(file, specs);
|
|
11385
|
-
}
|
|
11824
|
+
/** @deprecated filter by `this.projects` yourself */
|
|
11825
|
+
getModuleProjects(filepath) {
|
|
11826
|
+
return this.projects.filter((project) => {
|
|
11827
|
+
return project.getModulesByFilepath(filepath).size;
|
|
11828
|
+
});
|
|
11386
11829
|
}
|
|
11387
|
-
|
|
11830
|
+
/**
|
|
11831
|
+
* Should the server be kept running after the tests are done.
|
|
11832
|
+
*/
|
|
11388
11833
|
shouldKeepServer() {
|
|
11389
11834
|
return !!this.config?.watch;
|
|
11390
11835
|
}
|
|
11836
|
+
/**
|
|
11837
|
+
* Register a handler that will be called when the server is restarted due to a config change.
|
|
11838
|
+
*/
|
|
11391
11839
|
onServerRestart(fn) {
|
|
11392
11840
|
this._onRestartListeners.push(fn);
|
|
11393
11841
|
}
|
|
11394
|
-
|
|
11395
|
-
|
|
11396
|
-
|
|
11842
|
+
/**
|
|
11843
|
+
* Register a handler that will be called when the test run is cancelled with `vitest.cancelCurrentRun`.
|
|
11844
|
+
*/
|
|
11397
11845
|
onCancel(fn) {
|
|
11398
11846
|
this._onCancelListeners.push(fn);
|
|
11399
11847
|
}
|
|
11848
|
+
/**
|
|
11849
|
+
* Register a handler that will be called when the server is closed.
|
|
11850
|
+
*/
|
|
11400
11851
|
onClose(fn) {
|
|
11401
11852
|
this._onClose.push(fn);
|
|
11402
11853
|
}
|
|
11854
|
+
/**
|
|
11855
|
+
* Register a handler that will be called when the tests are rerunning.
|
|
11856
|
+
*/
|
|
11403
11857
|
onTestsRerun(fn) {
|
|
11404
11858
|
this._onUserTestsRerun.push(fn);
|
|
11405
11859
|
}
|
|
11860
|
+
/**
|
|
11861
|
+
* Register a handler that will be called when a file is changed.
|
|
11862
|
+
* This callback should return `true` of `false` indicating whether the test file needs to be rerun.
|
|
11863
|
+
* @example
|
|
11864
|
+
* const testsToRun = [resolve('./test.spec.ts')]
|
|
11865
|
+
* vitest.onFilterWatchedSpecification(specification => testsToRun.includes(specification.moduleId))
|
|
11866
|
+
*/
|
|
11867
|
+
onFilterWatchedSpecification(fn) {
|
|
11868
|
+
this._onFilterWatchedSpecification.push(fn);
|
|
11869
|
+
}
|
|
11870
|
+
/** @internal */
|
|
11871
|
+
onAfterSetServer(fn) {
|
|
11872
|
+
this._onSetServer.push(fn);
|
|
11873
|
+
}
|
|
11874
|
+
}
|
|
11875
|
+
function assert(condition, property, name = property) {
|
|
11876
|
+
if (!condition) {
|
|
11877
|
+
throw new Error(`The ${name} was not set. It means that \`vitest.${property}\` was called before the Vite server was established. Either await the Vitest promise or check that it is initialized with \`vitest.ready()\` before accessing \`vitest.${property}\`.`);
|
|
11878
|
+
}
|
|
11406
11879
|
}
|
|
11407
11880
|
|
|
11408
11881
|
async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
|
|
11409
11882
|
const userConfig = deepMerge({}, options);
|
|
11410
|
-
const getRoot = () => ctx.config?.root || options.root || process.cwd();
|
|
11411
11883
|
async function UIPlugin() {
|
|
11412
|
-
await ctx.packageInstaller.ensureInstalled("@vitest/ui",
|
|
11884
|
+
await ctx.packageInstaller.ensureInstalled("@vitest/ui", options.root || process.cwd(), ctx.version);
|
|
11413
11885
|
return (await import('@vitest/ui')).default(ctx);
|
|
11414
11886
|
}
|
|
11415
11887
|
return [
|
|
@@ -11459,7 +11931,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
|
|
|
11459
11931
|
ws: testConfig.api?.middlewareMode ? false : void 0,
|
|
11460
11932
|
preTransformRequests: false,
|
|
11461
11933
|
fs: {
|
|
11462
|
-
allow: resolveFsAllow(
|
|
11934
|
+
allow: resolveFsAllow(options.root || process.cwd(), testConfig.config)
|
|
11463
11935
|
}
|
|
11464
11936
|
},
|
|
11465
11937
|
build: {
|
|
@@ -11535,7 +12007,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
|
|
|
11535
12007
|
config.css.modules ??= {};
|
|
11536
12008
|
if (config.css.modules) {
|
|
11537
12009
|
config.css.modules.generateScopedName = (name, filename) => {
|
|
11538
|
-
const root =
|
|
12010
|
+
const root = ctx.config.root || options.root || process.cwd();
|
|
11539
12011
|
return generateScopedClassName(
|
|
11540
12012
|
classNameStrategy,
|
|
11541
12013
|
name,
|
|
@@ -11566,6 +12038,11 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
|
|
|
11566
12038
|
viteConfig.server.watch = null;
|
|
11567
12039
|
}
|
|
11568
12040
|
hijackVitePluginInject(viteConfig);
|
|
12041
|
+
Object.defineProperty(viteConfig, "_vitest", {
|
|
12042
|
+
value: options,
|
|
12043
|
+
enumerable: false,
|
|
12044
|
+
configurable: true
|
|
12045
|
+
});
|
|
11569
12046
|
},
|
|
11570
12047
|
configureServer: {
|
|
11571
12048
|
// runs after vite:import-analysis as it relies on `server` instance on Vite 5
|
|
@@ -11576,7 +12053,7 @@ async function VitestPlugin(options = {}, ctx = new Vitest("test")) {
|
|
|
11576
12053
|
console.log("[debug] watcher is ready");
|
|
11577
12054
|
});
|
|
11578
12055
|
}
|
|
11579
|
-
await ctx.
|
|
12056
|
+
await ctx._setServer(options, server, userConfig);
|
|
11580
12057
|
if (options.api && options.watch) {
|
|
11581
12058
|
(await Promise.resolve().then(function () { return setup$1; })).setup(ctx);
|
|
11582
12059
|
}
|
|
@@ -11848,7 +12325,7 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout2) {
|
|
|
11848
12325
|
return ctx.updateSnapshot();
|
|
11849
12326
|
}
|
|
11850
12327
|
if (name === "a" || name === "return") {
|
|
11851
|
-
const files = await ctx.
|
|
12328
|
+
const files = await ctx._globTestFilepaths();
|
|
11852
12329
|
return ctx.changeNamePattern("", files, "rerun all tests");
|
|
11853
12330
|
}
|
|
11854
12331
|
if (name === "r") {
|
|
@@ -11867,7 +12344,7 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout2) {
|
|
|
11867
12344
|
return inputFilePattern();
|
|
11868
12345
|
}
|
|
11869
12346
|
if (name === "b") {
|
|
11870
|
-
await ctx.
|
|
12347
|
+
await ctx._initBrowserServers();
|
|
11871
12348
|
ctx.projects.forEach((project) => {
|
|
11872
12349
|
ctx.logger.log();
|
|
11873
12350
|
ctx.logger.printBrowserBanner(project);
|
|
@@ -11900,7 +12377,7 @@ function registerConsoleShortcuts(ctx, stdin = process.stdin, stdout2) {
|
|
|
11900
12377
|
return;
|
|
11901
12378
|
}
|
|
11902
12379
|
const files = ctx.state.getFilepaths();
|
|
11903
|
-
const cliFiles = ctx.config.standalone && !files.length ? await ctx.
|
|
12380
|
+
const cliFiles = ctx.config.standalone && !files.length ? await ctx._globTestFilepaths() : void 0;
|
|
11904
12381
|
await ctx.changeNamePattern(
|
|
11905
12382
|
filter?.trim() || "",
|
|
11906
12383
|
cliFiles,
|
|
@@ -12013,6 +12490,10 @@ async function startVitest(mode, cliFilters = [], options = {}, viteOverrides, v
|
|
|
12013
12490
|
ctx.logger.error(e.message);
|
|
12014
12491
|
return ctx;
|
|
12015
12492
|
}
|
|
12493
|
+
if (e instanceof IncludeTaskLocationDisabledError || e instanceof RangeLocationFilterProvidedError || e instanceof LocationFilterFileNotFoundError) {
|
|
12494
|
+
ctx.logger.printError(e, { verbose: false });
|
|
12495
|
+
return ctx;
|
|
12496
|
+
}
|
|
12016
12497
|
process.exitCode = 1;
|
|
12017
12498
|
ctx.logger.printError(e, { fullStack: true, type: "Unhandled Error" });
|
|
12018
12499
|
ctx.logger.error("\n\n");
|
|
@@ -12050,11 +12531,10 @@ async function prepareVitest(mode, options = {}, viteOverrides, vitestOptions) {
|
|
|
12050
12531
|
function processCollected(ctx, files, options) {
|
|
12051
12532
|
let errorsPrinted = false;
|
|
12052
12533
|
forEachSuite(files, (suite) => {
|
|
12053
|
-
|
|
12054
|
-
errors.forEach((error) => {
|
|
12534
|
+
suite.errors().forEach((error) => {
|
|
12055
12535
|
errorsPrinted = true;
|
|
12056
12536
|
ctx.logger.printError(error, {
|
|
12057
|
-
project:
|
|
12537
|
+
project: suite.project
|
|
12058
12538
|
});
|
|
12059
12539
|
});
|
|
12060
12540
|
});
|
|
@@ -12112,43 +12592,50 @@ function processJsonOutput(files, options) {
|
|
|
12112
12592
|
writeFileSync(jsonPath, JSON.stringify(formatCollectedAsJSON(files), null, 2));
|
|
12113
12593
|
}
|
|
12114
12594
|
}
|
|
12115
|
-
function forEachSuite(
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12119
|
-
|
|
12595
|
+
function forEachSuite(modules, callback) {
|
|
12596
|
+
modules.forEach((testModule) => {
|
|
12597
|
+
callback(testModule);
|
|
12598
|
+
for (const suite of testModule.children.allSuites()) {
|
|
12599
|
+
callback(suite);
|
|
12120
12600
|
}
|
|
12121
12601
|
});
|
|
12122
12602
|
}
|
|
12123
12603
|
function formatCollectedAsJSON(files) {
|
|
12124
|
-
|
|
12125
|
-
|
|
12126
|
-
|
|
12604
|
+
const results = [];
|
|
12605
|
+
files.forEach((file) => {
|
|
12606
|
+
for (const test of file.children.allTests()) {
|
|
12607
|
+
if (test.skipped()) {
|
|
12608
|
+
continue;
|
|
12609
|
+
}
|
|
12127
12610
|
const result = {
|
|
12128
|
-
name:
|
|
12129
|
-
file:
|
|
12611
|
+
name: test.fullName,
|
|
12612
|
+
file: test.module.moduleId
|
|
12130
12613
|
};
|
|
12131
|
-
if (test.
|
|
12132
|
-
result.projectName = test.
|
|
12614
|
+
if (test.project.name) {
|
|
12615
|
+
result.projectName = test.project.name;
|
|
12133
12616
|
}
|
|
12134
12617
|
if (test.location) {
|
|
12135
12618
|
result.location = test.location;
|
|
12136
12619
|
}
|
|
12137
|
-
|
|
12138
|
-
}
|
|
12139
|
-
})
|
|
12620
|
+
results.push(result);
|
|
12621
|
+
}
|
|
12622
|
+
});
|
|
12623
|
+
return results;
|
|
12140
12624
|
}
|
|
12141
|
-
function formatCollectedAsString(
|
|
12142
|
-
|
|
12143
|
-
|
|
12144
|
-
|
|
12145
|
-
|
|
12146
|
-
|
|
12147
|
-
return `[${test.file.projectName}] ${name}`;
|
|
12625
|
+
function formatCollectedAsString(testModules) {
|
|
12626
|
+
const results = [];
|
|
12627
|
+
testModules.forEach((testModule) => {
|
|
12628
|
+
for (const test of testModule.children.allTests()) {
|
|
12629
|
+
if (test.skipped()) {
|
|
12630
|
+
continue;
|
|
12148
12631
|
}
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
|
|
12632
|
+
const fullName = `${test.module.task.name} > ${test.fullName}`;
|
|
12633
|
+
results.push(
|
|
12634
|
+
(test.project.name ? `[${test.project.name}] ` : "") + fullName
|
|
12635
|
+
);
|
|
12636
|
+
}
|
|
12637
|
+
});
|
|
12638
|
+
return results;
|
|
12152
12639
|
}
|
|
12153
12640
|
const envPackageNames = {
|
|
12154
12641
|
"jsdom": "jsdom",
|
|
@@ -12178,4 +12665,4 @@ var cliApi = /*#__PURE__*/Object.freeze({
|
|
|
12178
12665
|
startVitest: startVitest
|
|
12179
12666
|
});
|
|
12180
12667
|
|
|
12181
|
-
export { FilesNotFoundError as F, GitNotFoundError as G,
|
|
12668
|
+
export { FilesNotFoundError as F, GitNotFoundError as G, 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 };
|