@vitest/coverage-istanbul 0.22.1 → 0.23.0
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.
@@ -1,7 +1,7 @@
|
|
1
1
|
const COVERAGE_STORE_KEY = "__VITEST_COVERAGE__";
|
2
2
|
|
3
3
|
async function getProvider() {
|
4
|
-
const { IstanbulCoverageProvider } = await import('./provider-
|
4
|
+
const { IstanbulCoverageProvider } = await import('./provider-a5dc6d7e.js');
|
5
5
|
return new IstanbulCoverageProvider();
|
6
6
|
}
|
7
7
|
function takeCoverage() {
|
@@ -0,0 +1,11 @@
|
|
1
|
+
const COVERAGE_STORE_KEY = "__VITEST_COVERAGE__";
|
2
|
+
|
3
|
+
async function getProvider() {
|
4
|
+
const { IstanbulCoverageProvider } = await import('./provider-e9ab8aec.js');
|
5
|
+
return new IstanbulCoverageProvider();
|
6
|
+
}
|
7
|
+
function takeCoverage() {
|
8
|
+
return globalThis[COVERAGE_STORE_KEY];
|
9
|
+
}
|
10
|
+
|
11
|
+
export { COVERAGE_STORE_KEY as C, getProvider as g, takeCoverage as t };
|
package/dist/index.d.ts
CHANGED
@@ -197,6 +197,7 @@ interface TestExclude {
|
|
197
197
|
excludeNodeModules?: boolean;
|
198
198
|
}): {
|
199
199
|
shouldInstrument(filePath: string): boolean;
|
200
|
+
glob(cwd: string): Promise<string[]>;
|
200
201
|
};
|
201
202
|
}
|
202
203
|
declare class IstanbulCoverageProvider implements CoverageProvider {
|
@@ -224,6 +225,7 @@ declare class IstanbulCoverageProvider implements CoverageProvider {
|
|
224
225
|
clean(clean?: boolean): Promise<void>;
|
225
226
|
reportCoverage(): Promise<void>;
|
226
227
|
checkThresholds(coverageMap: CoverageMap, thresholds: Record<Threshold, number | undefined>): void;
|
228
|
+
includeUntestedFiles(coverageMap: CoverageMap): Promise<void>;
|
227
229
|
}
|
228
230
|
|
229
231
|
declare function getProvider(): Promise<IstanbulCoverageProvider>;
|
package/dist/index.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export { g as getProvider, t as takeCoverage } from './index-
|
1
|
+
export { g as getProvider, t as takeCoverage } from './index-aa0610b9.js';
|
@@ -7,7 +7,7 @@ import libCoverage from 'istanbul-lib-coverage';
|
|
7
7
|
import libSourceMaps from 'istanbul-lib-source-maps';
|
8
8
|
import { createInstrumenter } from 'istanbul-lib-instrument';
|
9
9
|
import _TestExclude from 'test-exclude';
|
10
|
-
import { C as COVERAGE_STORE_KEY } from './index-
|
10
|
+
import { C as COVERAGE_STORE_KEY } from './index-7fc35403.js';
|
11
11
|
|
12
12
|
function normalizeWindowsPath(input = "") {
|
13
13
|
if (!input.includes("\\")) {
|
@@ -204,6 +204,7 @@ class IstanbulCoverageProvider {
|
|
204
204
|
produceSourceMap: true,
|
205
205
|
autoWrap: false,
|
206
206
|
esModules: true,
|
207
|
+
compact: false,
|
207
208
|
coverageVariable: COVERAGE_STORE_KEY,
|
208
209
|
coverageGlobalScope: "globalThis",
|
209
210
|
coverageGlobalScopeFunc: false,
|
@@ -211,6 +212,7 @@ class IstanbulCoverageProvider {
|
|
211
212
|
});
|
212
213
|
this.testExclude = new _TestExclude({
|
213
214
|
cwd: ctx.config.root,
|
215
|
+
include: typeof this.options.include === "undefined" ? void 0 : [...this.options.include],
|
214
216
|
exclude: [...defaultExclude, ...defaultInclude, ...this.options.exclude],
|
215
217
|
excludeNodeModules: true,
|
216
218
|
extension: configDefaults.coverage.extension
|
@@ -0,0 +1,335 @@
|
|
1
|
+
import { existsSync, promises } from 'fs';
|
2
|
+
import path from 'path';
|
3
|
+
import { defaultExclude, defaultInclude, configDefaults } from 'vitest/config';
|
4
|
+
import libReport from 'istanbul-lib-report';
|
5
|
+
import reports from 'istanbul-reports';
|
6
|
+
import libCoverage from 'istanbul-lib-coverage';
|
7
|
+
import libSourceMaps from 'istanbul-lib-source-maps';
|
8
|
+
import { createInstrumenter } from 'istanbul-lib-instrument';
|
9
|
+
import _TestExclude from 'test-exclude';
|
10
|
+
import { C as COVERAGE_STORE_KEY } from './index-aa0610b9.js';
|
11
|
+
|
12
|
+
function normalizeWindowsPath(input = "") {
|
13
|
+
if (!input.includes("\\")) {
|
14
|
+
return input;
|
15
|
+
}
|
16
|
+
return input.replace(/\\/g, "/");
|
17
|
+
}
|
18
|
+
|
19
|
+
const _UNC_REGEX = /^[/][/]/;
|
20
|
+
const _UNC_DRIVE_REGEX = /^[/][/]([.]{1,2}[/])?([a-zA-Z]):[/]/;
|
21
|
+
const _IS_ABSOLUTE_RE = /^\/|^\\|^[a-zA-Z]:[/\\]/;
|
22
|
+
const sep = "/";
|
23
|
+
const delimiter = ":";
|
24
|
+
const normalize = function(path2) {
|
25
|
+
if (path2.length === 0) {
|
26
|
+
return ".";
|
27
|
+
}
|
28
|
+
path2 = normalizeWindowsPath(path2);
|
29
|
+
const isUNCPath = path2.match(_UNC_REGEX);
|
30
|
+
const hasUNCDrive = isUNCPath && path2.match(_UNC_DRIVE_REGEX);
|
31
|
+
const isPathAbsolute = isAbsolute(path2);
|
32
|
+
const trailingSeparator = path2[path2.length - 1] === "/";
|
33
|
+
path2 = normalizeString(path2, !isPathAbsolute);
|
34
|
+
if (path2.length === 0) {
|
35
|
+
if (isPathAbsolute) {
|
36
|
+
return "/";
|
37
|
+
}
|
38
|
+
return trailingSeparator ? "./" : ".";
|
39
|
+
}
|
40
|
+
if (trailingSeparator) {
|
41
|
+
path2 += "/";
|
42
|
+
}
|
43
|
+
if (isUNCPath) {
|
44
|
+
if (hasUNCDrive) {
|
45
|
+
return `//./${path2}`;
|
46
|
+
}
|
47
|
+
return `//${path2}`;
|
48
|
+
}
|
49
|
+
return isPathAbsolute && !isAbsolute(path2) ? `/${path2}` : path2;
|
50
|
+
};
|
51
|
+
const join = function(...args) {
|
52
|
+
if (args.length === 0) {
|
53
|
+
return ".";
|
54
|
+
}
|
55
|
+
let joined;
|
56
|
+
for (let i = 0; i < args.length; ++i) {
|
57
|
+
const arg = args[i];
|
58
|
+
if (arg.length > 0) {
|
59
|
+
if (joined === void 0) {
|
60
|
+
joined = arg;
|
61
|
+
} else {
|
62
|
+
joined += `/${arg}`;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
if (joined === void 0) {
|
67
|
+
return ".";
|
68
|
+
}
|
69
|
+
return normalize(joined);
|
70
|
+
};
|
71
|
+
const resolve = function(...args) {
|
72
|
+
args = args.map((arg) => normalizeWindowsPath(arg));
|
73
|
+
let resolvedPath = "";
|
74
|
+
let resolvedAbsolute = false;
|
75
|
+
for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
76
|
+
const path2 = i >= 0 ? args[i] : process.cwd();
|
77
|
+
if (path2.length === 0) {
|
78
|
+
continue;
|
79
|
+
}
|
80
|
+
resolvedPath = `${path2}/${resolvedPath}`;
|
81
|
+
resolvedAbsolute = isAbsolute(path2);
|
82
|
+
}
|
83
|
+
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
84
|
+
if (resolvedAbsolute && !isAbsolute(resolvedPath)) {
|
85
|
+
return `/${resolvedPath}`;
|
86
|
+
}
|
87
|
+
return resolvedPath.length > 0 ? resolvedPath : ".";
|
88
|
+
};
|
89
|
+
function normalizeString(path2, allowAboveRoot) {
|
90
|
+
let res = "";
|
91
|
+
let lastSegmentLength = 0;
|
92
|
+
let lastSlash = -1;
|
93
|
+
let dots = 0;
|
94
|
+
let char = null;
|
95
|
+
for (let i = 0; i <= path2.length; ++i) {
|
96
|
+
if (i < path2.length) {
|
97
|
+
char = path2[i];
|
98
|
+
} else if (char === "/") {
|
99
|
+
break;
|
100
|
+
} else {
|
101
|
+
char = "/";
|
102
|
+
}
|
103
|
+
if (char === "/") {
|
104
|
+
if (lastSlash === i - 1 || dots === 1) ; else if (dots === 2) {
|
105
|
+
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
|
106
|
+
if (res.length > 2) {
|
107
|
+
const lastSlashIndex = res.lastIndexOf("/");
|
108
|
+
if (lastSlashIndex === -1) {
|
109
|
+
res = "";
|
110
|
+
lastSegmentLength = 0;
|
111
|
+
} else {
|
112
|
+
res = res.slice(0, lastSlashIndex);
|
113
|
+
lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
114
|
+
}
|
115
|
+
lastSlash = i;
|
116
|
+
dots = 0;
|
117
|
+
continue;
|
118
|
+
} else if (res.length !== 0) {
|
119
|
+
res = "";
|
120
|
+
lastSegmentLength = 0;
|
121
|
+
lastSlash = i;
|
122
|
+
dots = 0;
|
123
|
+
continue;
|
124
|
+
}
|
125
|
+
}
|
126
|
+
if (allowAboveRoot) {
|
127
|
+
res += res.length > 0 ? "/.." : "..";
|
128
|
+
lastSegmentLength = 2;
|
129
|
+
}
|
130
|
+
} else {
|
131
|
+
if (res.length > 0) {
|
132
|
+
res += `/${path2.slice(lastSlash + 1, i)}`;
|
133
|
+
} else {
|
134
|
+
res = path2.slice(lastSlash + 1, i);
|
135
|
+
}
|
136
|
+
lastSegmentLength = i - lastSlash - 1;
|
137
|
+
}
|
138
|
+
lastSlash = i;
|
139
|
+
dots = 0;
|
140
|
+
} else if (char === "." && dots !== -1) {
|
141
|
+
++dots;
|
142
|
+
} else {
|
143
|
+
dots = -1;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
return res;
|
147
|
+
}
|
148
|
+
const isAbsolute = function(p) {
|
149
|
+
return _IS_ABSOLUTE_RE.test(p);
|
150
|
+
};
|
151
|
+
const toNamespacedPath = function(p) {
|
152
|
+
return normalizeWindowsPath(p);
|
153
|
+
};
|
154
|
+
const extname = function(p) {
|
155
|
+
return path.posix.extname(normalizeWindowsPath(p));
|
156
|
+
};
|
157
|
+
const relative = function(from, to) {
|
158
|
+
return path.posix.relative(normalizeWindowsPath(from), normalizeWindowsPath(to));
|
159
|
+
};
|
160
|
+
const dirname = function(p) {
|
161
|
+
return path.posix.dirname(normalizeWindowsPath(p));
|
162
|
+
};
|
163
|
+
const format = function(p) {
|
164
|
+
return normalizeWindowsPath(path.posix.format(p));
|
165
|
+
};
|
166
|
+
const basename = function(p, ext) {
|
167
|
+
return path.posix.basename(normalizeWindowsPath(p), ext);
|
168
|
+
};
|
169
|
+
const parse = function(p) {
|
170
|
+
return path.posix.parse(normalizeWindowsPath(p));
|
171
|
+
};
|
172
|
+
|
173
|
+
const _path = /*#__PURE__*/Object.freeze({
|
174
|
+
__proto__: null,
|
175
|
+
sep: sep,
|
176
|
+
delimiter: delimiter,
|
177
|
+
normalize: normalize,
|
178
|
+
join: join,
|
179
|
+
resolve: resolve,
|
180
|
+
normalizeString: normalizeString,
|
181
|
+
isAbsolute: isAbsolute,
|
182
|
+
toNamespacedPath: toNamespacedPath,
|
183
|
+
extname: extname,
|
184
|
+
relative: relative,
|
185
|
+
dirname: dirname,
|
186
|
+
format: format,
|
187
|
+
basename: basename,
|
188
|
+
parse: parse
|
189
|
+
});
|
190
|
+
|
191
|
+
({
|
192
|
+
..._path
|
193
|
+
});
|
194
|
+
|
195
|
+
class IstanbulCoverageProvider {
|
196
|
+
constructor() {
|
197
|
+
this.name = "istanbul";
|
198
|
+
this.coverages = [];
|
199
|
+
}
|
200
|
+
initialize(ctx) {
|
201
|
+
this.ctx = ctx;
|
202
|
+
this.options = resolveIstanbulOptions(ctx.config.coverage, ctx.config.root);
|
203
|
+
this.instrumenter = createInstrumenter({
|
204
|
+
produceSourceMap: true,
|
205
|
+
autoWrap: false,
|
206
|
+
esModules: true,
|
207
|
+
compact: false,
|
208
|
+
coverageVariable: COVERAGE_STORE_KEY,
|
209
|
+
coverageGlobalScope: "globalThis",
|
210
|
+
coverageGlobalScopeFunc: false,
|
211
|
+
ignoreClassMethods: this.options.ignoreClassMethods
|
212
|
+
});
|
213
|
+
this.testExclude = new _TestExclude({
|
214
|
+
cwd: ctx.config.root,
|
215
|
+
include: typeof this.options.include === "undefined" ? void 0 : [...this.options.include],
|
216
|
+
exclude: [...defaultExclude, ...defaultInclude, ...this.options.exclude],
|
217
|
+
excludeNodeModules: true,
|
218
|
+
extension: configDefaults.coverage.extension
|
219
|
+
});
|
220
|
+
}
|
221
|
+
resolveOptions() {
|
222
|
+
return this.options;
|
223
|
+
}
|
224
|
+
onFileTransform(sourceCode, id, pluginCtx) {
|
225
|
+
if (!this.testExclude.shouldInstrument(id))
|
226
|
+
return;
|
227
|
+
const { sourcesContent, ...sourceMap } = pluginCtx.getCombinedSourcemap();
|
228
|
+
const code = this.instrumenter.instrumentSync(sourceCode, id, sourceMap);
|
229
|
+
const map = this.instrumenter.lastSourceMap();
|
230
|
+
return { code, map };
|
231
|
+
}
|
232
|
+
onAfterSuiteRun({ coverage }) {
|
233
|
+
this.coverages.push(coverage);
|
234
|
+
}
|
235
|
+
async clean(clean = true) {
|
236
|
+
if (clean && existsSync(this.options.reportsDirectory))
|
237
|
+
await promises.rm(this.options.reportsDirectory, { recursive: true, force: true });
|
238
|
+
this.coverages = [];
|
239
|
+
}
|
240
|
+
async reportCoverage() {
|
241
|
+
const mergedCoverage = this.coverages.reduce((coverage, previousCoverageMap) => {
|
242
|
+
const map = libCoverage.createCoverageMap(coverage);
|
243
|
+
map.merge(previousCoverageMap);
|
244
|
+
return map;
|
245
|
+
}, {});
|
246
|
+
if (this.options.all)
|
247
|
+
await this.includeUntestedFiles(mergedCoverage);
|
248
|
+
const sourceMapStore = libSourceMaps.createSourceMapStore();
|
249
|
+
const coverageMap = await sourceMapStore.transformCoverage(mergedCoverage);
|
250
|
+
const context = libReport.createContext({
|
251
|
+
dir: this.options.reportsDirectory,
|
252
|
+
coverageMap,
|
253
|
+
sourceFinder: sourceMapStore.sourceFinder,
|
254
|
+
watermarks: this.options.watermarks
|
255
|
+
});
|
256
|
+
for (const reporter of this.options.reporter) {
|
257
|
+
reports.create(reporter, {
|
258
|
+
skipFull: this.options.skipFull
|
259
|
+
}).execute(context);
|
260
|
+
}
|
261
|
+
if (this.options.branches || this.options.functions || this.options.lines || this.options.statements) {
|
262
|
+
this.checkThresholds(coverageMap, {
|
263
|
+
branches: this.options.branches,
|
264
|
+
functions: this.options.functions,
|
265
|
+
lines: this.options.lines,
|
266
|
+
statements: this.options.statements
|
267
|
+
});
|
268
|
+
}
|
269
|
+
}
|
270
|
+
checkThresholds(coverageMap, thresholds) {
|
271
|
+
const summaries = this.options.perFile ? coverageMap.files().map((file) => ({
|
272
|
+
file,
|
273
|
+
summary: coverageMap.fileCoverageFor(file).toSummary()
|
274
|
+
})) : [{
|
275
|
+
file: null,
|
276
|
+
summary: coverageMap.getCoverageSummary()
|
277
|
+
}];
|
278
|
+
for (const { summary, file } of summaries) {
|
279
|
+
for (const thresholdKey of ["lines", "functions", "statements", "branches"]) {
|
280
|
+
const threshold = thresholds[thresholdKey];
|
281
|
+
if (threshold !== void 0) {
|
282
|
+
const coverage = summary.data[thresholdKey].pct;
|
283
|
+
if (coverage < threshold) {
|
284
|
+
process.exitCode = 1;
|
285
|
+
let errorMessage = `ERROR: Coverage for ${thresholdKey} (${coverage}%) does not meet`;
|
286
|
+
if (!this.options.perFile)
|
287
|
+
errorMessage += " global";
|
288
|
+
errorMessage += ` threshold (${threshold}%)`;
|
289
|
+
if (this.options.perFile && file)
|
290
|
+
errorMessage += ` for ${relative("./", file).replace(/\\/g, "/")}`;
|
291
|
+
console.error(errorMessage);
|
292
|
+
}
|
293
|
+
}
|
294
|
+
}
|
295
|
+
}
|
296
|
+
}
|
297
|
+
async includeUntestedFiles(coverageMap) {
|
298
|
+
const includedFiles = await this.testExclude.glob(this.ctx.config.root);
|
299
|
+
const uncoveredFiles = includedFiles.map((file) => resolve(this.ctx.config.root, file)).filter((file) => !coverageMap.data[file]);
|
300
|
+
const transformResults = await Promise.all(uncoveredFiles.map(async (filename) => {
|
301
|
+
const transformResult = await this.ctx.vitenode.transformRequest(filename);
|
302
|
+
return { transformResult, filename };
|
303
|
+
}));
|
304
|
+
for (const { transformResult, filename } of transformResults) {
|
305
|
+
const sourceMap = transformResult == null ? void 0 : transformResult.map;
|
306
|
+
if (sourceMap) {
|
307
|
+
this.instrumenter.instrumentSync(
|
308
|
+
transformResult.code,
|
309
|
+
filename,
|
310
|
+
{
|
311
|
+
...sourceMap,
|
312
|
+
version: sourceMap.version.toString()
|
313
|
+
}
|
314
|
+
);
|
315
|
+
const lastCoverage = this.instrumenter.lastFileCoverage();
|
316
|
+
if (lastCoverage)
|
317
|
+
coverageMap.data[lastCoverage.path] = lastCoverage;
|
318
|
+
}
|
319
|
+
}
|
320
|
+
}
|
321
|
+
}
|
322
|
+
function resolveIstanbulOptions(options, root) {
|
323
|
+
const reportsDirectory = resolve(root, options.reportsDirectory || configDefaults.coverage.reportsDirectory);
|
324
|
+
const resolved = {
|
325
|
+
...configDefaults.coverage,
|
326
|
+
...options,
|
327
|
+
provider: "istanbul",
|
328
|
+
reportsDirectory,
|
329
|
+
tempDirectory: resolve(reportsDirectory, "tmp"),
|
330
|
+
reporter: Array.isArray(options.reporter) ? options.reporter : [options.reporter]
|
331
|
+
};
|
332
|
+
return resolved;
|
333
|
+
}
|
334
|
+
|
335
|
+
export { IstanbulCoverageProvider };
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vitest/coverage-istanbul",
|
3
3
|
"type": "module",
|
4
|
-
"version": "0.
|
4
|
+
"version": "0.23.0",
|
5
5
|
"description": "Istanbul coverage provider for Vitest",
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
7
7
|
"license": "MIT",
|
@@ -43,7 +43,7 @@
|
|
43
43
|
"istanbul-lib-source-maps": "^4.0.1",
|
44
44
|
"istanbul-reports": "^3.1.5",
|
45
45
|
"test-exclude": "^6.0.0",
|
46
|
-
"vitest": "0.
|
46
|
+
"vitest": "0.23.0"
|
47
47
|
},
|
48
48
|
"devDependencies": {
|
49
49
|
"@types/istanbul-lib-coverage": "^2.0.4",
|