[assert helpers] ReactFlight (#31860)
Ricky committed
Dec 20, 2024 at 12:41 UTC
99471c02dd6631df1892bf76d932afd22fffa5e3
1 file changed
+474
-166
packages/react-client/src/__tests__/ReactFlight-test.js
+474
-166
@@ -1467,13 +1467,12 @@ describe('ReactFlight', () => {
1467
1468
const transport = ReactNoopFlightServer.render(<App />);
1469
1470
- await expect(async () => {
1471
- await act(() => {
1472
- startTransition(() => {
1473
- ReactNoop.render(ReactNoopFlightClient.read(transport));
1474
- });
1470
+ await act(() => {
1471
+ startTransition(() => {
1472
+ ReactNoop.render(ReactNoopFlightClient.read(transport));
1473
});
1476
- }).toErrorDev(
1474
+ });
1475
+ assertConsoleErrorDev([
1476
'Each child in a list should have a unique "key" prop.\n' +
1477
'\n' +
1478
'Check the render method of `Component`. See https://react.dev/link/warning-keys for more information.\n' +
@@ -1483,7 +1482,7 @@ describe('ReactFlight', () => {
1482
? ''
1483
: ' in Indirection (at **)\n') +
1484
' in App (at **)',
1486
- );
1485
+ ]);
1486
});
1487
1488
it('should trigger the inner most error boundary inside a Client Component', async () => {
@@ -1541,17 +1540,47 @@ describe('ReactFlight', () => {
1540
return 123;
1541
},
1542
};
1544
- expect(() => {
1545
- const transport = ReactNoopFlightServer.render(<input value={obj} />);
1546
- ReactNoopFlightClient.read(transport);
1547
- }).toErrorDev(
1548
- 'Only plain objects can be passed to Client Components from Server Components. ' +
1549
- 'Objects with toJSON methods are not supported. ' +
1550
- 'Convert it manually to a simple value before passing it to props.\n' +
1551
- ' <input value={{toJSON: ...}}>\n' +
1552
- ' ^^^^^^^^^^^^^^^',
1553
- {withoutStack: true},
1554
- );
1543
+ const transport = ReactNoopFlightServer.render(<input value={obj} />);
1544
+ if (gate(flags => flags.enableOwnerStacks)) {
1545
+ assertConsoleErrorDev(
1546
+ [
1547
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1548
+ 'Objects with toJSON methods are not supported. ' +
1549
+ 'Convert it manually to a simple value before passing it to props.\n' +
1550
+ ' <input value={{toJSON: ...}}>\n' +
1551
+ ' ^^^^^^^^^^^^^^^',
1552
+ ],
1553
+ {withoutStack: true},
1554
+ );
1555
+ }
1556
+
1557
+ ReactNoopFlightClient.read(transport);
1558
+ if (gate(flags => flags.enableOwnerStacks)) {
1559
+ assertConsoleErrorDev([
1560
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1561
+ 'Objects with toJSON methods are not supported. ' +
1562
+ 'Convert it manually to a simple value before passing it to props.\n' +
1563
+ ' <input value={{toJSON: ...}}>\n' +
1564
+ ' ^^^^^^^^^^^^^^^\n' +
1565
+ ' at (<anonymous>)',
1566
+ ]);
1567
+ } else {
1568
+ assertConsoleErrorDev(
1569
+ [
1570
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1571
+ 'Objects with toJSON methods are not supported. ' +
1572
+ 'Convert it manually to a simple value before passing it to props.\n' +
1573
+ ' <input value={{toJSON: ...}}>\n' +
1574
+ ' ^^^^^^^^^^^^^^^',
1575
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1576
+ 'Objects with toJSON methods are not supported. ' +
1577
+ 'Convert it manually to a simple value before passing it to props.\n' +
1578
+ ' <input value={{toJSON: ...}}>\n' +
1579
+ ' ^^^^^^^^^^^^^^^',
1580
+ ],
1581
+ {withoutStack: true},
1582
+ );
1583
+ }
1584
});
1585
1586
it('should warn in DEV if a toJSON instance is passed to a host component child', () => {
@@ -1560,43 +1589,123 @@ describe('ReactFlight', () => {
1589
return 123;
1590
}
1591
}
1563
- expect(() => {
1564
- const transport = ReactNoopFlightServer.render(
1565
- <div>Womp womp: {new MyError('spaghetti')}</div>,
1592
+ const transport = ReactNoopFlightServer.render(
1593
+ <div>Womp womp: {new MyError('spaghetti')}</div>,
1594
+ );
1595
+ if (gate(flags => flags.enableOwnerStacks)) {
1596
+ assertConsoleErrorDev(
1597
+ [
1598
+ 'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
1599
+ ' <div>Womp womp: {Error}</div>\n' +
1600
+ ' ^^^^^^^',
1601
+ ],
1602
+ {withoutStack: true},
1603
);
1567
- ReactNoopFlightClient.read(transport);
1568
- }).toErrorDev(
1569
- 'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
1570
- ' <div>Womp womp: {Error}</div>\n' +
1571
- ' ^^^^^^^',
1572
- {withoutStack: true},
1573
- );
1604
+ }
1605
+
1606
+ ReactNoopFlightClient.read(transport);
1607
+ if (gate(flags => flags.enableOwnerStacks)) {
1608
+ assertConsoleErrorDev([
1609
+ 'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
1610
+ ' <div>Womp womp: {Error}</div>\n' +
1611
+ ' ^^^^^^^\n' +
1612
+ ' at (<anonymous>)',
1613
+ ]);
1614
+ } else {
1615
+ assertConsoleErrorDev(
1616
+ [
1617
+ 'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
1618
+ ' <div>Womp womp: {Error}</div>\n' +
1619
+ ' ^^^^^^^',
1620
+ 'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
1621
+ ' <div>Womp womp: {Error}</div>\n' +
1622
+ ' ^^^^^^^',
1623
+ ],
1624
+ {withoutStack: true},
1625
+ );
1626
+ }
1627
});
1628
1629
it('should warn in DEV if a special object is passed to a host component', () => {
1577
- expect(() => {
1578
- const transport = ReactNoopFlightServer.render(<input value={Math} />);
1579
- ReactNoopFlightClient.read(transport);
1580
- }).toErrorDev(
1581
- 'Only plain objects can be passed to Client Components from Server Components. ' +
1582
- 'Math objects are not supported.\n' +
1583
- ' <input value={Math}>\n' +
1584
- ' ^^^^^^',
1585
- {withoutStack: true},
1586
- );
1630
+ const transport = ReactNoopFlightServer.render(<input value={Math} />);
1631
+ if (gate(flags => flags.enableOwnerStacks)) {
1632
+ assertConsoleErrorDev(
1633
+ [
1634
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1635
+ 'Math objects are not supported.\n' +
1636
+ ' <input value={Math}>\n' +
1637
+ ' ^^^^^^',
1638
+ ],
1639
+ {withoutStack: true},
1640
+ );
1641
+ }
1642
+
1643
+ ReactNoopFlightClient.read(transport);
1644
+ if (gate(flags => flags.enableOwnerStacks)) {
1645
+ assertConsoleErrorDev([
1646
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1647
+ 'Math objects are not supported.\n' +
1648
+ ' <input value={Math}>\n' +
1649
+ ' ^^^^^^\n' +
1650
+ ' at (<anonymous>)',
1651
+ ]);
1652
+ } else {
1653
+ assertConsoleErrorDev(
1654
+ [
1655
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1656
+ 'Math objects are not supported.\n' +
1657
+ ' <input value={Math}>\n' +
1658
+ ' ^^^^^^',
1659
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1660
+ 'Math objects are not supported.\n' +
1661
+ ' <input value={Math}>\n' +
1662
+ ' ^^^^^^',
1663
+ ],
1664
+ {withoutStack: true},
1665
+ );
1666
+ }
1667
});
1668
1669
it('should warn in DEV if an object with symbols is passed to a host component', () => {
1590
- expect(() => {
1591
- const transport = ReactNoopFlightServer.render(
1592
- <input value={{[Symbol.iterator]: {}}} />,
1670
+ const transport = ReactNoopFlightServer.render(
1671
+ <input value={{[Symbol.iterator]: {}}} />,
1672
+ );
1673
+ if (gate(flags => flags.enableOwnerStacks)) {
1674
+ assertConsoleErrorDev(
1675
+ [
1676
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1677
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1678
+ ' <input value={{}}>\n' +
1679
+ ' ^^^^',
1680
+ ],
1681
+ {withoutStack: true},
1682
);
1594
- ReactNoopFlightClient.read(transport);
1595
- }).toErrorDev(
1596
- 'Only plain objects can be passed to Client Components from Server Components. ' +
1597
- 'Objects with symbol properties like Symbol.iterator are not supported.',
1598
- {withoutStack: true},
1599
- );
1683
+ }
1684
+
1685
+ ReactNoopFlightClient.read(transport);
1686
+ if (gate(flags => flags.enableOwnerStacks)) {
1687
+ assertConsoleErrorDev([
1688
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1689
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1690
+ ' <input value={{}}>\n' +
1691
+ ' ^^^^\n' +
1692
+ ' at (<anonymous>)',
1693
+ ]);
1694
+ } else {
1695
+ assertConsoleErrorDev(
1696
+ [
1697
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1698
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1699
+ ' <input value={{}}>\n' +
1700
+ ' ^^^^',
1701
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1702
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1703
+ ' <input value={{}}>\n' +
1704
+ ' ^^^^',
1705
+ ],
1706
+ {withoutStack: true},
1707
+ );
1708
+ }
1709
});
1710
1711
it('should warn in DEV if a toJSON instance is passed to a Client Component', () => {
@@ -1609,14 +1718,47 @@ describe('ReactFlight', () => {
1718
return <div>{value}</div>;
1719
}
1720
const Client = clientReference(ClientImpl);
1612
- expect(() => {
1613
- const transport = ReactNoopFlightServer.render(<Client value={obj} />);
1614
- ReactNoopFlightClient.read(transport);
1615
- }).toErrorDev(
1616
- 'Only plain objects can be passed to Client Components from Server Components. ' +
1617
- 'Objects with toJSON methods are not supported.',
1618
- {withoutStack: true},
1619
- );
1721
+ const transport = ReactNoopFlightServer.render(<Client value={obj} />);
1722
+ if (gate(flags => flags.enableOwnerStacks)) {
1723
+ assertConsoleErrorDev(
1724
+ [
1725
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1726
+ 'Objects with toJSON methods are not supported. ' +
1727
+ 'Convert it manually to a simple value before passing it to props.\n' +
1728
+ ' <... value={{toJSON: ...}}>\n' +
1729
+ ' ^^^^^^^^^^^^^^^',
1730
+ ],
1731
+ {withoutStack: true},
1732
+ );
1733
+ }
1734
+
1735
+ ReactNoopFlightClient.read(transport);
1736
+ if (gate(flags => flags.enableOwnerStacks)) {
1737
+ assertConsoleErrorDev([
1738
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1739
+ 'Objects with toJSON methods are not supported. ' +
1740
+ 'Convert it manually to a simple value before passing it to props.\n' +
1741
+ ' <... value={{toJSON: ...}}>\n' +
1742
+ ' ^^^^^^^^^^^^^^^\n' +
1743
+ ' at (<anonymous>)',
1744
+ ]);
1745
+ } else {
1746
+ assertConsoleErrorDev(
1747
+ [
1748
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1749
+ 'Objects with toJSON methods are not supported. ' +
1750
+ 'Convert it manually to a simple value before passing it to props.\n' +
1751
+ ' <... value={{toJSON: ...}}>\n' +
1752
+ ' ^^^^^^^^^^^^^^^',
1753
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1754
+ 'Objects with toJSON methods are not supported. ' +
1755
+ 'Convert it manually to a simple value before passing it to props.\n' +
1756
+ ' <... value={{toJSON: ...}}>\n' +
1757
+ ' ^^^^^^^^^^^^^^^',
1758
+ ],
1759
+ {withoutStack: true},
1760
+ );
1761
+ }
1762
});
1763
1764
it('should warn in DEV if a toJSON instance is passed to a Client Component child', () => {
@@ -1629,19 +1771,49 @@ describe('ReactFlight', () => {
1771
return <div>{children}</div>;
1772
}
1773
const Client = clientReference(ClientImpl);
1632
- expect(() => {
1633
- const transport = ReactNoopFlightServer.render(
1634
- <Client>Current date: {obj}</Client>,
1774
+ const transport = ReactNoopFlightServer.render(
1775
+ <Client>Current date: {obj}</Client>,
1776
+ );
1777
+ if (gate(flags => flags.enableOwnerStacks)) {
1778
+ assertConsoleErrorDev(
1779
+ [
1780
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1781
+ 'Objects with toJSON methods are not supported. ' +
1782
+ 'Convert it manually to a simple value before passing it to props.\n' +
1783
+ ' <>Current date: {{toJSON: ...}}</>\n' +
1784
+ ' ^^^^^^^^^^^^^^^',
1785
+ ],
1786
+ {withoutStack: true},
1787
);
1636
- ReactNoopFlightClient.read(transport);
1637
- }).toErrorDev(
1638
- 'Only plain objects can be passed to Client Components from Server Components. ' +
1639
- 'Objects with toJSON methods are not supported. ' +
1640
- 'Convert it manually to a simple value before passing it to props.\n' +
1641
- ' <>Current date: {{toJSON: ...}}</>\n' +
1642
- ' ^^^^^^^^^^^^^^^',
1643
- {withoutStack: true},
1644
- );
1788
+ }
1789
+
1790
+ ReactNoopFlightClient.read(transport);
1791
+ if (gate(flags => flags.enableOwnerStacks)) {
1792
+ assertConsoleErrorDev([
1793
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1794
+ 'Objects with toJSON methods are not supported. ' +
1795
+ 'Convert it manually to a simple value before passing it to props.\n' +
1796
+ ' <>Current date: {{toJSON: ...}}</>\n' +
1797
+ ' ^^^^^^^^^^^^^^^\n' +
1798
+ ' at (<anonymous>)',
1799
+ ]);
1800
+ } else {
1801
+ assertConsoleErrorDev(
1802
+ [
1803
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1804
+ 'Objects with toJSON methods are not supported. ' +
1805
+ 'Convert it manually to a simple value before passing it to props.\n' +
1806
+ ' <>Current date: {{toJSON: ...}}</>\n' +
1807
+ ' ^^^^^^^^^^^^^^^',
1808
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1809
+ 'Objects with toJSON methods are not supported. ' +
1810
+ 'Convert it manually to a simple value before passing it to props.\n' +
1811
+ ' <>Current date: {{toJSON: ...}}</>\n' +
1812
+ ' ^^^^^^^^^^^^^^^',
1813
+ ],
1814
+ {withoutStack: true},
1815
+ );
1816
+ }
1817
});
1818
1819
it('should warn in DEV if a special object is passed to a Client Component', () => {
@@ -1649,16 +1821,44 @@ describe('ReactFlight', () => {
1821
return <div>{value}</div>;
1822
}
1823
const Client = clientReference(ClientImpl);
1652
- expect(() => {
1653
- const transport = ReactNoopFlightServer.render(<Client value={Math} />);
1654
- ReactNoopFlightClient.read(transport);
1655
- }).toErrorDev(
1656
- 'Only plain objects can be passed to Client Components from Server Components. ' +
1657
- 'Math objects are not supported.\n' +
1658
- ' <... value={Math}>\n' +
1659
- ' ^^^^^^',
1660
- {withoutStack: true},
1661
- );
1824
+ const transport = ReactNoopFlightServer.render(<Client value={Math} />);
1825
+
1826
+ if (gate(flags => flags.enableOwnerStacks)) {
1827
+ assertConsoleErrorDev(
1828
+ [
1829
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1830
+ 'Math objects are not supported.\n' +
1831
+ ' <... value={Math}>\n' +
1832
+ ' ^^^^^^',
1833
+ ],
1834
+ {withoutStack: true},
1835
+ );
1836
+ }
1837
+
1838
+ ReactNoopFlightClient.read(transport);
1839
+ if (gate(flags => flags.enableOwnerStacks)) {
1840
+ assertConsoleErrorDev([
1841
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1842
+ 'Math objects are not supported.\n' +
1843
+ ' <... value={Math}>\n' +
1844
+ ' ^^^^^^\n' +
1845
+ ' at (<anonymous>)',
1846
+ ]);
1847
+ } else {
1848
+ assertConsoleErrorDev(
1849
+ [
1850
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1851
+ 'Math objects are not supported.\n' +
1852
+ ' <... value={Math}>\n' +
1853
+ ' ^^^^^^',
1854
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1855
+ 'Math objects are not supported.\n' +
1856
+ ' <... value={Math}>\n' +
1857
+ ' ^^^^^^',
1858
+ ],
1859
+ {withoutStack: true},
1860
+ );
1861
+ }
1862
});
1863
1864
it('should warn in DEV if an object with symbols is passed to a Client Component', () => {
@@ -1666,16 +1866,46 @@ describe('ReactFlight', () => {
1866
return <div>{value}</div>;
1867
}
1868
const Client = clientReference(ClientImpl);
1669
- expect(() => {
1670
- const transport = ReactNoopFlightServer.render(
1671
- <Client value={{[Symbol.iterator]: {}}} />,
1869
+ assertConsoleErrorDev([]);
1870
+ const transport = ReactNoopFlightServer.render(
1871
+ <Client value={{[Symbol.iterator]: {}}} />,
1872
+ );
1873
+ if (gate(flags => flags.enableOwnerStacks)) {
1874
+ assertConsoleErrorDev(
1875
+ [
1876
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1877
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1878
+ ' <... value={{}}>\n' +
1879
+ ' ^^^^',
1880
+ ],
1881
+ {withoutStack: true},
1882
);
1673
- ReactNoopFlightClient.read(transport);
1674
- }).toErrorDev(
1675
- 'Only plain objects can be passed to Client Components from Server Components. ' +
1676
- 'Objects with symbol properties like Symbol.iterator are not supported.',
1677
- {withoutStack: true},
1678
- );
1883
+ }
1884
+
1885
+ ReactNoopFlightClient.read(transport);
1886
+
1887
+ if (gate(flags => flags.enableOwnerStacks)) {
1888
+ assertConsoleErrorDev([
1889
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1890
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1891
+ ' <... value={{}}>\n' +
1892
+ ' ^^^^\n',
1893
+ ]);
1894
+ } else {
1895
+ assertConsoleErrorDev(
1896
+ [
1897
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1898
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1899
+ ' <... value={{}}>\n' +
1900
+ ' ^^^^',
1901
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1902
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1903
+ ' <... value={{}}>\n' +
1904
+ ' ^^^^',
1905
+ ],
1906
+ {withoutStack: true},
1907
+ );
1908
+ }
1909
});
1910
1911
it('should warn in DEV if a special object is passed to a nested object in Client Component', () => {
@@ -1683,18 +1913,41 @@ describe('ReactFlight', () => {
1913
return <div>{value}</div>;
1914
}
1915
const Client = clientReference(ClientImpl);
1686
- expect(() => {
1687
- const transport = ReactNoopFlightServer.render(
1688
- <Client value={{hello: Math, title: <h1>hi</h1>}} />,
1689
- );
1690
- ReactNoopFlightClient.read(transport);
1691
- }).toErrorDev(
1692
- 'Only plain objects can be passed to Client Components from Server Components. ' +
1693
- 'Math objects are not supported.\n' +
1694
- ' {hello: Math, title: <h1/>}\n' +
1695
- ' ^^^^',
1696
- {withoutStack: true},
1916
+ const transport = ReactNoopFlightServer.render(
1917
+ <Client value={{[Symbol.iterator]: {}}} />,
1918
);
1919
+ ReactNoopFlightClient.read(transport);
1920
+
1921
+ if (gate(flags => flags.enableOwnerStacks)) {
1922
+ assertConsoleErrorDev([
1923
+ [
1924
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1925
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1926
+ ' <... value={{}}>\n' +
1927
+ ' ^^^^',
1928
+ {withoutStack: true},
1929
+ ],
1930
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1931
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1932
+ ' <... value={{}}>\n' +
1933
+ ' ^^^^\n' +
1934
+ ' at (<anonymous>)',
1935
+ ]);
1936
+ } else {
1937
+ assertConsoleErrorDev(
1938
+ [
1939
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1940
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1941
+ ' <... value={{}}>\n' +
1942
+ ' ^^^^',
1943
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1944
+ 'Objects with symbol properties like Symbol.iterator are not supported.\n' +
1945
+ ' <... value={{}}>\n' +
1946
+ ' ^^^^',
1947
+ ],
1948
+ {withoutStack: true},
1949
+ );
1950
+ }
1951
});
1952
1953
it('should warn in DEV if a special object is passed to a nested array in Client Component', () => {
@@ -1702,20 +1955,40 @@ describe('ReactFlight', () => {
1955
return <div>{value}</div>;
1956
}
1957
const Client = clientReference(ClientImpl);
1705
- expect(() => {
1706
- const transport = ReactNoopFlightServer.render(
1707
- <Client
1708
- value={['looooong string takes up noise', Math, <h1>hi</h1>]}
1709
- />,
1710
- );
1711
- ReactNoopFlightClient.read(transport);
1712
- }).toErrorDev(
1713
- 'Only plain objects can be passed to Client Components from Server Components. ' +
1714
- 'Math objects are not supported.\n' +
1715
- ' [..., Math, <h1/>]\n' +
1716
- ' ^^^^',
1717
- {withoutStack: true},
1958
+ const transport = ReactNoopFlightServer.render(
1959
+ <Client value={['looooong string takes up noise', Math, <h1>hi</h1>]} />,
1960
);
1961
+ ReactNoopFlightClient.read(transport);
1962
+ if (gate(flags => flags.enableOwnerStacks)) {
1963
+ assertConsoleErrorDev([
1964
+ [
1965
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1966
+ 'Math objects are not supported.\n' +
1967
+ ' [..., Math, <h1/>]\n' +
1968
+ ' ^^^^',
1969
+ {withoutStack: true},
1970
+ ],
1971
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1972
+ 'Math objects are not supported.\n' +
1973
+ ' [..., Math, <h1/>]\n' +
1974
+ ' ^^^^\n' +
1975
+ ' at (<anonymous>)',
1976
+ ]);
1977
+ } else {
1978
+ assertConsoleErrorDev(
1979
+ [
1980
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1981
+ 'Math objects are not supported.\n' +
1982
+ ' [..., Math, <h1/>]\n' +
1983
+ ' ^^^^',
1984
+ 'Only plain objects can be passed to Client Components from Server Components. ' +
1985
+ 'Math objects are not supported.\n' +
1986
+ ' [..., Math, <h1/>]\n' +
1987
+ ' ^^^^',
1988
+ ],
1989
+ {withoutStack: true},
1990
+ );
1991
+ }
1992
});
1993
1994
it('should NOT warn in DEV for key getters', () => {
@@ -1729,63 +2002,100 @@ describe('ReactFlight', () => {
2002
key: "this has a key but parent doesn't",
2003
});
2004
}
1732
- expect(() => {
1733
- // While we're on the server we need to have the Server version active to track component stacks.
1734
- jest.resetModules();
1735
- jest.mock('react', () => ReactServer);
1736
- const transport = ReactNoopFlightServer.render(
1737
- ReactServer.createElement(
1738
- 'div',
1739
- null,
1740
- Array(6).fill(ReactServer.createElement(NoKey)),
1741
- ),
1742
- );
1743
- jest.resetModules();
1744
- jest.mock('react', () => React);
1745
- ReactNoopFlightClient.read(transport);
1746
- }).toErrorDev('Each child in a list should have a unique "key" prop.');
2005
+ // While we're on the server we need to have the Server version active to track component stacks.
2006
+ jest.resetModules();
2007
+ jest.mock('react', () => ReactServer);
2008
+ const transport = ReactNoopFlightServer.render(
2009
+ ReactServer.createElement(
2010
+ 'div',
2011
+ null,
2012
+ Array(6).fill(ReactServer.createElement(NoKey)),
2013
+ ),
2014
+ );
2015
+ jest.resetModules();
2016
+ jest.mock('react', () => React);
2017
+ ReactNoopFlightClient.read(transport);
2018
+ if (gate(flags => flags.enableOwnerStacks)) {
2019
+ assertConsoleErrorDev([
2020
+ 'Each child in a list should have a unique "key" prop. ' +
2021
+ 'See https://react.dev/link/warning-keys for more information.\n' +
2022
+ ' in NoKey (at **)',
2023
+ 'Each child in a list should have a unique "key" prop. ' +
2024
+ 'See https://react.dev/link/warning-keys for more information.\n' +
2025
+ ' in NoKey (at **)',
2026
+ ]);
2027
+ } else {
2028
+ assertConsoleErrorDev([
2029
+ 'Each child in a list should have a unique "key" prop.\n\n' +
2030
+ 'Check the top-level render call using <div>. ' +
2031
+ 'See https://react.dev/link/warning-keys for more information.\n' +
2032
+ ' in NoKey (at **)',
2033
+ ]);
2034
+ }
2035
});
2036
2037
// @gate !__DEV__ || enableOwnerStacks
2038
it('should warn in DEV a child is missing keys on a fragment', () => {
1751
- expect(() => {
1752
- // While we're on the server we need to have the Server version active to track component stacks.
1753
- jest.resetModules();
1754
- jest.mock('react', () => ReactServer);
1755
- const transport = ReactNoopFlightServer.render(
1756
- ReactServer.createElement(
1757
- 'div',
1758
- null,
1759
- Array(6).fill(ReactServer.createElement(ReactServer.Fragment)),
1760
- ),
1761
- );
1762
- jest.resetModules();
1763
- jest.mock('react', () => React);
1764
- ReactNoopFlightClient.read(transport);
1765
- }).toErrorDev('Each child in a list should have a unique "key" prop.');
2039
+ // While we're on the server we need to have the Server version active to track component stacks.
2040
+ jest.resetModules();
2041
+ jest.mock('react', () => ReactServer);
2042
+ const transport = ReactNoopFlightServer.render(
2043
+ ReactServer.createElement(
2044
+ 'div',
2045
+ null,
2046
+ Array(6).fill(ReactServer.createElement(ReactServer.Fragment)),
2047
+ ),
2048
+ );
2049
+ jest.resetModules();
2050
+ jest.mock('react', () => React);
2051
+ ReactNoopFlightClient.read(transport);
2052
+ if (gate(flags => flags.enableOwnerStacks)) {
2053
+ assertConsoleErrorDev([
2054
+ 'Each child in a list should have a unique "key" prop. ' +
2055
+ 'See https://react.dev/link/warning-keys for more information.\n' +
2056
+ ' in Fragment (at **)',
2057
+ 'Each child in a list should have a unique "key" prop. ' +
2058
+ 'See https://react.dev/link/warning-keys for more information.\n' +
2059
+ ' in Fragment (at **)',
2060
+ ]);
2061
+ } else {
2062
+ assertConsoleErrorDev([
2063
+ 'Each child in a list should have a unique "key" prop.\n\n' +
2064
+ 'Check the top-level render call using <div>. ' +
2065
+ 'See https://react.dev/link/warning-keys for more information.\n' +
2066
+ ' in Fragment (at **)',
2067
+ ]);
2068
+ }
2069
});
2070
2071
it('should warn in DEV a child is missing keys in client component', async () => {
2072
function ParentClient({children}) {
2073
return children;
2074
}
1772
- const Parent = clientReference(ParentClient);
1773
- await expect(async () => {
2075
+
2076
+ await act(async () => {
2077
+ const Parent = clientReference(ParentClient);
2078
const transport = ReactNoopFlightServer.render(
2079
<Parent>{Array(6).fill(<div>no key</div>)}</Parent>,
2080
);
2081
ReactNoopFlightClient.read(transport);
1778
- await act(async () => {
1779
- ReactNoop.render(await ReactNoopFlightClient.read(transport));
1780
- });
1781
- }).toErrorDev(
1782
- gate(flags => flags.enableOwnerStacks)
1783
- ? 'Each child in a list should have a unique "key" prop.' +
1784
- '\n\nCheck the top-level render call using <ParentClient>. ' +
1785
- 'See https://react.dev/link/warning-keys for more information.'
1786
- : 'Each child in a list should have a unique "key" prop. ' +
1787
- 'See https://react.dev/link/warning-keys for more information.',
1788
- );
2082
+
2083
+ ReactNoop.render(await ReactNoopFlightClient.read(transport));
2084
+ });
2085
+ if (gate(flags => flags.enableOwnerStacks)) {
2086
+ assertConsoleErrorDev([
2087
+ 'Each child in a list should have a unique "key" prop.\n\n' +
2088
+ 'Check the top-level render call using <ParentClient>. ' +
2089
+ 'See https://react.dev/link/warning-keys for more information.\n' +
2090
+ ' in div (at **)',
2091
+ ]);
2092
+ } else {
2093
+ assertConsoleErrorDev([
2094
+ 'Each child in a list should have a unique "key" prop. ' +
2095
+ 'See https://react.dev/link/warning-keys for more information.\n' +
2096
+ ' in div (at **)',
2097
+ ]);
2098
+ }
2099
});
2100
2101
it('should error if a class instance is passed to a host component', () => {
@@ -3135,19 +3445,17 @@ describe('ReactFlight', () => {
3445
},
3446
);
3447
3138
- let transport;
3139
- expect(() => {
3140
- // Reset the modules so that we get a new overridden console on top of the
3141
- // one installed by expect. This ensures that we still emit console.error
3142
- // calls.
3143
- jest.resetModules();
3144
- jest.mock('react', () => require('react/react.react-server'));
3145
- ReactServer = require('react');
3146
- ReactNoopFlightServer = require('react-noop-renderer/flight-server');
3147
- transport = ReactNoopFlightServer.render({
3148
- root: ReactServer.createElement(App),
3149
- });
3150
- }).toErrorDev('err');
3448
+ // Reset the modules so that we get a new overridden console on top of the
3449
+ // one installed by expect. This ensures that we still emit console.error
3450
+ // calls.
3451
+ jest.resetModules();
3452
+ jest.mock('react', () => require('react/react.react-server'));
3453
+ ReactServer = require('react');
3454
+ ReactNoopFlightServer = require('react-noop-renderer/flight-server');
3455
+ const transport = ReactNoopFlightServer.render({
3456
+ root: ReactServer.createElement(App),
3457
+ });
3458
+ assertConsoleErrorDev(['Error: err']);
3459
3460
expect(mockConsoleLog).toHaveBeenCalledTimes(1);
3461
expect(mockConsoleLog.mock.calls[0][0]).toBe('hi');