Skip to content

Commit

Permalink
fix(coverage): v8 provider to pick source maps without url query para…
Browse files Browse the repository at this point in the history
…ms (#3784)
  • Loading branch information
AriPerkkio committed Jul 28, 2023
1 parent cdab465 commit 280e674
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 26 deletions.
36 changes: 26 additions & 10 deletions packages/coverage-v8/src/provider.ts
Expand Up @@ -13,7 +13,8 @@ import remapping from '@ampproject/remapping'
import { normalize, resolve } from 'pathe'
import c from 'picocolors'
import { provider } from 'std-env'
import type { EncodedSourceMap } from 'vite-node'
import { cleanUrl } from 'vite-node/utils'
import type { EncodedSourceMap, FetchResult } from 'vite-node'
import { coverageConfigDefaults, defaultExclude, defaultInclude } from 'vitest/config'
import { BaseCoverageProvider } from 'vitest/coverage'
import type { AfterSuiteRunMeta, CoverageProvider, CoverageV8Options, ReportContext, ResolvedCoverageOptions } from 'vitest'
Expand All @@ -36,6 +37,7 @@ interface TestExclude {
}

type Options = ResolvedCoverageOptions<'v8'>
type TransformResults = Map<string, FetchResult>

// TODO: vite-node should export this
const WRAPPER_LENGTH = 185
Expand Down Expand Up @@ -99,18 +101,19 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
if (provider === 'stackblitz')
this.ctx.logger.log(c.blue(' % ') + c.yellow('@vitest/coverage-v8 does not work on Stackblitz. Report will be empty.'))

const transformResults = normalizeTransformResults(this.ctx.projects.map(project => project.vitenode.fetchCache))
const merged = mergeProcessCovs(this.coverages)
const scriptCoverages = merged.result.filter(result => this.testExclude.shouldInstrument(fileURLToPath(result.url)))

if (this.options.all && allTestsRun) {
const coveredFiles = Array.from(scriptCoverages.map(r => r.url))
const untestedFiles = await this.getUntestedFiles(coveredFiles)
const untestedFiles = await this.getUntestedFiles(coveredFiles, transformResults)

scriptCoverages.push(...untestedFiles)
}

const converted = await Promise.all(scriptCoverages.map(async ({ url, functions }) => {
const sources = await this.getSources(url, functions)
const sources = await this.getSources(url, transformResults, functions)

// If no source map was found from vite-node we can assume this file was not run in the wrapper
const wrapperLength = sources.sourceMap ? WRAPPER_LENGTH : 0
Expand Down Expand Up @@ -177,14 +180,14 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
}
}

private async getUntestedFiles(testedFiles: string[]): Promise<Profiler.ScriptCoverage[]> {
private async getUntestedFiles(testedFiles: string[], transformResults: TransformResults): Promise<Profiler.ScriptCoverage[]> {
const includedFiles = await this.testExclude.glob(this.ctx.config.root)
const uncoveredFiles = includedFiles
.map(file => pathToFileURL(resolve(this.ctx.config.root, file)))
.filter(file => !testedFiles.includes(file.href))

return await Promise.all(uncoveredFiles.map(async (uncoveredFile) => {
const { source } = await this.getSources(uncoveredFile.href)
const { source } = await this.getSources(uncoveredFile.href, transformResults)

return {
url: uncoveredFile.href,
Expand All @@ -204,16 +207,14 @@ export class V8CoverageProvider extends BaseCoverageProvider implements Coverage
}))
}

private async getSources(url: string, functions: Profiler.FunctionCoverage[] = []): Promise<{
private async getSources(url: string, transformResults: TransformResults, functions: Profiler.FunctionCoverage[] = []): Promise<{
source: string
originalSource?: string
sourceMap?: { sourcemap: EncodedSourceMap }
}> {
const filePath = normalize(fileURLToPath(url))
const transformResult = this.ctx.projects
.map(project => project.vitenode.fetchCache.get(filePath)?.result)
.filter(Boolean)
.shift()

const transformResult = transformResults.get(filePath)

const map = transformResult?.map
const code = transformResult?.code
Expand Down Expand Up @@ -277,3 +278,18 @@ function findLongestFunctionLength(functions: Profiler.FunctionCoverage[]) {
return Math.max(previous, maxEndOffset)
}, 0)
}

function normalizeTransformResults(fetchCaches: Map<string, { result: FetchResult }>[]) {
const normalized: TransformResults = new Map()

for (const fetchCache of fetchCaches) {
for (const [key, value] of fetchCache.entries()) {
const cleanEntry = cleanUrl(key)

if (!normalized.has(cleanEntry))
normalized.set(cleanEntry, value.result)
}
}

return normalized
}
Expand Up @@ -704,12 +704,11 @@ exports[`v8 json report 1`] = `
"0": 1,
"1": 1,
"2": 1,
"3": 1,
},
"statementMap": {
"0": {
"end": {
"column": 50,
"column": 38,
"line": 1,
},
"start": {
Expand All @@ -719,7 +718,7 @@ exports[`v8 json report 1`] = `
},
"1": {
"end": {
"column": 38,
"column": 0,
"line": 2,
},
"start": {
Expand All @@ -729,24 +728,14 @@ exports[`v8 json report 1`] = `
},
"2": {
"end": {
"column": 0,
"column": 21,
"line": 3,
},
"start": {
"column": 0,
"line": 3,
},
},
"3": {
"end": {
"column": 39,
"line": 4,
},
"start": {
"column": 0,
"line": 4,
},
},
},
},
"<process-cwd>/src/Defined.vue": {
Expand Down
3 changes: 1 addition & 2 deletions test/coverage-test/src/Counter/index.ts
@@ -1,4 +1,3 @@
import CounterComponent from './Counter.component'
import CounterVue from './Counter.vue'

export { CounterComponent, CounterVue }
export { CounterVue }

0 comments on commit 280e674

Please sign in to comment.