@vitest/coverage-istanbul 2.0.0-beta.9 → 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 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(providerPath);
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, defaultExclude, defaultInclude } from 'vitest/config';
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(ctx.config.root, config.reportsDirectory || coverageConfigDefaults.reportsDirectory),
132
- reporter: this.resolveReporters(config.reporter || coverageConfigDefaults.reporter),
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: typeof this.options.include === "undefined" ? void 0 : [...this.options.include],
155
- exclude: [...defaultExclude, ...defaultInclude, ...this.options.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(this.options.reportsDirectory, tempDirectory);
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("_ts_decorate", "/* istanbul ignore next */_ts_decorate");
173
- const code = this.instrumenter.instrumentSync(sourceCode, id, sourceMap);
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
- if (transformMode !== "web" && transformMode !== "ssr")
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(this.coverageFilesDirectory, `coverage-${uniqueId++}.json`);
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, { recursive: true, force: true, maxRetries: 10 });
200
- if (existsSync(this.coverageFilesDirectory))
201
- await promises.rm(this.coverageFilesDirectory, { recursive: true, force: true, maxRetries: 10 });
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 [coveragePerProject.ssr, coveragePerProject.web]) {
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(filenames, this.options.processingConcurrency)) {
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(chunk.map(async (filename) => {
221
- const contents = await promises.readFile(filename, "utf-8");
222
- const coverage = JSON.parse(contents);
223
- coverageMapByTransformMode.merge(coverage);
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(coverageMapByTransformMode);
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(coveredFiles);
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(c.blue(" % ") + c.dim("Coverage report from ") + c.yellow(this.name));
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('Missing configurationFile. The "coverage.thresholds.autoUpdate" can only be enabled when configuration file is used.');
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(await promises.readFile(configFilePath, "utf8"));
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(configFilePath, configModule.generate().code, "utf-8")
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((file) => resolve(this.ctx.config.root, file));
299
- if (this.ctx.config.changed)
300
- includedFiles = (this.ctx.config.related || []).filter((file) => includedFiles.includes(file));
301
- const uncoveredFiles = includedFiles.filter((file) => !coveredFiles.includes(file));
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-beta.9",
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-beta.9"
40
+ "vitest": "2.0.0"
41
41
  },
42
42
  "dependencies": {
43
- "debug": "^4.3.4",
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.2",
46
+ "istanbul-lib-instrument": "^6.0.3",
46
47
  "istanbul-lib-report": "^3.0.1",
47
- "istanbul-lib-source-maps": "^5.0.4",
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.0",
51
- "test-exclude": "^6.0.0"
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-beta.9"
62
+ "vitest": "2.0.0"
62
63
  },
63
64
  "scripts": {
64
65
  "build": "rimraf dist && rollup -c",