@samitouri / QOS-React-2 / commits / fc90eb6368

Codemod more tests to waitFor pattern (#26494)

Andrew Clark committed Mar 28, 2023 at 00:03 UTC fc90eb636876d54d99ace2773dd4923f3e848106
2 files changed +78 -46
packages/react-dom/src/__tests__/ReactUpdates-test.js
+7 -12
@@ -1627,7 +1627,6 @@ describe('ReactUpdates', () => {
1627 const [step, setStep] = React.useState(0);
1628 React.useEffect(() => {
1629 setStep(x => x + 1);
1630 - Scheduler.log(step);
1630 });
1631 return step;
1632 }
@@ -1642,23 +1641,19 @@ describe('ReactUpdates', () => {
1641 console.error = (e, s) => {
1642 error = e;
1643 stack = s;
1644 + Scheduler.log('stop');
1645 };
1646 try {
1647 const container = document.createElement('div');
1648 - expect(() => {
1649 - const root = ReactDOMClient.createRoot(container);
1650 - root.render(<App />);
1651 - while (error === null) {
1652 - Scheduler.unstable_flushNumberOfYields(1);
1653 - Scheduler.unstable_clearLog();
1654 - }
1655 - expect(stack).toContain(' NonTerminating');
1656 - // rethrow error to prevent going into an infinite loop when act() exits
1657 - throw error;
1658 - }).toThrow('Maximum update depth exceeded.');
1648 + const root = ReactDOMClient.createRoot(container);
1649 + root.render(<App />);
1650 + await waitFor(['stop']);
1651 } finally {
1652 console.error = originalConsoleError;
1653 }
1654 +
1655 + expect(error).toContain('Maximum update depth exceeded');
1656 + expect(stack).toContain('at NonTerminating');
1657 });
1658
1659 it('can have nested updates if they do not cross the limit', async () => {
packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js
+71 -34
@@ -36,13 +36,9 @@ describe('ReactIncrementalUpdates', () => {
36 assertLog = InternalTestUtils.assertLog;
37 });
38
39 - function flushNextRenderIfExpired() {
40 - // This will start rendering the next level of work. If the work hasn't
41 - // expired yet, React will exit without doing anything. If it has expired,
42 - // it will schedule a sync task.
43 - Scheduler.unstable_flushExpired();
44 - // Flush the sync task.
45 - ReactNoop.flushSync();
39 + function Text({text}) {
40 + Scheduler.log(text);
41 + return text;
42 }
43
44 it('applies updates in order of priority', async () => {
@@ -528,35 +524,38 @@ describe('ReactIncrementalUpdates', () => {
524 setCount = _setCount;
525 Scheduler.log('Render: ' + count);
526 useLayoutEffect(() => {
531 - setCount(prevCount => prevCount + 1);
527 + setCount(1);
528 Scheduler.log('Commit: ' + count);
529 }, []);
534 - return null;
530 + return <Text text="Child" />;
531 }
532
533 await act(async () => {
534 React.startTransition(() => {
535 ReactNoop.render(<App />);
536 });
541 - flushNextRenderIfExpired();
537 assertLog([]);
543 - await waitForAll(['Render: 0', 'Commit: 0', 'Render: 1']);
538 + await waitForAll([
539 + 'Render: 0',
540 + 'Child',
541 + 'Commit: 0',
542 + 'Render: 1',
543 + 'Child',
544 + ]);
545
546 Scheduler.unstable_advanceTime(10000);
547 React.startTransition(() => {
548 setCount(2);
549 });
549 - flushNextRenderIfExpired();
550 - assertLog([]);
550 + // The transition should not have expired, so we should be able to
551 + // partially render it.
552 + await waitFor(['Render: 2']);
553 + // Now do the rest
554 + await waitForAll(['Child']);
555 });
556 });
557
554 - it('regression: does not expire soon due to previous flushSync', () => {
555 - function Text({text}) {
556 - Scheduler.log(text);
557 - return text;
558 - }
559 -
558 + it('regression: does not expire soon due to previous flushSync', async () => {
559 ReactNoop.flushSync(() => {
560 ReactNoop.render(<Text text="A" />);
561 });
@@ -565,32 +564,70 @@ describe('ReactIncrementalUpdates', () => {
564 Scheduler.unstable_advanceTime(10000);
565
566 React.startTransition(() => {
568 - ReactNoop.render(<Text text="B" />);
567 + ReactNoop.render(
568 + <>
569 + <Text text="A" />
570 + <Text text="B" />
571 + <Text text="C" />
572 + <Text text="D" />
573 + </>,
574 + );
575 + });
576 + // The transition should not have expired, so we should be able to
577 + // partially render it.
578 + await waitFor(['A']);
579 +
580 + // FIXME: We should be able to partially render B, too, but currently it
581 + // expires. This is an existing bug that I discovered, which will be fixed
582 + // in a PR that I'm currently working on.
583 + //
584 + // Correct behavior:
585 + // await waitFor(['B']);
586 + // await waitForAll(['C', 'D']);
587 + //
588 + // Current behavior:
589 + await waitFor(['B'], {
590 + additionalLogsAfterAttemptingToYield: ['C', 'D'],
591 });
570 - flushNextRenderIfExpired();
571 - assertLog([]);
592 });
593
574 - it('regression: does not expire soon due to previous expired work', () => {
575 - function Text({text}) {
576 - Scheduler.log(text);
577 - return text;
578 - }
579 -
594 + it('regression: does not expire soon due to previous expired work', async () => {
595 React.startTransition(() => {
581 - ReactNoop.render(<Text text="A" />);
596 + ReactNoop.render(
597 + <>
598 + <Text text="A" />
599 + <Text text="B" />
600 + <Text text="C" />
601 + <Text text="D" />
602 + </>,
603 + );
604 });
605 + await waitFor(['A']);
606 +
607 + // This will expire the rest of the update
608 Scheduler.unstable_advanceTime(10000);
584 - flushNextRenderIfExpired();
585 - assertLog(['A']);
609 + await waitFor(['B'], {
610 + additionalLogsAfterAttemptingToYield: ['C', 'D'],
611 + });
612
613 Scheduler.unstable_advanceTime(10000);
614
615 + // Now do another transition. This one should not expire.
616 React.startTransition(() => {
590 - ReactNoop.render(<Text text="B" />);
617 + ReactNoop.render(
618 + <>
619 + <Text text="A" />
620 + <Text text="B" />
621 + <Text text="C" />
622 + <Text text="D" />
623 + </>,
624 + );
625 });
592 - flushNextRenderIfExpired();
593 - assertLog([]);
626 + // The transition should not have expired, so we should be able to
627 + // partially render it.
628 + await waitFor(['A']);
629 + await waitFor(['B']);
630 + await waitForAll(['C', 'D']);
631 });
632
633 it('when rebasing, does not exclude updates that were already committed, regardless of priority', async () => {