@vitest/coverage-istanbul 2.1.2 → 2.1.3

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.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { IstanbulCoverageProvider } from './provider.js';
2
- import 'vitest';
2
+ import 'magicast';
3
+ import 'vitest/node';
3
4
  import 'vitest/coverage';
5
+ import 'test-exclude';
4
6
  import 'istanbul-lib-coverage';
5
7
  import 'istanbul-lib-instrument';
6
8
 
@@ -1,65 +1,24 @@
1
- import { CoverageProvider, Vitest, AfterSuiteRunMeta, ReportContext, ResolvedCoverageOptions } from 'vitest';
1
+ import * as magicast from 'magicast';
2
+ import { ResolvedCoverageOptions, CoverageProvider, Vitest, ReportContext } from 'vitest/node';
2
3
  import { BaseCoverageProvider } from 'vitest/coverage';
3
- import { CoverageMap } from 'istanbul-lib-coverage';
4
+ import TestExclude from 'test-exclude';
5
+ import libCoverage, { CoverageMap } from 'istanbul-lib-coverage';
4
6
  import { Instrumenter } from 'istanbul-lib-instrument';
5
7
 
6
- type Options = ResolvedCoverageOptions<'istanbul'>;
7
- /**
8
- * Holds info about raw coverage results that are stored on file system:
9
- *
10
- * ```json
11
- * "project-a": {
12
- * "web": {
13
- * "tests/math.test.ts": "coverage-1.json",
14
- * "tests/utils.test.ts": "coverage-2.json",
15
- * // ^^^^^^^^^^^^^^^ Raw coverage on file system
16
- * },
17
- * "ssr": { ... },
18
- * "browser": { ... },
19
- * },
20
- * "project-b": ...
21
- * ```
22
- */
23
- type CoverageFiles = Map<NonNullable<AfterSuiteRunMeta['projectName']> | typeof DEFAULT_PROJECT, Record<AfterSuiteRunMeta['transformMode'], {
24
- [TestFilenames: string]: string;
25
- }>>;
26
- interface TestExclude {
27
- new (opts: {
28
- cwd?: string | string[];
29
- include?: string | string[];
30
- exclude?: string | string[];
31
- extension?: string | string[];
32
- excludeNodeModules?: boolean;
33
- relativePath?: boolean;
34
- }): {
35
- shouldInstrument: (filePath: string) => boolean;
36
- glob: (cwd: string) => Promise<string[]>;
37
- };
38
- }
39
- declare const DEFAULT_PROJECT: unique symbol;
40
- declare class IstanbulCoverageProvider extends BaseCoverageProvider implements CoverageProvider {
41
- name: string;
42
- ctx: Vitest;
43
- options: Options;
8
+ declare class IstanbulCoverageProvider extends BaseCoverageProvider<ResolvedCoverageOptions<'istanbul'>> implements CoverageProvider {
9
+ name: "istanbul";
10
+ version: string;
44
11
  instrumenter: Instrumenter;
45
- testExclude: InstanceType<TestExclude>;
46
- coverageFiles: CoverageFiles;
47
- coverageFilesDirectory: string;
48
- pendingPromises: Promise<void>[];
12
+ testExclude: InstanceType<typeof TestExclude>;
49
13
  initialize(ctx: Vitest): void;
50
- resolveOptions(): Options;
51
14
  onFileTransform(sourceCode: string, id: string, pluginCtx: any): {
52
15
  code: string;
53
16
  map: any;
54
17
  } | undefined;
55
- onAfterSuiteRun({ coverage, transformMode, projectName, testFiles }: AfterSuiteRunMeta): void;
56
- clean(clean?: boolean): Promise<void>;
18
+ createCoverageMap(): libCoverage.CoverageMap;
57
19
  generateCoverage({ allTestsRun }: ReportContext): Promise<CoverageMap>;
58
- reportCoverage(coverageMap: unknown, { allTestsRun }: ReportContext): Promise<void>;
59
- private cleanAfterRun;
60
- onTestFailure(): Promise<void>;
61
20
  generateReports(coverageMap: CoverageMap, allTestsRun: boolean | undefined): Promise<void>;
62
- mergeReports(coverageMaps: unknown[]): Promise<void>;
21
+ parseConfigModule(configFilePath: string): Promise<magicast.ProxifiedModule<any>>;
63
22
  private getCoverageMapForUncoveredFiles;
64
23
  }
65
24
 
package/dist/provider.js CHANGED
@@ -1,16 +1,15 @@
1
- import { promises, existsSync, readdirSync, writeFileSync } from 'node:fs';
2
- import { coverageConfigDefaults } from 'vitest/config';
1
+ import { promises } from 'node:fs';
3
2
  import { BaseCoverageProvider } from 'vitest/coverage';
4
3
  import c from 'tinyrainbow';
5
4
  import { parseModule } from 'magicast';
6
5
  import createDebug from 'debug';
6
+ import TestExclude from 'test-exclude';
7
7
  import libReport from 'istanbul-lib-report';
8
8
  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
12
  import { defaults } from '@istanbuljs/schema';
13
- import _TestExclude from 'test-exclude';
14
13
  import { C as COVERAGE_STORE_KEY } from './constants-BCJfMgEg.js';
15
14
 
16
15
  const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
@@ -108,53 +107,24 @@ const isAbsolute = function(p) {
108
107
  return _IS_ABSOLUTE_RE.test(p);
109
108
  };
110
109
 
111
- var version = "2.1.2";
110
+ var version = "2.1.3";
112
111
 
113
- const DEFAULT_PROJECT = Symbol.for("default-project");
114
112
  const debug = createDebug("vitest:coverage");
115
- let uniqueId = 0;
116
113
  class IstanbulCoverageProvider extends BaseCoverageProvider {
117
114
  name = "istanbul";
118
- ctx;
119
- options;
115
+ version = version;
120
116
  instrumenter;
121
117
  testExclude;
122
- coverageFiles = /* @__PURE__ */ new Map();
123
- coverageFilesDirectory;
124
- pendingPromises = [];
125
118
  initialize(ctx) {
126
- const config = ctx.config.coverage;
127
- if (ctx.version !== version) {
128
- ctx.logger.warn(
129
- c.yellow(
130
- `Loaded ${c.inverse(c.yellow(` vitest@${ctx.version} `))} and ${c.inverse(c.yellow(` @vitest/coverage-istanbul@${version} `))}.
131
- Running mixed versions is not supported and may lead into bugs
132
- Update your dependencies and make sure the versions match.`
133
- )
134
- );
135
- }
136
- this.ctx = ctx;
137
- this.options = {
138
- ...coverageConfigDefaults,
139
- // User's options
140
- ...config,
141
- // Resolved fields
142
- provider: "istanbul",
143
- reportsDirectory: resolve(
144
- ctx.config.root,
145
- config.reportsDirectory || coverageConfigDefaults.reportsDirectory
146
- ),
147
- reporter: this.resolveReporters(
148
- config.reporter || coverageConfigDefaults.reporter
149
- ),
150
- thresholds: config.thresholds && {
151
- ...config.thresholds,
152
- lines: config.thresholds["100"] ? 100 : config.thresholds.lines,
153
- branches: config.thresholds["100"] ? 100 : config.thresholds.branches,
154
- functions: config.thresholds["100"] ? 100 : config.thresholds.functions,
155
- statements: config.thresholds["100"] ? 100 : config.thresholds.statements
156
- }
157
- };
119
+ this._initialize(ctx);
120
+ this.testExclude = new TestExclude({
121
+ cwd: ctx.config.root,
122
+ include: this.options.include,
123
+ exclude: this.options.exclude,
124
+ excludeNodeModules: true,
125
+ extension: this.options.extension,
126
+ relativePath: !this.options.allowExternal
127
+ });
158
128
  this.instrumenter = createInstrumenter({
159
129
  produceSourceMap: true,
160
130
  autoWrap: false,
@@ -173,23 +143,6 @@ Update your dependencies and make sure the versions match.`
173
143
  importAttributesKeyword: "with"
174
144
  }
175
145
  });
176
- this.testExclude = new _TestExclude({
177
- cwd: ctx.config.root,
178
- include: this.options.include,
179
- exclude: this.options.exclude,
180
- excludeNodeModules: true,
181
- extension: this.options.extension,
182
- relativePath: !this.options.allowExternal
183
- });
184
- const shard = this.ctx.config.shard;
185
- const tempDirectory = `.tmp${shard ? `-${shard.index}-${shard.count}` : ""}`;
186
- this.coverageFilesDirectory = resolve(
187
- this.options.reportsDirectory,
188
- tempDirectory
189
- );
190
- }
191
- resolveOptions() {
192
- return this.options;
193
146
  }
194
147
  onFileTransform(sourceCode, id, pluginCtx) {
195
148
  if (!this.testExclude.shouldInstrument(id)) {
@@ -209,92 +162,26 @@ Update your dependencies and make sure the versions match.`
209
162
  const map = this.instrumenter.lastSourceMap();
210
163
  return { code, map };
211
164
  }
212
- /*
213
- * Coverage and meta information passed from Vitest runners.
214
- * Note that adding new entries here and requiring on those without
215
- * backwards compatibility is a breaking change.
216
- */
217
- onAfterSuiteRun({ coverage, transformMode, projectName, testFiles }) {
218
- if (!coverage) {
219
- return;
220
- }
221
- if (transformMode !== "web" && transformMode !== "ssr" && transformMode !== "browser") {
222
- throw new Error(`Invalid transform mode: ${transformMode}`);
223
- }
224
- let entry = this.coverageFiles.get(projectName || DEFAULT_PROJECT);
225
- if (!entry) {
226
- entry = { web: {}, ssr: {}, browser: {} };
227
- this.coverageFiles.set(projectName || DEFAULT_PROJECT, entry);
228
- }
229
- const testFilenames = testFiles.join();
230
- const filename = resolve(
231
- this.coverageFilesDirectory,
232
- `coverage-${uniqueId++}.json`
233
- );
234
- entry[transformMode][testFilenames] = filename;
235
- const promise = promises.writeFile(filename, JSON.stringify(coverage), "utf-8");
236
- this.pendingPromises.push(promise);
237
- }
238
- async clean(clean = true) {
239
- if (clean && existsSync(this.options.reportsDirectory)) {
240
- await promises.rm(this.options.reportsDirectory, {
241
- recursive: true,
242
- force: true,
243
- maxRetries: 10
244
- });
245
- }
246
- if (existsSync(this.coverageFilesDirectory)) {
247
- await promises.rm(this.coverageFilesDirectory, {
248
- recursive: true,
249
- force: true,
250
- maxRetries: 10
251
- });
252
- }
253
- await promises.mkdir(this.coverageFilesDirectory, { recursive: true });
254
- this.coverageFiles = /* @__PURE__ */ new Map();
255
- this.pendingPromises = [];
165
+ createCoverageMap() {
166
+ return libCoverage.createCoverageMap({});
256
167
  }
257
168
  async generateCoverage({ allTestsRun }) {
258
- const coverageMap = libCoverage.createCoverageMap({});
259
- let index = 0;
260
- const total = this.pendingPromises.length;
261
- await Promise.all(this.pendingPromises);
262
- this.pendingPromises = [];
263
- for (const coveragePerProject of this.coverageFiles.values()) {
264
- for (const coverageByTestfiles of [
265
- coveragePerProject.ssr,
266
- coveragePerProject.web,
267
- coveragePerProject.browser
268
- ]) {
269
- const coverageMapByTransformMode = libCoverage.createCoverageMap({});
270
- const filenames = Object.values(coverageByTestfiles);
271
- for (const chunk of this.toSlices(
272
- filenames,
273
- this.options.processingConcurrency
274
- )) {
275
- if (debug.enabled) {
276
- index += chunk.length;
277
- debug("Covered files %d/%d", index, total);
278
- }
279
- await Promise.all(
280
- chunk.map(async (filename) => {
281
- const contents = await promises.readFile(filename, "utf-8");
282
- const coverage = JSON.parse(contents);
283
- coverageMapByTransformMode.merge(coverage);
284
- })
285
- );
286
- }
287
- const transformedCoverage = await transformCoverage(
288
- coverageMapByTransformMode
289
- );
169
+ const coverageMap = this.createCoverageMap();
170
+ let coverageMapByTransformMode = this.createCoverageMap();
171
+ await this.readCoverageFiles({
172
+ onFileRead(coverage) {
173
+ coverageMapByTransformMode.merge(coverage);
174
+ },
175
+ onFinished: async () => {
176
+ const transformedCoverage = await transformCoverage(coverageMapByTransformMode);
290
177
  coverageMap.merge(transformedCoverage);
291
- }
292
- }
178
+ coverageMapByTransformMode = this.createCoverageMap();
179
+ },
180
+ onDebug: debug
181
+ });
293
182
  if (this.options.all && (allTestsRun || !this.options.cleanOnRerun)) {
294
183
  const coveredFiles = coverageMap.files();
295
- const uncoveredCoverage = await this.getCoverageMapForUncoveredFiles(
296
- coveredFiles
297
- );
184
+ const uncoveredCoverage = await this.getCoverageMapForUncoveredFiles(coveredFiles);
298
185
  coverageMap.merge(await transformCoverage(uncoveredCoverage));
299
186
  }
300
187
  if (this.options.excludeAfterRemap) {
@@ -302,28 +189,6 @@ Update your dependencies and make sure the versions match.`
302
189
  }
303
190
  return coverageMap;
304
191
  }
305
- async reportCoverage(coverageMap, { allTestsRun }) {
306
- await this.generateReports(
307
- coverageMap || libCoverage.createCoverageMap({}),
308
- allTestsRun
309
- );
310
- const keepResults = !this.options.cleanOnRerun && this.ctx.config.watch;
311
- if (!keepResults) {
312
- await this.cleanAfterRun();
313
- }
314
- }
315
- async cleanAfterRun() {
316
- this.coverageFiles = /* @__PURE__ */ new Map();
317
- await promises.rm(this.coverageFilesDirectory, { recursive: true });
318
- if (readdirSync(this.options.reportsDirectory).length === 0) {
319
- await promises.rm(this.options.reportsDirectory, { recursive: true });
320
- }
321
- }
322
- async onTestFailure() {
323
- if (!this.options.reportOnFailure) {
324
- await this.cleanAfterRun();
325
- }
326
- }
327
192
  async generateReports(coverageMap, allTestsRun) {
328
193
  const context = libReport.createContext({
329
194
  dir: this.options.reportsDirectory,
@@ -343,46 +208,13 @@ Update your dependencies and make sure the versions match.`
343
208
  }).execute(context);
344
209
  }
345
210
  if (this.options.thresholds) {
346
- const resolvedThresholds = this.resolveThresholds({
347
- coverageMap,
348
- thresholds: this.options.thresholds,
349
- createCoverageMap: () => libCoverage.createCoverageMap({}),
350
- root: this.ctx.config.root
351
- });
352
- this.checkThresholds({
353
- thresholds: resolvedThresholds,
354
- perFile: this.options.thresholds.perFile,
355
- onError: (error) => this.ctx.logger.error(error)
356
- });
357
- if (this.options.thresholds.autoUpdate && allTestsRun) {
358
- if (!this.ctx.server.config.configFile) {
359
- throw new Error(
360
- 'Missing configurationFile. The "coverage.thresholds.autoUpdate" can only be enabled when configuration file is used.'
361
- );
362
- }
363
- const configFilePath = this.ctx.server.config.configFile;
364
- const configModule = parseModule(
365
- await promises.readFile(configFilePath, "utf8")
366
- );
367
- this.updateThresholds({
368
- thresholds: resolvedThresholds,
369
- perFile: this.options.thresholds.perFile,
370
- configurationFile: configModule,
371
- onUpdate: () => writeFileSync(
372
- configFilePath,
373
- configModule.generate().code,
374
- "utf-8"
375
- )
376
- });
377
- }
211
+ await this.reportThresholds(coverageMap, allTestsRun);
378
212
  }
379
213
  }
380
- async mergeReports(coverageMaps) {
381
- const coverageMap = libCoverage.createCoverageMap({});
382
- for (const coverage of coverageMaps) {
383
- coverageMap.merge(coverage);
384
- }
385
- await this.generateReports(coverageMap, true);
214
+ async parseConfigModule(configFilePath) {
215
+ return parseModule(
216
+ await promises.readFile(configFilePath, "utf8")
217
+ );
386
218
  }
387
219
  async getCoverageMapForUncoveredFiles(coveredFiles) {
388
220
  const allFiles = await this.testExclude.glob(this.ctx.config.root);
@@ -396,7 +228,7 @@ Update your dependencies and make sure the versions match.`
396
228
  }
397
229
  const uncoveredFiles = includedFiles.filter((file) => !coveredFiles.includes(file)).sort();
398
230
  const cacheKey = (/* @__PURE__ */ new Date()).getTime();
399
- const coverageMap = libCoverage.createCoverageMap({});
231
+ const coverageMap = this.createCoverageMap();
400
232
  const transform = this.createUncoveredFileTransformer(this.ctx);
401
233
  for (const [index, filename] of uncoveredFiles.entries()) {
402
234
  debug("Uncovered file %s %d/%d", filename, index, uncoveredFiles.length);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vitest/coverage-istanbul",
3
3
  "type": "module",
4
- "version": "2.1.2",
4
+ "version": "2.1.3",
5
5
  "description": "Istanbul coverage provider for Vitest",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -37,7 +37,7 @@
37
37
  "dist"
38
38
  ],
39
39
  "peerDependencies": {
40
- "vitest": "2.1.2"
40
+ "vitest": "2.1.3"
41
41
  },
42
42
  "dependencies": {
43
43
  "@istanbuljs/schema": "^0.1.3",
@@ -58,8 +58,9 @@
58
58
  "@types/istanbul-lib-report": "^3.0.3",
59
59
  "@types/istanbul-lib-source-maps": "^4.0.4",
60
60
  "@types/istanbul-reports": "^3.0.4",
61
+ "@types/test-exclude": "^6.0.2",
61
62
  "pathe": "^1.1.2",
62
- "vitest": "2.1.2"
63
+ "vitest": "2.1.3"
63
64
  },
64
65
  "scripts": {
65
66
  "build": "rimraf dist && rollup -c",