@@ -1484,6 +1484,154 @@ describe('ReactDOMFizzServer', () => {
1484
1484
expect ( getVisibleChildren ( container ) ) . toEqual ( < div > Hello</ div > ) ;
1485
1485
} ) ;
1486
1486
1487
+ // @gate experimental && enableSuspenseAvoidThisFallback
1488
+ it ( 'should respect unstable_avoidThisFallback' , async ( ) => {
1489
+ const resolved = {
1490
+ 0 : false ,
1491
+ 1 : false ,
1492
+ } ;
1493
+ const promiseRes = { } ;
1494
+ const promises = {
1495
+ 0 : new Promise ( res => {
1496
+ promiseRes [ 0 ] = ( ) => {
1497
+ resolved [ 0 ] = true ;
1498
+ res ( ) ;
1499
+ } ;
1500
+ } ) ,
1501
+ 1 : new Promise ( res => {
1502
+ promiseRes [ 1 ] = ( ) => {
1503
+ resolved [ 1 ] = true ;
1504
+ res ( ) ;
1505
+ } ;
1506
+ } ) ,
1507
+ } ;
1508
+
1509
+ const InnerComponent = ( { isClient, depth} ) => {
1510
+ if ( isClient ) {
1511
+ // Resuspend after re-rendering on client to check that fallback shows on client
1512
+ throw new Promise ( ( ) => { } ) ;
1513
+ }
1514
+ if ( ! resolved [ depth ] ) {
1515
+ throw promises [ depth ] ;
1516
+ }
1517
+ return (
1518
+ < div >
1519
+ < Text text = { `resolved ${ depth } ` } />
1520
+ </ div >
1521
+ ) ;
1522
+ } ;
1523
+
1524
+ function App ( { isClient} ) {
1525
+ return (
1526
+ < div >
1527
+ < Text text = "Non Suspense Content" />
1528
+ < Suspense
1529
+ fallback = {
1530
+ < span >
1531
+ < Text text = "Avoided Fallback" />
1532
+ </ span >
1533
+ }
1534
+ unstable_avoidThisFallback = { true } >
1535
+ < InnerComponent isClient = { isClient } depth = { 0 } />
1536
+ < div >
1537
+ < Suspense fallback = { < Text text = "Fallback" /> } >
1538
+ < Suspense
1539
+ fallback = {
1540
+ < span >
1541
+ < Text text = "Avoided Fallback2" />
1542
+ </ span >
1543
+ }
1544
+ unstable_avoidThisFallback = { true } >
1545
+ < InnerComponent isClient = { isClient } depth = { 1 } />
1546
+ </ Suspense >
1547
+ </ Suspense >
1548
+ </ div >
1549
+ </ Suspense >
1550
+ </ div >
1551
+ ) ;
1552
+ }
1553
+
1554
+ await jest . runAllTimers ( ) ;
1555
+
1556
+ await act ( async ( ) => {
1557
+ const { startWriting} = ReactDOMFizzServer . pipeToNodeWritable (
1558
+ < App isClient = { false } /> ,
1559
+ writable ,
1560
+ ) ;
1561
+ startWriting ( ) ;
1562
+ } ) ;
1563
+
1564
+ // Nothing is output since root has a suspense with avoidedThisFallback that hasn't resolved
1565
+ expect ( getVisibleChildren ( container ) ) . toEqual ( undefined ) ;
1566
+ expect ( container . innerHTML ) . not . toContain ( 'Avoided Fallback' ) ;
1567
+
1568
+ // resolve first suspense component with avoidThisFallback
1569
+ await act ( async ( ) => {
1570
+ promiseRes [ 0 ] ( ) ;
1571
+ } ) ;
1572
+
1573
+ expect ( getVisibleChildren ( container ) ) . toEqual (
1574
+ < div >
1575
+ Non Suspense Content
1576
+ < div > resolved 0</ div >
1577
+ < div > Fallback</ div >
1578
+ </ div > ,
1579
+ ) ;
1580
+
1581
+ expect ( container . innerHTML ) . not . toContain ( 'Avoided Fallback2' ) ;
1582
+
1583
+ await act ( async ( ) => {
1584
+ promiseRes [ 1 ] ( ) ;
1585
+ } ) ;
1586
+
1587
+ expect ( getVisibleChildren ( container ) ) . toEqual (
1588
+ < div >
1589
+ Non Suspense Content
1590
+ < div > resolved 0</ div >
1591
+ < div >
1592
+ < div > resolved 1</ div >
1593
+ </ div >
1594
+ </ div > ,
1595
+ ) ;
1596
+
1597
+ let root ;
1598
+ await act ( async ( ) => {
1599
+ root = ReactDOM . hydrateRoot ( container , < App isClient = { false } /> ) ;
1600
+ Scheduler . unstable_flushAll ( ) ;
1601
+ await jest . runAllTimers ( ) ;
1602
+ } ) ;
1603
+
1604
+ // No change after hydration
1605
+ expect ( getVisibleChildren ( container ) ) . toEqual (
1606
+ < div >
1607
+ Non Suspense Content
1608
+ < div > resolved 0</ div >
1609
+ < div >
1610
+ < div > resolved 1</ div >
1611
+ </ div >
1612
+ </ div > ,
1613
+ ) ;
1614
+
1615
+ await act ( async ( ) => {
1616
+ // Trigger update by changing isClient to true
1617
+ root . render ( < App isClient = { true } /> ) ;
1618
+ Scheduler . unstable_flushAll ( ) ;
1619
+ await jest . runAllTimers ( ) ;
1620
+ } ) ;
1621
+
1622
+ // Now that we've resuspended at the root we show the root fallback
1623
+ expect ( getVisibleChildren ( container ) ) . toEqual (
1624
+ < div >
1625
+ Non Suspense Content
1626
+ < div style = "display: none;" > resolved 0</ div >
1627
+ < div style = "display: none;" >
1628
+ < div > resolved 1</ div >
1629
+ </ div >
1630
+ < span > Avoided Fallback</ span >
1631
+ </ div > ,
1632
+ ) ;
1633
+ } ) ;
1634
+
1487
1635
// @gate supportsNativeUseSyncExternalStore
1488
1636
// @gate experimental
1489
1637
it ( 'calls getServerSnapshot instead of getSnapshot' , async ( ) => {
0 commit comments