@samitouri / QOS-React-2 / commits / 432ffc9d0f

Convert more Scheduler.unstable_flushAll in tests to new test utils (#26369)

`Scheduler.unstable_flushAll` in existing tests doesn't work with microtask. This PR converts most of the remaining `Scheduler.unstable_flushAll()` calls to using internal test utilities to unblock refactoring `ensureRootIsScheduled` with scheduling a microtask.

Tianyu Yao committed Mar 10, 2023 at 17:56 UTC 432ffc9d0ff2ade0174c76cc23614e0d76963fb1
6 files changed +332 -270
packages/react-dom/src/events/__tests__/DOMPluginEventSystem-test.internal.js
+159 -117
@@ -80,11 +80,11 @@ describe('DOMPluginEventSystem', () => {
80 ReactDOMClient = require('react-dom/client');
81 Scheduler = require('scheduler');
82 ReactDOMServer = require('react-dom/server');
83 - act = require('internal-test-utils').act;
83
84 const InternalTestUtils = require('internal-test-utils');
85 waitForAll = InternalTestUtils.waitForAll;
86 waitFor = InternalTestUtils.waitFor;
87 + act = InternalTestUtils.act;
88
89 container = document.createElement('div');
90 document.body.appendChild(container);
@@ -635,8 +635,9 @@ describe('DOMPluginEventSystem', () => {
635 // We're going to use a different root as a parent.
636 // This lets us detect whether an event goes through React's event system.
637 const parentRoot = ReactDOMClient.createRoot(parentContainer);
638 - parentRoot.render(<Parent />);
639 - Scheduler.unstable_flushAll();
638 + await act(() => {
639 + parentRoot.render(<Parent />);
640 + });
641
642 childSlotRef.current.appendChild(childContainer);
643
@@ -647,9 +648,9 @@ describe('DOMPluginEventSystem', () => {
648 suspend = true;
649
650 // Hydrate asynchronously.
650 - ReactDOMClient.hydrateRoot(childContainer, <App />);
651 - jest.runAllTimers();
652 - Scheduler.unstable_flushAll();
651 + await act(() => {
652 + ReactDOMClient.hydrateRoot(childContainer, <App />);
653 + });
654
655 // The Suspense boundary is not yet hydrated.
656 await act(() => {
@@ -1305,7 +1306,7 @@ describe('DOMPluginEventSystem', () => {
1306 });
1307
1308 // @gate www
1308 - it('can render correctly with the ReactDOMServer hydration', () => {
1309 + it('can render correctly with the ReactDOMServer hydration', async () => {
1310 const clickEvent = jest.fn();
1311 const spanRef = React.createRef();
1312 const setClick = ReactDOM.unstable_createEventHandle('click');
@@ -1324,14 +1325,15 @@ describe('DOMPluginEventSystem', () => {
1325 const output = ReactDOMServer.renderToString(<Test />);
1326 expect(output).toBe(`<div><span>Hello world</span></div>`);
1327 container.innerHTML = output;
1327 - ReactDOM.hydrate(<Test />, container);
1328 - Scheduler.unstable_flushAll();
1328 + await act(() => {
1329 + ReactDOM.hydrate(<Test />, container);
1330 + });
1331 dispatchClickEvent(spanRef.current);
1332 expect(clickEvent).toHaveBeenCalledTimes(1);
1333 });
1334
1335 // @gate www
1334 - it('should correctly work for a basic "click" listener', () => {
1336 + it('should correctly work for a basic "click" listener', async () => {
1337 let log = [];
1338 const clickEvent = jest.fn(event => {
1339 log.push({
@@ -1357,8 +1359,9 @@ describe('DOMPluginEventSystem', () => {
1359 );
1360 }
1361
1360 - ReactDOM.render(<Test />, container);
1361 - Scheduler.unstable_flushAll();
1362 + await act(() => {
1363 + ReactDOM.render(<Test />, container);
1364 + });
1365
1366 expect(container.innerHTML).toBe(
1367 '<button><div>Click me!</div></button>',
@@ -1378,15 +1381,17 @@ describe('DOMPluginEventSystem', () => {
1381 expect(clickEvent).toBeCalledTimes(1);
1382
1383 // Unmounting the container and clicking should not work
1381 - ReactDOM.render(null, container);
1382 - Scheduler.unstable_flushAll();
1384 + await act(() => {
1385 + ReactDOM.render(null, container);
1386 + });
1387
1388 dispatchClickEvent(divElement);
1389 expect(clickEvent).toBeCalledTimes(1);
1390
1391 // Re-rendering the container and clicking should work
1388 - ReactDOM.render(<Test />, container);
1389 - Scheduler.unstable_flushAll();
1392 + await act(() => {
1393 + ReactDOM.render(<Test />, container);
1394 + });
1395
1396 divElement = divRef.current;
1397 dispatchClickEvent(divElement);
@@ -1421,8 +1426,9 @@ describe('DOMPluginEventSystem', () => {
1426 }
1427
1428 let clickEvent2 = jest.fn();
1424 - ReactDOM.render(<Test2 clickEvent2={clickEvent2} />, container);
1425 - Scheduler.unstable_flushAll();
1429 + await act(() => {
1430 + ReactDOM.render(<Test2 clickEvent2={clickEvent2} />, container);
1431 + });
1432
1433 divElement = divRef.current;
1434 dispatchClickEvent(divElement);
@@ -1430,8 +1436,9 @@ describe('DOMPluginEventSystem', () => {
1436
1437 // Reset the function we pass in, so it's different
1438 clickEvent2 = jest.fn();
1433 - ReactDOM.render(<Test2 clickEvent2={clickEvent2} />, container);
1434 - Scheduler.unstable_flushAll();
1439 + await act(() => {
1440 + ReactDOM.render(<Test2 clickEvent2={clickEvent2} />, container);
1441 + });
1442
1443 divElement = divRef.current;
1444 dispatchClickEvent(divElement);
@@ -1439,7 +1446,7 @@ describe('DOMPluginEventSystem', () => {
1446 });
1447
1448 // @gate www
1442 - it('should correctly work for setting and clearing a basic "click" listener', () => {
1449 + it('should correctly work for setting and clearing a basic "click" listener', async () => {
1450 const clickEvent = jest.fn();
1451 const divRef = React.createRef();
1452 const buttonRef = React.createRef();
@@ -1461,16 +1468,18 @@ describe('DOMPluginEventSystem', () => {
1468 );
1469 }
1470
1464 - ReactDOM.render(<Test off={false} />, container);
1465 - Scheduler.unstable_flushAll();
1471 + await act(() => {
1472 + ReactDOM.render(<Test off={false} />, container);
1473 + });
1474
1475 let divElement = divRef.current;
1476 dispatchClickEvent(divElement);
1477 expect(clickEvent).toBeCalledTimes(1);
1478
1479 // The listener should get unmounted
1472 - ReactDOM.render(<Test off={true} />, container);
1473 - Scheduler.unstable_flushAll();
1480 + await act(() => {
1481 + ReactDOM.render(<Test off={true} />, container);
1482 + });
1483
1484 clickEvent.mockClear();
1485
@@ -1480,7 +1489,7 @@ describe('DOMPluginEventSystem', () => {
1489 });
1490
1491 // @gate www
1483 - it('should handle the target being a text node', () => {
1492 + it('should handle the target being a text node', async () => {
1493 const clickEvent = jest.fn();
1494 const buttonRef = React.createRef();
1495 const setClick = ReactDOM.unstable_createEventHandle('click');
@@ -1493,8 +1502,9 @@ describe('DOMPluginEventSystem', () => {
1502 return <button ref={buttonRef}>Click me!</button>;
1503 }
1504
1496 - ReactDOM.render(<Test />, container);
1497 - Scheduler.unstable_flushAll();
1505 + await act(() => {
1506 + ReactDOM.render(<Test />, container);
1507 + });
1508
1509 const textNode = buttonRef.current.firstChild;
1510 dispatchClickEvent(textNode);
@@ -1502,7 +1512,7 @@ describe('DOMPluginEventSystem', () => {
1512 });
1513
1514 // @gate www
1505 - it('handle propagation of click events', () => {
1515 + it('handle propagation of click events', async () => {
1516 const buttonRef = React.createRef();
1517 const divRef = React.createRef();
1518 const log = [];
@@ -1546,8 +1556,9 @@ describe('DOMPluginEventSystem', () => {
1556 );
1557 }
1558
1549 - ReactDOM.render(<Test />, container);
1550 - Scheduler.unstable_flushAll();
1559 + await act(() => {
1560 + ReactDOM.render(<Test />, container);
1561 + });
1562
1563 const buttonElement = buttonRef.current;
1564 dispatchClickEvent(buttonElement);
@@ -1571,7 +1582,7 @@ describe('DOMPluginEventSystem', () => {
1582 });
1583
1584 // @gate www
1574 - it('handle propagation of click events mixed with onClick events', () => {
1585 + it('handle propagation of click events mixed with onClick events', async () => {
1586 const buttonRef = React.createRef();
1587 const divRef = React.createRef();
1588 const log = [];
@@ -1610,8 +1621,9 @@ describe('DOMPluginEventSystem', () => {
1621 );
1622 }
1623
1613 - ReactDOM.render(<Test />, container);
1614 - Scheduler.unstable_flushAll();
1624 + await act(() => {
1625 + ReactDOM.render(<Test />, container);
1626 + });
1627
1628 const buttonElement = buttonRef.current;
1629 dispatchClickEvent(buttonElement);
@@ -1631,7 +1643,7 @@ describe('DOMPluginEventSystem', () => {
1643 });
1644
1645 // @gate www
1634 - it('should correctly work for a basic "click" listener on the outer target', () => {
1646 + it('should correctly work for a basic "click" listener on the outer target', async () => {
1647 const log = [];
1648 const clickEvent = jest.fn(event => {
1649 log.push({
@@ -1657,8 +1669,9 @@ describe('DOMPluginEventSystem', () => {
1669 );
1670 }
1671
1660 - ReactDOM.render(<Test />, container);
1661 - Scheduler.unstable_flushAll();
1672 + await act(() => {
1673 + ReactDOM.render(<Test />, container);
1674 + });
1675
1676 expect(container.innerHTML).toBe(
1677 '<button><div>Click me!</div></button>',
@@ -1682,8 +1695,9 @@ describe('DOMPluginEventSystem', () => {
1695 expect(clickEvent).toBeCalledTimes(1);
1696
1697 // Re-rendering the container and clicking should work
1685 - ReactDOM.render(<Test />, container);
1686 - Scheduler.unstable_flushAll();
1698 + await act(() => {
1699 + ReactDOM.render(<Test />, container);
1700 + });
1701
1702 divElement = divRef.current;
1703 dispatchClickEvent(divElement);
@@ -1696,7 +1710,7 @@ describe('DOMPluginEventSystem', () => {
1710 });
1711
1712 // @gate www
1699 - it('should correctly handle many nested target listeners', () => {
1713 + it('should correctly handle many nested target listeners', async () => {
1714 const buttonRef = React.createRef();
1715 const targetListener1 = jest.fn();
1716 const targetListener2 = jest.fn();
@@ -1741,8 +1755,9 @@ describe('DOMPluginEventSystem', () => {
1755 return <button ref={buttonRef}>Click me!</button>;
1756 }
1757
1744 - ReactDOM.render(<Test />, container);
1745 - Scheduler.unstable_flushAll();
1758 + await act(() => {
1759 + ReactDOM.render(<Test />, container);
1760 + });
1761
1762 let buttonElement = buttonRef.current;
1763 dispatchClickEvent(buttonElement);
@@ -1787,8 +1802,9 @@ describe('DOMPluginEventSystem', () => {
1802 return <button ref={buttonRef}>Click me!</button>;
1803 }
1804
1790 - ReactDOM.render(<Test2 />, container);
1791 - Scheduler.unstable_flushAll();
1805 + await act(() => {
1806 + ReactDOM.render(<Test2 />, container);
1807 + });
1808
1809 buttonElement = buttonRef.current;
1810 dispatchClickEvent(buttonElement);
@@ -1799,7 +1815,7 @@ describe('DOMPluginEventSystem', () => {
1815 });
1816
1817 // @gate www
1802 - it('should correctly handle stopPropagation correctly for target events', () => {
1818 + it('should correctly handle stopPropagation correctly for target events', async () => {
1819 const buttonRef = React.createRef();
1820 const divRef = React.createRef();
1821 const clickEvent = jest.fn();
@@ -1828,8 +1844,9 @@ describe('DOMPluginEventSystem', () => {
1844 );
1845 }
1846
1831 - ReactDOM.render(<Test />, container);
1832 - Scheduler.unstable_flushAll();
1847 + await act(() => {
1848 + ReactDOM.render(<Test />, container);
1849 + });
1850
1851 const divElement = divRef.current;
1852 dispatchClickEvent(divElement);
@@ -1837,7 +1854,7 @@ describe('DOMPluginEventSystem', () => {
1854 });
1855
1856 // @gate www
1840 - it('should correctly handle stopPropagation correctly for many target events', () => {
1857 + it('should correctly handle stopPropagation correctly for many target events', async () => {
1858 const buttonRef = React.createRef();
1859 const targetListener1 = jest.fn(e => e.stopPropagation());
1860 const targetListener2 = jest.fn(e => e.stopPropagation());
@@ -1878,8 +1895,9 @@ describe('DOMPluginEventSystem', () => {
1895 return <button ref={buttonRef}>Click me!</button>;
1896 }
1897
1881 - ReactDOM.render(<Test />, container);
1882 - Scheduler.unstable_flushAll();
1898 + await act(() => {
1899 + ReactDOM.render(<Test />, container);
1900 + });
1901
1902 const buttonElement = buttonRef.current;
1903 dispatchClickEvent(buttonElement);
@@ -1890,7 +1908,7 @@ describe('DOMPluginEventSystem', () => {
1908 });
1909
1910 // @gate www
1893 - it('should correctly handle stopPropagation for mixed capture/bubbling target listeners', () => {
1911 + it('should correctly handle stopPropagation for mixed capture/bubbling target listeners', async () => {
1912 const buttonRef = React.createRef();
1913 const targetListener1 = jest.fn(e => e.stopPropagation());
1914 const targetListener2 = jest.fn(e => e.stopPropagation());
@@ -1935,8 +1953,9 @@ describe('DOMPluginEventSystem', () => {
1953 return <button ref={buttonRef}>Click me!</button>;
1954 }
1955
1938 - ReactDOM.render(<Test />, container);
1939 - Scheduler.unstable_flushAll();
1956 + await act(() => {
1957 + ReactDOM.render(<Test />, container);
1958 + });
1959
1960 const buttonElement = buttonRef.current;
1961 dispatchClickEvent(buttonElement);
@@ -1996,7 +2015,7 @@ describe('DOMPluginEventSystem', () => {
2015 });
2016
2017 // @gate www
1999 - it('should correctly work for a basic "click" window listener', () => {
2018 + it('should correctly work for a basic "click" window listener', async () => {
2019 const log = [];
2020 const clickEvent = jest.fn(event => {
2021 log.push({
@@ -2015,8 +2034,9 @@ describe('DOMPluginEventSystem', () => {
2034
2035 return <button>Click anything!</button>;
2036 }
2018 - ReactDOM.render(<Test />, container);
2019 - Scheduler.unstable_flushAll();
2037 + await act(() => {
2038 + ReactDOM.render(<Test />, container);
2039 + });
2040
2041 expect(container.innerHTML).toBe(
2042 '<button>Click anything!</button>',
@@ -2032,22 +2052,24 @@ describe('DOMPluginEventSystem', () => {
2052 });
2053
2054 // Unmounting the container and clicking should not work
2035 - ReactDOM.render(null, container);
2036 - Scheduler.unstable_flushAll();
2055 + await act(() => {
2056 + ReactDOM.render(null, container);
2057 + });
2058
2059 dispatchClickEvent(document.body);
2060 expect(clickEvent).toBeCalledTimes(1);
2061
2062 // Re-rendering and clicking the body should work again
2042 - ReactDOM.render(<Test />, container);
2043 - Scheduler.unstable_flushAll();
2063 + await act(() => {
2064 + ReactDOM.render(<Test />, container);
2065 + });
2066
2067 dispatchClickEvent(document.body);
2068 expect(clickEvent).toBeCalledTimes(2);
2069 });
2070
2071 // @gate www
2050 - it('handle propagation of click events on the window', () => {
2072 + it('handle propagation of click events on the window', async () => {
2073 const buttonRef = React.createRef();
2074 const divRef = React.createRef();
2075 const log = [];
@@ -2098,8 +2120,9 @@ describe('DOMPluginEventSystem', () => {
2120 );
2121 }
2122
2101 - ReactDOM.render(<Test />, container);
2102 - Scheduler.unstable_flushAll();
2123 + await act(() => {
2124 + ReactDOM.render(<Test />, container);
2125 + });
2126
2127 const buttonElement = buttonRef.current;
2128 dispatchClickEvent(buttonElement);
@@ -2127,7 +2150,7 @@ describe('DOMPluginEventSystem', () => {
2150 });
2151
2152 // @gate www
2130 - it('should correctly handle stopPropagation for mixed listeners', () => {
2153 + it('should correctly handle stopPropagation for mixed listeners', async () => {
2154 const buttonRef = React.createRef();
2155 const rootListener1 = jest.fn(e => e.stopPropagation());
2156 const rootListener2 = jest.fn();
@@ -2166,8 +2189,9 @@ describe('DOMPluginEventSystem', () => {
2189 return <button ref={buttonRef}>Click me!</button>;
2190 }
2191
2169 - ReactDOM.render(<Test />, container);
2170 - Scheduler.unstable_flushAll();
2192 + await act(() => {
2193 + ReactDOM.render(<Test />, container);
2194 + });
2195
2196 const buttonElement = buttonRef.current;
2197 dispatchClickEvent(buttonElement);
@@ -2178,7 +2202,7 @@ describe('DOMPluginEventSystem', () => {
2202 });
2203
2204 // @gate www
2181 - it('should correctly handle stopPropagation for delegated listeners', () => {
2205 + it('should correctly handle stopPropagation for delegated listeners', async () => {
2206 const buttonRef = React.createRef();
2207 const rootListener1 = jest.fn(e => e.stopPropagation());
2208 const rootListener2 = jest.fn();
@@ -2211,9 +2235,9 @@ describe('DOMPluginEventSystem', () => {
2235 return <button ref={buttonRef}>Click me!</button>;
2236 }
2237
2214 - ReactDOM.render(<Test />, container);
2215 -
2216 - Scheduler.unstable_flushAll();
2238 + await act(() => {
2239 + ReactDOM.render(<Test />, container);
2240 + });
2241
2242 const buttonElement = buttonRef.current;
2243 dispatchClickEvent(buttonElement);
@@ -2224,7 +2248,7 @@ describe('DOMPluginEventSystem', () => {
2248 });
2249
2250 // @gate www
2227 - it('handle propagation of click events on the window and document', () => {
2251 + it('handle propagation of click events on the window and document', async () => {
2252 const buttonRef = React.createRef();
2253 const divRef = React.createRef();
2254 const log = [];
@@ -2282,8 +2306,9 @@ describe('DOMPluginEventSystem', () => {
2306 );
2307 }
2308
2285 - ReactDOM.render(<Test />, container);
2286 - Scheduler.unstable_flushAll();
2309 + await act(() => {
2310 + ReactDOM.render(<Test />, container);
2311 + });
2312
2313 const buttonElement = buttonRef.current;
2314 dispatchClickEvent(buttonElement);
@@ -2349,7 +2374,7 @@ describe('DOMPluginEventSystem', () => {
2374 });
2375
2376 // @gate www
2352 - it('beforeblur and afterblur are called after a focused element is unmounted', () => {
2377 + it('beforeblur and afterblur are called after a focused element is unmounted', async () => {
2378 const log = [];
2379 // We have to persist here because we want to read relatedTarget later.
2380 const onAfterBlur = jest.fn(e => {
@@ -2385,8 +2410,9 @@ describe('DOMPluginEventSystem', () => {
2410 );
2411 };
2412
2388 - ReactDOM.render(<Component show={true} />, container);
2389 - Scheduler.unstable_flushAll();
2413 + await act(() => {
2414 + ReactDOM.render(<Component show={true} />, container);
2415 + });
2416
2417 const inner = innerRef.current;
2418 const target = createEventTarget(inner);
@@ -2394,8 +2420,9 @@ describe('DOMPluginEventSystem', () => {
2420 expect(onBeforeBlur).toHaveBeenCalledTimes(0);
2421 expect(onAfterBlur).toHaveBeenCalledTimes(0);
2422
2397 - ReactDOM.render(<Component show={false} />, container);
2398 - Scheduler.unstable_flushAll();
2423 + await act(() => {
2424 + ReactDOM.render(<Component show={false} />, container);
2425 + });
2426
2427 expect(onBeforeBlur).toHaveBeenCalledTimes(1);
2428 expect(onAfterBlur).toHaveBeenCalledTimes(1);
@@ -2406,7 +2433,7 @@ describe('DOMPluginEventSystem', () => {
2433 });
2434
2435 // @gate www
2409 - it('beforeblur and afterblur are called after a nested focused element is unmounted', () => {
2436 + it('beforeblur and afterblur are called after a nested focused element is unmounted', async () => {
2437 const log = [];
2438 // We have to persist here because we want to read relatedTarget later.
2439 const onAfterBlur = jest.fn(e => {
@@ -2446,8 +2473,9 @@ describe('DOMPluginEventSystem', () => {
2473 );
2474 };
2475
2449 - ReactDOM.render(<Component show={true} />, container);
2450 - Scheduler.unstable_flushAll();
2476 + await act(() => {
2477 + ReactDOM.render(<Component show={true} />, container);
2478 + });
2479
2480 const inner = innerRef.current;
2481 const target = createEventTarget(inner);
@@ -2455,8 +2483,9 @@ describe('DOMPluginEventSystem', () => {
2483 expect(onBeforeBlur).toHaveBeenCalledTimes(0);
2484 expect(onAfterBlur).toHaveBeenCalledTimes(0);
2485
2458 - ReactDOM.render(<Component show={false} />, container);
2459 - Scheduler.unstable_flushAll();
2486 + await act(() => {
2487 + ReactDOM.render(<Component show={false} />, container);
2488 + });
2489
2490 expect(onBeforeBlur).toHaveBeenCalledTimes(1);
2491 expect(onAfterBlur).toHaveBeenCalledTimes(1);
@@ -2467,7 +2496,7 @@ describe('DOMPluginEventSystem', () => {
2496 });
2497
2498 // @gate www
2470 - it('beforeblur should skip handlers from a deleted subtree after the focused element is unmounted', () => {
2499 + it('beforeblur should skip handlers from a deleted subtree after the focused element is unmounted', async () => {
2500 const onBeforeBlur = jest.fn();
2501 const innerRef = React.createRef();
2502 const innerRef2 = React.createRef();
@@ -2505,16 +2534,18 @@ describe('DOMPluginEventSystem', () => {
2534 );
2535 };
2536
2508 - ReactDOM.render(<Component show={true} />, container);
2509 - Scheduler.unstable_flushAll();
2537 + await act(() => {
2538 + ReactDOM.render(<Component show={true} />, container);
2539 + });
2540
2541 const inner = innerRef.current;
2542 const target = createEventTarget(inner);
2543 target.focus();
2544 expect(onBeforeBlur).toHaveBeenCalledTimes(0);
2545
2516 - ReactDOM.render(<Component show={false} />, container);
2517 - Scheduler.unstable_flushAll();
2546 + await act(() => {
2547 + ReactDOM.render(<Component show={false} />, container);
2548 + });
2549
2550 expect(onBeforeBlur).toHaveBeenCalledTimes(1);
2551 });
@@ -2745,7 +2776,7 @@ describe('DOMPluginEventSystem', () => {
2776 });
2777
2778 // @gate www
2748 - it('handle propagation of click events between disjointed comment roots', () => {
2779 + it('handle propagation of click events between disjointed comment roots', async () => {
2780 const buttonRef = React.createRef();
2781 const divRef = React.createRef();
2782 const log = [];
@@ -2792,11 +2823,13 @@ describe('DOMPluginEventSystem', () => {
2823 const disjointedNode = document.createComment(
2824 ' react-mount-point-unstable ',
2825 );
2795 - ReactDOM.render(<Parent />, container);
2796 - Scheduler.unstable_flushAll();
2826 + await act(() => {
2827 + ReactDOM.render(<Parent />, container);
2828 + });
2829 buttonRef.current.appendChild(disjointedNode);
2798 - ReactDOM.render(<Child />, disjointedNode);
2799 - Scheduler.unstable_flushAll();
2830 + await act(() => {
2831 + ReactDOM.render(<Child />, disjointedNode);
2832 + });
2833
2834 const buttonElement = buttonRef.current;
2835 dispatchClickEvent(buttonElement);
@@ -2816,7 +2849,7 @@ describe('DOMPluginEventSystem', () => {
2849 });
2850
2851 // @gate www
2819 - it('propagates known createEventHandle events through portals without inner listeners', () => {
2852 + it('propagates known createEventHandle events through portals without inner listeners', async () => {
2853 const buttonRef = React.createRef();
2854 const divRef = React.createRef();
2855 const log = [];
@@ -2859,8 +2892,9 @@ describe('DOMPluginEventSystem', () => {
2892 );
2893 }
2894
2862 - ReactDOM.render(<Parent />, container);
2863 - Scheduler.unstable_flushAll();
2895 + await act(() => {
2896 + ReactDOM.render(<Parent />, container);
2897 + });
2898
2899 const divElement = divRef.current;
2900 const buttonElement = buttonRef.current;
@@ -2885,10 +2919,11 @@ describe('DOMPluginEventSystem', () => {
2919 ReactDOMClient = require('react-dom/client');
2920 Scheduler = require('scheduler');
2921 ReactDOMServer = require('react-dom/server');
2922 + act = require('internal-test-utils').act;
2923 });
2924
2925 // @gate www
2891 - it('handle propagation of click events on a scope', () => {
2926 + it('handle propagation of click events on a scope', async () => {
2927 const buttonRef = React.createRef();
2928 const log = [];
2929 const onClick = jest.fn(e =>
@@ -2929,8 +2964,9 @@ describe('DOMPluginEventSystem', () => {
2964 );
2965 }
2966
2932 - ReactDOM.render(<Test />, container);
2933 - Scheduler.unstable_flushAll();
2967 + await act(() => {
2968 + ReactDOM.render(<Test />, container);
2969 + });
2970
2971 const buttonElement = buttonRef.current;
2972 dispatchClickEvent(buttonElement);
@@ -2944,7 +2980,7 @@ describe('DOMPluginEventSystem', () => {
2980 });
2981
2982 // @gate www
2947 - it('handle mixed propagation of click events on a scope', () => {
2983 + it('handle mixed propagation of click events on a scope', async () => {
2984 const buttonRef = React.createRef();
2985 const divRef = React.createRef();
2986 const log = [];
@@ -3000,8 +3036,9 @@ describe('DOMPluginEventSystem', () => {
3036 );
3037 }
3038
3003 - ReactDOM.render(<Test />, container);
3004 - Scheduler.unstable_flushAll();
3039 + await act(() => {
3040 + ReactDOM.render(<Test />, container);
3041 + });
3042
3043 const buttonElement = buttonRef.current;
3044 dispatchClickEvent(buttonElement);
@@ -3035,7 +3072,7 @@ describe('DOMPluginEventSystem', () => {
3072 });
3073
3074 // @gate www
3038 - it('should not handle the target being a dangling text node within a scope', () => {
3075 + it('should not handle the target being a dangling text node within a scope', async () => {
3076 const clickEvent = jest.fn();
3077 const buttonRef = React.createRef();
3078 const TestScope = React.unstable_Scope;
@@ -3055,8 +3092,9 @@ describe('DOMPluginEventSystem', () => {
3092 );
3093 }
3094
3058 - ReactDOM.render(<Test />, container);
3059 - Scheduler.unstable_flushAll();
3095 + await act(() => {
3096 + ReactDOM.render(<Test />, container);
3097 + });
3098
3099 const textNode = buttonRef.current.firstChild;
3100 dispatchClickEvent(textNode);
@@ -3066,7 +3104,7 @@ describe('DOMPluginEventSystem', () => {
3104 });
3105
3106 // @gate www
3069 - it('handle stopPropagation (inner) correctly between scopes', () => {
3107 + it('handle stopPropagation (inner) correctly between scopes', async () => {
3108 const buttonRef = React.createRef();
3109 const outerOnClick = jest.fn();
3110 const innerOnClick = jest.fn(e => e.stopPropagation());
@@ -3097,8 +3135,9 @@ describe('DOMPluginEventSystem', () => {
3135 );
3136 }
3137
3100 - ReactDOM.render(<Test />, container);
3101 - Scheduler.unstable_flushAll();
3138 + await act(() => {
3139 + ReactDOM.render(<Test />, container);
3140 + });
3141
3142 const buttonElement = buttonRef.current;
3143 dispatchClickEvent(buttonElement);
@@ -3108,7 +3147,7 @@ describe('DOMPluginEventSystem', () => {
3147 });
3148
3149 // @gate www
3111 - it('handle stopPropagation (outer) correctly between scopes', () => {
3150 + it('handle stopPropagation (outer) correctly between scopes', async () => {
3151 const buttonRef = React.createRef();
3152 const outerOnClick = jest.fn(e => e.stopPropagation());
3153 const innerOnClick = jest.fn();
@@ -3139,8 +3178,9 @@ describe('DOMPluginEventSystem', () => {
3178 );
3179 }
3180
3142 - ReactDOM.render(<Test />, container);
3143 - Scheduler.unstable_flushAll();
3181 + await act(() => {
3182 + ReactDOM.render(<Test />, container);
3183 + });
3184
3185 const buttonElement = buttonRef.current;
3186 dispatchClickEvent(buttonElement);
@@ -3150,7 +3190,7 @@ describe('DOMPluginEventSystem', () => {
3190 });
3191
3192 // @gate www
3153 - it('handle stopPropagation (inner and outer) correctly between scopes', () => {
3193 + it('handle stopPropagation (inner and outer) correctly between scopes', async () => {
3194 const buttonRef = React.createRef();
3195 const onClick = jest.fn(e => e.stopPropagation());
3196 const TestScope = React.unstable_Scope;
@@ -3180,8 +3220,9 @@ describe('DOMPluginEventSystem', () => {
3220 );
3221 }
3222
3183 - ReactDOM.render(<Test />, container);
3184 - Scheduler.unstable_flushAll();
3223 + await act(() => {
3224 + ReactDOM.render(<Test />, container);
3225 + });
3226
3227 const buttonElement = buttonRef.current;
3228 dispatchClickEvent(buttonElement);
@@ -3190,7 +3231,7 @@ describe('DOMPluginEventSystem', () => {
3231 });
3232
3233 // @gate www
3193 - it('should be able to register handlers for events affected by the intervention', () => {
3234 + it('should be able to register handlers for events affected by the intervention', async () => {
3235 const rootContainer = document.createElement('div');
3236 container.appendChild(rootContainer);
3237
@@ -3232,8 +3273,9 @@ describe('DOMPluginEventSystem', () => {
3273 return <div ref={ref}>test</div>;
3274 }
3275
3235 - ReactDOM.render(<Component />, rootContainer);
3236 - Scheduler.unstable_flushAll();
3276 + await act(() => {
3277 + ReactDOM.render(<Component />, rootContainer);
3278 + });
3279
3280 dispatchEvent(ref.current, 'touchstart');
3281 dispatchEvent(ref.current, 'touchmove');
packages/react-interactions/events/src/dom/create-event-handle/__tests__/useFocus-test.internal.js
+46 -42
@@ -15,7 +15,7 @@ let React;
15 let ReactFeatureFlags;
16 let ReactDOM;
17 let useFocus;
18 -let Scheduler;
18 +let act;
19
20 function initializeModules(hasPointerEvents) {
21 setPointerEvent(hasPointerEvents);
@@ -24,8 +24,7 @@ function initializeModules(hasPointerEvents) {
24 ReactFeatureFlags.enableCreateEventHandleAPI = true;
25 React = require('react');
26 ReactDOM = require('react-dom');
27 - Scheduler = require('scheduler');
28 -
27 + act = require('internal-test-utils').act;
28 // TODO: This import throws outside of experimental mode. Figure out better
29 // strategy for gated imports.
30 if (__EXPERIMENTAL__ || global.__WWW__) {
@@ -54,7 +53,7 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
53 describe('disabled', () => {
54 let onBlur, onFocus, ref;
55
57 - const componentInit = () => {
56 + const componentInit = async () => {
57 onBlur = jest.fn();
58 onFocus = jest.fn();
59 ref = React.createRef();
@@ -66,13 +65,14 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
65 });
66 return <div ref={ref} />;
67 };
69 - ReactDOM.render(<Component />, container);
70 - Scheduler.unstable_flushAll();
68 + await act(() => {
69 + ReactDOM.render(<Component />, container);
70 + });
71 };
72
73 // @gate www
74 - it('does not call callbacks', () => {
75 - componentInit();
74 + it('does not call callbacks', async () => {
75 + await componentInit();
76 const target = createEventTarget(ref.current);
77 target.focus();
78 target.blur();
@@ -84,7 +84,7 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
84 describe('onBlur', () => {
85 let onBlur, ref;
86
87 - const componentInit = () => {
87 + const componentInit = async () => {
88 onBlur = jest.fn();
89 ref = React.createRef();
90 const Component = () => {
@@ -93,13 +93,14 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
93 });
94 return <div ref={ref} />;
95 };
96 - ReactDOM.render(<Component />, container);
97 - Scheduler.unstable_flushAll();
96 + await act(() => {
97 + ReactDOM.render(<Component />, container);
98 + });
99 };
100
101 // @gate www
101 - it('is called after "blur" event', () => {
102 - componentInit();
102 + it('is called after "blur" event', async () => {
103 + await componentInit();
104 const target = createEventTarget(ref.current);
105 target.focus();
106 target.blur();
@@ -110,7 +111,7 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
111 describe('onFocus', () => {
112 let onFocus, ref, innerRef;
113
113 - const componentInit = () => {
114 + const componentInit = async () => {
115 onFocus = jest.fn();
116 ref = React.createRef();
117 innerRef = React.createRef();
@@ -124,21 +125,22 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
125 </div>
126 );
127 };
127 - ReactDOM.render(<Component />, container);
128 - Scheduler.unstable_flushAll();
128 + await act(() => {
129 + ReactDOM.render(<Component />, container);
130 + });
131 };
132
133 // @gate www
132 - it('is called after "focus" event', () => {
133 - componentInit();
134 + it('is called after "focus" event', async () => {
135 + await componentInit();
136 const target = createEventTarget(ref.current);
137 target.focus();
138 expect(onFocus).toHaveBeenCalledTimes(1);
139 });
140
141 // @gate www
140 - it('is not called if descendants of target receive focus', () => {
141 - componentInit();
142 + it('is not called if descendants of target receive focus', async () => {
143 + await componentInit();
144 const target = createEventTarget(innerRef.current);
145 target.focus();
146 expect(onFocus).not.toBeCalled();
@@ -148,7 +150,7 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
150 describe('onFocusChange', () => {
151 let onFocusChange, ref, innerRef;
152
151 - const componentInit = () => {
153 + const componentInit = async () => {
154 onFocusChange = jest.fn();
155 ref = React.createRef();
156 innerRef = React.createRef();
@@ -162,13 +164,14 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
164 </div>
165 );
166 };
165 - ReactDOM.render(<Component />, container);
166 - Scheduler.unstable_flushAll();
167 + await act(() => {
168 + ReactDOM.render(<Component />, container);
169 + });
170 };
171
172 // @gate www
170 - it('is called after "blur" and "focus" events', () => {
171 - componentInit();
173 + it('is called after "blur" and "focus" events', async () => {
174 + await componentInit();
175 const target = createEventTarget(ref.current);
176 target.focus();
177 expect(onFocusChange).toHaveBeenCalledTimes(1);
@@ -179,8 +182,8 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
182 });
183
184 // @gate www
182 - it('is not called after "blur" and "focus" events on descendants', () => {
183 - componentInit();
185 + it('is not called after "blur" and "focus" events on descendants', async () => {
186 + await componentInit();
187 const target = createEventTarget(innerRef.current);
188 target.focus();
189 expect(onFocusChange).toHaveBeenCalledTimes(0);
@@ -192,7 +195,7 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
195 describe('onFocusVisibleChange', () => {
196 let onFocusVisibleChange, ref, innerRef;
197
195 - const componentInit = () => {
198 + const componentInit = async () => {
199 onFocusVisibleChange = jest.fn();
200 ref = React.createRef();
201 innerRef = React.createRef();
@@ -206,13 +209,14 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
209 </div>
210 );
211 };
209 - ReactDOM.render(<Component />, container);
210 - Scheduler.unstable_flushAll();
212 + await act(() => {
213 + ReactDOM.render(<Component />, container);
214 + });
215 };
216
217 // @gate www
214 - it('is called after "focus" and "blur" if keyboard navigation is active', () => {
215 - componentInit();
218 + it('is called after "focus" and "blur" if keyboard navigation is active', async () => {
219 + await componentInit();
220 const target = createEventTarget(ref.current);
221 const containerTarget = createEventTarget(container);
222 // use keyboard first
@@ -226,8 +230,8 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
230 });
231
232 // @gate www
229 - it('is called if non-keyboard event is dispatched on target previously focused with keyboard', () => {
230 - componentInit();
233 + it('is called if non-keyboard event is dispatched on target previously focused with keyboard', async () => {
234 + await componentInit();
235 const target = createEventTarget(ref.current);
236 const containerTarget = createEventTarget(container);
237 // use keyboard first
@@ -245,8 +249,8 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
249 });
250
251 // @gate www
248 - it('is not called after "focus" and "blur" events without keyboard', () => {
249 - componentInit();
252 + it('is not called after "focus" and "blur" events without keyboard', async () => {
253 + await componentInit();
254 const target = createEventTarget(ref.current);
255 const containerTarget = createEventTarget(container);
256 target.pointerdown();
@@ -257,8 +261,8 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
261 });
262
263 // @gate www
260 - it('is not called after "blur" and "focus" events on descendants', () => {
261 - componentInit();
264 + it('is not called after "blur" and "focus" events on descendants', async () => {
265 + await componentInit();
266 const innerTarget = createEventTarget(innerRef.current);
267 const containerTarget = createEventTarget(container);
268 containerTarget.keydown({key: 'Tab'});
@@ -271,7 +275,7 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
275
276 describe('nested Focus components', () => {
277 // @gate www
274 - it('propagates events in the correct order', () => {
278 + it('propagates events in the correct order', async () => {
279 const events = [];
280 const innerRef = React.createRef();
281 const outerRef = React.createRef();
@@ -301,9 +305,9 @@ describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
305 );
306 };
307
304 - ReactDOM.render(<Outer />, container);
305 - Scheduler.unstable_flushAll();
306 -
308 + await act(() => {
309 + ReactDOM.render(<Outer />, container);
310 + });
311 const innerTarget = createEventTarget(innerRef.current);
312 const outerTarget = createEventTarget(outerRef.current);
313
packages/react-interactions/events/src/dom/create-event-handle/__tests__/useFocusWithin-test.internal.js
+49 -49
@@ -17,7 +17,6 @@ let ReactDOM;
17 let ReactDOMClient;
18 let useFocusWithin;
19 let act;
20 -let Scheduler;
20
21 function initializeModules(hasPointerEvents) {
22 setPointerEvent(hasPointerEvents);
@@ -28,7 +27,6 @@ function initializeModules(hasPointerEvents) {
27 React = require('react');
28 ReactDOM = require('react-dom');
29 ReactDOMClient = require('react-dom/client');
31 - Scheduler = require('scheduler');
30 act = require('internal-test-utils').act;
31
32 // TODO: This import throws outside of experimental mode. Figure out better
@@ -64,7 +62,7 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
62 describe('disabled', () => {
63 let onFocusWithinChange, onFocusWithinVisibleChange, ref;
64
67 - const componentInit = () => {
65 + const componentInit = async () => {
66 onFocusWithinChange = jest.fn();
67 onFocusWithinVisibleChange = jest.fn();
68 ref = React.createRef();
@@ -76,13 +74,14 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
74 });
75 return <div ref={focusWithinRef} />;
76 };
79 - ReactDOM.render(<Component />, container);
80 - Scheduler.unstable_flushAll();
77 + await act(() => {
78 + ReactDOM.render(<Component />, container);
79 + });
80 };
81
82 // @gate www
84 - it('prevents custom events being dispatched', () => {
85 - componentInit();
83 + it('prevents custom events being dispatched', async () => {
84 + await componentInit();
85 const target = createEventTarget(ref.current);
86 target.focus();
87 target.blur();
@@ -106,18 +105,19 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
105 );
106 };
107
109 - const componentInit = () => {
108 + const componentInit = async () => {
109 onFocusWithinChange = jest.fn();
110 ref = React.createRef();
111 innerRef = React.createRef();
112 innerRef2 = React.createRef();
114 - ReactDOM.render(<Component show={true} />, container);
115 - Scheduler.unstable_flushAll();
113 + await act(() => {
114 + ReactDOM.render(<Component show={true} />, container);
115 + });
116 };
117
118 // @gate www
119 - it('is called after "blur" and "focus" events on focus target', () => {
120 - componentInit();
119 + it('is called after "blur" and "focus" events on focus target', async () => {
120 + await componentInit();
121 const target = createEventTarget(ref.current);
122 target.focus();
123 expect(onFocusWithinChange).toHaveBeenCalledTimes(1);
@@ -128,8 +128,8 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
128 });
129
130 // @gate www
131 - it('is called after "blur" and "focus" events on descendants', () => {
132 - componentInit();
131 + it('is called after "blur" and "focus" events on descendants', async () => {
132 + await componentInit();
133 const target = createEventTarget(innerRef.current);
134 target.focus();
135 expect(onFocusWithinChange).toHaveBeenCalledTimes(1);
@@ -140,8 +140,8 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
140 });
141
142 // @gate www
143 - it('is only called once when focus moves within and outside the subtree', () => {
144 - componentInit();
143 + it('is only called once when focus moves within and outside the subtree', async () => {
144 + await componentInit();
145 const node = ref.current;
146 const innerNode1 = innerRef.current;
147 const innerNode2 = innerRef.current;
@@ -182,18 +182,19 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
182 );
183 };
184
185 - const componentInit = () => {
185 + const componentInit = async () => {
186 onFocusWithinVisibleChange = jest.fn();
187 ref = React.createRef();
188 innerRef = React.createRef();
189 innerRef2 = React.createRef();
190 - ReactDOM.render(<Component show={true} />, container);
191 - Scheduler.unstable_flushAll();
190 + await act(() => {
191 + ReactDOM.render(<Component show={true} />, container);
192 + });
193 };
194
195 // @gate www
195 - it('is called after "focus" and "blur" on focus target if keyboard was used', () => {
196 - componentInit();
196 + it('is called after "focus" and "blur" on focus target if keyboard was used', async () => {
197 + await componentInit();
198 const target = createEventTarget(ref.current);
199 const containerTarget = createEventTarget(container);
200 // use keyboard first
@@ -207,8 +208,8 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
208 });
209
210 // @gate www
210 - it('is called after "focus" and "blur" on descendants if keyboard was used', () => {
211 - componentInit();
211 + it('is called after "focus" and "blur" on descendants if keyboard was used', async () => {
212 + await componentInit();
213 const innerTarget = createEventTarget(innerRef.current);
214 const containerTarget = createEventTarget(container);
215 // use keyboard first
@@ -222,8 +223,8 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
223 });
224
225 // @gate www
225 - it('is called if non-keyboard event is dispatched on target previously focused with keyboard', () => {
226 - componentInit();
226 + it('is called if non-keyboard event is dispatched on target previously focused with keyboard', async () => {
227 + await componentInit();
228 const node = ref.current;
229 const innerNode1 = innerRef.current;
230 const innerNode2 = innerRef2.current;
@@ -260,8 +261,8 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
261 });
262
263 // @gate www
263 - it('is not called after "focus" and "blur" events without keyboard', () => {
264 - componentInit();
264 + it('is not called after "focus" and "blur" events without keyboard', async () => {
265 + await componentInit();
266 const innerTarget = createEventTarget(innerRef.current);
267 innerTarget.pointerdown();
268 innerTarget.pointerup();
@@ -270,8 +271,8 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
271 });
272
273 // @gate www
273 - it('is only called once when focus moves within and outside the subtree', () => {
274 - componentInit();
274 + it('is only called once when focus moves within and outside the subtree', async () => {
275 + await componentInit();
276 const node = ref.current;
277 const innerNode1 = innerRef.current;
278 const innerNode2 = innerRef2.current;
@@ -338,7 +339,7 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
339 });
340
341 // @gate www
341 - it('is called after a focused element is unmounted', () => {
342 + it('is called after a focused element is unmounted', async () => {
343 const Component = ({show}) => {
344 const focusWithinRef = useFocusWithin(ref, {
345 onBeforeBlurWithin,
@@ -352,8 +353,9 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
353 );
354 };
355
355 - ReactDOM.render(<Component show={true} />, container);
356 - Scheduler.unstable_flushAll();
356 + await act(() => {
357 + ReactDOM.render(<Component show={true} />, container);
358 + });
359
360 const inner = innerRef.current;
361 const target = createEventTarget(inner);
@@ -370,7 +372,7 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
372 });
373
374 // @gate www
373 - it('is called after a nested focused element is unmounted', () => {
375 + it('is called after a nested focused element is unmounted', async () => {
376 const Component = ({show}) => {
377 const focusWithinRef = useFocusWithin(ref, {
378 onBeforeBlurWithin,
@@ -388,8 +390,9 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
390 );
391 };
392
391 - ReactDOM.render(<Component show={true} />, container);
392 - Scheduler.unstable_flushAll();
393 + await act(() => {
394 + ReactDOM.render(<Component show={true} />, container);
395 + });
396
397 const inner = innerRef.current;
398 const target = createEventTarget(inner);
@@ -406,7 +409,7 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
409 });
410
411 // @gate www
409 - it('is called after many elements are unmounted', () => {
412 + it('is called after many elements are unmounted', async () => {
413 const buttonRef = React.createRef();
414 const inputRef = React.createRef();
415
@@ -429,8 +432,9 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
432 );
433 };
434
432 - ReactDOM.render(<Component show={true} />, container);
433 - Scheduler.unstable_flushAll();
435 + await act(() => {
436 + ReactDOM.render(<Component show={true} />, container);
437 + });
438
439 inputRef.current.focus();
440 expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
@@ -441,7 +445,7 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
445 });
446
447 // @gate www
444 - it('is called after a nested focused element is unmounted (with scope query)', () => {
448 + it('is called after a nested focused element is unmounted (with scope query)', async () => {
449 const TestScope = React.unstable_Scope;
450 const testScopeQuery = (type, props) => true;
451 let targetNodes;
@@ -464,15 +468,17 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
468 );
469 };
470
467 - ReactDOM.render(<Component show={true} />, container);
468 - Scheduler.unstable_flushAll();
471 + await act(() => {
472 + ReactDOM.render(<Component show={true} />, container);
473 + });
474
475 const inner = innerRef.current;
476 const target = createEventTarget(inner);
477 target.keydown({key: 'Tab'});
478 target.focus();
474 - ReactDOM.render(<Component show={false} />, container);
475 - Scheduler.unstable_flushAll();
479 + await act(() => {
480 + ReactDOM.render(<Component show={false} />, container);
481 + });
482 expect(targetNodes).toEqual([targetNode]);
483 });
484
@@ -511,7 +517,6 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
517 await act(() => {
518 root.render(<Component />);
519 });
514 - jest.runAllTimers();
520 expect(container2.innerHTML).toBe('<div><input></div>');
521
522 const inner = innerRef.current;
@@ -525,7 +530,6 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
530 await act(() => {
531 root.render(<Component />);
532 });
528 - jest.runAllTimers();
533 expect(container2.innerHTML).toBe(
534 '<div><input style="display: none;">Loading...</div>',
535 );
@@ -570,7 +574,6 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
574 await act(() => {
575 root.render(<Component />);
576 });
573 - jest.runAllTimers();
577
578 expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
579 expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
@@ -579,14 +582,12 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
582 await act(() => {
583 root.render(<Component />);
584 });
582 - jest.runAllTimers();
585 expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
586 expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
587
588 await act(() => {
589 root.render(<Component />);
590 });
589 - jest.runAllTimers();
591 expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
592 expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
593
@@ -595,7 +596,6 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
596 await act(() => {
597 root.render(<Component />);
598 });
598 - jest.runAllTimers();
599 expect(onBeforeBlurWithin).toHaveBeenCalledTimes(1);
600 expect(onAfterBlurWithin).toHaveBeenCalledTimes(1);
601
packages/react-reconciler/src/__tests__/ErrorBoundaryReconciliation-test.internal.js
+19 -16
@@ -5,8 +5,8 @@ describe('ErrorBoundaryReconciliation', () => {
5 let React;
6 let ReactFeatureFlags;
7 let ReactTestRenderer;
8 - let Scheduler;
8 let span;
9 + let act;
10
11 beforeEach(() => {
12 jest.resetModules();
@@ -16,8 +16,7 @@ describe('ErrorBoundaryReconciliation', () => {
16 ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
17 ReactTestRenderer = require('react-test-renderer');
18 React = require('react');
19 - Scheduler = require('scheduler');
20 -
19 + act = require('internal-test-utils').act;
20 DidCatchErrorBoundary = class extends React.Component {
21 state = {error: null};
22 componentDidCatch(error) {
@@ -52,23 +51,27 @@ describe('ErrorBoundaryReconciliation', () => {
51 });
52
53 [true, false].forEach(isConcurrent => {
55 - function sharedTest(ErrorBoundary, fallbackTagName) {
56 - const renderer = ReactTestRenderer.create(
57 - <ErrorBoundary fallbackTagName={fallbackTagName}>
58 - <BrokenRender fail={false} />
59 - </ErrorBoundary>,
60 - {unstable_isConcurrent: isConcurrent},
61 - );
62 - Scheduler.unstable_flushAll();
63 - expect(renderer).toMatchRenderedOutput(<span prop="BrokenRender" />);
54 + async function sharedTest(ErrorBoundary, fallbackTagName) {
55 + let renderer;
56
65 - expect(() => {
66 - renderer.update(
57 + await act(() => {
58 + renderer = ReactTestRenderer.create(
59 <ErrorBoundary fallbackTagName={fallbackTagName}>
68 - <BrokenRender fail={true} />
60 + <BrokenRender fail={false} />
61 </ErrorBoundary>,
62 + {unstable_isConcurrent: isConcurrent},
63 );
71 - Scheduler.unstable_flushAll();
64 + });
65 + expect(renderer).toMatchRenderedOutput(<span prop="BrokenRender" />);
66 +
67 + await expect(async () => {
68 + await act(() => {
69 + renderer.update(
70 + <ErrorBoundary fallbackTagName={fallbackTagName}>
71 + <BrokenRender fail={true} />
72 + </ErrorBoundary>,
73 + );
74 + });
75 }).toErrorDev(isConcurrent ? ['invalid', 'invalid'] : ['invalid']);
76 const Fallback = fallbackTagName;
77 expect(renderer).toMatchRenderedOutput(<Fallback prop="ErrorBoundary" />);
packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js
+52 -36
@@ -16,7 +16,6 @@ describe('ReactSuspenseList', () => {
16 React = require('react');
17 ReactNoop = require('react-noop-renderer');
18 Scheduler = require('scheduler');
19 - act = require('internal-test-utils').act;
19 Profiler = React.Profiler;
20 Suspense = React.Suspense;
21 if (gate(flags => flags.enableSuspenseList)) {
@@ -27,6 +26,7 @@ describe('ReactSuspenseList', () => {
26 waitForAll = InternalTestUtils.waitForAll;
27 assertLog = InternalTestUtils.assertLog;
28 waitFor = InternalTestUtils.waitFor;
29 + act = InternalTestUtils.act;
30 });
31
32 function Text(props) {
@@ -53,7 +53,7 @@ describe('ReactSuspenseList', () => {
53 }
54
55 // @gate enableSuspenseList
56 - it('warns if an unsupported revealOrder option is used', () => {
56 + it('warns if an unsupported revealOrder option is used', async () => {
57 function Foo() {
58 return (
59 <SuspenseList revealOrder="something">
@@ -62,9 +62,11 @@ describe('ReactSuspenseList', () => {
62 );
63 }
64
65 - ReactNoop.render(<Foo />);
66 -
67 - expect(() => Scheduler.unstable_flushAll()).toErrorDev([
65 + await expect(async () => {
66 + await act(() => {
67 + ReactNoop.render(<Foo />);
68 + });
69 + }).toErrorDev([
70 'Warning: "something" is not a supported revealOrder on ' +
71 '<SuspenseList />. Did you mean "together", "forwards" or "backwards"?' +
72 '\n in SuspenseList (at **)' +
@@ -73,7 +75,7 @@ describe('ReactSuspenseList', () => {
75 });
76
77 // @gate enableSuspenseList
76 - it('warns if a upper case revealOrder option is used', () => {
78 + it('warns if a upper case revealOrder option is used', async () => {
79 function Foo() {
80 return (
81 <SuspenseList revealOrder="TOGETHER">
@@ -82,9 +84,11 @@ describe('ReactSuspenseList', () => {
84 );
85 }
86
85 - ReactNoop.render(<Foo />);
86 -
87 - expect(() => Scheduler.unstable_flushAll()).toErrorDev([
87 + await expect(async () => {
88 + await act(() => {
89 + ReactNoop.render(<Foo />);
90 + });
91 + }).toErrorDev([
92 'Warning: "TOGETHER" is not a valid value for revealOrder on ' +
93 '<SuspenseList />. Use lowercase "together" instead.' +
94 '\n in SuspenseList (at **)' +
@@ -93,7 +97,7 @@ describe('ReactSuspenseList', () => {
97 });
98
99 // @gate enableSuspenseList
96 - it('warns if a misspelled revealOrder option is used', () => {
100 + it('warns if a misspelled revealOrder option is used', async () => {
101 function Foo() {
102 return (
103 <SuspenseList revealOrder="forward">
@@ -102,9 +106,11 @@ describe('ReactSuspenseList', () => {
106 );
107 }
108
105 - ReactNoop.render(<Foo />);
106 -
107 - expect(() => Scheduler.unstable_flushAll()).toErrorDev([
109 + await expect(async () => {
110 + await act(() => {
111 + ReactNoop.render(<Foo />);
112 + });
113 + }).toErrorDev([
114 'Warning: "forward" is not a valid value for revealOrder on ' +
115 '<SuspenseList />. React uses the -s suffix in the spelling. ' +
116 'Use "forwards" instead.' +
@@ -131,13 +137,15 @@ describe('ReactSuspenseList', () => {
137 // No warning
138 await waitForAll([]);
139
134 - ReactNoop.render(
135 - <Foo>
136 - <Suspense fallback="Loading">Child</Suspense>
137 - </Foo>,
138 - );
139 -
140 - expect(() => Scheduler.unstable_flushAll()).toErrorDev([
140 + await expect(async () => {
141 + await act(() => {
142 + ReactNoop.render(
143 + <Foo>
144 + <Suspense fallback="Loading">Child</Suspense>
145 + </Foo>,
146 + );
147 + });
148 + }).toErrorDev([
149 'Warning: A single row was passed to a <SuspenseList revealOrder="forwards" />. ' +
150 'This is not useful since it needs multiple rows. ' +
151 'Did you mean to pass multiple children or an array?' +
@@ -147,7 +155,7 @@ describe('ReactSuspenseList', () => {
155 });
156
157 // @gate enableSuspenseList
150 - it('warns if a single fragment is passed to a "backwards" list', () => {
158 + it('warns if a single fragment is passed to a "backwards" list', async () => {
159 function Foo() {
160 return (
161 <SuspenseList revealOrder="backwards">
@@ -156,9 +164,11 @@ describe('ReactSuspenseList', () => {
164 );
165 }
166
159 - ReactNoop.render(<Foo />);
160 -
161 - expect(() => Scheduler.unstable_flushAll()).toErrorDev([
167 + await expect(async () => {
168 + await act(() => {
169 + ReactNoop.render(<Foo />);
170 + });
171 + }).toErrorDev([
172 'Warning: A single row was passed to a <SuspenseList revealOrder="backwards" />. ' +
173 'This is not useful since it needs multiple rows. ' +
174 'Did you mean to pass multiple children or an array?' +
@@ -168,7 +178,7 @@ describe('ReactSuspenseList', () => {
178 });
179
180 // @gate enableSuspenseList
171 - it('warns if a nested array is passed to a "forwards" list', () => {
181 + it('warns if a nested array is passed to a "forwards" list', async () => {
182 function Foo({items}) {
183 return (
184 <SuspenseList revealOrder="forwards">
@@ -182,9 +192,11 @@ describe('ReactSuspenseList', () => {
192 );
193 }
194
185 - ReactNoop.render(<Foo items={['A', 'B']} />);
186 -
187 - expect(() => Scheduler.unstable_flushAll()).toErrorDev([
195 + await expect(async () => {
196 + await act(() => {
197 + ReactNoop.render(<Foo items={['A', 'B']} />);
198 + });
199 + }).toErrorDev([
200 'Warning: A nested array was passed to row #0 in <SuspenseList />. ' +
201 'Wrap it in an additional SuspenseList to configure its revealOrder: ' +
202 '<SuspenseList revealOrder=...> ... ' +
@@ -1471,7 +1483,7 @@ describe('ReactSuspenseList', () => {
1483 });
1484
1485 // @gate enableSuspenseList
1474 - it('warns if an unsupported tail option is used', () => {
1486 + it('warns if an unsupported tail option is used', async () => {
1487 function Foo() {
1488 return (
1489 <SuspenseList revealOrder="forwards" tail="collapse">
@@ -1481,9 +1493,11 @@ describe('ReactSuspenseList', () => {
1493 );
1494 }
1495
1484 - ReactNoop.render(<Foo />);
1485 -
1486 - expect(() => Scheduler.unstable_flushAll()).toErrorDev([
1496 + await expect(async () => {
1497 + await act(() => {
1498 + ReactNoop.render(<Foo />);
1499 + });
1500 + }).toErrorDev([
1501 'Warning: "collapse" is not a supported value for tail on ' +
1502 '<SuspenseList />. Did you mean "collapsed" or "hidden"?' +
1503 '\n in SuspenseList (at **)' +
@@ -1492,7 +1506,7 @@ describe('ReactSuspenseList', () => {
1506 });
1507
1508 // @gate enableSuspenseList
1495 - it('warns if a tail option is used with "together"', () => {
1509 + it('warns if a tail option is used with "together"', async () => {
1510 function Foo() {
1511 return (
1512 <SuspenseList revealOrder="together" tail="collapsed">
@@ -1501,9 +1515,11 @@ describe('ReactSuspenseList', () => {
1515 );
1516 }
1517
1504 - ReactNoop.render(<Foo />);
1505 -
1506 - expect(() => Scheduler.unstable_flushAll()).toErrorDev([
1518 + await expect(async () => {
1519 + await act(() => {
1520 + ReactNoop.render(<Foo />);
1521 + });
1522 + }).toErrorDev([
1523 'Warning: <SuspenseList tail="collapsed" /> is only valid if ' +
1524 'revealOrder is "forwards" or "backwards". ' +
1525 'Did you mean to specify revealOrder="forwards"?' +
packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.js
+7 -10
@@ -13,7 +13,7 @@ let ReactDOM;
13 let React;
14 let ReactCache;
15 let ReactTestRenderer;
16 -let Scheduler;
16 +let waitForAll;
17
18 describe('ReactTestRenderer', () => {
19 beforeEach(() => {
@@ -25,7 +25,8 @@ describe('ReactTestRenderer', () => {
25 React = require('react');
26 ReactCache = require('react-cache');
27 ReactTestRenderer = require('react-test-renderer');
28 - Scheduler = require('scheduler');
28 + const InternalTestUtils = require('internal-test-utils');
29 + waitForAll = InternalTestUtils.waitForAll;
30 });
31
32 it('should warn if used to render a ReactDOM portal', () => {
@@ -85,16 +86,14 @@ describe('ReactTestRenderer', () => {
86
87 const root = ReactTestRenderer.create(<App text="initial" />);
88 PendingResources.initial('initial');
88 - await Promise.resolve();
89 - Scheduler.unstable_flushAll();
89 + await waitForAll([]);
90 expect(root.toJSON()).toEqual('initial');
91
92 root.update(<App text="dynamic" />);
93 expect(root.toJSON()).toEqual('fallback');
94
95 PendingResources.dynamic('dynamic');
96 - await Promise.resolve();
97 - Scheduler.unstable_flushAll();
96 + await waitForAll([]);
97 expect(root.toJSON()).toEqual('dynamic');
98 });
99
@@ -111,16 +110,14 @@ describe('ReactTestRenderer', () => {
110
111 const root = ReactTestRenderer.create(<App text="initial" />);
112 PendingResources.initial('initial');
114 - await Promise.resolve();
115 - Scheduler.unstable_flushAll();
113 + await waitForAll([]);
114 expect(root.toJSON().children).toEqual(['initial']);
115
116 root.update(<App text="dynamic" />);
117 expect(root.toJSON().children).toEqual(['fallback']);
118
119 PendingResources.dynamic('dynamic');
122 - await Promise.resolve();
123 - Scheduler.unstable_flushAll();
120 + await waitForAll([]);
121 expect(root.toJSON().children).toEqual(['dynamic']);
122 });
123 });