[READ-ONLY] Mirror of https://github.com/vitest-dev/vitest. Next generation testing framework powered by Vite. vitest.dev
test testing-tools vite
12

Configure Feed

Select the types of activity you want to include in your feed.

fix(coverage): invalidate circular modules correctly on rerun with coverage (#9096)

authored by

Fai and committed by
GitHub
(Nov 25, 2025, 10:58 AM +0100) 6f22c675 3326cc9f

+61
+1
packages/coverage-istanbul/src/provider.ts
··· 239 239 if (node.id && !this.transformedModuleIds.has(node.id)) { 240 240 moduleGraph.invalidateModule(node, seen) 241 241 } 242 + seen.add(node) // to avoid infinite loops in circular dependencies 242 243 node.importedModules.forEach((mod) => { 243 244 this.invalidateTree(mod, moduleGraph, seen) 244 245 })
+33
test/coverage-test/test/run-dynamic-coverage.test.ts
··· 26 26 expect(coverageMap.files()).toContain('<process-cwd>/fixtures/src/math.ts') 27 27 }) 28 28 29 + test('enableCoverage() invalidates circular modules', async () => { 30 + await cleanupCoverageJson() 31 + 32 + await expect(readCoverageMap(), 'coverage map should not be on the disk').rejects.toThrowError(/no such file/) 33 + 34 + // Simulating user actions in the VSCode Vitest extension: 35 + // 1. User clicks "Run Test with Coverage" to generate coverage files normally 36 + const { ctx } = await runVitest({ 37 + include: ['fixtures/test/circular.test.ts'], 38 + watch: false, 39 + coverage: { 40 + enabled: true, 41 + reporter: 'json', 42 + }, 43 + }) 44 + 45 + const coverageMap = await readCoverageMap() 46 + expect(coverageMap.files()).toEqual([ 47 + '<process-cwd>/fixtures/src/circularA.ts', 48 + '<process-cwd>/fixtures/src/circularB.ts', 49 + ]) 50 + 51 + // 2. User reruns tests with coverage 52 + await ctx!.enableCoverage() 53 + await ctx!.rerunFiles() 54 + 55 + const coverageMap2 = await readCoverageMap() 56 + expect(coverageMap2.files()).toEqual([ 57 + '<process-cwd>/fixtures/src/circularA.ts', 58 + '<process-cwd>/fixtures/src/circularB.ts', 59 + ]) 60 + }) 61 + 29 62 test('disableCoverage() stops collecting coverage going forward', async () => { 30 63 const { ctx } = await runVitest({ 31 64 include: ['fixtures/test/math.test.ts'],
+7
test/coverage-test/fixtures/src/circularA.ts
··· 1 + import { circularB } from './circularB' 2 + 3 + export const CalledB: number[] = [] 4 + 5 + export function circularA() { 6 + return circularB() 7 + }
+5
test/coverage-test/fixtures/src/circularB.ts
··· 1 + import { CalledB } from './circularA' 2 + 3 + export function circularB() { 4 + return CalledB.push(CalledB.length) 5 + }
+15
test/coverage-test/fixtures/test/circular.test.ts
··· 1 + import { expect, it } from 'vitest' 2 + import { CalledB, circularA } from '../src/circularA' 3 + 4 + it('circular', () => { 5 + CalledB.length = 0 6 + 7 + circularA() 8 + 9 + expect(CalledB.length).toBe(1) 10 + 11 + circularA() 12 + circularA() 13 + 14 + expect(CalledB).toEqual([0, 1, 2]) 15 + })