@@ -201,14 +201,7 @@ describe('ReactOffscreen', () => {
201201 } ) ;
202202 // No layout effect.
203203 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" /> ) ;
212205
213206 // Unhide the tree. The layout effect is mounted.
214207 await act ( async ( ) => {
@@ -255,14 +248,7 @@ describe('ReactOffscreen', () => {
255248 ) ;
256249 } ) ;
257250 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" /> ) ;
266252
267253 // Unhide the tree. The layout effect is re-mounted.
268254 await act ( async ( ) => {
@@ -299,14 +285,7 @@ describe('ReactOffscreen', () => {
299285 ) ;
300286 } ) ;
301287 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" /> ) ;
310289
311290 // Show the tree. The layout effect is mounted.
312291 await act ( async ( ) => {
@@ -328,14 +307,7 @@ describe('ReactOffscreen', () => {
328307 ) ;
329308 } ) ;
330309 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" /> ) ;
339311 } ) ;
340312
341313 // @gate experimental || www
@@ -385,4 +357,80 @@ describe('ReactOffscreen', () => {
385357 } ) ;
386358 expect ( Scheduler ) . toHaveYielded ( [ 'Unmount layout' ] ) ;
387359 } ) ;
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+ } ) ;
388436} ) ;
0 commit comments