@@ -69,6 +69,67 @@ 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 = browsersToCheck
83+ . map ( ( b ) => normalizeBrowserName ( b ) . browser )
84+ . filter ( ( b ) => ! [ 'chrome' , 'chromium' , 'edge' ] . includes ( b ) ) . length > 0 ;
85+
86+ if ( hasNonChromium ) {
87+ determinedProvider = 'istanbul' ;
88+ } else {
89+ const projectRequire = createRequire ( projectSourceRoot + '/' ) ;
90+ const checkInstalled = ( pkg : string ) => {
91+ try { projectRequire . resolve ( pkg ) ; return true ; } catch { return false ; }
92+ } ;
93+ const hasIstanbul = checkInstalled ( '@vitest/coverage-istanbul' ) ;
94+ const hasV8 = checkInstalled ( '@vitest/coverage-v8' ) ;
95+
96+ if ( hasIstanbul && ! hasV8 ) {
97+ determinedProvider = 'istanbul' ;
98+ } else {
99+ determinedProvider = 'v8' ;
100+ }
101+ }
102+ }
103+
104+ return determinedProvider ;
105+ }
106+
107+ function getBrowsersToCheck (
108+ browser : BrowserConfigOptions | undefined ,
109+ testConfigBrowser : BrowserConfigOptions | undefined ,
110+ ) : string [ ] {
111+ const browsersToCheck : string [ ] = [ ] ;
112+
113+ // 1. Check browsers passed by the Angular CLI options
114+ const cliBrowser = browser as CustomBrowserConfigOptions | undefined ;
115+ if ( cliBrowser ?. instances ) {
116+ browsersToCheck . push ( ...cliBrowser . instances . map ( ( i ) => i . browser ) ) ;
117+ }
118+
119+ // 2. Check browsers defined in the user's vitest.config.ts
120+ const userBrowser = testConfigBrowser as CustomBrowserConfigOptions | undefined ;
121+ if ( userBrowser ) {
122+ if ( userBrowser . instances ) {
123+ browsersToCheck . push ( ...userBrowser . instances . map ( ( i ) => i . browser ) ) ;
124+ }
125+ if ( userBrowser . name ) {
126+ browsersToCheck . push ( userBrowser . name ) ;
127+ }
128+ }
129+
130+ return browsersToCheck ;
131+ }
132+
72133export async function createVitestConfigPlugin (
73134 options : VitestConfigPluginOptions ,
74135) : Promise < VitestPlugins [ 0 ] > {
@@ -89,6 +150,13 @@ export async function createVitestConfigPlugin(
89150 async config ( config ) {
90151 const testConfig = config . test ;
91152
153+ const determinedProvider = determineCoverageProvider (
154+ browser ,
155+ testConfig ,
156+ options . coverage . enabled ,
157+ projectSourceRoot ,
158+ ) ;
159+
92160 if ( reporters !== undefined ) {
93161 delete testConfig ?. reporters ;
94162 }
@@ -155,8 +223,8 @@ export async function createVitestConfigPlugin(
155223 ( browser || testConfig ?. browser ?. enabled ) &&
156224 ( options . coverage . enabled || testConfig ?. coverage ?. enabled )
157225 ) {
158- // Validate that enabled browsers support V8 coverage
159- validateBrowserCoverage ( browser , testConfig ?. browser ) ;
226+ // Validate that enabled browsers support the selected coverage provider
227+ validateBrowserCoverage ( browser , testConfig ?. browser , determinedProvider ) ;
160228
161229 projectPlugins . unshift ( createSourcemapSupportPlugin ( ) ) ;
162230 setupFiles . unshift ( 'virtual:source-map-support' ) ;
@@ -208,6 +276,7 @@ export async function createVitestConfigPlugin(
208276 options . coverage ,
209277 testConfig ?. coverage ,
210278 projectName ,
279+ determinedProvider ,
211280 ) ,
212281 // eslint-disable-next-line @typescript-eslint/no-explicit-any
213282 ...( reporters ? ( { reporters } as any ) : { } ) ,
@@ -434,25 +503,12 @@ interface CustomBrowserConfigOptions {
434503function validateBrowserCoverage (
435504 browser : BrowserConfigOptions | undefined ,
436505 testConfigBrowser : BrowserConfigOptions | undefined ,
506+ provider ?: string ,
437507) : 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- }
508+ if ( provider === 'istanbul' ) {
509+ return ;
455510 }
511+ const browsersToCheck = getBrowsersToCheck ( browser , testConfigBrowser ) ;
456512
457513 // Normalize and filter unsupported browsers
458514 const unsupportedBrowsers = browsersToCheck
@@ -473,6 +529,7 @@ async function generateCoverageOption(
473529 optionsCoverage : NormalizedUnitTestBuilderOptions [ 'coverage' ] ,
474530 configCoverage : VitestCoverageOption | undefined ,
475531 projectName : string ,
532+ provider ?: 'istanbul' | 'v8' | 'custom' ,
476533) : Promise < VitestCoverageOption > {
477534 let defaultExcludes : string [ ] = [ ] ;
478535 // When a coverage exclude option is provided, Vitest's default coverage excludes
@@ -486,6 +543,7 @@ async function generateCoverageOption(
486543 }
487544
488545 return {
546+ provider,
489547 excludeAfterRemap : true ,
490548 reportsDirectory :
491549 configCoverage ?. reportsDirectory ?? toPosixPath ( path . join ( 'coverage' , projectName ) ) ,
0 commit comments