@@ -281,17 +281,14 @@ describe('ReactDeferredValue', () => {
await act(async () => {
root.render(
);
- // In the regression, the memoized value was not updated during non-urgent
- // updates, so this would flip the deferred value back to the initial
- // value (1) instead of reusing the current one (2).
- expect(Scheduler).toFlushUntilNextPaint(['Original: 3']);
+ await waitForPaint(['Original: 3']);
expect(root).toMatchRenderedOutput(
,
);
- expect(Scheduler).toFlushUntilNextPaint(['Deferred: 3']);
+ await waitForPaint(['Deferred: 3']);
expect(root).toMatchRenderedOutput(
Original: 3
diff --git a/packages/react-reconciler/src/__tests__/ReactDisableSchedulerTimeoutBasedOnReactExpirationTime-test.internal.js b/packages/react-reconciler/src/__tests__/ReactDisableSchedulerTimeoutBasedOnReactExpirationTime-test.internal.js
index 2d6828eca1dba..3af4d3738c441 100644
--- a/packages/react-reconciler/src/__tests__/ReactDisableSchedulerTimeoutBasedOnReactExpirationTime-test.internal.js
+++ b/packages/react-reconciler/src/__tests__/ReactDisableSchedulerTimeoutBasedOnReactExpirationTime-test.internal.js
@@ -5,6 +5,7 @@ let Scheduler;
let Suspense;
let scheduleCallback;
let NormalPriority;
+let waitForAll;
describe('ReactSuspenseList', () => {
beforeEach(() => {
@@ -20,6 +21,9 @@ describe('ReactSuspenseList', () => {
scheduleCallback = Scheduler.unstable_scheduleCallback;
NormalPriority = Scheduler.unstable_NormalPriority;
+
+ const InternalTestUtils = require('internal-test-utils');
+ waitForAll = InternalTestUtils.waitForAll;
});
function Text(props) {
@@ -61,16 +65,12 @@ describe('ReactSuspenseList', () => {
const root = ReactNoop.createRoot(null);
root.render(
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
React.startTransition(() => {
root.render(
);
});
- expect(Scheduler).toFlushAndYield([
- 'Suspend! [A]',
- 'Suspend! [B]',
- 'Loading...',
- ]);
+ await waitForAll(['Suspend! [A]', 'Suspend! [B]', 'Loading...']);
expect(root).toMatchRenderedOutput(null);
Scheduler.unstable_advanceTime(2000);
@@ -92,7 +92,7 @@ describe('ReactSuspenseList', () => {
// task should not jump the queue ahead of B.
await expect(Scheduler).toFlushAndYieldThrough(['Resolve B']);
- expect(Scheduler).toFlushAndYield(['A', 'B']);
+ await waitForAll(['A', 'B']);
expect(root).toMatchRenderedOutput('AB');
});
});
diff --git a/packages/react-reconciler/src/__tests__/ReactEffectOrdering-test.js b/packages/react-reconciler/src/__tests__/ReactEffectOrdering-test.js
index b8de6c47b9f36..90034cf06e5ef 100644
--- a/packages/react-reconciler/src/__tests__/ReactEffectOrdering-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactEffectOrdering-test.js
@@ -18,8 +18,9 @@ let Scheduler;
let act;
let useEffect;
let useLayoutEffect;
+let assertLog;
-describe('ReactHooksWithNoopRenderer', () => {
+describe('ReactEffectOrdering', () => {
beforeEach(() => {
jest.resetModules();
jest.useFakeTimers();
@@ -30,6 +31,9 @@ describe('ReactHooksWithNoopRenderer', () => {
act = require('jest-react').act;
useEffect = React.useEffect;
useLayoutEffect = React.useLayoutEffect;
+
+ const InternalTestUtils = require('internal-test-utils');
+ assertLog = InternalTestUtils.assertLog;
});
test('layout unmounts on deletion are fired in parent -> child order', async () => {
@@ -56,7 +60,7 @@ describe('ReactHooksWithNoopRenderer', () => {
await act(async () => {
root.render(null);
});
- expect(Scheduler).toHaveYielded(['Unmount parent', 'Unmount child']);
+ assertLog(['Unmount parent', 'Unmount child']);
});
test('passive unmounts on deletion are fired in parent -> child order', async () => {
@@ -83,6 +87,6 @@ describe('ReactHooksWithNoopRenderer', () => {
await act(async () => {
root.render(null);
});
- expect(Scheduler).toHaveYielded(['Unmount parent', 'Unmount child']);
+ assertLog(['Unmount parent', 'Unmount child']);
});
});
diff --git a/packages/react-reconciler/src/__tests__/ReactExpiration-test.js b/packages/react-reconciler/src/__tests__/ReactExpiration-test.js
index fb041f948f15d..2556a16ac3b21 100644
--- a/packages/react-reconciler/src/__tests__/ReactExpiration-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactExpiration-test.js
@@ -18,6 +18,9 @@ let resolveText;
let startTransition;
let useState;
let useEffect;
+let assertLog;
+let waitFor;
+let waitForAll;
describe('ReactExpiration', () => {
beforeEach(() => {
@@ -31,6 +34,11 @@ describe('ReactExpiration', () => {
useState = React.useState;
useEffect = React.useEffect;
+ const InternalTestUtils = require('internal-test-utils');
+ assertLog = InternalTestUtils.assertLog;
+ waitFor = InternalTestUtils.waitFor;
+ waitForAll = InternalTestUtils.waitForAll;
+
const textCache = new Map();
readText = text => {
@@ -136,7 +144,7 @@ describe('ReactExpiration', () => {
expect(ReactNoop).toMatchRenderedOutput(
);
});
- it('two updates of like priority in the same event always flush within the same batch', () => {
+ it('two updates of like priority in the same event always flush within the same batch', async () => {
class TextClass extends React.Component {
componentDidMount() {
Scheduler.unstable_yieldValue(`${this.props.text} [commit]`);
@@ -163,37 +171,32 @@ describe('ReactExpiration', () => {
});
// Advance the timer.
Scheduler.unstable_advanceTime(2000);
- // Partially flush the first update, then interrupt it.
- expect(Scheduler).toFlushAndYieldThrough(['A [render]']);
+ await waitFor(['A [render]']);
interrupt();
- // Don't advance time by enough to expire the first update.
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(ReactNoop).toMatchRenderedOutput(null);
// Schedule another update.
ReactNoop.render(
);
- // Both updates are batched
- expect(Scheduler).toFlushAndYield(['B [render]', 'B [commit]']);
+ await waitForAll(['B [render]', 'B [commit]']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Now do the same thing again, except this time don't flush any work in
// between the two updates.
ReactNoop.render(
);
Scheduler.unstable_advanceTime(2000);
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(ReactNoop).toMatchRenderedOutput(
);
// Schedule another update.
ReactNoop.render(
);
- // The updates should flush in the same batch, since as far as the scheduler
- // knows, they may have occurred inside the same event.
- expect(Scheduler).toFlushAndYield(['B [render]', 'B [commit]']);
+ await waitForAll(['B [render]', 'B [commit]']);
});
it(
'two updates of like priority in the same event always flush within the ' +
"same batch, even if there's a sync update in between",
- () => {
+ async () => {
class TextClass extends React.Component {
componentDidMount() {
Scheduler.unstable_yieldValue(`${this.props.text} [commit]`);
@@ -220,25 +223,22 @@ describe('ReactExpiration', () => {
});
// Advance the timer.
Scheduler.unstable_advanceTime(2000);
- // Partially flush the first update, then interrupt it.
- expect(Scheduler).toFlushAndYieldThrough(['A [render]']);
+ await waitFor(['A [render]']);
interrupt();
- // Don't advance time by enough to expire the first update.
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(ReactNoop).toMatchRenderedOutput(null);
// Schedule another update.
ReactNoop.render(
);
- // Both updates are batched
- expect(Scheduler).toFlushAndYield(['B [render]', 'B [commit]']);
+ await waitForAll(['B [render]', 'B [commit]']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Now do the same thing again, except this time don't flush any work in
// between the two updates.
ReactNoop.render(
);
Scheduler.unstable_advanceTime(2000);
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(ReactNoop).toMatchRenderedOutput(
);
// Perform some synchronous work. The scheduler must assume we're inside
@@ -247,13 +247,11 @@ describe('ReactExpiration', () => {
// Schedule another update.
ReactNoop.render(
);
- // The updates should flush in the same batch, since as far as the scheduler
- // knows, they may have occurred inside the same event.
- expect(Scheduler).toFlushAndYield(['B [render]', 'B [commit]']);
+ await waitForAll(['B [render]', 'B [commit]']);
},
);
- it('cannot update at the same expiration time that is already rendering', () => {
+ it('cannot update at the same expiration time that is already rendering', async () => {
const store = {text: 'initial'};
const subscribers = [];
class Connected extends React.Component {
@@ -292,7 +290,7 @@ describe('ReactExpiration', () => {
React.startTransition(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'initial [A] [render]',
'initial [B] [render]',
'initial [C] [render]',
@@ -307,10 +305,7 @@ describe('ReactExpiration', () => {
React.startTransition(() => {
subscribers.forEach(s => s.setState({text: '1'}));
});
- expect(Scheduler).toFlushAndYieldThrough([
- '1 [A] [render]',
- '1 [B] [render]',
- ]);
+ await waitFor(['1 [A] [render]', '1 [B] [render]']);
// Before the update can finish, update again. Even though no time has
// advanced, this update should be given a different expiration time than
@@ -318,13 +313,10 @@ describe('ReactExpiration', () => {
React.startTransition(() => {
subscribers.forEach(s => s.setState({text: '2'}));
});
- expect(Scheduler).toFlushAndYieldThrough([
- '1 [C] [render]',
- '1 [D] [render]',
- ]);
+ await waitFor(['1 [C] [render]', '1 [D] [render]']);
});
- it('stops yielding if CPU-bound update takes too long to finish', () => {
+ it('stops yielding if CPU-bound update takes too long to finish', async () => {
const root = ReactNoop.createRoot();
function App() {
return (
@@ -342,18 +334,18 @@ describe('ReactExpiration', () => {
root.render(
);
});
- expect(Scheduler).toFlushAndYieldThrough(['A']);
- expect(Scheduler).toFlushAndYieldThrough(['B']);
- expect(Scheduler).toFlushAndYieldThrough(['C']);
+ await waitFor(['A']);
+ await waitFor(['B']);
+ await waitFor(['C']);
Scheduler.unstable_advanceTime(10000);
flushNextRenderIfExpired();
- expect(Scheduler).toHaveYielded(['D', 'E']);
+ assertLog(['D', 'E']);
expect(root).toMatchRenderedOutput('ABCDE');
});
- it('root expiration is measured from the time of the first update', () => {
+ it('root expiration is measured from the time of the first update', async () => {
Scheduler.unstable_advanceTime(10000);
const root = ReactNoop.createRoot();
@@ -372,14 +364,14 @@ describe('ReactExpiration', () => {
root.render(
);
});
- expect(Scheduler).toFlushAndYieldThrough(['A']);
- expect(Scheduler).toFlushAndYieldThrough(['B']);
- expect(Scheduler).toFlushAndYieldThrough(['C']);
+ await waitFor(['A']);
+ await waitFor(['B']);
+ await waitFor(['C']);
Scheduler.unstable_advanceTime(10000);
flushNextRenderIfExpired();
- expect(Scheduler).toHaveYielded(['D', 'E']);
+ assertLog(['D', 'E']);
expect(root).toMatchRenderedOutput('ABCDE');
});
@@ -404,14 +396,14 @@ describe('ReactExpiration', () => {
// The update should not have expired yet.
flushNextRenderIfExpired();
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(ReactNoop).toMatchRenderedOutput(null);
// Advance the time some more to expire the update.
Scheduler.unstable_advanceTime(10000);
flushNextRenderIfExpired();
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(ReactNoop).toMatchRenderedOutput('Hi');
});
@@ -427,14 +419,14 @@ describe('ReactExpiration', () => {
ReactNoop.render('Hi');
});
flushNextRenderIfExpired();
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(ReactNoop).toMatchRenderedOutput(null);
// Advancing by ~5 seconds should be sufficient to expire the update. (I
// used a slightly larger number to allow for possible rounding.)
Scheduler.unstable_advanceTime(6000);
flushNextRenderIfExpired();
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(ReactNoop).toMatchRenderedOutput('Hi');
});
@@ -463,7 +455,7 @@ describe('ReactExpiration', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Sync pri: 0', 'Normal pri: 0']);
+ assertLog(['Sync pri: 0', 'Normal pri: 0']);
expect(root).toMatchRenderedOutput('Sync pri: 0, Normal pri: 0');
// First demonstrate what happens when there's no starvation
@@ -471,18 +463,16 @@ describe('ReactExpiration', () => {
React.startTransition(() => {
updateNormalPri();
});
- expect(Scheduler).toFlushAndYieldThrough(['Sync pri: 0']);
+ await waitFor(['Sync pri: 0']);
updateSyncPri();
- expect(Scheduler).toHaveYielded(['Sync pri: 1', 'Normal pri: 0']);
+ assertLog(['Sync pri: 1', 'Normal pri: 0']);
// The remaining work hasn't expired, so the render phase is time sliced.
// In other words, we can flush just the first child without flushing
// the rest.
Scheduler.unstable_flushNumberOfYields(1);
- // Yield right after first child.
- expect(Scheduler).toHaveYielded(['Sync pri: 1']);
- // Now do the rest.
- expect(Scheduler).toFlushAndYield(['Normal pri: 1']);
+ assertLog(['Sync pri: 1']);
+ await waitForAll(['Normal pri: 1']);
});
expect(root).toMatchRenderedOutput('Sync pri: 1, Normal pri: 1');
@@ -491,7 +481,7 @@ describe('ReactExpiration', () => {
React.startTransition(() => {
updateNormalPri();
});
- expect(Scheduler).toFlushAndYieldThrough(['Sync pri: 1']);
+ await waitFor(['Sync pri: 1']);
// This time, a lot of time has elapsed since the normal pri update
// started rendering. (This should advance time by some number that's
@@ -500,12 +490,12 @@ describe('ReactExpiration', () => {
Scheduler.unstable_advanceTime(10000);
updateSyncPri();
- expect(Scheduler).toHaveYielded(['Sync pri: 2', 'Normal pri: 1']);
+ assertLog(['Sync pri: 2', 'Normal pri: 1']);
// The remaining work _has_ expired, so the render phase is _not_ time
// sliced. Attempting to flush just the first child also flushes the rest.
Scheduler.unstable_flushNumberOfYields(1);
- expect(Scheduler).toHaveYielded(['Sync pri: 2', 'Normal pri: 2']);
+ assertLog(['Sync pri: 2', 'Normal pri: 2']);
});
expect(root).toMatchRenderedOutput('Sync pri: 2, Normal pri: 2');
});
@@ -534,16 +524,16 @@ describe('ReactExpiration', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Sync pri: 0', 'Idle pri: 0']);
+ assertLog(['Sync pri: 0', 'Idle pri: 0']);
expect(root).toMatchRenderedOutput('Sync pri: 0, Idle pri: 0');
// First demonstrate what happens when there's no starvation
await act(async () => {
updateIdlePri();
- expect(Scheduler).toFlushAndYieldThrough(['Sync pri: 0']);
+ await waitFor(['Sync pri: 0']);
updateSyncPri();
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Interrupt idle update to render sync update
'Sync pri: 1',
'Idle pri: 0',
@@ -556,7 +546,7 @@ describe('ReactExpiration', () => {
// Do the same thing, but starve the first update
await act(async () => {
updateIdlePri();
- expect(Scheduler).toFlushAndYieldThrough(['Sync pri: 1']);
+ await waitFor(['Sync pri: 1']);
// Advance a ridiculously large amount of time to demonstrate that the
// idle work never expires
@@ -564,8 +554,7 @@ describe('ReactExpiration', () => {
updateSyncPri();
});
- // Same thing should happen as last time
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Interrupt idle update to render sync update
'Sync pri: 2',
'Idle pri: 1',
@@ -597,14 +586,14 @@ describe('ReactExpiration', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A0', 'B0', 'C']);
+ assertLog(['A0', 'B0', 'C']);
expect(root).toMatchRenderedOutput('A0B0C');
await act(async () => {
startTransition(() => {
setA(1);
});
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
+ await waitFor(['A1']);
startTransition(() => {
setB(1);
});
@@ -614,12 +603,12 @@ describe('ReactExpiration', () => {
// (entangled), we should be able to finish the in-progress transition
// without also including the next one.
Scheduler.unstable_flushNumberOfYields(1);
- expect(Scheduler).toHaveYielded(['B0', 'C']);
+ assertLog(['B0', 'C']);
expect(root).toMatchRenderedOutput('A1B0C');
// The next transition also finishes without yielding.
Scheduler.unstable_flushNumberOfYields(1);
- expect(Scheduler).toHaveYielded(['A1', 'B1', 'C']);
+ assertLog(['A1', 'B1', 'C']);
expect(root).toMatchRenderedOutput('A1B1C');
});
});
@@ -642,28 +631,21 @@ describe('ReactExpiration', () => {
await resolveText('A0');
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A0', 'B', 'C']);
+ assertLog(['A0', 'B', 'C']);
expect(root).toMatchRenderedOutput('A0BC');
await act(async () => {
React.startTransition(() => {
root.render(
);
});
- expect(Scheduler).toFlushAndYield([
- 'Suspend! [A1]',
- 'B',
- 'C',
- 'Loading...',
- ]);
+ await waitForAll(['Suspend! [A1]', 'B', 'C', 'Loading...']);
// Lots of time elapses before the promise resolves
Scheduler.unstable_advanceTime(10000);
await resolveText('A1');
- expect(Scheduler).toHaveYielded(['Promise resolved [A1]']);
+ assertLog(['Promise resolved [A1]']);
- // But the update doesn't expire, because it was IO bound. So we can
- // partially rendering without finishing.
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
+ await waitFor(['A1']);
expect(root).toMatchRenderedOutput('A0BC');
// Lots more time elapses. We're CPU-bound now, so we should treat this
@@ -672,7 +654,7 @@ describe('ReactExpiration', () => {
// The rest of the update finishes without yielding.
Scheduler.unstable_flushNumberOfYields(1);
- expect(Scheduler).toHaveYielded(['B', 'C']);
+ assertLog(['B', 'C']);
});
});
@@ -696,13 +678,13 @@ describe('ReactExpiration', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A0', 'B0']);
+ assertLog(['A0', 'B0']);
await act(async () => {
startTransition(() => {
setA(1);
});
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
+ await waitFor(['A1']);
// Expire the in-progress update
Scheduler.unstable_advanceTime(10000);
@@ -710,12 +692,12 @@ describe('ReactExpiration', () => {
ReactNoop.flushSync(() => {
setB(1);
});
- expect(Scheduler).toHaveYielded(['A0', 'B1']);
+ assertLog(['A0', 'B1']);
// Now flush the original update. Because it expired, it should finish
// without yielding.
Scheduler.unstable_flushNumberOfYields(1);
- expect(Scheduler).toHaveYielded(['A1', 'B1']);
+ assertLog(['A1', 'B1']);
});
});
@@ -737,7 +719,7 @@ describe('ReactExpiration', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A0', 'B0', 'C0', 'Effect: 0']);
+ assertLog(['A0', 'B0', 'C0', 'Effect: 0']);
expect(root).toMatchRenderedOutput('A0B0C0');
await act(async () => {
@@ -749,9 +731,8 @@ describe('ReactExpiration', () => {
// The update finishes without yielding. But it does not flush the effect.
Scheduler.unstable_flushNumberOfYields(1);
- expect(Scheduler).toHaveYielded(['A1', 'B1', 'C1']);
+ assertLog(['A1', 'B1', 'C1']);
});
- // The effect flushes after paint.
- expect(Scheduler).toHaveYielded(['Effect: 1']);
+ assertLog(['Effect: 1']);
});
});
diff --git a/packages/react-reconciler/src/__tests__/ReactFlushSync-test.js b/packages/react-reconciler/src/__tests__/ReactFlushSync-test.js
index 2ec6aa4889420..4e3e948c46268 100644
--- a/packages/react-reconciler/src/__tests__/ReactFlushSync-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactFlushSync-test.js
@@ -5,6 +5,8 @@ let act;
let useState;
let useEffect;
let startTransition;
+let assertLog;
+let waitForPaint;
// TODO: Migrate tests to React DOM instead of React Noop
@@ -19,6 +21,10 @@ describe('ReactFlushSync', () => {
useState = React.useState;
useEffect = React.useEffect;
startTransition = React.startTransition;
+
+ const InternalTestUtils = require('internal-test-utils');
+ assertLog = InternalTestUtils.assertLog;
+ waitForPaint = InternalTestUtils.waitForPaint;
});
function Text({text}) {
@@ -27,6 +33,8 @@ describe('ReactFlushSync', () => {
}
test('changes priority of updates in useEffect', async () => {
+ spyOnDev(console, 'error').mockImplementation(() => {});
+
function App() {
const [syncState, setSyncState] = useState(0);
const [state, setState] = useState(0);
@@ -44,29 +52,33 @@ describe('ReactFlushSync', () => {
React.startTransition(() => {
root.render(
);
});
- // This will yield right before the passive effect fires
- expect(Scheduler).toFlushUntilNextPaint(['0, 0']);
+ await waitForPaint(['0, 0']);
// The passive effect will schedule a sync update and a normal update.
// They should commit in two separate batches. First the sync one.
- expect(() => {
- expect(Scheduler).toFlushUntilNextPaint(
- gate(flags => flags.enableUnifiedSyncLane) ? ['1, 1'] : ['1, 0'],
- );
- }).toErrorDev('flushSync was called from inside a lifecycle method');
+ await waitForPaint(
+ gate(flags => flags.enableUnifiedSyncLane) ? ['1, 1'] : ['1, 0'],
+ );
// The remaining update is not sync
ReactNoop.flushSync();
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
if (gate(flags => flags.enableUnifiedSyncLane)) {
- expect(Scheduler).toFlushUntilNextPaint([]);
+ await waitForPaint([]);
} else {
- // Now flush it.
- expect(Scheduler).toFlushUntilNextPaint(['1, 1']);
+ await waitForPaint(['1, 1']);
}
});
expect(root).toMatchRenderedOutput('1, 1');
+
+ if (__DEV__) {
+ expect(console.error.mock.calls[0][0]).toContain(
+ 'flushSync was called from inside a lifecycle method. React ' +
+ 'cannot flush when React is already rendering. Consider moving this ' +
+ 'call to a scheduler task or micro task.%s',
+ );
+ }
});
test('nested with startTransition', async () => {
@@ -84,7 +96,7 @@ describe('ReactFlushSync', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['0, 0']);
+ assertLog(['0, 0']);
expect(root).toMatchRenderedOutput('0, 0');
await act(async () => {
@@ -100,12 +112,10 @@ describe('ReactFlushSync', () => {
});
});
});
- // Only the sync update should have flushed
- expect(Scheduler).toHaveYielded(['1, 0']);
+ assertLog(['1, 0']);
expect(root).toMatchRenderedOutput('1, 0');
});
- // Now the async update has flushed, too.
- expect(Scheduler).toHaveYielded(['1, 1']);
+ assertLog(['1, 1']);
expect(root).toMatchRenderedOutput('1, 1');
});
@@ -122,7 +132,7 @@ describe('ReactFlushSync', () => {
ReactNoop.flushSync(() => {
root.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Child',
// Because the pending effect was the result of a sync update, calling
// flushSync should flush it.
@@ -145,15 +155,14 @@ describe('ReactFlushSync', () => {
ReactNoop.flushSync(() => {
root.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Child',
// Because we're in legacy mode, we shouldn't have flushed the passive
// effects yet.
]);
expect(root).toMatchRenderedOutput('Child');
});
- // Effect flushes after paint.
- expect(Scheduler).toHaveYielded(['Effect']);
+ assertLog(['Effect']);
});
test('flush pending passive effects before scope is called in legacy mode', async () => {
@@ -172,7 +181,7 @@ describe('ReactFlushSync', () => {
ReactNoop.flushSync(() => {
root.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
1,
// Because we're in legacy mode, we shouldn't have flushed the passive
// effects yet.
@@ -184,10 +193,10 @@ describe('ReactFlushSync', () => {
// fired, before the scope function is called.
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Effect: 1', 2]);
+ assertLog(['Effect: 1', 2]);
expect(root).toMatchRenderedOutput('2');
});
- expect(Scheduler).toHaveYielded(['Effect: 2']);
+ assertLog(['Effect: 2']);
});
test("do not flush passive effects synchronously when they aren't the result of a sync render", async () => {
@@ -201,15 +210,14 @@ describe('ReactFlushSync', () => {
const root = ReactNoop.createRoot();
await act(async () => {
root.render(
);
- expect(Scheduler).toFlushUntilNextPaint([
+ await waitForPaint([
'Child',
// Because the passive effect was not the result of a sync update, it
// should not flush before paint.
]);
expect(root).toMatchRenderedOutput('Child');
});
- // Effect flushes after paint.
- expect(Scheduler).toHaveYielded(['Effect']);
+ assertLog(['Effect']);
});
test('does not flush pending passive effects', async () => {
@@ -223,15 +231,13 @@ describe('ReactFlushSync', () => {
const root = ReactNoop.createRoot();
await act(async () => {
root.render(
);
- expect(Scheduler).toFlushUntilNextPaint(['Child']);
+ await waitForPaint(['Child']);
expect(root).toMatchRenderedOutput('Child');
// Passive effects are pending. Calling flushSync should not affect them.
ReactNoop.flushSync();
- // Effects still haven't fired.
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
});
- // Now the effects have fired.
- expect(Scheduler).toHaveYielded(['Effect']);
+ assertLog(['Effect']);
});
});
diff --git a/packages/react-reconciler/src/__tests__/ReactFragment-test.js b/packages/react-reconciler/src/__tests__/ReactFragment-test.js
index f56602881dfcc..7de3300bf33b7 100644
--- a/packages/react-reconciler/src/__tests__/ReactFragment-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactFragment-test.js
@@ -12,6 +12,7 @@
let React;
let ReactNoop;
let Scheduler;
+let waitForAll;
describe('ReactFragment', () => {
beforeEach(function () {
@@ -20,9 +21,12 @@ describe('ReactFragment', () => {
React = require('react');
ReactNoop = require('react-noop-renderer');
Scheduler = require('scheduler');
+
+ const InternalTestUtils = require('internal-test-utils');
+ waitForAll = InternalTestUtils.waitForAll;
});
- it('should render a single child via noop renderer', () => {
+ it('should render a single child via noop renderer', async () => {
const element = (
<>
foo
@@ -30,21 +34,21 @@ describe('ReactFragment', () => {
);
ReactNoop.render(element);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(
foo);
});
- it('should render zero children via noop renderer', () => {
+ it('should render zero children via noop renderer', async () => {
const element =
;
ReactNoop.render(element);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(null);
});
- it('should render multiple children via noop renderer', () => {
+ it('should render multiple children via noop renderer', async () => {
const element = (
<>
hello
world
@@ -52,7 +56,7 @@ describe('ReactFragment', () => {
);
ReactNoop.render(element);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -61,13 +65,13 @@ describe('ReactFragment', () => {
);
});
- it('should render an iterable via noop renderer', () => {
+ it('should render an iterable via noop renderer', async () => {
const element = (
<>{new Set([
hi,
bye])}>
);
ReactNoop.render(element);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -77,7 +81,7 @@ describe('ReactFragment', () => {
);
});
- it('should preserve state of children with 1 level nesting', function () {
+ it('should preserve state of children with 1 level nesting', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -102,10 +106,10 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
@@ -116,13 +120,13 @@ describe('ReactFragment', () => {
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful', 'Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should preserve state between top-level fragments', function () {
+ it('should preserve state between top-level fragments', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -148,22 +152,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful', 'Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should preserve state of children nested at same level', function () {
+ it('should preserve state of children nested at same level', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -198,10 +202,10 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
@@ -212,13 +216,13 @@ describe('ReactFragment', () => {
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful', 'Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should not preserve state in non-top-level fragment nesting', function () {
+ it('should not preserve state in non-top-level fragment nesting', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -246,22 +250,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should not preserve state of children if nested 2 levels without siblings', function () {
+ it('should not preserve state of children if nested 2 levels without siblings', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -287,22 +291,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should not preserve state of children if nested 2 levels with siblings', function () {
+ it('should not preserve state of children if nested 2 levels with siblings', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -329,10 +333,10 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
@@ -343,13 +347,13 @@ describe('ReactFragment', () => {
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should preserve state between array nested in fragment and fragment', function () {
+ it('should preserve state between array nested in fragment and fragment', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -373,22 +377,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful', 'Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should preserve state between top level fragment and array', function () {
+ it('should preserve state between top level fragment and array', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -412,22 +416,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful', 'Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should not preserve state between array nested in fragment and double nested fragment', function () {
+ it('should not preserve state between array nested in fragment and double nested fragment', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -453,22 +457,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should not preserve state between array nested in fragment and double nested array', function () {
+ it('should not preserve state between array nested in fragment and double nested array', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -490,22 +494,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should preserve state between double nested fragment and double nested array', function () {
+ it('should preserve state between double nested fragment and double nested array', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -531,22 +535,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful', 'Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should not preserve state of children when the keys are different', function () {
+ it('should not preserve state of children when the keys are different', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -573,10 +577,10 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
@@ -587,13 +591,13 @@ describe('ReactFragment', () => {
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should not preserve state between unkeyed and keyed fragment', function () {
+ it('should not preserve state between unkeyed and keyed fragment', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -619,22 +623,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should preserve state with reordering in multiple levels', function () {
+ it('should preserve state with reordering in multiple levels', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -672,10 +676,10 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
@@ -689,7 +693,7 @@ describe('ReactFragment', () => {
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful', 'Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
@@ -703,7 +707,7 @@ describe('ReactFragment', () => {
);
});
- it('should not preserve state when switching to a keyed fragment to an array', function () {
+ it('should not preserve state when switching to a keyed fragment to an array', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -735,7 +739,7 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
@@ -751,7 +755,7 @@ describe('ReactFragment', () => {
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
@@ -762,7 +766,7 @@ describe('ReactFragment', () => {
);
});
- it('should not preserve state when switching a nested unkeyed fragment to a passthrough component', function () {
+ it('should not preserve state when switching a nested unkeyed fragment to a passthrough component', async function () {
const ops = [];
function Passthrough({children}) {
@@ -796,22 +800,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should not preserve state when switching a nested keyed fragment to a passthrough component', function () {
+ it('should not preserve state when switching a nested keyed fragment to a passthrough component', async function () {
const ops = [];
function Passthrough({children}) {
@@ -845,22 +849,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should not preserve state when switching a nested keyed array to a passthrough component', function () {
+ it('should not preserve state when switching a nested keyed array to a passthrough component', async function () {
const ops = [];
function Passthrough({children}) {
@@ -890,22 +894,22 @@ describe('ReactFragment', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
expect(ReactNoop).toMatchRenderedOutput(
Hello
);
});
- it('should preserve state when it does not change positions', function () {
+ it('should preserve state when it does not change positions', async function () {
const ops = [];
class Stateful extends React.Component {
@@ -940,8 +944,7 @@ describe('ReactFragment', () => {
);
ReactNoop.render(
);
- // The key warning gets deduped because it's in the same component.
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
@@ -952,8 +955,7 @@ describe('ReactFragment', () => {
);
ReactNoop.render(
);
- // The key warning gets deduped because it's in the same component.
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual(['Update Stateful', 'Update Stateful']);
expect(ReactNoop).toMatchRenderedOutput(
diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
index 31326a338e840..3a268504136df 100644
--- a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
@@ -280,13 +280,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Render empty shell.
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Foo']);
+ await waitForAll(['Foo']);
// The update will suspend.
React.startTransition(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Foo',
'Bar',
// A suspends
@@ -299,8 +299,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Resolve the data
await resolveText('A');
- // Renders successfully
- expect(Scheduler).toFlushAndYield(['Foo', 'Bar', 'A', 'B']);
+ await waitForAll(['Foo', 'Bar', 'A', 'B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -322,7 +321,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend! [A]',
'Loading A...',
'Suspend! [B]',
@@ -339,7 +338,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// normal view. The second Suspense should still show the placeholder.
await resolveText('A');
- expect(Scheduler).toFlushAndYield(['A']);
+ await waitForAll(['A']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -351,7 +350,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// normal view.
await resolveText('B');
- expect(Scheduler).toFlushAndYield(['B']);
+ await waitForAll(['B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -364,7 +363,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
it('continues rendering siblings after suspending', async () => {
// A shell is needed. The update cause it to suspend.
ReactNoop.render(
} />);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
// B suspends. Continue rendering the remaining siblings.
React.startTransition(() => {
ReactNoop.render(
@@ -376,21 +375,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
);
});
- // B suspends. Continue rendering the remaining siblings.
- expect(Scheduler).toFlushAndYield([
- 'A',
- 'Suspend! [B]',
- 'C',
- 'D',
- 'Loading...',
- ]);
+ await waitForAll(['A', 'Suspend! [B]', 'C', 'D', 'Loading...']);
// Did not commit yet.
expect(ReactNoop).toMatchRenderedOutput(null);
// Wait for data to resolve
await resolveText('B');
- // Renders successfully
- expect(Scheduler).toFlushAndYield(['A', 'B', 'C', 'D']);
+ await waitForAll(['A', 'B', 'C', 'D']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -436,18 +427,18 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(null);
React.startTransition(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYield(['Suspend! [Result]', 'Loading...']);
+ await waitForAll(['Suspend! [Result]', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput(null);
await rejectText('Result', new Error('Failed to load: Result'));
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Error! [Result]',
// React retries one more time
@@ -494,12 +485,12 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Suspend! [Result]', 'Loading...']);
+ await waitForAll(['Suspend! [Result]', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput(
);
await rejectText('Result', new Error('Failed to load: Result'));
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Error! [Result]',
// React retries one more time
@@ -526,9 +517,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial mount
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['A', 'Suspend! [1]', 'Loading...']);
+ await waitForAll(['A', 'Suspend! [1]', 'Loading...']);
await resolveText('1');
- expect(Scheduler).toFlushAndYield(['A', '1']);
+ await waitForAll(['A', '1']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -538,7 +529,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Update the low-pri text
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'A',
// Suspends
'Suspend! [2]',
@@ -583,13 +574,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(null);
React.startTransition(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
+ await waitForAll(['Suspend! [A]', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput(null);
// Advance React's virtual time by enough to fall into a new async bucket,
@@ -598,11 +589,11 @@ describe('ReactSuspenseWithNoopRenderer', () => {
React.startTransition(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'B', 'Loading...']);
+ await waitForAll(['Suspend! [A]', 'B', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput(null);
await resolveText('A');
- expect(Scheduler).toFlushAndYield(['A', 'B']);
+ await waitForAll(['A', 'B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -632,7 +623,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// The first update suspends
'Suspend! [Async]',
// but we have another pending update that we can work on
@@ -675,7 +666,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
root.render(
);
});
await advanceTimers(1000);
- expect(Scheduler).toHaveYielded(['Sibling', 'Step 0']);
+ assertLog(['Sibling', 'Step 0']);
// Schedule an update at several distinct expiration times
await act(async () => {
@@ -683,27 +674,27 @@ describe('ReactSuspenseWithNoopRenderer', () => {
root.render(
);
});
Scheduler.unstable_advanceTime(1000);
- expect(Scheduler).toFlushAndYieldThrough(['Sibling']);
+ await waitFor(['Sibling']);
interrupt();
React.startTransition(() => {
root.render(
);
});
Scheduler.unstable_advanceTime(1000);
- expect(Scheduler).toFlushAndYieldThrough(['Sibling']);
+ await waitFor(['Sibling']);
interrupt();
React.startTransition(() => {
root.render(
);
});
Scheduler.unstable_advanceTime(1000);
- expect(Scheduler).toFlushAndYieldThrough(['Sibling']);
+ await waitFor(['Sibling']);
interrupt();
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Sibling', 'Step 4']);
+ assertLog(['Sibling', 'Step 4']);
});
// @gate enableLegacyCache
@@ -713,7 +704,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
} />
,
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
ReactNoop.render(
@@ -724,7 +715,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// The async child suspends
'Suspend! [Async]',
// Render the placeholder
@@ -739,9 +730,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// the update.
ReactNoop.expire(10000);
await advanceTimers(10000);
- // No additional rendering work is required, since we already prepared
- // the placeholder.
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
// Should have committed the placeholder.
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -752,7 +741,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Once the promise resolves, we render the suspended view
await resolveText('Async');
- expect(Scheduler).toFlushAndYield(['Async']);
+ await waitForAll(['Async']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -778,7 +767,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Sync',
// The async content suspends
'Suspend! [Outer content]',
@@ -796,7 +785,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Resolve the outer promise.
await resolveText('Outer content');
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Outer content',
'Suspend! [Inner content]',
'Loading inner...',
@@ -824,7 +813,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Finally, flush the inner promise. We should see the complete screen.
await resolveText('Inner content');
- expect(Scheduler).toFlushAndYield(['Inner content']);
+ await waitForAll(['Inner content']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -848,7 +837,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
),
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
// The async child suspends
'Suspend! [Async]',
// We immediately render the fallback UI
@@ -866,7 +855,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Once the promise resolves, we render the suspended view
await resolveText('Async');
- expect(Scheduler).toFlushAndYield(['Async']);
+ await waitForAll(['Async']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -889,7 +878,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
),
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend! [Async]',
'Suspend! [Loading (inner)...]',
'Sync',
@@ -906,7 +895,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
} />
,
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
ReactNoop.render(
@@ -917,7 +906,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// The async child suspends
'Suspend! [Async]',
'Loading...',
@@ -932,7 +921,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// expiration time.
ReactNoop.expire(2000);
await advanceTimers(2000);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -942,7 +931,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Once the promise resolves, we render the suspended view
await resolveText('Async');
- expect(Scheduler).toFlushAndYield(['Async']);
+ await waitForAll(['Async']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -958,7 +947,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
} />
,
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
React.startTransition(() => {
ReactNoop.render(
@@ -971,7 +960,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
);
});
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// The async child suspends
'Suspend! [Async]',
'Loading...',
@@ -987,13 +976,12 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await advanceTimers(2000);
expect(ReactNoop).toMatchRenderedOutput(null);
- // Even flushing won't yield a fallback in a transition.
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(null);
// Once the promise resolves, we render the suspended view
await resolveText('Async');
- expect(Scheduler).toFlushAndYield(['Async', 'Sync']);
+ await waitForAll(['Async', 'Sync']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -1010,7 +998,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
} />
>,
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
expect(root).toMatchRenderedOutput(null);
React.startTransition(() => {
root.render(
@@ -1022,13 +1010,11 @@ describe('ReactSuspenseWithNoopRenderer', () => {
>,
);
});
- expect(Scheduler).toFlushAndYieldThrough(['Suspend! [Async]', 'Sibling']);
+ await waitFor(['Suspend! [Async]', 'Sibling']);
await resolveText('Async');
- // Because we're already showing a fallback, interrupt the current render
- // and restart immediately.
- expect(Scheduler).toFlushAndYield(['Async', 'Sibling']);
+ await waitForAll(['Async', 'Sibling']);
expect(root).toMatchRenderedOutput(
<>
@@ -1063,17 +1049,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
);
- expect(Scheduler).toFlushAndYield([
- 'Suspend! [A]',
- 'Suspend! [B]',
- 'Loading...',
- ]);
+ await waitForAll(['Suspend! [A]', 'Suspend! [B]', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput(
);
await resolveText('A');
await resolveText('B');
- expect(Scheduler).toFlushAndYield(['A', 'B']);
+ await waitForAll(['A', 'B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -1085,7 +1067,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// @gate enableLegacyCache
it('can resume rendering earlier than a timeout', async () => {
ReactNoop.render(
} />);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
React.startTransition(() => {
ReactNoop.render(
@@ -1094,13 +1076,12 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
);
});
- expect(Scheduler).toFlushAndYield(['Suspend! [Async]', 'Loading...']);
+ await waitForAll(['Suspend! [Async]', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput(null);
// Resolve the promise
await resolveText('Async');
- // We can now resume rendering
- expect(Scheduler).toFlushAndYield(['Async']);
+ await waitForAll(['Async']);
expect(ReactNoop).toMatchRenderedOutput(
);
});
@@ -1121,37 +1102,34 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// First mount without suspending. This ensures we already have content
// showing so that subsequent updates will suspend.
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['S']);
+ await waitForAll(['S']);
// Schedule an update, and suspend for up to 5 seconds.
React.startTransition(() => ReactNoop.render(
));
- // The update should suspend.
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
+ await waitForAll(['Suspend! [A]', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Advance time until right before it expires.
await advanceTimers(4999);
ReactNoop.expire(4999);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(
);
// Schedule another low priority update.
React.startTransition(() => ReactNoop.render(
));
- // This update should also suspend.
- expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
+ await waitForAll(['Suspend! [B]', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Schedule a regular update. Its expiration time will fall between
// the expiration times of the previous two updates.
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['C']);
+ await waitForAll(['C']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Flush the remaining work.
await resolveText('A');
await resolveText('B');
- // Nothing else to render.
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(
);
});
@@ -1188,17 +1166,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
jest.advanceTimersByTime(1000);
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
- 'Suspend! [goodbye]',
- 'Loading...',
- 'Commit: goodbye',
- ]);
+ await waitForAll(['Suspend! [goodbye]', 'Loading...', 'Commit: goodbye']);
expect(ReactNoop).toMatchRenderedOutput(
);
await resolveText('goodbye');
expect(ReactNoop).toMatchRenderedOutput(
);
- expect(Scheduler).toFlushAndYield(['goodbye']);
+ await waitForAll(['goodbye']);
expect(ReactNoop).toMatchRenderedOutput(
);
});
@@ -1223,18 +1197,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
- 'Suspend! [A]',
- 'Suspend! [B]',
- 'Suspend! [C]',
- ]);
+ await waitForAll(['Suspend! [A]', 'Suspend! [B]', 'Suspend! [C]']);
expect(ReactNoop).toMatchRenderedOutput('Loading...');
await resolveText('A');
await resolveText('B');
await resolveText('C');
- expect(Scheduler).toFlushAndYield(['A', 'B', 'C']);
+ await waitForAll(['A', 'B', 'C']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -1257,14 +1227,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Times out immediately, ignoring the specified threshold.
ReactNoop.renderLegacySyncRoot(
);
- expect(Scheduler).toHaveYielded(['Suspend! [Result]', 'Loading...']);
+ assertLog(['Suspend! [Result]', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput(
);
await act(async () => {
resolveText('Result');
});
- expect(Scheduler).toHaveYielded(['Result']);
+ assertLog(['Result']);
expect(ReactNoop).toMatchRenderedOutput(
);
});
@@ -1300,7 +1270,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial mount.
await seedNextTextCache('Step: 1');
ReactNoop.renderLegacySyncRoot(
);
- expect(Scheduler).toHaveYielded(['Step: 1', 'Sibling']);
+ assertLog(['Step: 1', 'Sibling']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -1333,7 +1303,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
resolveText('Step: 2');
});
- expect(Scheduler).toHaveYielded(['Step: 2']);
+ assertLog(['Step: 2']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -1381,7 +1351,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
ReactNoop.renderLegacySyncRoot(
, () =>
Scheduler.unstable_yieldValue('Commit root'),
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'A',
'Suspend! [B]',
'C',
@@ -1407,7 +1377,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
resolveText('B');
});
- expect(Scheduler).toHaveYielded(['B']);
+ assertLog(['B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -1442,22 +1412,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
);
- expect(Scheduler).toHaveYielded([
- 'constructor',
- 'Suspend! [Hi]',
- 'Loading...',
- ]);
+ assertLog(['constructor', 'Suspend! [Hi]', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput(
);
await act(async () => {
resolveText('Hi');
});
- expect(Scheduler).toHaveYielded([
- 'constructor',
- 'Hi',
- 'componentDidMount',
- ]);
+ assertLog(['constructor', 'Hi', 'componentDidMount']);
expect(ReactNoop).toMatchRenderedOutput(
);
});
@@ -1489,7 +1451,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
ReactNoop.renderLegacySyncRoot(
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend! [Hi]',
'Loading...',
// Re-render due to lifecycle update
@@ -1499,7 +1461,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
resolveText('Hi');
});
- expect(Scheduler).toHaveYielded(['Hi']);
+ assertLog(['Hi']);
expect(ReactNoop).toMatchRenderedOutput(
);
});
@@ -1532,7 +1494,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
ReactNoop.renderLegacySyncRoot(
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend! [Hi]',
'Loading...',
// The child should have already been hidden
@@ -1545,7 +1507,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
resolveText('Hi');
});
- expect(Scheduler).toHaveYielded(['Hi']);
+ assertLog(['Hi']);
});
} else {
// @gate enableLegacyCache
@@ -1578,7 +1540,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
ReactNoop.renderLegacySyncRoot(
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend! [Hi]',
'Loading...',
// The child should have already been hidden
@@ -1589,7 +1551,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
resolveText('Hi');
});
- expect(Scheduler).toHaveYielded(['Hi']);
+ assertLog(['Hi']);
});
}
@@ -1622,7 +1584,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
);
- expect(Scheduler).toHaveYielded(['Suspend! [Async]']);
+ assertLog(['Suspend! [Async]']);
expect(ReactNoop).toMatchRenderedOutput(
'Caught an error: Error in host config.',
);
@@ -1661,7 +1623,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Mount']);
+ assertLog(['Mount']);
expect(root).toMatchRenderedOutput('Child');
// Suspend the child. This puts it into an inconsistent state.
@@ -1674,7 +1636,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(null);
});
- expect(Scheduler).toHaveYielded(['Unmount']);
+ assertLog(['Unmount']);
});
});
@@ -1726,7 +1688,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
ReactNoop.renderLegacySyncRoot(
, () =>
Scheduler.unstable_yieldValue('Commit root'),
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'A',
'Suspend! [B]',
'C',
@@ -1802,7 +1764,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
ReactNoop.renderLegacySyncRoot(
, () =>
Scheduler.unstable_yieldValue('Commit root'),
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'A',
'Suspend! [B]',
'C',
@@ -1816,8 +1778,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
'Commit root',
]);
- // Flush passive effects.
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Effect [A]',
// B's effect should not fire because it suspended
// 'Effect [B]',
@@ -1837,7 +1798,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
resolveText('B');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'B',
'Destroy Layout Effect [Loading...]',
'Layout Effect [B]',
@@ -1850,7 +1811,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
Scheduler.unstable_yieldValue('Commit root'),
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'A',
'Suspend! [B2]',
'C',
@@ -1862,8 +1823,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
'Commit root',
]);
- // Flush passive effects.
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// B2's effect should not fire because it suspended
// 'Effect [B2]',
'Effect [Loading...]',
@@ -1873,7 +1833,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
resolveText('B2');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'B2',
'Destroy Layout Effect [Loading...]',
'Destroy Layout Effect [B]',
@@ -1896,19 +1856,18 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Foo']);
+ await waitForAll(['Foo']);
React.startTransition(() => {
ReactNoop.render(
);
});
Scheduler.unstable_advanceTime(100);
await advanceTimers(100);
- // Start rendering
- expect(Scheduler).toFlushAndYieldThrough(['Foo']);
+ await waitFor(['Foo']);
// For some reason it took a long time to render Foo.
Scheduler.unstable_advanceTime(1250);
await advanceTimers(1250);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// A suspends
'Suspend! [A]',
'Loading...',
@@ -1919,24 +1878,19 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Flush some of the time
Scheduler.unstable_advanceTime(450);
await advanceTimers(450);
- // Because we've already been waiting for so long we can
- // wait a bit longer. Still nothing...
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(null);
// Eventually we'll show the fallback.
Scheduler.unstable_advanceTime(500);
await advanceTimers(500);
- // No need to rerender.
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
// Since this is a transition, we never fallback.
expect(ReactNoop).toMatchRenderedOutput(null);
// Flush the promise completely
await resolveText('A');
- // Renders successfully
- // TODO: Why does this render Foo
- expect(Scheduler).toFlushAndYield(['Foo', 'A']);
+ await waitForAll(['Foo', 'A']);
expect(ReactNoop).toMatchRenderedOutput(
);
});
@@ -1955,8 +1909,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- // Start rendering
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Foo',
// A suspends
'Suspend! [A]',
@@ -1972,8 +1925,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
Scheduler.unstable_advanceTime(5000);
await advanceTimers(5000);
- // Retry with the new content.
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'A',
// B still suspends
'Suspend! [B]',
@@ -1991,8 +1943,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Flush the last promise completely
await resolveText('B');
- // Renders successfully
- expect(Scheduler).toFlushAndYield(['B']);
+ await waitForAll(['B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2016,8 +1967,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- // Start rendering
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Foo',
// A suspends
'Suspend! [A]',
@@ -2030,8 +1980,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await resolveText('A');
- // Retry with the new content.
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'A',
// B still suspends
'Suspend! [B]',
@@ -2046,8 +1995,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Before we commit another Promise resolves.
// We're still showing the first loading state.
expect(ReactNoop).toMatchRenderedOutput(
);
- // Restart and render the complete content.
- expect(Scheduler).toFlushAndYield(['A', 'B']);
+ await waitForAll(['A', 'B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2068,18 +2016,18 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Foo']);
+ await waitForAll(['Foo']);
React.startTransition(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYieldThrough(['Foo']);
+ await waitFor(['Foo']);
// Advance some time.
Scheduler.unstable_advanceTime(100);
await advanceTimers(100);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// A suspends
'Suspend! [A]',
'Loading...',
@@ -2092,11 +2040,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
Scheduler.unstable_advanceTime(500);
jest.advanceTimersByTime(500);
- // We should have already shown the fallback.
- // When we wrote this test, we inferred the start time of high priority
- // updates as way earlier in the past. This test ensures that we don't
- // use this assumption to add a very long JND.
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
// Transitions never fallback.
expect(ReactNoop).toMatchRenderedOutput(null);
});
@@ -2173,14 +2117,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded(['Suspend! [A]']);
+ assertLog(['Suspend! [A]']);
expect(ReactNoop).toMatchRenderedOutput('Loading...');
act(() => {
ReactNoop.flushSync(() => showB());
});
- expect(Scheduler).toHaveYielded(['Suspend! [A]', 'Suspend! [B]']);
+ assertLog(['Suspend! [A]', 'Suspend! [B]']);
});
// TODO: flip to "warns" when this is implemented again.
@@ -2236,7 +2180,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// also make sure lowpriority is okay
await act(async () => show(true));
- expect(Scheduler).toHaveYielded(['Suspend! [A]']);
+ assertLog(['Suspend! [A]']);
await resolveText('A');
expect(ReactNoop).toMatchRenderedOutput('Loading...');
@@ -2262,7 +2206,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// also make sure lowpriority is okay
await act(async () => _setShow(true));
- expect(Scheduler).toHaveYielded(['Suspend! [A]']);
+ assertLog(['Suspend! [A]']);
await resolveText('A');
expect(ReactNoop).toMatchRenderedOutput('Loading...');
@@ -2286,17 +2230,12 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
- 'Foo',
- 'Suspend! [A]',
- 'B',
- 'Initial load...',
- ]);
+ await waitForAll(['Foo', 'Suspend! [A]', 'B', 'Initial load...']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Eventually we resolve and show the data.
await resolveText('A');
- expect(Scheduler).toFlushAndYield(['A', 'B']);
+ await waitForAll(['A', 'B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2306,13 +2245,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Update to show C
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
- 'Foo',
- 'A',
- 'Suspend! [C]',
- 'Updating...',
- 'B',
- ]);
+ await waitForAll(['Foo', 'A', 'Suspend! [C]', 'Updating...', 'B']);
// Flush to skip suspended time.
Scheduler.unstable_advanceTime(600);
await advanceTimers(600);
@@ -2328,7 +2261,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Later we load the data.
await resolveText('C');
- expect(Scheduler).toFlushAndYield(['A', 'C']);
+ await waitForAll(['A', 'C']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2354,7 +2287,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Foo',
'Suspend! [A]',
'B',
@@ -2364,7 +2297,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Eventually we resolve and show the data.
await resolveText('A');
- expect(Scheduler).toFlushAndYield(['A']);
+ await waitForAll(['A']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2374,7 +2307,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Update to show C
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Foo',
'A',
'Suspend! [C]',
@@ -2393,7 +2326,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Later we load the data.
await resolveText('C');
- expect(Scheduler).toFlushAndYield(['A', 'C']);
+ await waitForAll(['A', 'C']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2422,12 +2355,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
- 'Foo',
- 'A',
- 'Suspend! [B]',
- 'Loading B...',
- ]);
+ await waitForAll(['Foo', 'A', 'Suspend! [B]', 'Loading B...']);
// Flush to skip suspended time.
Scheduler.unstable_advanceTime(600);
await advanceTimers(600);
@@ -2463,19 +2391,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Foo', 'A']);
+ await waitForAll(['Foo', 'A']);
expect(ReactNoop).toMatchRenderedOutput(
);
React.startTransition(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYield([
- 'Foo',
- 'A',
- 'Suspend! [B]',
- 'Loading B...',
- ]);
+ await waitForAll(['Foo', 'A', 'Suspend! [B]', 'Loading B...']);
// Still suspended.
expect(ReactNoop).toMatchRenderedOutput(
);
@@ -2506,14 +2429,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Foo', 'A']);
+ await waitForAll(['Foo', 'A']);
expect(ReactNoop).toMatchRenderedOutput(
);
React.startTransition(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Foo',
'A',
'Suspend! [B]',
@@ -2543,7 +2466,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
ReactNoop.render(
);
@@ -2552,14 +2475,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
Scheduler.unstable_advanceTime(1500);
await advanceTimers(1500);
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading A...']);
+ await waitForAll(['Suspend! [A]', 'Loading A...']);
// We're still suspended.
expect(ReactNoop).toMatchRenderedOutput(null);
// Schedule an update at idle pri.
ReactNoop.idleUpdates(() => ReactNoop.render(
));
- // We won't even work on Idle priority.
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
// We're still suspended.
expect(ReactNoop).toMatchRenderedOutput(null);
@@ -2592,7 +2514,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial render.
React.startTransition(() => ReactNoop.render(
));
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
+ await waitForAll(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state.
Scheduler.unstable_advanceTime(400);
await advanceTimers(400);
@@ -2600,13 +2522,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Later we load the data.
await resolveText('A');
- expect(Scheduler).toFlushAndYield(['A']);
+ await waitForAll(['A']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Start transition.
React.startTransition(() => ReactNoop.render(
));
- expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
+ await waitForAll(['Suspend! [B]', 'Loading...']);
Scheduler.unstable_advanceTime(100000);
await advanceTimers(100000);
// Even after lots of time has passed, we have still not yet flushed the
@@ -2614,7 +2536,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(ReactNoop).toMatchRenderedOutput(
);
// Later we load the data.
await resolveText('B');
- expect(Scheduler).toFlushAndYield(['B']);
+ await waitForAll(['B']);
expect(ReactNoop).toMatchRenderedOutput(
);
});
@@ -2635,13 +2557,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
// Initial render.
await act(async () => {
React.startTransition(() => transitionToPage('A'));
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
+ await waitForAll(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state.
Scheduler.unstable_advanceTime(400);
await advanceTimers(400);
@@ -2650,14 +2572,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Later we load the data.
await resolveText('A');
- expect(Scheduler).toFlushAndYield(['A']);
+ await waitForAll(['A']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Start transition.
await act(async () => {
React.startTransition(() => transitionToPage('B'));
- expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
+ await waitForAll(['Suspend! [B]', 'Loading...']);
Scheduler.unstable_advanceTime(100000);
await advanceTimers(100000);
// Even after lots of time has passed, we have still not yet flushed the
@@ -2666,7 +2588,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
});
// Later we load the data.
await resolveText('B');
- expect(Scheduler).toFlushAndYield(['B']);
+ await waitForAll(['B']);
expect(ReactNoop).toMatchRenderedOutput(
);
});
@@ -2690,13 +2612,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
// Initial render.
await act(async () => {
React.startTransition(() => transitionToPage('A'));
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
+ await waitForAll(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state.
Scheduler.unstable_advanceTime(400);
await advanceTimers(400);
@@ -2705,14 +2627,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Later we load the data.
await resolveText('A');
- expect(Scheduler).toFlushAndYield(['A']);
+ await waitForAll(['A']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Start transition.
await act(async () => {
React.startTransition(() => transitionToPage('B'));
- expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
+ await waitForAll(['Suspend! [B]', 'Loading...']);
Scheduler.unstable_advanceTime(100000);
await advanceTimers(100000);
// Even after lots of time has passed, we have still not yet flushed the
@@ -2721,7 +2643,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
});
// Later we load the data.
await resolveText('B');
- expect(Scheduler).toFlushAndYield(['B']);
+ await waitForAll(['B']);
expect(ReactNoop).toMatchRenderedOutput(
);
});
});
@@ -2740,7 +2662,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial render.
React.startTransition(() => ReactNoop.render(
));
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
+ await waitForAll(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state.
Scheduler.unstable_advanceTime(400);
await advanceTimers(400);
@@ -2748,13 +2670,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Later we load the data.
await resolveText('A');
- expect(Scheduler).toFlushAndYield(['A']);
+ await waitForAll(['A']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Start transition.
React.startTransition(() => ReactNoop.render(
));
- expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
+ await waitForAll(['Suspend! [B]', 'Loading...']);
Scheduler.unstable_advanceTime(2999);
await advanceTimers(2999);
// Since the timeout is infinite (or effectively infinite),
@@ -2763,12 +2685,12 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Later we load the data.
await resolveText('B');
- expect(Scheduler).toFlushAndYield(['B']);
+ await waitForAll(['B']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Start a long (infinite) transition.
React.startTransition(() => ReactNoop.render(
));
- expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']);
+ await waitForAll(['Suspend! [C]', 'Loading...']);
// Even after lots of time has passed, we have still not yet flushed the
// loading state.
@@ -2794,13 +2716,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
// Initial render.
await act(async () => {
React.startTransition(() => transitionToPage('A'));
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
+ await waitForAll(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state.
Scheduler.unstable_advanceTime(400);
await advanceTimers(400);
@@ -2809,14 +2731,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Later we load the data.
await resolveText('A');
- expect(Scheduler).toFlushAndYield(['A']);
+ await waitForAll(['A']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Start transition.
await act(async () => {
React.startTransition(() => transitionToPage('B'));
- expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
+ await waitForAll(['Suspend! [B]', 'Loading...']);
Scheduler.unstable_advanceTime(2999);
await advanceTimers(2999);
@@ -2827,14 +2749,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Later we load the data.
await resolveText('B');
- expect(Scheduler).toFlushAndYield(['B']);
+ await waitForAll(['B']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Start a long (infinite) transition.
await act(async () => {
React.startTransition(() => transitionToPage('C'));
- expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']);
+ await waitForAll(['Suspend! [C]', 'Loading...']);
// Even after lots of time has passed, we have still not yet flushed the
// loading state.
@@ -2864,13 +2786,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
// Initial render.
await act(async () => {
React.startTransition(() => transitionToPage('A'));
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
+ await waitForAll(['Suspend! [A]', 'Loading...']);
// Only a short time is needed to unsuspend the initial loading state.
Scheduler.unstable_advanceTime(400);
await advanceTimers(400);
@@ -2879,14 +2801,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Later we load the data.
await resolveText('A');
- expect(Scheduler).toFlushAndYield(['A']);
+ await waitForAll(['A']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Start transition.
await act(async () => {
React.startTransition(() => transitionToPage('B'));
- expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
+ await waitForAll(['Suspend! [B]', 'Loading...']);
Scheduler.unstable_advanceTime(2999);
await advanceTimers(2999);
// Since the timeout is infinite (or effectively infinite),
@@ -2896,14 +2818,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Later we load the data.
await resolveText('B');
- expect(Scheduler).toFlushAndYield(['B']);
+ await waitForAll(['B']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Start a long (infinite) transition.
await act(async () => {
React.startTransition(() => transitionToPage('C'));
- expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']);
+ await waitForAll(['Suspend! [C]', 'Loading...']);
// Even after lots of time has passed, we have still not yet flushed the
// loading state.
@@ -2931,9 +2853,9 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial render.
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Hi!', 'Suspend! [A]', 'Loading...']);
+ await waitForAll(['Hi!', 'Suspend! [A]', 'Loading...']);
await resolveText('A');
- expect(Scheduler).toFlushAndYield(['Hi!', 'A']);
+ await waitForAll(['Hi!', 'A']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2944,7 +2866,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Start transition.
React.startTransition(() => ReactNoop.render(
));
- expect(Scheduler).toFlushAndYield(['Hi!', 'Suspend! [B]', 'Loading B...']);
+ await waitForAll(['Hi!', 'Suspend! [B]', 'Loading B...']);
// Suspended
expect(ReactNoop).toMatchRenderedOutput(
@@ -2955,7 +2877,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
);
Scheduler.unstable_advanceTime(1800);
await advanceTimers(1800);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
// We should still be suspended here because this loading state should be avoided.
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2964,7 +2886,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
>,
);
await resolveText('B');
- expect(Scheduler).toFlushAndYield(['Hi!', 'B']);
+ await waitForAll(['Hi!', 'B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2994,7 +2916,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial render.
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Hi!', 'A']);
+ await waitForAll(['Hi!', 'A']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -3005,7 +2927,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Start transition.
React.startTransition(() => ReactNoop.render(
));
- expect(Scheduler).toFlushAndYield(['Hi!', 'Suspend! [B]', 'Loading B...']);
+ await waitForAll(['Hi!', 'Suspend! [B]', 'Loading B...']);
// Suspended
expect(ReactNoop).toMatchRenderedOutput(
@@ -3016,7 +2938,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
);
Scheduler.unstable_advanceTime(1800);
await advanceTimers(1800);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
// We should still be suspended here because this loading state should be avoided.
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -3025,7 +2947,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
>,
);
await resolveText('B');
- expect(Scheduler).toFlushAndYield(['Hi!', 'B']);
+ await waitForAll(['Hi!', 'B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -3051,13 +2973,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Suspend! [Initial]']);
+ assertLog(['Suspend! [Initial]']);
// Resolve initial render
await act(async () => {
await resolveText('Initial');
});
- expect(Scheduler).toHaveYielded(['Initial']);
+ assertLog(['Initial']);
expect(root).toMatchRenderedOutput(
);
await act(async () => {
@@ -3066,7 +2988,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
React.startTransition(() => {
root.render(
);
});
- expect(Scheduler).toFlushAndYield(['Suspend! [First update]']);
+ await waitForAll(['Suspend! [First update]']);
// Should not display a fallback
expect(root).toMatchRenderedOutput(
);
@@ -3075,7 +2997,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
React.startTransition(() => {
root.render(
);
});
- expect(Scheduler).toFlushAndYield(['Suspend! [Second update]']);
+ await waitForAll(['Suspend! [Second update]']);
// Should not display a fallback
expect(root).toMatchRenderedOutput(
);
@@ -3113,22 +3035,19 @@ describe('ReactSuspenseWithNoopRenderer', () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Foo']);
+ assertLog(['Foo']);
await act(async () => {
foo.setState({suspend: true});
- // In the regression that this covers, we would neglect to reset the
- // current debug phase after suspending (in the catch block), so React
- // thinks we're still inside the render phase.
- expect(Scheduler).toFlushAndYieldThrough(['Suspend!']);
+ await waitFor(['Suspend!']);
// Then when this setState happens, React would incorrectly fire a warning
// about updates that happen the render phase (only fired by classes).
foo.setState({suspend: false});
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// First setState
'Foo',
]);
@@ -3159,7 +3078,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial render.
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYieldThrough(['Commit']);
+ await waitFor(['Commit']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Start transition.
@@ -3167,16 +3086,16 @@ describe('ReactSuspenseWithNoopRenderer', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
+ await waitForAll(['Suspend! [A]', 'Loading...']);
await resolveText('A');
- expect(Scheduler).toFlushAndYieldThrough(['A', 'Commit']);
+ await waitFor(['A', 'Commit']);
expect(ReactNoop).toMatchRenderedOutput(
<>
>,
);
- expect(Scheduler).toFlushAndYield(['Offscreen']);
+ await waitForAll(['Offscreen']);
expect(ReactNoop).toMatchRenderedOutput(
<>
Offscreen
@@ -3208,27 +3127,26 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Initial render.
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYieldThrough(['Commit']);
+ await waitFor(['Commit']);
expect(ReactNoop).toMatchRenderedOutput(
);
- // Partially render through the hidden content.
- expect(Scheduler).toFlushAndYieldThrough(['Suspend! [A]']);
+ await waitFor(['Suspend! [A]']);
// Start transition.
React.startTransition(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
+ await waitForAll(['Suspend! [A]', 'Loading...']);
await resolveText('A');
- expect(Scheduler).toFlushAndYieldThrough(['A', 'Commit']);
+ await waitFor(['A', 'Commit']);
expect(ReactNoop).toMatchRenderedOutput(
<>
>,
);
- expect(Scheduler).toFlushAndYield(['A', 'Offscreen']);
+ await waitForAll(['A', 'Offscreen']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -3269,7 +3187,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A']);
+ assertLog(['A']);
expect(root).toMatchRenderedOutput(
);
await act(async () => {
@@ -3283,7 +3201,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await resolveText('C');
setText('C');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// First we attempt the high pri update. It suspends.
'Suspend! [B]',
'Loading...',
@@ -3323,7 +3241,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A']);
+ assertLog(['A']);
expect(root).toMatchRenderedOutput(
);
await act(async () => {
@@ -3337,7 +3255,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
setText('C');
});
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// First we attempt the high pri update. It suspends.
'Suspend! [B]',
'Loading...',
@@ -3352,8 +3270,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
>,
);
- // Now flush the remaining work. The Idle update successfully finishes.
- expect(Scheduler).toFlushAndYield(['C']);
+ await waitForAll(['C']);
expect(root).toMatchRenderedOutput(
);
});
},
@@ -3392,13 +3309,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A']);
+ assertLog(['A']);
expect(root).toMatchRenderedOutput(
);
await act(async () => {
// Schedule an update inside the Suspense boundary that suspends.
setAppText('B');
- expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
+ await waitForAll(['Suspend! [B]', 'Loading...']);
});
expect(root).toMatchRenderedOutput(
@@ -3418,7 +3335,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
});
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// First try to render the high pri update. Still suspended.
'Suspend! [C]',
'Loading...',
@@ -3477,7 +3394,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A']);
+ assertLog(['A']);
// At this point, the setState return path follows current fiber.
expect(root).toMatchRenderedOutput(
);
@@ -3486,7 +3403,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
setText('B');
});
- expect(Scheduler).toHaveYielded(['B']);
+ assertLog(['B']);
// Now the setState return path follows the *alternate* fiber.
expect(root).toMatchRenderedOutput(
);
@@ -3494,7 +3411,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
setText('C');
});
- expect(Scheduler).toHaveYielded(['Suspend! [C]', 'Loading...']);
+ assertLog(['Suspend! [C]', 'Loading...']);
// Commit. This will insert a fragment fiber to wrap around the component
// that triggered the update.
@@ -3516,9 +3433,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
setText('D');
});
- // Even though the fragment fiber is not part of the return path, we should
- // be able to finish rendering.
- expect(Scheduler).toHaveYielded(['D']);
+ assertLog(['D']);
expect(root).toMatchRenderedOutput(
);
},
);
@@ -3554,7 +3469,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A']);
+ assertLog(['A']);
// At this point, the setState return path follows current fiber.
expect(root).toMatchRenderedOutput(
);
@@ -3563,7 +3478,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
setText('B');
});
- expect(Scheduler).toHaveYielded(['B']);
+ assertLog(['B']);
// Now the setState return path follows the *alternate* fiber.
expect(root).toMatchRenderedOutput(
);
@@ -3571,7 +3486,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
setText('C');
});
- expect(Scheduler).toHaveYielded(['Suspend! [C]', 'Loading...']);
+ assertLog(['Suspend! [C]', 'Loading...']);
// Commit. This will insert a fragment fiber to wrap around the component
// that triggered the update.
@@ -3598,9 +3513,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
setText('E');
});
});
- // Even though the fragment fiber is not part of the return path, we should
- // be able to finish rendering.
- expect(Scheduler).toHaveYielded(['Suspend! [D]', 'E']);
+ assertLog(['Suspend! [D]', 'E']);
expect(root).toMatchRenderedOutput(
);
},
);
@@ -3663,7 +3576,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Outer text: A',
'Outer step: 0',
'Inner text: A',
@@ -3683,7 +3596,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
setText('B');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Outer text: B',
'Outer step: 0',
'Suspend! [Inner text: B]',
@@ -3709,10 +3622,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
});
});
- // Only the outer part can update. The inner part should still show a
- // fallback because we haven't finished loading B yet. Otherwise, the
- // inner text would be inconsistent with the outer text.
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Outer text: B',
'Outer step: 1',
'Suspend! [Inner text: B]',
@@ -3733,11 +3643,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
await resolveText('Inner text: B');
});
- expect(Scheduler).toHaveYielded([
- 'Inner text: B',
- 'Inner step: 1',
- 'Commit Child',
- ]);
+ assertLog(['Inner text: B', 'Inner step: 1', 'Commit Child']);
expect(root).toMatchRenderedOutput(
<>
@@ -3802,7 +3708,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Outer: A0', 'Inner: A0', 'Commit Child']);
+ assertLog(['Outer: A0', 'Inner: A0', 'Commit Child']);
expect(root).toMatchRenderedOutput(
<>
@@ -3814,11 +3720,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
setText('B');
});
- expect(Scheduler).toHaveYielded([
- 'Outer: B0',
- 'Suspend! [Inner: B0]',
- 'Loading...',
- ]);
+ assertLog(['Outer: B0', 'Suspend! [Inner: B0]', 'Loading...']);
// Commit the placeholder
await advanceTimers(250);
expect(root).toMatchRenderedOutput(
@@ -3837,7 +3739,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
});
});
- expect(Scheduler).toHaveYielded(['Outer: B1', 'Inner: B1', 'Commit Child']);
+ assertLog(['Outer: B1', 'Inner: B1', 'Commit Child']);
expect(root).toMatchRenderedOutput(
<>
@@ -3895,20 +3797,15 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['']);
+ assertLog(['']);
expect(root).toMatchRenderedOutput(
);
// Update to "a". That will suspend.
await act(async () => {
setTextWithShortTransition('a');
- expect(Scheduler).toFlushAndYield([
- 'Pending...',
- '',
- 'Suspend! [a]',
- 'Loading...',
- ]);
+ await waitForAll(['Pending...', '', 'Suspend! [a]', 'Loading...']);
});
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(root).toMatchRenderedOutput(
<>
@@ -3919,7 +3816,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Update to "b". That will suspend, too.
await act(async () => {
setTextWithLongTransition('b');
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// Neither is resolved yet.
'Pending...',
'',
@@ -3927,7 +3824,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
'Loading...',
]);
});
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(root).toMatchRenderedOutput(
<>
@@ -3939,7 +3836,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
await resolveText('a');
- expect(Scheduler).toFlushAndYield(['Suspend! [b]', 'Loading...']);
+ await waitForAll(['Suspend! [b]', 'Loading...']);
expect(root).toMatchRenderedOutput(
<>
@@ -3951,7 +3848,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
await resolveText('b');
});
- expect(Scheduler).toHaveYielded(['b']);
+ assertLog(['b']);
// The bug was that the pending state got stuck forever.
expect(root).toMatchRenderedOutput(
);
});
@@ -3977,7 +3874,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
,
);
});
- expect(Scheduler).toHaveYielded(['A']);
+ assertLog(['A']);
expect(root).toMatchRenderedOutput(
);
await act(async () => {
@@ -3985,22 +3882,19 @@ describe('ReactSuspenseWithNoopRenderer', () => {
ReactNoop.idleUpdates(() => {
setText('B');
});
- // Suspend the first update. The second update doesn't run because it has
- // Idle priority.
- expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
+ await waitForAll(['Suspend! [B]', 'Loading...']);
// Commit the fallback. Now we'll try working on Idle.
jest.runAllTimers();
- // It also suspends.
- expect(Scheduler).toFlushAndYield(['Suspend! [B]']);
+ await waitForAll(['Suspend! [B]']);
});
await act(async () => {
setText('B');
await resolveText('B');
});
- expect(Scheduler).toHaveYielded(['B']);
+ assertLog(['B']);
expect(root).toMatchRenderedOutput(
);
});
@@ -4026,7 +3920,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
>,
);
});
- expect(Scheduler).toHaveYielded(['A', 'Suspend! [Async]', 'Loading...']);
+ assertLog(['A', 'Suspend! [Async]', 'Loading...']);
expect(root).toMatchRenderedOutput(
<>
@@ -4040,8 +3934,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
// Before the retry happens, schedule a new update.
setText('B');
- // The update should be allowed to finish before the retry is attempted.
- expect(Scheduler).toFlushUntilNextPaint(['B']);
+ await waitForPaint(['B']);
expect(root).toMatchRenderedOutput(
<>
@@ -4049,8 +3942,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
>,
);
});
- // Then do the retry.
- expect(Scheduler).toHaveYielded(['Async']);
+ assertLog(['Async']);
expect(root).toMatchRenderedOutput(
<>
@@ -4087,13 +3979,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Mount Child']);
+ assertLog(['Mount Child']);
expect(root).toMatchRenderedOutput(
);
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Suspend! [Async]', 'Loading...']);
+ assertLog(['Suspend! [Async]', 'Loading...']);
expect(root).toMatchRenderedOutput(
<>
@@ -4104,7 +3996,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(null);
});
- expect(Scheduler).toHaveYielded(['Unmount Child']);
+ assertLog(['Unmount Child']);
});
// @gate enableLegacyCache
@@ -4135,13 +4027,13 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Mount Child']);
+ assertLog(['Mount Child']);
expect(root).toMatchRenderedOutput(
);
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Suspend! [Async]', 'Loading...']);
+ assertLog(['Suspend! [Async]', 'Loading...']);
expect(root).toMatchRenderedOutput(
<>
@@ -4152,7 +4044,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(null);
});
- expect(Scheduler).toHaveYielded(['Unmount Child']);
+ assertLog(['Unmount Child']);
});
// @gate enableLegacyCache
@@ -4202,7 +4094,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(root).toMatchRenderedOutput(
);
// Update. This will cause two separate trees to suspend. The first tree
@@ -4221,7 +4113,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Suspend! [Async]', 'Loading...', 'Hi']);
+ assertLog(['Suspend! [Async]', 'Loading...', 'Hi']);
expect(root).toMatchRenderedOutput(