@vitest/coverage-istanbul 0.23.4 → 0.24.1

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.
@@ -0,0 +1,11 @@
1
+ const COVERAGE_STORE_KEY = "__VITEST_COVERAGE__";
2
+
3
+ async function getProvider() {
4
+ const { IstanbulCoverageProvider } = await import('./provider-142aaa2f.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.js CHANGED
@@ -1 +1 @@
1
- export { g as getProvider, t as takeCoverage } from './index-aa0610b9.js';
1
+ export { g as getProvider, t as takeCoverage } from './index-01de7c40.js';
@@ -0,0 +1,336 @@
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-01de7c40.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
+ projectRoot: this.ctx.config.root
260
+ }).execute(context);
261
+ }
262
+ if (this.options.branches || this.options.functions || this.options.lines || this.options.statements) {
263
+ this.checkThresholds(coverageMap, {
264
+ branches: this.options.branches,
265
+ functions: this.options.functions,
266
+ lines: this.options.lines,
267
+ statements: this.options.statements
268
+ });
269
+ }
270
+ }
271
+ checkThresholds(coverageMap, thresholds) {
272
+ const summaries = this.options.perFile ? coverageMap.files().map((file) => ({
273
+ file,
274
+ summary: coverageMap.fileCoverageFor(file).toSummary()
275
+ })) : [{
276
+ file: null,
277
+ summary: coverageMap.getCoverageSummary()
278
+ }];
279
+ for (const { summary, file } of summaries) {
280
+ for (const thresholdKey of ["lines", "functions", "statements", "branches"]) {
281
+ const threshold = thresholds[thresholdKey];
282
+ if (threshold !== void 0) {
283
+ const coverage = summary.data[thresholdKey].pct;
284
+ if (coverage < threshold) {
285
+ process.exitCode = 1;
286
+ let errorMessage = `ERROR: Coverage for ${thresholdKey} (${coverage}%) does not meet`;
287
+ if (!this.options.perFile)
288
+ errorMessage += " global";
289
+ errorMessage += ` threshold (${threshold}%)`;
290
+ if (this.options.perFile && file)
291
+ errorMessage += ` for ${relative("./", file).replace(/\\/g, "/")}`;
292
+ console.error(errorMessage);
293
+ }
294
+ }
295
+ }
296
+ }
297
+ }
298
+ async includeUntestedFiles(coverageMap) {
299
+ const includedFiles = await this.testExclude.glob(this.ctx.config.root);
300
+ const uncoveredFiles = includedFiles.map((file) => resolve(this.ctx.config.root, file)).filter((file) => !coverageMap.data[file]);
301
+ const transformResults = await Promise.all(uncoveredFiles.map(async (filename) => {
302
+ const transformResult = await this.ctx.vitenode.transformRequest(filename);
303
+ return { transformResult, filename };
304
+ }));
305
+ for (const { transformResult, filename } of transformResults) {
306
+ const sourceMap = transformResult == null ? void 0 : transformResult.map;
307
+ if (sourceMap) {
308
+ this.instrumenter.instrumentSync(
309
+ transformResult.code,
310
+ filename,
311
+ {
312
+ ...sourceMap,
313
+ version: sourceMap.version.toString()
314
+ }
315
+ );
316
+ const lastCoverage = this.instrumenter.lastFileCoverage();
317
+ if (lastCoverage)
318
+ coverageMap.data[lastCoverage.path] = lastCoverage;
319
+ }
320
+ }
321
+ }
322
+ }
323
+ function resolveIstanbulOptions(options, root) {
324
+ const reportsDirectory = resolve(root, options.reportsDirectory || configDefaults.coverage.reportsDirectory);
325
+ const resolved = {
326
+ ...configDefaults.coverage,
327
+ ...options,
328
+ provider: "istanbul",
329
+ reportsDirectory,
330
+ tempDirectory: resolve(reportsDirectory, "tmp"),
331
+ reporter: Array.isArray(options.reporter) ? options.reporter : [options.reporter]
332
+ };
333
+ return resolved;
334
+ }
335
+
336
+ 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.23.4",
4
+ "version": "0.24.1",
5
5
  "description": "Istanbul coverage provider for Vitest",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -38,12 +38,12 @@
38
38
  ],
39
39
  "dependencies": {
40
40
  "istanbul-lib-coverage": "^3.2.0",
41
- "istanbul-lib-instrument": "^5.2.0",
41
+ "istanbul-lib-instrument": "^5.2.1",
42
42
  "istanbul-lib-report": "^3.0.0",
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.23.4"
46
+ "vitest": "0.24.1"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/istanbul-lib-coverage": "^2.0.4",