@@ -69,6 +69,74 @@ async function findTestEnvironment(
6969 }
7070}
7171
72+ function determineCoverageProvider (
73+ browser : BrowserConfigOptions | undefined ,
74+ testConfig : InlineConfig | undefined ,
75+ optionsCoverageEnabled : boolean | undefined ,
76+ projectSourceRoot : string ,
77+ ) : 'istanbul' | 'v8' | 'custom' | undefined {
78+ let determinedProvider = testConfig ?. coverage ?. provider ;
79+ if ( ! determinedProvider && ( optionsCoverageEnabled || testConfig ?. coverage ?. enabled ) ) {
80+ const browsersToCheck = getBrowsersToCheck ( browser , testConfig ?. browser ) ;
81+
82+ const hasNonChromium =
83+ browsersToCheck
84+ . map ( ( b ) => normalizeBrowserName ( b ) . browser )
85+ . filter ( ( b ) => ! [ 'chrome' , 'chromium' , 'edge' ] . includes ( b ) ) . length > 0 ;
86+
87+ if ( hasNonChromium ) {
88+ determinedProvider = 'istanbul' ;
89+ } else {
90+ const projectRequire = createRequire ( projectSourceRoot + '/' ) ;
91+ const checkInstalled = ( pkg : string ) => {
92+ try {
93+ projectRequire . resolve ( pkg ) ;
94+
95+ return true ;
96+ } catch {
97+ return false ;
98+ }
99+ } ;
100+ const hasIstanbul = checkInstalled ( '@vitest/coverage-istanbul' ) ;
101+ const hasV8 = checkInstalled ( '@vitest/coverage-v8' ) ;
102+
103+ if ( hasIstanbul && ! hasV8 ) {
104+ determinedProvider = 'istanbul' ;
105+ } else {
106+ determinedProvider = 'v8' ;
107+ }
108+ }
109+ }
110+
111+ return determinedProvider ;
112+ }
113+
114+ function getBrowsersToCheck (
115+ browser : BrowserConfigOptions | undefined ,
116+ testConfigBrowser : BrowserConfigOptions | undefined ,
117+ ) : string [ ] {
118+ const browsersToCheck : string [ ] = [ ] ;
119+
120+ // 1. Check browsers passed by the Angular CLI options
121+ const cliBrowser = browser as CustomBrowserConfigOptions | undefined ;
122+ if ( cliBrowser ?. instances ) {
123+ browsersToCheck . push ( ...cliBrowser . instances . map ( ( i ) => i . browser ) ) ;
124+ }
125+
126+ // 2. Check browsers defined in the user's vitest.config.ts
127+ const userBrowser = testConfigBrowser as CustomBrowserConfigOptions | undefined ;
128+ if ( userBrowser ) {
129+ if ( userBrowser . instances ) {
130+ browsersToCheck . push ( ...userBrowser . instances . map ( ( i ) => i . browser ) ) ;
131+ }
132+ if ( userBrowser . name ) {
133+ browsersToCheck . push ( userBrowser . name ) ;
134+ }
135+ }
136+
137+ return browsersToCheck ;
138+ }
139+
72140export async function createVitestConfigPlugin (
73141 options : VitestConfigPluginOptions ,
74142) : Promise < VitestPlugins [ 0 ] > {
@@ -89,6 +157,13 @@ export async function createVitestConfigPlugin(
89157 async config ( config ) {
90158 const testConfig = config . test ;
91159
160+ const determinedProvider = determineCoverageProvider (
161+ browser ,
162+ testConfig ,
163+ options . coverage . enabled ,
164+ projectSourceRoot ,
165+ ) ;
166+
92167 if ( reporters !== undefined ) {
93168 delete testConfig ?. reporters ;
94169 }
@@ -155,8 +230,8 @@ export async function createVitestConfigPlugin(
155230 ( browser || testConfig ?. browser ?. enabled ) &&
156231 ( options . coverage . enabled || testConfig ?. coverage ?. enabled )
157232 ) {
158- // Validate that enabled browsers support V8 coverage
159- validateBrowserCoverage ( browser , testConfig ?. browser ) ;
233+ // Validate that enabled browsers support the selected coverage provider
234+ validateBrowserCoverage ( browser , testConfig ?. browser , determinedProvider ) ;
160235
161236 projectPlugins . unshift ( createSourcemapSupportPlugin ( ) ) ;
162237 setupFiles . unshift ( 'virtual:source-map-support' ) ;
@@ -208,6 +283,7 @@ export async function createVitestConfigPlugin(
208283 options . coverage ,
209284 testConfig ?. coverage ,
210285 projectName ,
286+ determinedProvider ,
211287 ) ,
212288 // eslint-disable-next-line @typescript-eslint/no-explicit-any
213289 ...( reporters ? ( { reporters } as any ) : { } ) ,
@@ -434,25 +510,12 @@ interface CustomBrowserConfigOptions {
434510function validateBrowserCoverage (
435511 browser : BrowserConfigOptions | undefined ,
436512 testConfigBrowser : BrowserConfigOptions | undefined ,
513+ provider ?: string ,
437514) : void {
438- const browsersToCheck : string [ ] = [ ] ;
439-
440- // 1. Check browsers passed by the Angular CLI options
441- const cliBrowser = browser as CustomBrowserConfigOptions | undefined ;
442- if ( cliBrowser ?. instances ) {
443- browsersToCheck . push ( ...cliBrowser . instances . map ( ( i ) => i . browser ) ) ;
444- }
445-
446- // 2. Check browsers defined in the user's vitest.config.ts
447- const userBrowser = testConfigBrowser as CustomBrowserConfigOptions | undefined ;
448- if ( userBrowser ) {
449- if ( userBrowser . instances ) {
450- browsersToCheck . push ( ...userBrowser . instances . map ( ( i ) => i . browser ) ) ;
451- }
452- if ( userBrowser . name ) {
453- browsersToCheck . push ( userBrowser . name ) ;
454- }
515+ if ( provider === 'istanbul' ) {
516+ return ;
455517 }
518+ const browsersToCheck = getBrowsersToCheck ( browser , testConfigBrowser ) ;
456519
457520 // Normalize and filter unsupported browsers
458521 const unsupportedBrowsers = browsersToCheck
@@ -473,6 +536,7 @@ async function generateCoverageOption(
473536 optionsCoverage : NormalizedUnitTestBuilderOptions [ 'coverage' ] ,
474537 configCoverage : VitestCoverageOption | undefined ,
475538 projectName : string ,
539+ provider ?: 'istanbul' | 'v8' | 'custom' ,
476540) : Promise < VitestCoverageOption > {
477541 let defaultExcludes : string [ ] = [ ] ;
478542 // When a coverage exclude option is provided, Vitest's default coverage excludes
@@ -486,6 +550,7 @@ async function generateCoverageOption(
486550 }
487551
488552 return {
553+ provider,
489554 excludeAfterRemap : true ,
490555 reportsDirectory :
491556 configCoverage ?. reportsDirectory ?? toPosixPath ( path . join ( 'coverage' , projectName ) ) ,
0 commit comments