Skip to content

Commit 687b633

Browse files
hi-ogawaCopilotclaude
authored
fix: fix vi.mock({ spy: true }) node v8 coverage (#9541)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: hi-ogawa <4232207+hi-ogawa@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 3f7a5f8 commit 687b633

File tree

8 files changed

+171
-47
lines changed

8 files changed

+171
-47
lines changed

packages/vitest/src/runtime/moduleRunner/moduleEvaluator.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,8 @@ export class VitestModuleEvaluator implements ModuleEvaluator {
315315
)})=>{{`
316316
const wrappedCode = `${codeDefinition}${code}\n}}`
317317
const options = {
318-
filename: module.id,
318+
// use original id for auto spy module (vi.mock(..., { spy: true }))
319+
filename: module.id.startsWith('mock:') ? module.id.slice(5) : module.id,
319320
lineOffset: 0,
320321
columnOffset: -codeDefinition.length,
321322
}

pnpm-lock.yaml

Lines changed: 37 additions & 46 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function double(value: number): number {
2+
return value * 2
3+
}
4+
5+
export function triple(value: number): number {
6+
return value * 3
7+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { expect, test, vi } from 'vitest'
2+
import { double, triple } from '../src/mock-target'
3+
4+
vi.mock(import('../src/mock-target'), { spy: true })
5+
6+
test('autospy calls original and can be spied on', () => {
7+
expect(double(5)).toBe(10)
8+
expect(double).toHaveBeenCalledWith(5)
9+
expect(triple).not.toHaveBeenCalled()
10+
})
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { expect, test, vi } from 'vitest'
2+
import { double, triple } from '../src/mock-target'
3+
4+
// Manual spy approach using importOriginal callback - this collects coverage
5+
vi.mock(import('../src/mock-target'), async (importOriginal) => {
6+
const actual = await importOriginal()
7+
return {
8+
double: vi.fn(actual.double),
9+
triple: vi.fn(actual.triple),
10+
}
11+
})
12+
13+
test('importActual calls original and can be spied on', () => {
14+
expect(double(5)).toBe(10)
15+
expect(double).toHaveBeenCalledWith(5)
16+
expect(triple).not.toHaveBeenCalled()
17+
})
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { expect } from 'vitest'
2+
import { readCoverageMap, runVitest, test } from '../utils'
3+
4+
test('vi.mock({ spy: true }) collects coverage of original module', async () => {
5+
await runVitest({
6+
include: ['fixtures/test/mock-autospy-fixture.test.ts'],
7+
coverage: {
8+
reporter: 'json',
9+
include: ['fixtures/src/mock-target.ts'],
10+
},
11+
})
12+
13+
const coverageMap = await readCoverageMap()
14+
expect(coverageMap).toMatchInlineSnapshot(`
15+
{
16+
"branches": "0/0 (100%)",
17+
"functions": "1/2 (50%)",
18+
"lines": "1/2 (50%)",
19+
"statements": "1/2 (50%)",
20+
}
21+
`)
22+
23+
const coverage = coverageMap.fileCoverageFor('<process-cwd>/fixtures/src/mock-target.ts')
24+
const functionCoverage = Object.keys(coverage.fnMap)
25+
.map(index => ({ name: coverage.fnMap[index].name, hits: coverage.f[index] }))
26+
.sort((a, b) => a.name.localeCompare(b.name))
27+
28+
expect(functionCoverage).toMatchInlineSnapshot(`
29+
[
30+
{
31+
"hits": 1,
32+
"name": "double",
33+
},
34+
{
35+
"hits": 0,
36+
"name": "triple",
37+
},
38+
]
39+
`)
40+
})

0 commit comments

Comments
 (0)