@@ -200,8 +200,45 @@ const validWrapperTypes = new Set([
200
200
ClassComponent ,
201
201
HostComponent ,
202
202
ForwardRef ,
203
+ // Normally skipped, but used when there's more than one root child.
204
+ HostRoot ,
203
205
] ) ;
204
206
207
+ function getChildren ( parent : Fiber ) {
208
+ const children = [ ] ;
209
+ const startingNode = parent ;
210
+ let node : Fiber = startingNode ;
211
+ if ( node . child === null ) {
212
+ return children ;
213
+ }
214
+ node . child . return = node ;
215
+ node = node . child ;
216
+ outer: while ( true ) {
217
+ let descend = false ;
218
+ if ( validWrapperTypes . has ( node . tag ) ) {
219
+ children . push ( wrapFiber ( node ) ) ;
220
+ } else if ( node . tag === HostText ) {
221
+ children . push ( '' + node . memoizedProps ) ;
222
+ } else {
223
+ descend = true ;
224
+ }
225
+ if ( descend && node . child !== null ) {
226
+ node . child . return = node ;
227
+ node = node . child ;
228
+ continue ;
229
+ }
230
+ while ( node . sibling === null ) {
231
+ if ( node . return === startingNode ) {
232
+ break outer;
233
+ }
234
+ node = ( node . return : any ) ;
235
+ }
236
+ ( node . sibling : any ) . return = node . return ;
237
+ node = ( node . sibling : any ) ;
238
+ }
239
+ return children ;
240
+ }
241
+
205
242
class ReactTestInstance {
206
243
_fiber : Fiber ;
207
244
@@ -246,6 +283,13 @@ class ReactTestInstance {
246
283
let parent = this . _fiber . return ;
247
284
while ( parent !== null ) {
248
285
if ( validWrapperTypes . has ( parent . tag ) ) {
286
+ if ( parent . tag === HostRoot ) {
287
+ // Special case: we only "materialize" instances for roots
288
+ // if they have more than a single child. So we'll check that now.
289
+ if ( getChildren ( parent ) . length < 2 ) {
290
+ return null ;
291
+ }
292
+ }
249
293
return wrapFiber ( parent ) ;
250
294
}
251
295
parent = parent . return ;
@@ -254,38 +298,7 @@ class ReactTestInstance {
254
298
}
255
299
256
300
get children ( ) : Array < ReactTestInstance | string > {
257
- const children = [ ] ;
258
- const startingNode = this . _currentFiber ( ) ;
259
- let node : Fiber = startingNode ;
260
- if ( node . child === null ) {
261
- return children ;
262
- }
263
- node . child . return = node ;
264
- node = node . child ;
265
- outer: while ( true ) {
266
- let descend = false ;
267
- if ( validWrapperTypes . has ( node . tag ) ) {
268
- children . push ( wrapFiber ( node ) ) ;
269
- } else if ( node . tag === HostText ) {
270
- children . push ( '' + node . memoizedProps ) ;
271
- } else {
272
- descend = true ;
273
- }
274
- if ( descend && node . child !== null ) {
275
- node . child . return = node ;
276
- node = node . child ;
277
- continue ;
278
- }
279
- while ( node . sibling === null ) {
280
- if ( node . return === startingNode ) {
281
- break outer;
282
- }
283
- node = ( node . return : any ) ;
284
- }
285
- ( node . sibling : any ) . return = node . return ;
286
- node = ( node . sibling : any ) ;
287
- }
288
- return children ;
301
+ return getChildren ( this . _currentFiber ( ) ) ;
289
302
}
290
303
291
304
// Custom search functions
@@ -469,10 +482,20 @@ const ReactTestRendererFiber = {
469
482
configurable : true ,
470
483
enumerable : true ,
471
484
get : function ( ) {
472
- if ( root === null || root . current . child === null ) {
485
+ if ( root === null ) {
486
+ throw new Error ( "Can't access .root on unmounted test renderer" ) ;
487
+ }
488
+ const children = getChildren ( root . current ) ;
489
+ if ( children . length === 0 ) {
473
490
throw new Error ( "Can't access .root on unmounted test renderer" ) ;
491
+ } else if ( children . length === 1 ) {
492
+ // Normally, we skip the root and just give you the child.
493
+ return children [ 0 ] ;
494
+ } else {
495
+ // However, we give you the root if there's more than one root child.
496
+ // We could make this the behavior for all cases but it would be a breaking change.
497
+ return wrapFiber ( root . current ) ;
474
498
}
475
- return wrapFiber ( root . current . child ) ;
476
499
} ,
477
500
} : Object ) ,
478
501
) ;
0 commit comments