@@ -38,6 +38,10 @@ function createIframe(container: HTMLDivElement, file: string) {
3838 iframe . setAttribute ( 'src' , `${ url . pathname } __vitest_test__/__test__/${ encodeURIComponent ( file ) } ` )
3939 iframe . setAttribute ( 'data-vitest' , 'true' )
4040
41+ const config = getConfig ( ) . browser
42+ iframe . style . width = `${ config . viewport . width } px`
43+ iframe . style . height = `${ config . viewport . height } px`
44+
4145 iframe . style . display = 'block'
4246 iframe . style . border = 'none'
4347 iframe . style . pointerEvents = 'none'
@@ -66,7 +70,14 @@ interface IframeErrorEvent {
6670 files : string [ ]
6771}
6872
69- type IframeChannelEvent = IframeDoneEvent | IframeErrorEvent
73+ interface IframeViewportEvent {
74+ type : 'viewport'
75+ width : number | string
76+ height : number | string
77+ id : string
78+ }
79+
80+ type IframeChannelEvent = IframeDoneEvent | IframeErrorEvent | IframeViewportEvent
7081
7182async function getContainer ( config : ResolvedConfig ) : Promise < HTMLDivElement > {
7283 if ( config . browser . ui ) {
@@ -99,6 +110,30 @@ client.ws.addEventListener('open', async () => {
99110 channel . addEventListener ( 'message' , async ( e : MessageEvent < IframeChannelEvent > ) : Promise < void > => {
100111 debug ( 'channel event' , JSON . stringify ( e . data ) )
101112 switch ( e . data . type ) {
113+ case 'viewport' : {
114+ const { width, height, id } = e . data
115+ const widthStr = typeof width === 'number' ? `${ width } px` : width
116+ const heightStr = typeof height === 'number' ? `${ height } px` : height
117+ const iframe = iframes . get ( id )
118+ if ( ! iframe ) {
119+ const error = new Error ( `Cannot find iframe with id ${ id } ` )
120+ channel . postMessage ( { type : 'viewport:fail' , id, error : error . message } )
121+ await client . rpc . onUnhandledError ( {
122+ name : 'Teardown Error' ,
123+ message : error . message ,
124+ } , 'Teardown Error' )
125+ return
126+ }
127+ iframe . style . width = widthStr
128+ iframe . style . height = heightStr
129+ const ui = getUiAPI ( )
130+ if ( ui ) {
131+ await new Promise ( r => requestAnimationFrame ( r ) )
132+ ui . recalculateDetailPanels ( )
133+ }
134+ channel . postMessage ( { type : 'viewport:done' , id } )
135+ break
136+ }
102137 case 'done' : {
103138 const filenames = e . data . filenames
104139 filenames . forEach ( filename => runningFiles . delete ( filename ) )
@@ -161,22 +196,32 @@ async function createTesters(testFiles: string[]) {
161196 container ,
162197 ID_ALL ,
163198 )
199+
200+ const ui = getUiAPI ( )
201+
202+ if ( ui ) {
203+ await new Promise ( r => requestAnimationFrame ( r ) )
204+ ui . recalculateDetailPanels ( )
205+ }
164206 }
165207 else {
166208 // otherwise, we need to wait for each iframe to finish before creating the next one
167209 // this is the most stable way to run tests in the browser
168210 for ( const file of testFiles ) {
169211 const ui = getUiAPI ( )
170212
213+ createIframe (
214+ container ,
215+ file ,
216+ )
217+
171218 if ( ui ) {
172219 const id = generateFileId ( file )
173220 ui . setCurrentById ( id )
221+ await new Promise ( r => requestAnimationFrame ( r ) )
222+ ui . recalculateDetailPanels ( )
174223 }
175224
176- createIframe (
177- container ,
178- file ,
179- )
180225 await new Promise < void > ( ( resolve ) => {
181226 channel . addEventListener ( 'message' , function handler ( e : MessageEvent < IframeChannelEvent > ) {
182227 // done and error can only be triggered by the previous iframe
0 commit comments