vitest 2.1.2 → 2.1.4
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 +320 -238
- package/dist/browser.d.ts +21 -21
- package/dist/browser.js +7 -7
- package/dist/chunks/{RandomSequencer.Bh5-tlNJ.js → RandomSequencer.CMRlh2v4.js} +143 -142
- package/dist/chunks/{base.tiemDJX6.js → base.C3xNdjV6.js} +3 -3
- package/dist/chunks/{benchmark.C8CRJYG4.js → benchmark.Cdu9hjj4.js} +2 -2
- package/dist/chunks/{benchmark.JVlTzojj.d.ts → benchmark.geERunq4.d.ts} +1 -1
- package/dist/chunks/{cac.B9PaPYY1.js → cac.DrfPaMvZ.js} +11 -10
- package/dist/chunks/{cli-api.CHxC4-U8.js → cli-api.CKrRYkw8.js} +3573 -3353
- package/dist/chunks/{console.DI3gHgtH.js → console.BYGVloWk.js} +3 -7
- package/dist/chunks/{coverage.zlNdAMHK.js → coverage.BoMDb1ip.js} +1 -1
- package/dist/chunks/{creator.Cf-MKt9i.js → creator.IIqd8RWT.js} +8 -8
- package/dist/chunks/{execute._eQQfgI8.js → execute.2pr0rHgK.js} +8 -6
- package/dist/chunks/{globals.HsM2o-0O.js → globals.Bp645TTJ.js} +8 -13
- package/dist/chunks/{index.BpSiYbpB.js → index.68735LiX.js} +28 -5
- package/dist/chunks/{index.BpojBOif.js → index.BJDntFik.js} +10 -10
- package/dist/chunks/{index.FcPVJkIQ.js → index.Bn81VaWg.js} +3828 -3790
- package/dist/chunks/{index.CPD77dLA.js → index.CqYx2Nsr.js} +7 -7
- package/dist/chunks/{index.Ckn0Cw1h.js → index.D3d79vc8.js} +6 -6
- package/dist/chunks/index.Dqe5k2Rk.js +54 -0
- package/dist/chunks/{node.Bx4JZjMG.js → node.AKq966Jp.js} +1 -5
- package/dist/chunks/{reporters.DAfKSDh5.d.ts → reporters.anwo7Y6a.d.ts} +1159 -1144
- package/dist/chunks/{resolveConfig.D1DENLPF.js → resolveConfig.DPmbhVlP.js} +2610 -2574
- package/dist/chunks/{rpc.B7Mfb-Yf.js → rpc.C3q9uwRX.js} +2 -2
- package/dist/chunks/{run-once.Sxe67Wng.js → run-once.2ogXb3JV.js} +1 -1
- package/dist/chunks/{runBaseTests.D-Gcin7G.js → runBaseTests.Dm-659zB.js} +21 -25
- package/dist/chunks/{setup-common.DF96bIYE.js → setup-common.DDmVKp6O.js} +3 -3
- package/dist/chunks/{suite.BMWOKiTe.d.ts → suite.B2jumIFP.d.ts} +2 -2
- package/dist/chunks/{utils.CY6Spixo.js → utils.BB4zjzR8.js} +2 -2
- package/dist/chunks/utils.C8RiOc4B.js +77 -0
- package/dist/chunks/{vi.DUs2eKik.js → vi.JMQoNY_Z.js} +94 -139
- package/dist/chunks/{vite.8fk186v-.d.ts → vite.BdBj-UWY.d.ts} +1 -1
- package/dist/chunks/{vm.CPXwWp4C.js → vm.jpyrB0xy.js} +5 -8
- package/dist/chunks/{worker.Chrs-_NL.d.ts → worker.BAlI9hII.d.ts} +50 -27
- package/dist/chunks/{worker.Qtv8v5nL.d.ts → worker.DHnGaO2M.d.ts} +1 -1
- package/dist/cli.js +3 -4
- package/dist/config.cjs +4 -4
- package/dist/config.d.ts +24 -19
- package/dist/config.js +4 -4
- package/dist/coverage.d.ts +72 -35
- package/dist/coverage.js +256 -118
- package/dist/environments.d.ts +2 -2
- package/dist/environments.js +1 -1
- package/dist/execute.d.ts +53 -53
- package/dist/execute.js +7 -6
- package/dist/index.d.ts +92 -1099
- package/dist/index.js +7 -18
- package/dist/node.d.ts +43 -41
- package/dist/node.js +23 -28
- package/dist/path.js +1 -1
- package/dist/reporters.d.ts +10 -10
- package/dist/reporters.js +12 -18
- package/dist/runners.d.ts +12 -19
- package/dist/runners.js +142 -148
- package/dist/snapshot.js +2 -6
- package/dist/suite.d.ts +2 -2
- package/dist/suite.js +2 -6
- package/dist/worker.js +5 -6
- package/dist/workers/forks.js +9 -8
- package/dist/workers/runVmTests.js +16 -20
- package/dist/workers/threads.js +9 -8
- package/dist/workers/vmForks.js +9 -12
- package/dist/workers/vmThreads.js +9 -12
- package/dist/workers.d.ts +13 -13
- package/dist/workers.js +14 -18
- package/package.json +27 -27
- package/dist/chunks/base.DwXGwWst.js +0 -89
- package/dist/chunks/env.CmHVDJnw.js +0 -7
- package/dist/chunks/index.CxRxs566.js +0 -23
- package/dist/chunks/index.mAqbj9F9.js +0 -140
- package/dist/chunks/tasks.BZnCS9aT.js +0 -18
- package/dist/chunks/utils.Ck2hJTRs.js +0 -23
- package/dist/chunks/{environment.CzISCQ7o.d.ts → environment.LoooBwUu.d.ts} +24 -24
- package/dist/chunks/{index.lVXYBqEP.js → index.BMoXz_-n.js} +186 -186
package/dist/config.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import '
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import '@vitest/runner';
|
|
6
|
-
import '@vitest/pretty-format';
|
|
1
|
+
import { UserConfig as UserConfig$1, ConfigEnv } from 'vite';
|
|
2
|
+
export { ConfigEnv, Plugin, UserConfig as ViteUserConfig, mergeConfig } from 'vite';
|
|
3
|
+
import { R as ResolvedCoverageOptions, c as CoverageV8Options, U as UserWorkspaceConfig, d as UserProjectConfigFn, e as UserProjectConfigExport, W as WorkspaceProjectConfiguration } from './chunks/reporters.anwo7Y6a.js';
|
|
4
|
+
import './chunks/vite.BdBj-UWY.js';
|
|
7
5
|
import './chunks/config.Crbj2GAb.js';
|
|
6
|
+
import '@vitest/pretty-format';
|
|
7
|
+
import '@vitest/runner';
|
|
8
8
|
import '@vitest/snapshot';
|
|
9
9
|
import '@vitest/snapshot/environment';
|
|
10
10
|
import 'vite-node';
|
|
11
|
-
import '
|
|
11
|
+
import 'chai';
|
|
12
|
+
import './chunks/environment.LoooBwUu.js';
|
|
12
13
|
import 'node:stream';
|
|
13
|
-
import 'vite-node/client';
|
|
14
|
-
import '@vitest/snapshot/manager';
|
|
15
|
-
import 'vite-node/server';
|
|
16
14
|
import '@vitest/utils';
|
|
17
15
|
import '@vitest/utils/source-map';
|
|
16
|
+
import 'vite-node/client';
|
|
17
|
+
import 'vite-node/server';
|
|
18
|
+
import '@vitest/snapshot/manager';
|
|
18
19
|
import 'node:fs';
|
|
19
|
-
import '
|
|
20
|
-
import './chunks/benchmark.JVlTzojj.js';
|
|
20
|
+
import './chunks/benchmark.geERunq4.js';
|
|
21
21
|
import '@vitest/runner/utils';
|
|
22
22
|
import 'tinybench';
|
|
23
23
|
|
|
@@ -71,12 +71,17 @@ declare const configDefaults: Readonly<{
|
|
|
71
71
|
disableConsoleIntercept: false;
|
|
72
72
|
}>;
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
type
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
/**
|
|
75
|
+
* @deprecated Use `ViteUserConfig` instead
|
|
76
|
+
*/
|
|
77
|
+
type UserConfig = UserConfig$1;
|
|
78
|
+
|
|
79
|
+
type UserConfigFnObject = (env: ConfigEnv) => UserConfig$1;
|
|
80
|
+
type UserConfigFnPromise = (env: ConfigEnv) => Promise<UserConfig$1>;
|
|
81
|
+
type UserConfigFn = (env: ConfigEnv) => UserConfig$1 | Promise<UserConfig$1>;
|
|
82
|
+
type UserConfigExport = UserConfig$1 | Promise<UserConfig$1> | UserConfigFnObject | UserConfigFnPromise | UserConfigFn;
|
|
83
|
+
declare function defineConfig(config: UserConfig$1): UserConfig$1;
|
|
84
|
+
declare function defineConfig(config: Promise<UserConfig$1>): Promise<UserConfig$1>;
|
|
80
85
|
declare function defineConfig(config: UserConfigFnObject): UserConfigFnObject;
|
|
81
86
|
declare function defineConfig(config: UserConfigExport): UserConfigExport;
|
|
82
87
|
declare function defineProject(config: UserWorkspaceConfig): UserWorkspaceConfig;
|
|
@@ -85,4 +90,4 @@ declare function defineProject(config: UserProjectConfigFn): UserProjectConfigFn
|
|
|
85
90
|
declare function defineProject(config: UserProjectConfigExport): UserProjectConfigExport;
|
|
86
91
|
declare function defineWorkspace(config: WorkspaceProjectConfiguration[]): WorkspaceProjectConfiguration[];
|
|
87
92
|
|
|
88
|
-
export { type UserConfigExport, type UserConfigFn, type UserConfigFnObject, type UserConfigFnPromise, UserProjectConfigExport, UserProjectConfigFn, UserWorkspaceConfig, WorkspaceProjectConfiguration, configDefaults, coverageConfigDefaults, defaultBrowserPort, defaultExclude, defaultInclude, defineConfig, defineProject, defineWorkspace, extraInlineDeps };
|
|
93
|
+
export { type UserConfig, type UserConfigExport, type UserConfigFn, type UserConfigFnObject, type UserConfigFnPromise, UserProjectConfigExport, UserProjectConfigFn, UserWorkspaceConfig, WorkspaceProjectConfiguration, configDefaults, coverageConfigDefaults, defaultBrowserPort, defaultExclude, defaultInclude, defineConfig, defineProject, defineWorkspace, extraInlineDeps };
|
package/dist/config.js
CHANGED
|
@@ -2,10 +2,6 @@ import os from 'node:os';
|
|
|
2
2
|
import { isCI } from 'std-env';
|
|
3
3
|
export { mergeConfig } from 'vite';
|
|
4
4
|
|
|
5
|
-
const isNode = typeof process < "u" && typeof process.stdout < "u" && !process.versions?.deno && !globalThis.window;
|
|
6
|
-
const isDeno = typeof process < "u" && typeof process.stdout < "u" && process.versions?.deno !== void 0;
|
|
7
|
-
(isNode || isDeno) && process.platform === "win32";
|
|
8
|
-
|
|
9
5
|
const defaultBrowserPort = 63315;
|
|
10
6
|
const extraInlineDeps = [
|
|
11
7
|
/^(?!.*node_modules).*\.mjs$/,
|
|
@@ -14,6 +10,10 @@ const extraInlineDeps = [
|
|
|
14
10
|
/vite\w*\/dist\/client\/env.mjs/
|
|
15
11
|
];
|
|
16
12
|
|
|
13
|
+
const isNode = typeof process < "u" && typeof process.stdout < "u" && !process.versions?.deno && !globalThis.window;
|
|
14
|
+
const isDeno = typeof process < "u" && typeof process.stdout < "u" && process.versions?.deno !== void 0;
|
|
15
|
+
(isNode || isDeno) && process.platform === "win32";
|
|
16
|
+
|
|
17
17
|
const defaultInclude = ["**/*.{test,spec}.?(c|m)[jt]s?(x)"];
|
|
18
18
|
const defaultExclude = [
|
|
19
19
|
"**/node_modules/**",
|
package/dist/coverage.d.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import * as vite from 'vite';
|
|
2
|
-
import {
|
|
3
|
-
import '
|
|
4
|
-
import '@vitest/pretty-format';
|
|
2
|
+
import { R as ResolvedCoverageOptions, V as Vitest, a as ReportContext } from './chunks/reporters.anwo7Y6a.js';
|
|
3
|
+
import { A as AfterSuiteRunMeta } from './chunks/environment.LoooBwUu.js';
|
|
5
4
|
import './chunks/config.Crbj2GAb.js';
|
|
5
|
+
import '@vitest/pretty-format';
|
|
6
|
+
import '@vitest/runner';
|
|
6
7
|
import '@vitest/snapshot';
|
|
7
8
|
import '@vitest/snapshot/environment';
|
|
8
9
|
import 'vite-node';
|
|
9
|
-
import '
|
|
10
|
+
import 'chai';
|
|
10
11
|
import 'node:stream';
|
|
11
|
-
import 'vite-node/client';
|
|
12
|
-
import '@vitest/snapshot/manager';
|
|
13
|
-
import 'vite-node/server';
|
|
14
12
|
import '@vitest/utils';
|
|
15
13
|
import '@vitest/utils/source-map';
|
|
14
|
+
import 'vite-node/client';
|
|
15
|
+
import 'vite-node/server';
|
|
16
|
+
import '@vitest/snapshot/manager';
|
|
16
17
|
import 'node:fs';
|
|
17
|
-
import '
|
|
18
|
-
import './chunks/benchmark.JVlTzojj.js';
|
|
18
|
+
import './chunks/benchmark.geERunq4.js';
|
|
19
19
|
import '@vitest/runner/utils';
|
|
20
20
|
import 'tinybench';
|
|
21
21
|
|
|
@@ -129,39 +129,76 @@ interface ResolvedThreshold {
|
|
|
129
129
|
name: string;
|
|
130
130
|
thresholds: Partial<Record<Threshold, number | undefined>>;
|
|
131
131
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Holds info about raw coverage results that are stored on file system:
|
|
134
|
+
*
|
|
135
|
+
* ```json
|
|
136
|
+
* "project-a": {
|
|
137
|
+
* "web": {
|
|
138
|
+
* "tests/math.test.ts": "coverage-1.json",
|
|
139
|
+
* "tests/utils.test.ts": "coverage-2.json",
|
|
140
|
+
* // ^^^^^^^^^^^^^^^ Raw coverage on file system
|
|
141
|
+
* },
|
|
142
|
+
* "ssr": { ... },
|
|
143
|
+
* "browser": { ... },
|
|
144
|
+
* },
|
|
145
|
+
* "project-b": ...
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
type CoverageFiles = Map<NonNullable<AfterSuiteRunMeta['projectName']> | symbol, Record<AfterSuiteRunMeta['transformMode'], {
|
|
149
|
+
[TestFilenames: string]: string;
|
|
150
|
+
}>>;
|
|
151
|
+
declare class BaseCoverageProvider<Options extends ResolvedCoverageOptions<'istanbul' | 'v8'>> {
|
|
152
|
+
ctx: Vitest;
|
|
153
|
+
readonly name: 'v8' | 'istanbul';
|
|
154
|
+
version: string;
|
|
155
|
+
options: Options;
|
|
156
|
+
coverageFiles: CoverageFiles;
|
|
157
|
+
pendingPromises: Promise<void>[];
|
|
158
|
+
coverageFilesDirectory: string;
|
|
159
|
+
_initialize(ctx: Vitest): void;
|
|
160
|
+
createCoverageMap(): CoverageMap;
|
|
161
|
+
generateReports(_: CoverageMap, __: boolean | undefined): Promise<void>;
|
|
162
|
+
parseConfigModule(_: string): Promise<{
|
|
163
|
+
generate: () => {
|
|
164
|
+
code: string;
|
|
165
|
+
};
|
|
166
|
+
}>;
|
|
167
|
+
resolveOptions(): Options;
|
|
168
|
+
clean(clean?: boolean): Promise<void>;
|
|
169
|
+
onAfterSuiteRun({ coverage, transformMode, projectName, testFiles }: AfterSuiteRunMeta): void;
|
|
170
|
+
readCoverageFiles<CoverageType>({ onFileRead, onFinished, onDebug }: {
|
|
171
|
+
/** Callback invoked with a single coverage result */
|
|
172
|
+
onFileRead: (data: CoverageType) => void;
|
|
173
|
+
/** Callback invoked once all results of a project for specific transform mode are read */
|
|
174
|
+
onFinished: (project: Vitest['projects'][number], transformMode: AfterSuiteRunMeta['transformMode']) => Promise<void>;
|
|
175
|
+
onDebug: ((...logs: any[]) => void) & {
|
|
176
|
+
enabled: boolean;
|
|
177
|
+
};
|
|
178
|
+
}): Promise<void>;
|
|
179
|
+
cleanAfterRun(): Promise<void>;
|
|
180
|
+
onTestFailure(): Promise<void>;
|
|
181
|
+
reportCoverage(coverageMap: unknown, { allTestsRun }: ReportContext): Promise<void>;
|
|
182
|
+
reportThresholds(coverageMap: CoverageMap, allTestsRun: boolean | undefined): Promise<void>;
|
|
150
183
|
/**
|
|
151
184
|
* Constructs collected coverage and users' threshold options into separate sets
|
|
152
185
|
* where each threshold set holds their own coverage maps. Threshold set is either
|
|
153
186
|
* for specific files defined by glob pattern or global for all other files.
|
|
154
187
|
*/
|
|
155
|
-
resolveThresholds
|
|
156
|
-
coverageMap: CoverageMap;
|
|
157
|
-
thresholds: NonNullable<BaseCoverageOptions['thresholds']>;
|
|
158
|
-
createCoverageMap: () => CoverageMap;
|
|
159
|
-
root: string;
|
|
160
|
-
}): ResolvedThreshold[];
|
|
188
|
+
private resolveThresholds;
|
|
161
189
|
/**
|
|
162
|
-
*
|
|
190
|
+
* Check collected coverage against configured thresholds. Sets exit code to 1 when thresholds not reached.
|
|
191
|
+
*/
|
|
192
|
+
private checkThresholds;
|
|
193
|
+
/**
|
|
194
|
+
* Check if current coverage is above configured thresholds and bump the thresholds if needed
|
|
163
195
|
*/
|
|
164
|
-
|
|
196
|
+
updateThresholds({ thresholds: allThresholds, onUpdate, configurationFile }: {
|
|
197
|
+
thresholds: ResolvedThreshold[];
|
|
198
|
+
configurationFile: unknown;
|
|
199
|
+
onUpdate: () => void;
|
|
200
|
+
}): Promise<void>;
|
|
201
|
+
mergeReports(coverageMaps: unknown[]): Promise<void>;
|
|
165
202
|
hasTerminalReporter(reporters: ResolvedCoverageOptions['reporter']): boolean;
|
|
166
203
|
toSlices<T>(array: T[], size: number): T[][];
|
|
167
204
|
createUncoveredFileTransformer(ctx: Vitest): (filename: string) => Promise<vite.TransformResult | null | undefined>;
|
package/dist/coverage.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { existsSync, promises, readdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { c as coverageConfigDefaults, r as resolveCoverageReporters, m as mm } from './chunks/resolveConfig.DPmbhVlP.js';
|
|
3
|
+
import { resolve, relative } from 'pathe';
|
|
4
|
+
import c from 'tinyrainbow';
|
|
5
|
+
import '@vitest/utils';
|
|
3
6
|
import 'node:path';
|
|
4
|
-
import 'node:fs';
|
|
5
7
|
import 'node:fs/promises';
|
|
6
8
|
import 'node:process';
|
|
7
9
|
import 'node:module';
|
|
@@ -9,29 +11,24 @@ import 'node:url';
|
|
|
9
11
|
import 'node:assert';
|
|
10
12
|
import 'node:v8';
|
|
11
13
|
import 'node:util';
|
|
12
|
-
import 'tinyrainbow';
|
|
13
14
|
import './chunks/constants.fzPh7AOq.js';
|
|
14
15
|
import 'node:os';
|
|
15
|
-
import './chunks/
|
|
16
|
+
import './chunks/RandomSequencer.CMRlh2v4.js';
|
|
16
17
|
import 'std-env';
|
|
17
|
-
import '@vitest/runner/utils';
|
|
18
|
-
import './chunks/base.DwXGwWst.js';
|
|
19
|
-
import '@vitest/utils';
|
|
20
|
-
import 'node:crypto';
|
|
21
|
-
import './chunks/RandomSequencer.Bh5-tlNJ.js';
|
|
22
18
|
import 'node:perf_hooks';
|
|
19
|
+
import '@vitest/runner/utils';
|
|
23
20
|
import '@vitest/utils/source-map';
|
|
24
21
|
import 'tinyexec';
|
|
25
|
-
import 'path';
|
|
26
|
-
import 'fs';
|
|
27
|
-
import 'module';
|
|
28
22
|
import 'vite';
|
|
23
|
+
import 'fs';
|
|
29
24
|
import 'vite-node/utils';
|
|
25
|
+
import 'node:crypto';
|
|
30
26
|
import './chunks/_commonjsHelpers.BFTU3MAI.js';
|
|
31
27
|
import 'util';
|
|
28
|
+
import 'path';
|
|
32
29
|
import 'node:events';
|
|
30
|
+
import './chunks/index.68735LiX.js';
|
|
33
31
|
import 'tinypool';
|
|
34
|
-
import './chunks/index.BpSiYbpB.js';
|
|
35
32
|
import 'node:worker_threads';
|
|
36
33
|
import './path.js';
|
|
37
34
|
|
|
@@ -42,125 +39,196 @@ const THRESHOLD_KEYS = [
|
|
|
42
39
|
"branches"
|
|
43
40
|
];
|
|
44
41
|
const GLOBAL_THRESHOLDS_KEY = "global";
|
|
42
|
+
const DEFAULT_PROJECT = Symbol.for("default-project");
|
|
43
|
+
let uniqueId = 0;
|
|
45
44
|
class BaseCoverageProvider {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
45
|
+
ctx;
|
|
46
|
+
name;
|
|
47
|
+
version;
|
|
48
|
+
options;
|
|
49
|
+
coverageFiles = /* @__PURE__ */ new Map();
|
|
50
|
+
pendingPromises = [];
|
|
51
|
+
coverageFilesDirectory;
|
|
52
|
+
_initialize(ctx) {
|
|
53
|
+
this.ctx = ctx;
|
|
54
|
+
if (ctx.version !== this.version) {
|
|
55
|
+
ctx.logger.warn(
|
|
56
|
+
c.yellow(
|
|
57
|
+
`Loaded ${c.inverse(c.yellow(` vitest@${ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/coverage-${this.name}@${this.version} `))}.
|
|
58
|
+
Running mixed versions is not supported and may lead into bugs
|
|
59
|
+
Update your dependencies and make sure the versions match.`
|
|
60
|
+
)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
const config = ctx.config.coverage;
|
|
64
|
+
this.options = {
|
|
65
|
+
...coverageConfigDefaults,
|
|
66
|
+
// User's options
|
|
67
|
+
...config,
|
|
68
|
+
// Resolved fields
|
|
69
|
+
provider: this.name,
|
|
70
|
+
reportsDirectory: resolve(
|
|
71
|
+
ctx.config.root,
|
|
72
|
+
config.reportsDirectory || coverageConfigDefaults.reportsDirectory
|
|
73
|
+
),
|
|
74
|
+
reporter: resolveCoverageReporters(
|
|
75
|
+
config.reporter || coverageConfigDefaults.reporter
|
|
76
|
+
),
|
|
77
|
+
thresholds: config.thresholds && {
|
|
78
|
+
...config.thresholds,
|
|
79
|
+
lines: config.thresholds["100"] ? 100 : config.thresholds.lines,
|
|
80
|
+
branches: config.thresholds["100"] ? 100 : config.thresholds.branches,
|
|
81
|
+
functions: config.thresholds["100"] ? 100 : config.thresholds.functions,
|
|
82
|
+
statements: config.thresholds["100"] ? 100 : config.thresholds.statements
|
|
83
83
|
}
|
|
84
|
+
};
|
|
85
|
+
const shard = this.ctx.config.shard;
|
|
86
|
+
const tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`;
|
|
87
|
+
this.coverageFilesDirectory = resolve(
|
|
88
|
+
this.options.reportsDirectory,
|
|
89
|
+
tempDirectory
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
createCoverageMap() {
|
|
93
|
+
throw new Error("BaseReporter's createCoverageMap was not overwritten");
|
|
94
|
+
}
|
|
95
|
+
async generateReports(_, __) {
|
|
96
|
+
throw new Error("BaseReporter's generateReports was not overwritten");
|
|
97
|
+
}
|
|
98
|
+
async parseConfigModule(_) {
|
|
99
|
+
throw new Error("BaseReporter's parseConfigModule was not overwritten");
|
|
100
|
+
}
|
|
101
|
+
resolveOptions() {
|
|
102
|
+
return this.options;
|
|
103
|
+
}
|
|
104
|
+
async clean(clean = true) {
|
|
105
|
+
if (clean && existsSync(this.options.reportsDirectory)) {
|
|
106
|
+
await promises.rm(this.options.reportsDirectory, {
|
|
107
|
+
recursive: true,
|
|
108
|
+
force: true,
|
|
109
|
+
maxRetries: 10
|
|
110
|
+
});
|
|
84
111
|
}
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
112
|
+
if (existsSync(this.coverageFilesDirectory)) {
|
|
113
|
+
await promises.rm(this.coverageFilesDirectory, {
|
|
114
|
+
recursive: true,
|
|
115
|
+
force: true,
|
|
116
|
+
maxRetries: 10
|
|
117
|
+
});
|
|
90
118
|
}
|
|
119
|
+
await promises.mkdir(this.coverageFilesDirectory, { recursive: true });
|
|
120
|
+
this.coverageFiles = /* @__PURE__ */ new Map();
|
|
121
|
+
this.pendingPromises = [];
|
|
91
122
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (perFile && file) {
|
|
127
|
-
errorMessage += ` for ${relative("./", file).replace(
|
|
128
|
-
/\\/g,
|
|
129
|
-
"/"
|
|
130
|
-
)}`;
|
|
131
|
-
}
|
|
132
|
-
onError(errorMessage);
|
|
133
|
-
}
|
|
123
|
+
onAfterSuiteRun({ coverage, transformMode, projectName, testFiles }) {
|
|
124
|
+
if (!coverage) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (transformMode !== "web" && transformMode !== "ssr" && transformMode !== "browser") {
|
|
128
|
+
throw new Error(`Invalid transform mode: ${transformMode}`);
|
|
129
|
+
}
|
|
130
|
+
let entry = this.coverageFiles.get(projectName || DEFAULT_PROJECT);
|
|
131
|
+
if (!entry) {
|
|
132
|
+
entry = { web: {}, ssr: {}, browser: {} };
|
|
133
|
+
this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry);
|
|
134
|
+
}
|
|
135
|
+
const testFilenames = testFiles.join();
|
|
136
|
+
const filename = resolve(
|
|
137
|
+
this.coverageFilesDirectory,
|
|
138
|
+
`coverage-${uniqueId++}.json`
|
|
139
|
+
);
|
|
140
|
+
entry[transformMode][testFilenames] = filename;
|
|
141
|
+
const promise = promises.writeFile(filename, JSON.stringify(coverage), "utf-8");
|
|
142
|
+
this.pendingPromises.push(promise);
|
|
143
|
+
}
|
|
144
|
+
async readCoverageFiles({ onFileRead, onFinished, onDebug }) {
|
|
145
|
+
let index = 0;
|
|
146
|
+
const total = this.pendingPromises.length;
|
|
147
|
+
await Promise.all(this.pendingPromises);
|
|
148
|
+
this.pendingPromises = [];
|
|
149
|
+
for (const [projectName, coveragePerProject] of this.coverageFiles.entries()) {
|
|
150
|
+
for (const [transformMode, coverageByTestfiles] of Object.entries(coveragePerProject)) {
|
|
151
|
+
const filenames = Object.values(coverageByTestfiles);
|
|
152
|
+
const project = this.ctx.getProjectByName(projectName);
|
|
153
|
+
for (const chunk of this.toSlices(filenames, this.options.processingConcurrency)) {
|
|
154
|
+
if (onDebug.enabled) {
|
|
155
|
+
index += chunk.length;
|
|
156
|
+
onDebug("Covered files %d/%d", index, total);
|
|
134
157
|
}
|
|
158
|
+
await Promise.all(
|
|
159
|
+
chunk.map(async (filename) => {
|
|
160
|
+
const contents = await promises.readFile(filename, "utf-8");
|
|
161
|
+
const coverage = JSON.parse(contents);
|
|
162
|
+
onFileRead(coverage);
|
|
163
|
+
})
|
|
164
|
+
);
|
|
135
165
|
}
|
|
166
|
+
await onFinished(project, transformMode);
|
|
136
167
|
}
|
|
137
168
|
}
|
|
138
169
|
}
|
|
170
|
+
async cleanAfterRun() {
|
|
171
|
+
this.coverageFiles = /* @__PURE__ */ new Map();
|
|
172
|
+
await promises.rm(this.coverageFilesDirectory, { recursive: true });
|
|
173
|
+
if (readdirSync(this.options.reportsDirectory).length === 0) {
|
|
174
|
+
await promises.rm(this.options.reportsDirectory, { recursive: true });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
async onTestFailure() {
|
|
178
|
+
if (!this.options.reportOnFailure) {
|
|
179
|
+
await this.cleanAfterRun();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
async reportCoverage(coverageMap, { allTestsRun }) {
|
|
183
|
+
await this.generateReports(
|
|
184
|
+
coverageMap || this.createCoverageMap(),
|
|
185
|
+
allTestsRun
|
|
186
|
+
);
|
|
187
|
+
const keepResults = !this.options.cleanOnRerun && this.ctx.config.watch;
|
|
188
|
+
if (!keepResults) {
|
|
189
|
+
await this.cleanAfterRun();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async reportThresholds(coverageMap, allTestsRun) {
|
|
193
|
+
const resolvedThresholds = this.resolveThresholds(coverageMap);
|
|
194
|
+
this.checkThresholds(resolvedThresholds);
|
|
195
|
+
if (this.options.thresholds?.autoUpdate && allTestsRun) {
|
|
196
|
+
if (!this.ctx.server.config.configFile) {
|
|
197
|
+
throw new Error(
|
|
198
|
+
'Missing configurationFile. The "coverage.thresholds.autoUpdate" can only be enabled when configuration file is used.'
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
const configFilePath = this.ctx.server.config.configFile;
|
|
202
|
+
const configModule = await this.parseConfigModule(configFilePath);
|
|
203
|
+
await this.updateThresholds({
|
|
204
|
+
thresholds: resolvedThresholds,
|
|
205
|
+
configurationFile: configModule,
|
|
206
|
+
onUpdate: () => writeFileSync(
|
|
207
|
+
configFilePath,
|
|
208
|
+
configModule.generate().code,
|
|
209
|
+
"utf-8"
|
|
210
|
+
)
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
139
214
|
/**
|
|
140
215
|
* Constructs collected coverage and users' threshold options into separate sets
|
|
141
216
|
* where each threshold set holds their own coverage maps. Threshold set is either
|
|
142
217
|
* for specific files defined by glob pattern or global for all other files.
|
|
143
218
|
*/
|
|
144
|
-
resolveThresholds({
|
|
145
|
-
coverageMap,
|
|
146
|
-
thresholds,
|
|
147
|
-
createCoverageMap,
|
|
148
|
-
root
|
|
149
|
-
}) {
|
|
219
|
+
resolveThresholds(coverageMap) {
|
|
150
220
|
const resolvedThresholds = [];
|
|
151
221
|
const files = coverageMap.files();
|
|
152
|
-
const globalCoverageMap = createCoverageMap();
|
|
153
|
-
for (const key of Object.keys(
|
|
154
|
-
thresholds
|
|
155
|
-
)) {
|
|
222
|
+
const globalCoverageMap = this.createCoverageMap();
|
|
223
|
+
for (const key of Object.keys(this.options.thresholds)) {
|
|
156
224
|
if (key === "perFile" || key === "autoUpdate" || key === "100" || THRESHOLD_KEYS.includes(key)) {
|
|
157
225
|
continue;
|
|
158
226
|
}
|
|
159
227
|
const glob = key;
|
|
160
|
-
const globThresholds = resolveGlobThresholds(thresholds[glob]);
|
|
161
|
-
const globCoverageMap = createCoverageMap();
|
|
228
|
+
const globThresholds = resolveGlobThresholds(this.options.thresholds[glob]);
|
|
229
|
+
const globCoverageMap = this.createCoverageMap();
|
|
162
230
|
const matchingFiles = files.filter(
|
|
163
|
-
(file) => mm.isMatch(relative(root, file), glob)
|
|
231
|
+
(file) => mm.isMatch(relative(this.ctx.config.root, file), glob)
|
|
164
232
|
);
|
|
165
233
|
for (const file of matchingFiles) {
|
|
166
234
|
const fileCoverage = coverageMap.fileCoverageFor(file);
|
|
@@ -180,19 +248,89 @@ class BaseCoverageProvider {
|
|
|
180
248
|
name: GLOBAL_THRESHOLDS_KEY,
|
|
181
249
|
coverageMap: globalCoverageMap,
|
|
182
250
|
thresholds: {
|
|
183
|
-
branches: thresholds
|
|
184
|
-
functions: thresholds
|
|
185
|
-
lines: thresholds
|
|
186
|
-
statements: thresholds
|
|
251
|
+
branches: this.options.thresholds?.branches,
|
|
252
|
+
functions: this.options.thresholds?.functions,
|
|
253
|
+
lines: this.options.thresholds?.lines,
|
|
254
|
+
statements: this.options.thresholds?.statements
|
|
187
255
|
}
|
|
188
256
|
});
|
|
189
257
|
return resolvedThresholds;
|
|
190
258
|
}
|
|
191
259
|
/**
|
|
192
|
-
*
|
|
260
|
+
* Check collected coverage against configured thresholds. Sets exit code to 1 when thresholds not reached.
|
|
261
|
+
*/
|
|
262
|
+
checkThresholds(allThresholds) {
|
|
263
|
+
for (const { coverageMap, thresholds, name } of allThresholds) {
|
|
264
|
+
if (thresholds.branches === void 0 && thresholds.functions === void 0 && thresholds.lines === void 0 && thresholds.statements === void 0) {
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const summaries = this.options.thresholds?.perFile ? coverageMap.files().map((file) => ({
|
|
268
|
+
file,
|
|
269
|
+
summary: coverageMap.fileCoverageFor(file).toSummary()
|
|
270
|
+
})) : [{ file: null, summary: coverageMap.getCoverageSummary() }];
|
|
271
|
+
for (const { summary, file } of summaries) {
|
|
272
|
+
for (const thresholdKey of THRESHOLD_KEYS) {
|
|
273
|
+
const threshold = thresholds[thresholdKey];
|
|
274
|
+
if (threshold !== void 0) {
|
|
275
|
+
const coverage = summary.data[thresholdKey].pct;
|
|
276
|
+
if (coverage < threshold) {
|
|
277
|
+
process.exitCode = 1;
|
|
278
|
+
let errorMessage = `ERROR: Coverage for ${thresholdKey} (${coverage}%) does not meet ${name === GLOBAL_THRESHOLDS_KEY ? name : `"${name}"`} threshold (${threshold}%)`;
|
|
279
|
+
if (this.options.thresholds?.perFile && file) {
|
|
280
|
+
errorMessage += ` for ${relative("./", file).replace(/\\/g, "/")}`;
|
|
281
|
+
}
|
|
282
|
+
this.ctx.logger.error(errorMessage);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Check if current coverage is above configured thresholds and bump the thresholds if needed
|
|
193
291
|
*/
|
|
194
|
-
|
|
195
|
-
|
|
292
|
+
async updateThresholds({ thresholds: allThresholds, onUpdate, configurationFile }) {
|
|
293
|
+
let updatedThresholds = false;
|
|
294
|
+
const config = resolveConfig(configurationFile);
|
|
295
|
+
assertConfigurationModule(config);
|
|
296
|
+
for (const { coverageMap, thresholds, name } of allThresholds) {
|
|
297
|
+
const summaries = this.options.thresholds?.perFile ? coverageMap.files().map(
|
|
298
|
+
(file) => coverageMap.fileCoverageFor(file).toSummary()
|
|
299
|
+
) : [coverageMap.getCoverageSummary()];
|
|
300
|
+
const thresholdsToUpdate = [];
|
|
301
|
+
for (const key of THRESHOLD_KEYS) {
|
|
302
|
+
const threshold = thresholds[key] ?? 100;
|
|
303
|
+
const actual = Math.min(
|
|
304
|
+
...summaries.map((summary) => summary[key].pct)
|
|
305
|
+
);
|
|
306
|
+
if (actual > threshold) {
|
|
307
|
+
thresholdsToUpdate.push([key, actual]);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (thresholdsToUpdate.length === 0) {
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
updatedThresholds = true;
|
|
314
|
+
for (const [threshold, newValue] of thresholdsToUpdate) {
|
|
315
|
+
if (name === GLOBAL_THRESHOLDS_KEY) {
|
|
316
|
+
config.test.coverage.thresholds[threshold] = newValue;
|
|
317
|
+
} else {
|
|
318
|
+
const glob = config.test.coverage.thresholds[name];
|
|
319
|
+
glob[threshold] = newValue;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (updatedThresholds) {
|
|
324
|
+
this.ctx.logger.log("Updating thresholds to configuration file. You may want to push with updated coverage thresholds.");
|
|
325
|
+
onUpdate();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
async mergeReports(coverageMaps) {
|
|
329
|
+
const coverageMap = this.createCoverageMap();
|
|
330
|
+
for (const coverage of coverageMaps) {
|
|
331
|
+
coverageMap.merge(coverage);
|
|
332
|
+
}
|
|
333
|
+
await this.generateReports(coverageMap, true);
|
|
196
334
|
}
|
|
197
335
|
hasTerminalReporter(reporters) {
|
|
198
336
|
return reporters.some(
|