@@ -201,14 +201,7 @@ describe('ReactOffscreen', () => {
201
201
} ) ;
202
202
// No layout effect.
203
203
expect ( Scheduler ) . toHaveYielded ( [ 'Child' ] ) ;
204
- if ( gate ( flags => flags . persistent ) ) {
205
- expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } prop = "Child" /> ) ;
206
- } else {
207
- // TODO: Offscreen does not yet hide/unhide children correctly in mutation
208
- // mode. Until we do, it should only be used inside a host component
209
- // wrapper whose visibility is toggled simultaneously.
210
- expect ( root ) . toMatchRenderedOutput ( < span prop = "Child" /> ) ;
211
- }
204
+ expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } prop = "Child" /> ) ;
212
205
213
206
// Unhide the tree. The layout effect is mounted.
214
207
await act ( async ( ) => {
@@ -255,14 +248,7 @@ describe('ReactOffscreen', () => {
255
248
) ;
256
249
} ) ;
257
250
expect ( Scheduler ) . toHaveYielded ( [ 'Unmount layout' , 'Child' ] ) ;
258
- if ( gate ( flags => flags . persistent ) ) {
259
- expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } prop = "Child" /> ) ;
260
- } else {
261
- // TODO: Offscreen does not yet hide/unhide children correctly in mutation
262
- // mode. Until we do, it should only be used inside a host component
263
- // wrapper whose visibility is toggled simultaneously.
264
- expect ( root ) . toMatchRenderedOutput ( < span prop = "Child" /> ) ;
265
- }
251
+ expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } prop = "Child" /> ) ;
266
252
267
253
// Unhide the tree. The layout effect is re-mounted.
268
254
await act ( async ( ) => {
@@ -299,14 +285,7 @@ describe('ReactOffscreen', () => {
299
285
) ;
300
286
} ) ;
301
287
expect ( Scheduler ) . toHaveYielded ( [ 'Child' ] ) ;
302
- if ( gate ( flags => flags . persistent ) ) {
303
- expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } prop = "Child" /> ) ;
304
- } else {
305
- // TODO: Offscreen does not yet hide/unhide children correctly in mutation
306
- // mode. Until we do, it should only be used inside a host component
307
- // wrapper whose visibility is toggled simultaneously.
308
- expect ( root ) . toMatchRenderedOutput ( < span prop = "Child" /> ) ;
309
- }
288
+ expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } prop = "Child" /> ) ;
310
289
311
290
// Show the tree. The layout effect is mounted.
312
291
await act ( async ( ) => {
@@ -328,14 +307,7 @@ describe('ReactOffscreen', () => {
328
307
) ;
329
308
} ) ;
330
309
expect ( Scheduler ) . toHaveYielded ( [ 'Unmount layout' , 'Child' ] ) ;
331
- if ( gate ( flags => flags . persistent ) ) {
332
- expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } prop = "Child" /> ) ;
333
- } else {
334
- // TODO: Offscreen does not yet hide/unhide children correctly in mutation
335
- // mode. Until we do, it should only be used inside a host component
336
- // wrapper whose visibility is toggled simultaneously.
337
- expect ( root ) . toMatchRenderedOutput ( < span prop = "Child" /> ) ;
338
- }
310
+ expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } prop = "Child" /> ) ;
339
311
} ) ;
340
312
341
313
// @gate experimental || www
@@ -385,4 +357,80 @@ describe('ReactOffscreen', () => {
385
357
} ) ;
386
358
expect ( Scheduler ) . toHaveYielded ( [ 'Unmount layout' ] ) ;
387
359
} ) ;
360
+
361
+ // @gate experimental || www
362
+ it ( 'hides new insertions into an already hidden tree' , async ( ) => {
363
+ const root = ReactNoop . createRoot ( ) ;
364
+ await act ( async ( ) => {
365
+ root . render (
366
+ < Offscreen mode = "hidden" >
367
+ < span > Hi</ span >
368
+ </ Offscreen > ,
369
+ ) ;
370
+ } ) ;
371
+ expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } > Hi</ span > ) ;
372
+
373
+ // Insert a new node into the hidden tree
374
+ await act ( async ( ) => {
375
+ root . render (
376
+ < Offscreen mode = "hidden" >
377
+ < span > Hi</ span >
378
+ < span > Something new</ span >
379
+ </ Offscreen > ,
380
+ ) ;
381
+ } ) ;
382
+ expect ( root ) . toMatchRenderedOutput (
383
+ < >
384
+ < span hidden = { true } > Hi</ span >
385
+ { /* This new node should also be hidden */ }
386
+ < span hidden = { true } > Something new</ span >
387
+ </ > ,
388
+ ) ;
389
+ } ) ;
390
+
391
+ // @gate experimental || www
392
+ it ( 'hides updated nodes inside an already hidden tree' , async ( ) => {
393
+ const root = ReactNoop . createRoot ( ) ;
394
+ await act ( async ( ) => {
395
+ root . render (
396
+ < Offscreen mode = "hidden" >
397
+ < span > Hi</ span >
398
+ </ Offscreen > ,
399
+ ) ;
400
+ } ) ;
401
+ expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } > Hi</ span > ) ;
402
+
403
+ // Set the `hidden` prop to on an already hidden node
404
+ await act ( async ( ) => {
405
+ root . render (
406
+ < Offscreen mode = "hidden" >
407
+ < span hidden = { false } > Hi</ span >
408
+ </ Offscreen > ,
409
+ ) ;
410
+ } ) ;
411
+ // It should still be hidden, because the Offscreen container overrides it
412
+ expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } > Hi</ span > ) ;
413
+
414
+ // Unhide the boundary
415
+ await act ( async ( ) => {
416
+ root . render (
417
+ < Offscreen mode = "visible" >
418
+ < span hidden = { true } > Hi</ span >
419
+ </ Offscreen > ,
420
+ ) ;
421
+ } ) ;
422
+ // It should still be hidden, because of the prop
423
+ expect ( root ) . toMatchRenderedOutput ( < span hidden = { true } > Hi</ span > ) ;
424
+
425
+ // Remove the `hidden` prop
426
+ await act ( async ( ) => {
427
+ root . render (
428
+ < Offscreen mode = "visible" >
429
+ < span > Hi</ span >
430
+ </ Offscreen > ,
431
+ ) ;
432
+ } ) ;
433
+ // Now it's visible
434
+ expect ( root ) . toMatchRenderedOutput ( < span > Hi</ span > ) ;
435
+ } ) ;
388
436
} ) ;
0 commit comments