Skip to content

Commit 0f44d2c

Browse files
feat: implement istanbul coverage support for browser testing (#3040)
Co-authored-by: AriPerkkio <ari.perkkio@gmail.com>
1 parent 09fec84 commit 0f44d2c

File tree

32 files changed

+458
-151
lines changed

32 files changed

+458
-151
lines changed

packages/browser/src/client/main.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ ws.addEventListener('open', async () => {
5757
const { getSafeTimers } = await importId('vitest/utils') as typeof import('vitest/utils')
5858
const safeRpc = createSafeRpc(client, getSafeTimers)
5959

60+
// @ts-expect-error untyped global for internal use
61+
globalThis.__vitest_browser__ = true
6062
// @ts-expect-error mocking vitest apis
6163
globalThis.__vitest_worker__ = {
6264
config,
@@ -82,11 +84,20 @@ async function runTests(paths: string[], config: any) {
8284
const viteClientPath = '/@vite/client'
8385
await import(viteClientPath)
8486

85-
const { startTests, setupCommonEnv, setupSnapshotEnvironment } = await importId('vitest/browser') as typeof import('vitest/browser')
87+
const {
88+
startTests,
89+
setupCommonEnv,
90+
setupSnapshotEnvironment,
91+
takeCoverageInsideWorker,
92+
} = await importId('vitest/browser') as typeof import('vitest/browser')
93+
94+
const executor = {
95+
executeId: (id: string) => importId(id),
96+
}
8697

8798
if (!runner) {
8899
const { VitestTestRunner } = await importId('vitest/runners') as typeof import('vitest/runners')
89-
const BrowserRunner = createBrowserRunner(VitestTestRunner)
100+
const BrowserRunner = createBrowserRunner(VitestTestRunner, { takeCoverage: () => takeCoverageInsideWorker(config.coverage, executor) })
90101
runner = new BrowserRunner({ config, browserHashMap })
91102
}
92103

@@ -104,7 +115,8 @@ async function runTests(paths: string[], config: any) {
104115
const now = `${new Date().getTime()}`
105116
files.forEach(i => browserHashMap.set(i, now))
106117

107-
await startTests(files, runner)
118+
for (const file of files)
119+
await startTests([file], runner)
108120
}
109121
finally {
110122
await rpcDone()

packages/browser/src/client/runner.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ interface BrowserRunnerOptions {
77
browserHashMap: Map<string, string>
88
}
99

10-
export function createBrowserRunner(original: any) {
10+
interface CoverageHandler {
11+
takeCoverage: () => Promise<unknown>
12+
}
13+
14+
export function createBrowserRunner(original: any, coverageModule: CoverageHandler | null) {
1115
return class BrowserTestRunner extends original {
1216
public config: ResolvedConfig
1317
hashMap = new Map<string, string>()
@@ -25,6 +29,12 @@ export function createBrowserRunner(original: any) {
2529
})
2630
}
2731

32+
async onAfterRunSuite() {
33+
await super.onAfterRunSuite?.()
34+
const coverage = await coverageModule?.takeCoverage?.()
35+
await rpc().onAfterSuiteRun({ coverage })
36+
}
37+
2838
onCollected(files: File[]): unknown {
2939
return rpc().onCollected(files)
3040
}

packages/browser/src/node/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ export default (base = '/'): Plugin[] => {
1818
{
1919
enforce: 'pre',
2020
name: 'vitest:browser',
21+
async config(viteConfig) {
22+
// Enables using ignore hint for coverage providers with @preserve keyword
23+
viteConfig.esbuild ||= {}
24+
viteConfig.esbuild.legalComments = 'inline'
25+
},
2126
async configureServer(server) {
2227
server.middlewares.use(
2328
base,

packages/coverage-c8/rollup.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import pkg from './package.json'
1010

1111
const entries = {
1212
index: 'src/index.ts',
13+
provider: 'src/provider.ts',
1314
}
1415

1516
const external = [

packages/coverage-c8/src/index.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
export * from './takeCoverage'
1+
import * as coverage from './takeCoverage'
22

3-
export async function getProvider() {
4-
const { C8CoverageProvider } = await import('./provider')
5-
return new C8CoverageProvider()
3+
export default {
4+
...coverage,
5+
async getProvider() {
6+
// to not bundle the provider
7+
const name = './provider.js'
8+
const { C8CoverageProvider } = await import(name) as typeof import('./provider')
9+
return new C8CoverageProvider()
10+
},
611
}

packages/coverage-istanbul/rollup.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import pkg from './package.json'
1010

1111
const entries = {
1212
index: 'src/index.ts',
13+
provider: 'src/provider.ts',
1314
}
1415

1516
const external = [

packages/coverage-istanbul/src/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { COVERAGE_STORE_KEY } from './constants'
22

33
export async function getProvider() {
4-
const { IstanbulCoverageProvider } = await import('./provider')
4+
// to not bundle the provider
5+
const providerPath = './provider.js'
6+
const { IstanbulCoverageProvider } = await import(providerPath) as typeof import('./provider')
57
return new IstanbulCoverageProvider()
68
}
79

@@ -15,3 +17,8 @@ export function takeCoverage() {
1517

1618
return coverage
1719
}
20+
21+
export default {
22+
getProvider,
23+
takeCoverage,
24+
}

packages/vitest/src/api/setup.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ export function setup(ctx: Vitest, server?: ViteDevServer) {
4646
ctx.state.updateTasks(packs)
4747
await ctx.report('onTaskUpdate', packs)
4848
},
49+
onAfterSuiteRun(meta) {
50+
ctx.coverageProvider?.onAfterSuiteRun(meta)
51+
},
4952
getFiles() {
5053
return ctx.state.getFiles()
5154
},

packages/vitest/src/api/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { TransformResult } from 'vite'
2-
import type { File, ModuleGraphData, Reporter, ResolvedConfig, SnapshotResult, TaskResultPack, UserConsoleLog } from '../types'
2+
import type { AfterSuiteRunMeta, File, ModuleGraphData, Reporter, ResolvedConfig, SnapshotResult, TaskResultPack, UserConsoleLog } from '../types'
33

44
export interface TransformResultWithSource extends TransformResult {
55
source?: string
@@ -8,6 +8,7 @@ export interface TransformResultWithSource extends TransformResult {
88
export interface WebSocketHandlers {
99
onCollected(files?: File[]): Promise<void>
1010
onTaskUpdate(packs: TaskResultPack[]): void
11+
onAfterSuiteRun(meta: AfterSuiteRunMeta): void
1112
onDone(name: string): void
1213
sendLog(log: UserConsoleLog): void
1314
getFiles(): File[]

packages/vitest/src/browser.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export { startTests } from '@vitest/runner'
22
export { setupCommonEnv } from './runtime/setup.common'
33
export { setupSnapshotEnvironment } from './integrations/snapshot/env'
4+
export { takeCoverageInsideWorker, stopCoverageInsideWorker, getCoverageProvider, startCoverageInsideWorker } from './integrations/coverage'

0 commit comments

Comments
 (0)