655
});
656
});
657
658
- it('does not throw out partially completed tree if it expires midway through', () => {
659
- function Text({text}) {
660
- Scheduler.unstable_yieldValue(text);
661
- return text;
662
- }
663
-
664
- function App({step}) {
665
- return (
666
- <>
667
- <Text text={`A${step}`} />
668
- <Text text={`B${step}`} />
669
- <Text text={`C${step}`} />
670
- </>
671
- );
672
- }
673
-
674
- function interrupt() {
675
- ReactNoop.flushSync(() => {
676
- ReactNoop.renderToRootWithID(null, 'other-root');
677
- });
678
- }
679
-
680
- // First, as a sanity check, assert what happens when four low pri
681
- // updates in separate batches are all flushed in the same callback
682
- ReactNoop.act(() => {
683
- ReactNoop.render(<App step={1} />);
684
- Scheduler.unstable_advanceTime(1000);
685
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
686
-
687
- interrupt();
688
-
689
- ReactNoop.render(<App step={2} />);
690
- Scheduler.unstable_advanceTime(1000);
691
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
692
-
693
- interrupt();
694
-
695
- ReactNoop.render(<App step={3} />);
696
- Scheduler.unstable_advanceTime(1000);
697
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
698
-
699
- interrupt();
700
-
701
- ReactNoop.render(<App step={4} />);
702
- Scheduler.unstable_advanceTime(1000);
703
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
704
-
705
- // Each update flushes in a separate commit.
706
- // Note: This isn't necessarily the ideal behavior. It might be better to
707
- // batch all of these updates together. The fact that they don't is an
708
- // implementation detail. The important part of this unit test is what
709
- // happens when they expire, in which case they really should be batched to
710
- // avoid blocking the main thread for a long time.
711
- expect(Scheduler).toFlushAndYield([
712
- // A1 already completed. Finish rendering the first level.
713
- 'B1',
714
- 'C1',
715
- // The remaining two levels complete sequentially.
716
- 'A2',
717
- 'B2',
718
- 'C2',
719
- 'A3',
720
- 'B3',
721
- 'C3',
722
- 'A4',
723
- 'B4',
724
- 'C4',
725
- ]);
726
- });
727
-
728
- ReactNoop.act(() => {
729
- // Now do the same thing over again, but this time, expire all the updates
730
- // instead of flushing them normally.
731
- ReactNoop.render(<App step={1} />);
732
- Scheduler.unstable_advanceTime(1000);
733
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
734
-
735
- interrupt();
736
-
737
- ReactNoop.render(<App step={2} />);
738
- Scheduler.unstable_advanceTime(1000);
739
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
740
-
741
- interrupt();
742
-
743
- ReactNoop.render(<App step={3} />);
744
- Scheduler.unstable_advanceTime(1000);
745
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
746
-
747
- interrupt();
748
-
749
- ReactNoop.render(<App step={4} />);
750
- Scheduler.unstable_advanceTime(1000);
751
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
752
-
753
- // Expire all the updates
754
- ReactNoop.expire(10000);
755
-
756
- expect(Scheduler).toHaveYielded([
757
- // A1 already completed. Finish rendering the first level.
758
- 'B1',
759
- 'C1',
760
- // Then render the remaining two levels in a single batch
761
- 'A4',
762
- 'B4',
763
- 'C4',
764
- ]);
765
- });
766
- });
767
-
658
it('when rebasing, does not exclude updates that were already committed, regardless of priority', async () => {
659
const {useState, useLayoutEffect} = React;
660