11import type { DevEnvironment , EnvironmentModuleNode } from 'vite'
22import type { Vitest } from '../node/core'
3- import type { ModuleGraphData } from '../types/general'
3+ import type { TestProject } from '../node/project'
4+ import type { TestModule } from '../node/reporters/reported-tasks'
5+ import type {
6+ ModuleGraphData ,
7+ SharedModuleGraphByProject ,
8+ SharedModuleGraphData ,
9+ } from '../types/general'
410import { getTestFileEnvironment } from './environments'
511
612export async function getModuleGraph (
@@ -9,13 +15,57 @@ export async function getModuleGraph(
915 testFilePath : string ,
1016 viteEnvironment ?: string ,
1117) : Promise < ModuleGraphData > {
12- const graph : Record < string , string [ ] > = { }
13- const externalized = new Set < string > ( )
14- const inlined = new Set < string > ( )
15-
1618 const project = ctx . getProjectByName ( projectName )
17- const browser = project . config . browser . enabled
19+ const environment = getModuleGraphEnvironment ( project , testFilePath , viteEnvironment )
20+ const collector = createModuleGraphCollector ( project , environment )
21+ const roots = collector . add ( testFilePath )
22+ return { modules : collector . data . modules , roots }
23+ }
1824
25+ export function getSharedModuleGraphByProject (
26+ testModules : ReadonlyArray < TestModule > ,
27+ ) : SharedModuleGraphByProject {
28+ const testModulesByProject = new Map < TestProject , TestModule [ ] > ( )
29+ for ( const testModule of testModules ) {
30+ const projectTestModules = testModulesByProject . get ( testModule . project ) ?? [ ]
31+ projectTestModules . push ( testModule )
32+ testModulesByProject . set ( testModule . project , projectTestModules )
33+ }
34+
35+ const result : SharedModuleGraphByProject = { }
36+ for ( const [ project , projectTestModules ] of testModulesByProject ) {
37+ result [ project . name ] = getSharedModuleGraphByEnvironment ( project , projectTestModules )
38+ }
39+ return result
40+ }
41+
42+ function getSharedModuleGraphByEnvironment (
43+ project : TestProject ,
44+ testModules : TestModule [ ] ,
45+ ) : SharedModuleGraphByProject [ string ] {
46+ const collectors : { [ environmentName : string ] : ModuleGraphCollector } = { }
47+ for ( const testModule of testModules ) {
48+ const environment = getModuleGraphEnvironment (
49+ project ,
50+ testModule . moduleId ,
51+ testModule . viteEnvironment ?. name ,
52+ )
53+ collectors [ environment . name ] ??= createModuleGraphCollector ( project , environment )
54+ collectors [ environment . name ] . add ( testModule . moduleId )
55+ }
56+ return Object . fromEntries (
57+ Object . entries ( collectors ) . map ( ( [ environmentName , collector ] ) => [
58+ environmentName ,
59+ collector . data ,
60+ ] ) ,
61+ )
62+ }
63+
64+ function getModuleGraphEnvironment (
65+ project : TestProject ,
66+ testFilePath : string ,
67+ viteEnvironment ?: string ,
68+ ) : DevEnvironment {
1969 let environment : DevEnvironment | undefined
2070
2171 if ( viteEnvironment ) {
@@ -24,15 +74,34 @@ export async function getModuleGraph(
2474 environment =
2575 project . config . experimental . viteModuleRunner === false
2676 ? project . vite . environments . __vitest__
27- : getTestFileEnvironment ( project , testFilePath , browser )
77+ : getTestFileEnvironment ( project , testFilePath , project . config . browser . enabled )
2878 }
2979
3080 if ( ! environment ) {
3181 throw new Error ( `Cannot find environment for ${ testFilePath } ` )
3282 }
83+ return environment
84+ }
85+
86+ interface ModuleGraphCollector {
87+ data : SharedModuleGraphData
88+ add : ( testFilePath : string ) => string [ ]
89+ }
90+
91+ function createModuleGraphCollector (
92+ project : TestProject ,
93+ environment : DevEnvironment ,
94+ ) : ModuleGraphCollector {
95+ const data : SharedModuleGraphData = { modules : { } , rootsByTestFile : { } }
96+ const browser = project . config . browser . enabled
3397 const seen = new Map < EnvironmentModuleNode , string > ( )
3498
35- function get ( mod ?: EnvironmentModuleNode ) {
99+ function addExternal ( id : string ) {
100+ data . modules [ id ] ??= { external : true , imports : [ ] }
101+ return id
102+ }
103+
104+ function get ( mod ?: EnvironmentModuleNode ) : string | undefined {
36105 if ( ! mod || ! mod . id ) {
37106 return
38107 }
@@ -50,37 +119,33 @@ export async function getModuleGraph(
50119 const id = clearId ( mod . id )
51120 seen . set ( mod , id )
52121 if ( id . startsWith ( '__vite-browser-external:' ) ) {
53- const external = id . slice ( '__vite-browser-external:' . length )
54- externalized . add ( external )
55- return external
122+ return addExternal ( id . slice ( '__vite-browser-external:' . length ) )
56123 }
57124 const external = project . _resolver . wasExternalized ( id )
58125 if ( typeof external === 'string' ) {
59- externalized . add ( external )
60- return external
126+ return addExternal ( external )
61127 }
62128 if ( browser && mod . file ?. includes ( project . browser ! . vite . config . cacheDir ) ) {
63- externalized . add ( mod . id )
64- return id
129+ return addExternal ( id )
65130 }
66- inlined . add ( id )
67- const mods = Array . from ( mod . importedModules ) . filter (
68- ( i ) => i . id && ! i . id . includes ( '/vitest/dist/' ) ,
69- )
70- graph [ id ] = mods . map ( ( m ) => get ( m ) ) . filter ( Boolean ) as string [ ]
131+ data . modules [ id ] = { external : false , imports : [ ] }
132+ data . modules [ id ] . imports = Array . from ( mod . importedModules )
133+ . filter ( ( i ) => i . id && ! i . id . includes ( '/vitest/dist/' ) )
134+ . map ( ( m ) => get ( m ) )
135+ . filter ( ( id ) => id != null )
71136 return id
72137 }
73138
74- get ( environment . moduleGraph . getModuleById ( testFilePath ) )
75- project . config . setupFiles . forEach ( ( setupFile ) => {
76- get ( environment . moduleGraph . getModuleById ( setupFile ) )
77- } )
78-
79- return {
80- graph,
81- externalized : Array . from ( externalized ) ,
82- inlined : Array . from ( inlined ) ,
139+ // graph roots of the test file including setup files
140+ function add ( testFilePath : string ) : string [ ] {
141+ const roots = [ testFilePath , ...project . config . setupFiles ]
142+ . map ( ( file ) => get ( environment . moduleGraph . getModuleById ( file ) ) )
143+ . filter ( ( id ) => id != null )
144+ data . rootsByTestFile [ testFilePath ] = roots
145+ return roots
83146 }
147+
148+ return { data, add }
84149}
85150
86151function clearId ( id ?: string | null ) {
0 commit comments