Skip to content

Commit 0fa80f5

Browse files
authored
fix(coverage): filenames containing brackets incorrectly showing as uncovered (#11531)
1 parent bf04b9c commit 0fa80f5

2 files changed

Lines changed: 38 additions & 8 deletions

File tree

‎packages/vitest/src/node/coverage.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,19 +221,22 @@ export class BaseCoverageProvider {
221221
include: string[],
222222
root: string,
223223
): Promise<string[]> {
224+
const tested = new Set(testedFiles.map((file) => slash(file)))
225+
224226
let includedFiles = await glob(include, {
225227
cwd: root,
226-
ignore: [...this.options.exclude, ...testedFiles.map((file) => slash(file))],
228+
ignore: this.options.exclude,
227229
absolute: true,
228230
dot: true,
229231
onlyFiles: true,
230232
})
231233

232234
// Run again through picomatch as tinyglobby's exclude pattern is different ({ "exclude": ["math"] } should ignore "src/math.ts")
233-
includedFiles = includedFiles.filter((file) => this.isIncluded(file, root))
235+
includedFiles = includedFiles.filter((file) => !tested.has(file) && this.isIncluded(file, root))
234236

235237
if (this.changedFiles) {
236-
includedFiles = this.changedFiles.filter((file) => includedFiles.includes(file))
238+
const included = new Set(includedFiles)
239+
includedFiles = this.changedFiles.filter((file) => included.has(file))
237240
}
238241

239242
return includedFiles.map((file) => slash(path.resolve(root, file)))

‎test/coverage-test/test/include-exclude.unit.test.ts‎

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import type { BaseCoverageProvider, CoverageOptions } from 'vitest/node'
2-
import { mkdirSync, rmSync } from 'node:fs'
3-
import { join, resolve, sep } from 'node:path'
2+
import { mkdirSync, rmSync, writeFileSync } from 'node:fs'
3+
import { dirname, join, relative, resolve, sep } from 'node:path'
44
import { Writable } from 'node:stream'
5+
import { normalize } from 'pathe'
56
import { expect, onTestFinished, test } from 'vitest'
67
import { createVitest } from 'vitest/node'
78

@@ -164,7 +165,35 @@ test('files with almost matching name, outside project when allowExternal: false
164165
expect(isIncluded(resolve(parent, './something-else/src/three.ts'))).toBe(false)
165166
})
166167

168+
test('tested files with glob characters in their path are not uncovered', async () => {
169+
const root = resolve(process.cwd(), `vitest-test-${crypto.randomUUID()}`)
170+
const tested = resolve(root, 'src/(app)/[id]/{page}.ts')
171+
const untested = resolve(root, 'src/(app)/[id]/untested.ts')
172+
173+
mkdirSync(dirname(tested), { recursive: true })
174+
writeFileSync(tested, '')
175+
writeFileSync(untested, '')
176+
onTestFinished(() => {
177+
rmSync(root, { recursive: true, force: true })
178+
})
179+
180+
const provider = await initProvider({ include: ['src/**'], root })
181+
const untestedFiles = await provider.getUntestedFiles([normalize(tested)])
182+
183+
expect(untestedFiles.map((file) => relative(root, file).replaceAll('\\', '/'))).toEqual([
184+
'src/(app)/[id]/untested.ts',
185+
])
186+
})
187+
167188
async function init(options: Partial<CoverageOptions> & { testInclude?: string[]; root?: string }) {
189+
const provider = await initProvider(options)
190+
191+
return (path: string) => provider.isIncluded(resolve(process.cwd(), path))
192+
}
193+
194+
async function initProvider(
195+
options: Partial<CoverageOptions> & { testInclude?: string[]; root?: string },
196+
) {
168197
const vitest = await createVitest(
169198
'test',
170199
{
@@ -184,7 +213,5 @@ async function init(options: Partial<CoverageOptions> & { testInclude?: string[]
184213
onTestFinished(() => vitest.close())
185214
await vitest.standalone()
186215

187-
const provider = vitest.coverageProvider as unknown as BaseCoverageProvider
188-
189-
return (path: string) => provider.isIncluded(resolve(process.cwd(), path))
216+
return vitest.coverageProvider as unknown as BaseCoverageProvider
190217
}

0 commit comments

Comments
 (0)