@vitest/coverage-istanbul 2.0.0-beta.8 → 2.0.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.
- package/dist/index.js +4 -1
- package/dist/provider.js +110 -61
- package/package.json +9 -8
package/dist/index.js
CHANGED
@@ -2,7 +2,10 @@ import { C as COVERAGE_STORE_KEY } from './constants-BCJfMgEg.js';
|
|
2
2
|
|
3
3
|
async function getProvider() {
|
4
4
|
const providerPath = "./provider.js";
|
5
|
-
const { IstanbulCoverageProvider } = await import(
|
5
|
+
const { IstanbulCoverageProvider } = await import(
|
6
|
+
/* @vite-ignore */
|
7
|
+
providerPath
|
8
|
+
);
|
6
9
|
return new IstanbulCoverageProvider();
|
7
10
|
}
|
8
11
|
function takeCoverage() {
|
package/dist/provider.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { promises, existsSync, readdirSync, writeFileSync } from 'node:fs';
|
2
|
-
import { coverageConfigDefaults
|
2
|
+
import { coverageConfigDefaults } from 'vitest/config';
|
3
3
|
import { BaseCoverageProvider } from 'vitest/coverage';
|
4
4
|
import c from 'picocolors';
|
5
5
|
import { parseModule } from 'magicast';
|
@@ -9,6 +9,7 @@ import reports from 'istanbul-reports';
|
|
9
9
|
import libCoverage from 'istanbul-lib-coverage';
|
10
10
|
import libSourceMaps from 'istanbul-lib-source-maps';
|
11
11
|
import { createInstrumenter } from 'istanbul-lib-instrument';
|
12
|
+
import { defaults } from '@istanbuljs/schema';
|
12
13
|
import _TestExclude from 'test-exclude';
|
13
14
|
import { C as COVERAGE_STORE_KEY } from './constants-BCJfMgEg.js';
|
14
15
|
|
@@ -128,8 +129,13 @@ class IstanbulCoverageProvider extends BaseCoverageProvider {
|
|
128
129
|
...config,
|
129
130
|
// Resolved fields
|
130
131
|
provider: "istanbul",
|
131
|
-
reportsDirectory: resolve(
|
132
|
-
|
132
|
+
reportsDirectory: resolve(
|
133
|
+
ctx.config.root,
|
134
|
+
config.reportsDirectory || coverageConfigDefaults.reportsDirectory
|
135
|
+
),
|
136
|
+
reporter: this.resolveReporters(
|
137
|
+
config.reporter || coverageConfigDefaults.reporter
|
138
|
+
),
|
133
139
|
thresholds: config.thresholds && {
|
134
140
|
...config.thresholds,
|
135
141
|
lines: config.thresholds["100"] ? 100 : config.thresholds.lines,
|
@@ -147,30 +153,48 @@ class IstanbulCoverageProvider extends BaseCoverageProvider {
|
|
147
153
|
// @ts-expect-error missing type
|
148
154
|
coverageGlobalScope: "globalThis",
|
149
155
|
coverageGlobalScopeFunc: false,
|
150
|
-
ignoreClassMethods: this.options.ignoreClassMethods
|
156
|
+
ignoreClassMethods: this.options.ignoreClassMethods,
|
157
|
+
parserPlugins: [
|
158
|
+
...defaults.instrumenter.parserPlugins,
|
159
|
+
["importAttributes", { deprecatedAssertSyntax: true }]
|
160
|
+
],
|
161
|
+
generatorOpts: {
|
162
|
+
importAttributesKeyword: "with"
|
163
|
+
}
|
151
164
|
});
|
152
165
|
this.testExclude = new _TestExclude({
|
153
166
|
cwd: ctx.config.root,
|
154
|
-
include:
|
155
|
-
exclude:
|
167
|
+
include: this.options.include,
|
168
|
+
exclude: this.options.exclude,
|
156
169
|
excludeNodeModules: true,
|
157
170
|
extension: this.options.extension,
|
158
171
|
relativePath: !this.options.allowExternal
|
159
172
|
});
|
160
173
|
const shard = this.ctx.config.shard;
|
161
174
|
const tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`;
|
162
|
-
this.coverageFilesDirectory = resolve(
|
175
|
+
this.coverageFilesDirectory = resolve(
|
176
|
+
this.options.reportsDirectory,
|
177
|
+
tempDirectory
|
178
|
+
);
|
163
179
|
}
|
164
180
|
resolveOptions() {
|
165
181
|
return this.options;
|
166
182
|
}
|
167
183
|
onFileTransform(sourceCode, id, pluginCtx) {
|
168
|
-
if (!this.testExclude.shouldInstrument(id))
|
184
|
+
if (!this.testExclude.shouldInstrument(id)) {
|
169
185
|
return;
|
186
|
+
}
|
170
187
|
const sourceMap = pluginCtx.getCombinedSourcemap();
|
171
188
|
sourceMap.sources = sourceMap.sources.map(removeQueryParameters);
|
172
|
-
sourceCode = sourceCode.replaceAll(
|
173
|
-
|
189
|
+
sourceCode = sourceCode.replaceAll(
|
190
|
+
"_ts_decorate",
|
191
|
+
"/* istanbul ignore next */_ts_decorate"
|
192
|
+
);
|
193
|
+
const code = this.instrumenter.instrumentSync(
|
194
|
+
sourceCode,
|
195
|
+
id,
|
196
|
+
sourceMap
|
197
|
+
);
|
174
198
|
const map = this.instrumenter.lastSourceMap();
|
175
199
|
return { code, map };
|
176
200
|
}
|
@@ -180,25 +204,40 @@ class IstanbulCoverageProvider extends BaseCoverageProvider {
|
|
180
204
|
* backwards compatibility is a breaking change.
|
181
205
|
*/
|
182
206
|
onAfterSuiteRun({ coverage, transformMode, projectName }) {
|
183
|
-
if (!coverage)
|
207
|
+
if (!coverage) {
|
184
208
|
return;
|
185
|
-
|
209
|
+
}
|
210
|
+
if (transformMode !== "web" && transformMode !== "ssr") {
|
186
211
|
throw new Error(`Invalid transform mode: ${transformMode}`);
|
212
|
+
}
|
187
213
|
let entry = this.coverageFiles.get(projectName || DEFAULT_PROJECT);
|
188
214
|
if (!entry) {
|
189
215
|
entry = { web: [], ssr: [] };
|
190
216
|
this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry);
|
191
217
|
}
|
192
|
-
const filename = resolve(
|
218
|
+
const filename = resolve(
|
219
|
+
this.coverageFilesDirectory,
|
220
|
+
`coverage-${uniqueId++}.json`
|
221
|
+
);
|
193
222
|
entry[transformMode].push(filename);
|
194
223
|
const promise = promises.writeFile(filename, JSON.stringify(coverage), "utf-8");
|
195
224
|
this.pendingPromises.push(promise);
|
196
225
|
}
|
197
226
|
async clean(clean = true) {
|
198
|
-
if (clean && existsSync(this.options.reportsDirectory))
|
199
|
-
await promises.rm(this.options.reportsDirectory, {
|
200
|
-
|
201
|
-
|
227
|
+
if (clean && existsSync(this.options.reportsDirectory)) {
|
228
|
+
await promises.rm(this.options.reportsDirectory, {
|
229
|
+
recursive: true,
|
230
|
+
force: true,
|
231
|
+
maxRetries: 10
|
232
|
+
});
|
233
|
+
}
|
234
|
+
if (existsSync(this.coverageFilesDirectory)) {
|
235
|
+
await promises.rm(this.coverageFilesDirectory, {
|
236
|
+
recursive: true,
|
237
|
+
force: true,
|
238
|
+
maxRetries: 10
|
239
|
+
});
|
240
|
+
}
|
202
241
|
await promises.mkdir(this.coverageFilesDirectory, { recursive: true });
|
203
242
|
this.coverageFiles = /* @__PURE__ */ new Map();
|
204
243
|
this.pendingPromises = [];
|
@@ -210,26 +249,38 @@ class IstanbulCoverageProvider extends BaseCoverageProvider {
|
|
210
249
|
await Promise.all(this.pendingPromises);
|
211
250
|
this.pendingPromises = [];
|
212
251
|
for (const coveragePerProject of this.coverageFiles.values()) {
|
213
|
-
for (const filenames of [
|
252
|
+
for (const filenames of [
|
253
|
+
coveragePerProject.ssr,
|
254
|
+
coveragePerProject.web
|
255
|
+
]) {
|
214
256
|
const coverageMapByTransformMode = libCoverage.createCoverageMap({});
|
215
|
-
for (const chunk of this.toSlices(
|
257
|
+
for (const chunk of this.toSlices(
|
258
|
+
filenames,
|
259
|
+
this.options.processingConcurrency
|
260
|
+
)) {
|
216
261
|
if (debug.enabled) {
|
217
262
|
index += chunk.length;
|
218
263
|
debug("Covered files %d/%d", index, total);
|
219
264
|
}
|
220
|
-
await Promise.all(
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
265
|
+
await Promise.all(
|
266
|
+
chunk.map(async (filename) => {
|
267
|
+
const contents = await promises.readFile(filename, "utf-8");
|
268
|
+
const coverage = JSON.parse(contents);
|
269
|
+
coverageMapByTransformMode.merge(coverage);
|
270
|
+
})
|
271
|
+
);
|
225
272
|
}
|
226
|
-
const transformedCoverage = await transformCoverage(
|
273
|
+
const transformedCoverage = await transformCoverage(
|
274
|
+
coverageMapByTransformMode
|
275
|
+
);
|
227
276
|
coverageMap.merge(transformedCoverage);
|
228
277
|
}
|
229
278
|
}
|
230
279
|
if (this.options.all && allTestsRun) {
|
231
280
|
const coveredFiles = coverageMap.files();
|
232
|
-
const uncoveredCoverage = await this.getCoverageMapForUncoveredFiles(
|
281
|
+
const uncoveredCoverage = await this.getCoverageMapForUncoveredFiles(
|
282
|
+
coveredFiles
|
283
|
+
);
|
233
284
|
coverageMap.merge(await transformCoverage(uncoveredCoverage));
|
234
285
|
}
|
235
286
|
return coverageMap;
|
@@ -243,8 +294,9 @@ class IstanbulCoverageProvider extends BaseCoverageProvider {
|
|
243
294
|
if (!keepResults) {
|
244
295
|
this.coverageFiles = /* @__PURE__ */ new Map();
|
245
296
|
await promises.rm(this.coverageFilesDirectory, { recursive: true });
|
246
|
-
if (readdirSync(this.options.reportsDirectory).length === 0)
|
297
|
+
if (readdirSync(this.options.reportsDirectory).length === 0) {
|
247
298
|
await promises.rm(this.options.reportsDirectory, { recursive: true });
|
299
|
+
}
|
248
300
|
}
|
249
301
|
}
|
250
302
|
async generateReports(coverageMap, allTestsRun) {
|
@@ -253,8 +305,11 @@ class IstanbulCoverageProvider extends BaseCoverageProvider {
|
|
253
305
|
coverageMap,
|
254
306
|
watermarks: this.options.watermarks
|
255
307
|
});
|
256
|
-
if (this.hasTerminalReporter(this.options.reporter))
|
257
|
-
this.ctx.logger.log(
|
308
|
+
if (this.hasTerminalReporter(this.options.reporter)) {
|
309
|
+
this.ctx.logger.log(
|
310
|
+
c.blue(" % ") + c.dim("Coverage report from ") + c.yellow(this.name)
|
311
|
+
);
|
312
|
+
}
|
258
313
|
for (const reporter of this.options.reporter) {
|
259
314
|
reports.create(reporter[0], {
|
260
315
|
skipFull: this.options.skipFull,
|
@@ -271,34 +326,50 @@ class IstanbulCoverageProvider extends BaseCoverageProvider {
|
|
271
326
|
});
|
272
327
|
this.checkThresholds({
|
273
328
|
thresholds: resolvedThresholds,
|
274
|
-
perFile: this.options.thresholds.perFile
|
329
|
+
perFile: this.options.thresholds.perFile,
|
330
|
+
onError: (error) => this.ctx.logger.error(error)
|
275
331
|
});
|
276
332
|
if (this.options.thresholds.autoUpdate && allTestsRun) {
|
277
|
-
if (!this.ctx.server.config.configFile)
|
278
|
-
throw new Error(
|
333
|
+
if (!this.ctx.server.config.configFile) {
|
334
|
+
throw new Error(
|
335
|
+
'Missing configurationFile. The "coverage.thresholds.autoUpdate" can only be enabled when configuration file is used.'
|
336
|
+
);
|
337
|
+
}
|
279
338
|
const configFilePath = this.ctx.server.config.configFile;
|
280
|
-
const configModule = parseModule(
|
339
|
+
const configModule = parseModule(
|
340
|
+
await promises.readFile(configFilePath, "utf8")
|
341
|
+
);
|
281
342
|
this.updateThresholds({
|
282
343
|
thresholds: resolvedThresholds,
|
283
344
|
perFile: this.options.thresholds.perFile,
|
284
345
|
configurationFile: configModule,
|
285
|
-
onUpdate: () => writeFileSync(
|
346
|
+
onUpdate: () => writeFileSync(
|
347
|
+
configFilePath,
|
348
|
+
configModule.generate().code,
|
349
|
+
"utf-8"
|
350
|
+
)
|
286
351
|
});
|
287
352
|
}
|
288
353
|
}
|
289
354
|
}
|
290
355
|
async mergeReports(coverageMaps) {
|
291
356
|
const coverageMap = libCoverage.createCoverageMap({});
|
292
|
-
for (const coverage of coverageMaps)
|
357
|
+
for (const coverage of coverageMaps) {
|
293
358
|
coverageMap.merge(coverage);
|
359
|
+
}
|
294
360
|
await this.generateReports(coverageMap, true);
|
295
361
|
}
|
296
362
|
async getCoverageMapForUncoveredFiles(coveredFiles) {
|
297
363
|
const allFiles = await this.testExclude.glob(this.ctx.config.root);
|
298
|
-
let includedFiles = allFiles.map(
|
299
|
-
|
300
|
-
|
301
|
-
|
364
|
+
let includedFiles = allFiles.map(
|
365
|
+
(file) => resolve(this.ctx.config.root, file)
|
366
|
+
);
|
367
|
+
if (this.ctx.config.changed) {
|
368
|
+
includedFiles = (this.ctx.config.related || []).filter(
|
369
|
+
(file) => includedFiles.includes(file)
|
370
|
+
);
|
371
|
+
}
|
372
|
+
const uncoveredFiles = includedFiles.filter((file) => !coveredFiles.includes(file)).sort();
|
302
373
|
const cacheKey = (/* @__PURE__ */ new Date()).getTime();
|
303
374
|
const coverageMap = libCoverage.createCoverageMap({});
|
304
375
|
for (const [index, filename] of uncoveredFiles.entries()) {
|
@@ -311,33 +382,11 @@ class IstanbulCoverageProvider extends BaseCoverageProvider {
|
|
311
382
|
}
|
312
383
|
}
|
313
384
|
async function transformCoverage(coverageMap) {
|
314
|
-
includeImplicitElseBranches(coverageMap);
|
315
385
|
const sourceMapStore = libSourceMaps.createSourceMapStore();
|
316
386
|
return await sourceMapStore.transformCoverage(coverageMap);
|
317
387
|
}
|
318
388
|
function removeQueryParameters(filename) {
|
319
389
|
return filename.split("?")[0];
|
320
390
|
}
|
321
|
-
function includeImplicitElseBranches(coverageMap) {
|
322
|
-
for (const file of coverageMap.files()) {
|
323
|
-
const fileCoverage = coverageMap.fileCoverageFor(file);
|
324
|
-
for (const branchMap of Object.values(fileCoverage.branchMap)) {
|
325
|
-
if (branchMap.type === "if") {
|
326
|
-
const lastIndex = branchMap.locations.length - 1;
|
327
|
-
if (lastIndex > 0) {
|
328
|
-
const elseLocation = branchMap.locations[lastIndex];
|
329
|
-
if (elseLocation && isEmptyCoverageRange(elseLocation)) {
|
330
|
-
const ifLocation = branchMap.locations[0];
|
331
|
-
elseLocation.start = { ...ifLocation.start };
|
332
|
-
elseLocation.end = { ...ifLocation.end };
|
333
|
-
}
|
334
|
-
}
|
335
|
-
}
|
336
|
-
}
|
337
|
-
}
|
338
|
-
}
|
339
|
-
function isEmptyCoverageRange(range) {
|
340
|
-
return range.start === void 0 || range.start.line === void 0 || range.start.column === void 0 || range.end === void 0 || range.end.line === void 0 || range.end.column === void 0;
|
341
|
-
}
|
342
391
|
|
343
392
|
export { IstanbulCoverageProvider };
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vitest/coverage-istanbul",
|
3
3
|
"type": "module",
|
4
|
-
"version": "2.0.0
|
4
|
+
"version": "2.0.0",
|
5
5
|
"description": "Istanbul coverage provider for Vitest",
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
7
7
|
"license": "MIT",
|
@@ -37,18 +37,19 @@
|
|
37
37
|
"dist"
|
38
38
|
],
|
39
39
|
"peerDependencies": {
|
40
|
-
"vitest": "2.0.0
|
40
|
+
"vitest": "2.0.0"
|
41
41
|
},
|
42
42
|
"dependencies": {
|
43
|
-
"
|
43
|
+
"@istanbuljs/schema": "^0.1.3",
|
44
|
+
"debug": "^4.3.5",
|
44
45
|
"istanbul-lib-coverage": "^3.2.2",
|
45
|
-
"istanbul-lib-instrument": "^6.0.
|
46
|
+
"istanbul-lib-instrument": "^6.0.3",
|
46
47
|
"istanbul-lib-report": "^3.0.1",
|
47
|
-
"istanbul-lib-source-maps": "^5.0.
|
48
|
+
"istanbul-lib-source-maps": "^5.0.6",
|
48
49
|
"istanbul-reports": "^3.1.7",
|
49
50
|
"magicast": "^0.3.4",
|
50
|
-
"picocolors": "^1.0.
|
51
|
-
"test-exclude": "^
|
51
|
+
"picocolors": "^1.0.1",
|
52
|
+
"test-exclude": "^7.0.1"
|
52
53
|
},
|
53
54
|
"devDependencies": {
|
54
55
|
"@types/debug": "^4.1.12",
|
@@ -58,7 +59,7 @@
|
|
58
59
|
"@types/istanbul-lib-source-maps": "^4.0.4",
|
59
60
|
"@types/istanbul-reports": "^3.0.4",
|
60
61
|
"pathe": "^1.1.2",
|
61
|
-
"vitest": "2.0.0
|
62
|
+
"vitest": "2.0.0"
|
62
63
|
},
|
63
64
|
"scripts": {
|
64
65
|
"build": "rimraf dist && rollup -c",
|