@@ -38,6 +38,10 @@ function createIframe(container: HTMLDivElement, file: string) {
38
38
iframe . setAttribute ( 'src' , `${ url . pathname } __vitest_test__/__test__/${ encodeURIComponent ( file ) } ` )
39
39
iframe . setAttribute ( 'data-vitest' , 'true' )
40
40
41
+ const config = getConfig ( ) . browser
42
+ iframe . style . width = `${ config . viewport . width } px`
43
+ iframe . style . height = `${ config . viewport . height } px`
44
+
41
45
iframe . style . display = 'block'
42
46
iframe . style . border = 'none'
43
47
iframe . style . pointerEvents = 'none'
@@ -66,7 +70,14 @@ interface IframeErrorEvent {
66
70
files : string [ ]
67
71
}
68
72
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
70
81
71
82
async function getContainer ( config : ResolvedConfig ) : Promise < HTMLDivElement > {
72
83
if ( config . browser . ui ) {
@@ -99,6 +110,30 @@ client.ws.addEventListener('open', async () => {
99
110
channel . addEventListener ( 'message' , async ( e : MessageEvent < IframeChannelEvent > ) : Promise < void > => {
100
111
debug ( 'channel event' , JSON . stringify ( e . data ) )
101
112
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
+ }
102
137
case 'done' : {
103
138
const filenames = e . data . filenames
104
139
filenames . forEach ( filename => runningFiles . delete ( filename ) )
@@ -161,22 +196,32 @@ async function createTesters(testFiles: string[]) {
161
196
container ,
162
197
ID_ALL ,
163
198
)
199
+
200
+ const ui = getUiAPI ( )
201
+
202
+ if ( ui ) {
203
+ await new Promise ( r => requestAnimationFrame ( r ) )
204
+ ui . recalculateDetailPanels ( )
205
+ }
164
206
}
165
207
else {
166
208
// otherwise, we need to wait for each iframe to finish before creating the next one
167
209
// this is the most stable way to run tests in the browser
168
210
for ( const file of testFiles ) {
169
211
const ui = getUiAPI ( )
170
212
213
+ createIframe (
214
+ container ,
215
+ file ,
216
+ )
217
+
171
218
if ( ui ) {
172
219
const id = generateFileId ( file )
173
220
ui . setCurrentById ( id )
221
+ await new Promise ( r => requestAnimationFrame ( r ) )
222
+ ui . recalculateDetailPanels ( )
174
223
}
175
224
176
- createIframe (
177
- container ,
178
- file ,
179
- )
180
225
await new Promise < void > ( ( resolve ) => {
181
226
channel . addEventListener ( 'message' , function handler ( e : MessageEvent < IframeChannelEvent > ) {
182
227
// done and error can only be triggered by the previous iframe
0 commit comments