@@ -2316,7 +2277,7 @@ describe('ReactSuspenseList', () => {
// Update the row adjacent to the list
act(() => updateAdjacent('C'));
- expect(Scheduler).toHaveYielded(['C']);
+ assertLog(['C']);
expect(ReactNoop).toMatchRenderedOutput(
@@ -2359,7 +2320,7 @@ describe('ReactSuspenseList', () => {
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['A', 'Sync B']);
+ await waitForAll(['A', 'Sync B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2373,7 +2334,7 @@ describe('ReactSuspenseList', () => {
// During an update we suspend on B.
act(() => setAsyncB(true));
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend! [B]',
'Loading B',
// The second pass is the "force hide" pass
@@ -2391,7 +2352,7 @@ describe('ReactSuspenseList', () => {
// This should leave the tree intact.
act(() => ReactNoop.render(
));
- expect(Scheduler).toHaveYielded(['A', 'Suspend! [B]', 'Loading B']);
+ assertLog(['A', 'Suspend! [B]', 'Loading B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2402,7 +2363,7 @@ describe('ReactSuspenseList', () => {
await AsyncB.resolve();
- expect(Scheduler).toFlushAndYield(['B']);
+ await waitForAll(['B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2448,7 +2409,7 @@ describe('ReactSuspenseList', () => {
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['A', 'Sync B']);
+ await waitForAll(['A', 'Sync B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2462,7 +2423,7 @@ describe('ReactSuspenseList', () => {
// During an update we suspend on B.
act(() => setAsyncB(true));
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend! [B]',
'Loading B',
// The second pass is the "force hide" pass
@@ -2480,7 +2441,7 @@ describe('ReactSuspenseList', () => {
// This should leave the tree intact.
act(() => ReactNoop.render(
));
- expect(Scheduler).toHaveYielded(['A', 'Suspend! [B]', 'Loading B']);
+ assertLog(['A', 'Suspend! [B]', 'Loading B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2491,7 +2452,7 @@ describe('ReactSuspenseList', () => {
await AsyncB.resolve();
- expect(Scheduler).toFlushAndYield(['B']);
+ await waitForAll(['B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2535,7 +2496,7 @@ describe('ReactSuspenseList', () => {
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(null);
@@ -2544,13 +2505,13 @@ describe('ReactSuspenseList', () => {
updateLowPri(true);
});
// Flush partially through.
- expect(Scheduler).toFlushAndYieldThrough(['B', 'C']);
+ await waitFor(['B', 'C']);
// Schedule another update at higher priority.
ReactNoop.flushSync(() => updateHighPri(true));
// That will intercept the previous render.
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend! [A]',
'Loading A',
// Re-render at forced.
@@ -2560,13 +2521,13 @@ describe('ReactSuspenseList', () => {
expect(ReactNoop).toMatchRenderedOutput(
Loading A);
// Try again on low-pri.
- expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading A']);
+ await waitForAll(['Suspend! [A]', 'Loading A']);
expect(ReactNoop).toMatchRenderedOutput(
Loading A);
});
await AsyncA.resolve();
- expect(Scheduler).toFlushAndYield(['A', 'B', 'C', 'D']);
+ await waitForAll(['A', 'B', 'C', 'D']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2612,7 +2573,7 @@ describe('ReactSuspenseList', () => {
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'A',
'Suspend! [B]',
'Loading B',
@@ -2631,7 +2592,7 @@ describe('ReactSuspenseList', () => {
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['A', 'B']);
+ await waitForAll(['A', 'B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2681,15 +2642,10 @@ describe('ReactSuspenseList', () => {
React.startTransition(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYieldThrough([
- 'App',
- 'First Pass A',
- 'Mount A',
- 'A',
- ]);
+ await waitFor(['App', 'First Pass A', 'Mount A', 'A']);
expect(ReactNoop).toMatchRenderedOutput(
A);
- expect(Scheduler).toFlushAndYieldThrough(['First Pass B', 'Mount B', 'B']);
+ await waitFor(['First Pass B', 'Mount B', 'B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
A
@@ -2697,7 +2653,7 @@ describe('ReactSuspenseList', () => {
>,
);
- expect(Scheduler).toFlushAndYield(['C']);
+ await waitForAll(['C']);
expect(ReactNoop).toMatchRenderedOutput(
<>
A
@@ -2749,7 +2705,7 @@ describe('ReactSuspenseList', () => {
React.startTransition(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toFlushAndYieldThrough([
+ await waitFor([
'App',
'First Pass A',
'Loading B',
@@ -2765,7 +2721,7 @@ describe('ReactSuspenseList', () => {
>,
);
- expect(Scheduler).toFlushAndYieldThrough(['First Pass B', 'Mount B', 'B']);
+ await waitFor(['First Pass B', 'Mount B', 'B']);
expect(ReactNoop).toMatchRenderedOutput(
<>
A
@@ -2774,7 +2730,7 @@ describe('ReactSuspenseList', () => {
>,
);
- expect(Scheduler).toFlushAndYield(['C']);
+ await waitForAll(['C']);
expect(ReactNoop).toMatchRenderedOutput(
<>
A
@@ -2840,13 +2796,7 @@ describe('ReactSuspenseList', () => {
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
- 'App',
- 'A',
- 'B',
- 'Suspend! [C]',
- 'Fallback',
- ]);
+ await waitForAll(['App', 'A', 'B', 'Suspend! [C]', 'Fallback']);
expect(ReactNoop).toMatchRenderedOutput(
<>
A
@@ -2868,7 +2818,7 @@ describe('ReactSuspenseList', () => {
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['App', 'A', 'B', 'C']);
+ await waitForAll(['App', 'A', 'B', 'C']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -2886,7 +2836,7 @@ describe('ReactSuspenseList', () => {
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'App',
'A',
'B',
@@ -2928,7 +2878,7 @@ describe('ReactSuspenseList', () => {
await C.resolve();
- expect(Scheduler).toFlushAndYield(['C', 'Suspend! [D]']);
+ await waitForAll(['C', 'Suspend! [D]']);
expect(ReactNoop).toMatchRenderedOutput(
<>
A
@@ -3003,12 +2953,7 @@ describe('ReactSuspenseList', () => {
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
- 'Suspend! [A]',
- 'Loading A',
- 'Loading B',
- 'Loading C',
- ]);
+ await waitForAll(['Suspend! [A]', 'Loading A', 'Loading B', 'Loading C']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -3020,7 +2965,7 @@ describe('ReactSuspenseList', () => {
await A.resolve();
- expect(Scheduler).toFlushAndYield(['A', 'Suspend! [B]']);
+ await waitForAll(['A', 'Suspend! [B]']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -3032,7 +2977,7 @@ describe('ReactSuspenseList', () => {
await B.resolve();
- expect(Scheduler).toFlushAndYield(['B', 'C']);
+ await waitForAll(['B', 'C']);
expect(ReactNoop).toMatchRenderedOutput(
<>
diff --git a/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js b/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js
index 9ebf8c9170c6f..f8fe9d10cdd83 100644
--- a/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js
+++ b/packages/react-reconciler/src/__tests__/ReactSuspensePlaceholder-test.internal.js
@@ -17,6 +17,8 @@ let ReactCache;
let Suspense;
let TextResource;
let textResourceShouldFail;
+let waitForAll;
+let assertLog;
describe('ReactSuspensePlaceholder', () => {
beforeEach(() => {
@@ -34,6 +36,10 @@ describe('ReactSuspensePlaceholder', () => {
Profiler = React.Profiler;
Suspense = React.Suspense;
+ const InternalTestUtils = require('internal-test-utils');
+ waitForAll = InternalTestUtils.waitForAll;
+ assertLog = InternalTestUtils.assertLog;
+
TextResource = ReactCache.unstable_createResource(
([text, ms = 0]) => {
let listeners = null;
@@ -106,7 +112,7 @@ describe('ReactSuspensePlaceholder', () => {
}
}
- it('times out children that are already hidden', () => {
+ it('times out children that are already hidden', async () => {
class HiddenText extends React.PureComponent {
render() {
const text = this.props.text;
@@ -132,13 +138,13 @@ describe('ReactSuspensePlaceholder', () => {
// Initial mount
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['A', 'Suspend! [B]', 'C', 'Loading...']);
+ await waitForAll(['A', 'Suspend! [B]', 'C', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput('Loading...');
jest.advanceTimersByTime(1000);
- expect(Scheduler).toHaveYielded(['Promise resolved [B]']);
+ assertLog(['Promise resolved [B]']);
- expect(Scheduler).toFlushAndYield(['A', 'B', 'C']);
+ await waitForAll(['A', 'B', 'C']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -150,11 +156,11 @@ describe('ReactSuspensePlaceholder', () => {
// Update
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Suspend! [B2]', 'C', 'Loading...']);
+ await waitForAll(['Suspend! [B2]', 'C', 'Loading...']);
// Time out the update
jest.advanceTimersByTime(750);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(
<>
A
@@ -166,8 +172,8 @@ describe('ReactSuspensePlaceholder', () => {
// Resolve the promise
jest.advanceTimersByTime(1000);
- expect(Scheduler).toHaveYielded(['Promise resolved [B2]']);
- expect(Scheduler).toFlushAndYield(['B2', 'C']);
+ assertLog(['Promise resolved [B2]']);
+ await waitForAll(['B2', 'C']);
// Render the final update. A should still be hidden, because it was
// given a `hidden` prop.
@@ -194,39 +200,34 @@ describe('ReactSuspensePlaceholder', () => {
// Initial mount
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['A', 'Suspend! [B]', 'C', 'Loading...']);
+ await waitForAll(['A', 'Suspend! [B]', 'C', 'Loading...']);
expect(ReactNoop).not.toMatchRenderedOutput('ABC');
jest.advanceTimersByTime(1000);
- expect(Scheduler).toHaveYielded(['Promise resolved [B]']);
- expect(Scheduler).toFlushAndYield(['A', 'B', 'C']);
+ assertLog(['Promise resolved [B]']);
+ await waitForAll(['A', 'B', 'C']);
expect(ReactNoop).toMatchRenderedOutput('ABC');
// Update
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
- 'A',
- 'Suspend! [B2]',
- 'C',
- 'Loading...',
- ]);
+ await waitForAll(['A', 'Suspend! [B2]', 'C', 'Loading...']);
// Time out the update
jest.advanceTimersByTime(750);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput('Loading...');
// Resolve the promise
jest.advanceTimersByTime(1000);
- expect(Scheduler).toHaveYielded(['Promise resolved [B2]']);
- expect(Scheduler).toFlushAndYield(['A', 'B2', 'C']);
+ assertLog(['Promise resolved [B2]']);
+ await waitForAll(['A', 'B2', 'C']);
// Render the final update. A should still be hidden, because it was
// given a `hidden` prop.
expect(ReactNoop).toMatchRenderedOutput('AB2C');
});
- it('preserves host context for text nodes', () => {
+ it('preserves host context for text nodes', async () => {
function App(props) {
return (
// uppercase is a special type that causes React Noop to render child
@@ -244,32 +245,27 @@ describe('ReactSuspensePlaceholder', () => {
// Initial mount
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['a', 'Suspend! [b]', 'c', 'Loading...']);
+ await waitForAll(['a', 'Suspend! [b]', 'c', 'Loading...']);
expect(ReactNoop).toMatchRenderedOutput(
LOADING...);
jest.advanceTimersByTime(1000);
- expect(Scheduler).toHaveYielded(['Promise resolved [b]']);
- expect(Scheduler).toFlushAndYield(['a', 'b', 'c']);
+ assertLog(['Promise resolved [b]']);
+ await waitForAll(['a', 'b', 'c']);
expect(ReactNoop).toMatchRenderedOutput(
ABC);
// Update
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
- 'a',
- 'Suspend! [b2]',
- 'c',
- 'Loading...',
- ]);
+ await waitForAll(['a', 'Suspend! [b2]', 'c', 'Loading...']);
// Time out the update
jest.advanceTimersByTime(750);
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(
LOADING...);
// Resolve the promise
jest.advanceTimersByTime(1000);
- expect(Scheduler).toHaveYielded(['Promise resolved [b2]']);
- expect(Scheduler).toFlushAndYield(['a', 'b2', 'c']);
+ assertLog(['Promise resolved [b2]']);
+ await waitForAll(['a', 'b2', 'c']);
// Render the final update. A should still be hidden, because it was
// given a `hidden` prop.
@@ -312,7 +308,7 @@ describe('ReactSuspensePlaceholder', () => {
describe('when suspending during mount', () => {
it('properly accounts for base durations when a suspended times out in a legacy tree', async () => {
ReactNoop.renderLegacySyncRoot(
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'App',
'Suspending',
'Suspend! [Loaded]',
@@ -330,11 +326,11 @@ describe('ReactSuspensePlaceholder', () => {
jest.advanceTimersByTime(1000);
- expect(Scheduler).toHaveYielded(['Promise resolved [Loaded]']);
+ assertLog(['Promise resolved [Loaded]']);
ReactNoop.flushSync();
- expect(Scheduler).toHaveYielded(['Loaded']);
+ assertLog(['Loaded']);
expect(ReactNoop).toMatchRenderedOutput('LoadedText');
expect(onRender).toHaveBeenCalledTimes(2);
@@ -345,10 +341,10 @@ describe('ReactSuspensePlaceholder', () => {
expect(onRender.mock.calls[1][3]).toBe(8);
});
- it('properly accounts for base durations when a suspended times out in a concurrent tree', () => {
+ it('properly accounts for base durations when a suspended times out in a concurrent tree', async () => {
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'App',
'Suspending',
'Suspend! [Loaded]',
@@ -368,8 +364,8 @@ describe('ReactSuspensePlaceholder', () => {
// Resolve the pending promise.
jest.advanceTimersByTime(1000);
- expect(Scheduler).toHaveYielded(['Promise resolved [Loaded]']);
- expect(Scheduler).toFlushAndYield(['Suspending', 'Loaded', 'Text']);
+ assertLog(['Promise resolved [Loaded]']);
+ await waitForAll(['Suspending', 'Loaded', 'Text']);
expect(ReactNoop).toMatchRenderedOutput('LoadedText');
expect(onRender).toHaveBeenCalledTimes(2);
@@ -385,7 +381,7 @@ describe('ReactSuspensePlaceholder', () => {
ReactNoop.renderLegacySyncRoot(
,
);
- expect(Scheduler).toHaveYielded(['App', 'Text']);
+ assertLog(['App', 'Text']);
expect(ReactNoop).toMatchRenderedOutput('Text');
expect(onRender).toHaveBeenCalledTimes(1);
@@ -395,7 +391,7 @@ describe('ReactSuspensePlaceholder', () => {
expect(onRender.mock.calls[0][3]).toBe(5);
ReactNoop.render(
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'App',
'Suspending',
'Suspend! [Loaded]',
@@ -415,7 +411,7 @@ describe('ReactSuspensePlaceholder', () => {
ReactNoop.renderLegacySyncRoot(
,
);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'App',
'Suspending',
'Suspend! [Loaded]',
@@ -429,11 +425,11 @@ describe('ReactSuspensePlaceholder', () => {
expect(onRender.mock.calls[1][3]).toBe(10);
jest.advanceTimersByTime(1000);
- expect(Scheduler).toHaveYielded(['Promise resolved [Loaded]']);
+ assertLog(['Promise resolved [Loaded]']);
ReactNoop.flushSync();
- expect(Scheduler).toHaveYielded(['Loaded']);
+ assertLog(['Loaded']);
expect(ReactNoop).toMatchRenderedOutput('LoadedNew');
expect(onRender).toHaveBeenCalledTimes(4);
@@ -444,7 +440,7 @@ describe('ReactSuspensePlaceholder', () => {
expect(onRender.mock.calls[3][3]).toBe(9);
});
- it('properly accounts for base durations when a suspended times out in a concurrent tree', () => {
+ it('properly accounts for base durations when a suspended times out in a concurrent tree', async () => {
ReactNoop.render(
<>
@@ -452,7 +448,7 @@ describe('ReactSuspensePlaceholder', () => {
>,
);
- expect(Scheduler).toFlushAndYield(['App', 'Text']);
+ await waitForAll(['App', 'Text']);
expect(ReactNoop).toMatchRenderedOutput('Text');
expect(onRender).toHaveBeenCalledTimes(1);
@@ -467,7 +463,7 @@ describe('ReactSuspensePlaceholder', () => {
>,
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'App',
'Suspending',
'Suspend! [Loaded]',
@@ -507,7 +503,7 @@ describe('ReactSuspensePlaceholder', () => {
// from timers.
Scheduler.unstable_advanceTime(100);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'App',
'Suspending',
'Suspend! [Loaded]',
@@ -520,17 +516,8 @@ describe('ReactSuspensePlaceholder', () => {
// Resolve the pending promise.
jest.advanceTimersByTime(100);
- expect(Scheduler).toHaveYielded([
- 'Promise resolved [Loaded]',
- 'Promise resolved [Sibling]',
- ]);
- expect(Scheduler).toFlushAndYield([
- 'App',
- 'Suspending',
- 'Loaded',
- 'New',
- 'Sibling',
- ]);
+ assertLog(['Promise resolved [Loaded]', 'Promise resolved [Sibling]']);
+ await waitForAll(['App', 'Suspending', 'Loaded', 'New', 'Sibling']);
expect(onRender).toHaveBeenCalledTimes(3);
// When the suspending data is resolved and our final UI is rendered,
diff --git a/packages/react-reconciler/src/__tests__/ReactThenable-test.js b/packages/react-reconciler/src/__tests__/ReactThenable-test.js
index cc51d48c669e3..c6804605c5809 100644
--- a/packages/react-reconciler/src/__tests__/ReactThenable-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactThenable-test.js
@@ -12,6 +12,10 @@ let Suspense;
let startTransition;
let cache;
let pendingTextRequests;
+let waitFor;
+let waitForPaint;
+let assertLog;
+let waitForAll;
describe('ReactThenable', () => {
beforeEach(() => {
@@ -29,6 +33,12 @@ describe('ReactThenable', () => {
startTransition = React.startTransition;
cache = React.cache;
+ const InternalTestUtils = require('internal-test-utils');
+ waitForAll = InternalTestUtils.waitForAll;
+ assertLog = InternalTestUtils.assertLog;
+ waitForPaint = InternalTestUtils.waitForPaint;
+ waitFor = InternalTestUtils.waitFor;
+
pendingTextRequests = new Map();
});
@@ -94,7 +104,7 @@ describe('ReactThenable', () => {
});
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// React will yield when the async component suspends.
'Suspend!',
'Resolve in microtask',
@@ -128,11 +138,7 @@ describe('ReactThenable', () => {
root.render(
);
});
});
- expect(Scheduler).toHaveYielded([
- 'Suspend!',
- 'Resolve in microtask',
- 'Async',
- ]);
+ assertLog(['Suspend!', 'Resolve in microtask', 'Async']);
expect(root).toMatchRenderedOutput('Async');
});
@@ -172,7 +178,7 @@ describe('ReactThenable', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Suspend!', 'Loading...']);
+ assertLog(['Suspend!', 'Loading...']);
expect(root).toMatchRenderedOutput('Loading...');
});
@@ -201,7 +207,7 @@ describe('ReactThenable', () => {
root.render(
);
});
});
- expect(Scheduler).toHaveYielded(['ABC']);
+ assertLog(['ABC']);
expect(root).toMatchRenderedOutput('ABC');
});
@@ -229,7 +235,7 @@ describe('ReactThenable', () => {
root.render(
);
});
});
- expect(Scheduler).toHaveYielded(['ABC']);
+ assertLog(['ABC']);
expect(root).toMatchRenderedOutput('ABC');
});
@@ -275,7 +281,7 @@ describe('ReactThenable', () => {
root.render(
);
});
});
- expect(Scheduler).toHaveYielded(['Oops!', 'Oops!']);
+ assertLog(['Oops!', 'Oops!']);
});
// @gate enableUseHook
@@ -308,7 +314,7 @@ describe('ReactThenable', () => {
root.render(
);
});
});
- expect(Scheduler).toHaveYielded(['ABCD']);
+ assertLog(['ABCD']);
expect(root).toMatchRenderedOutput('ABCD');
});
@@ -344,7 +350,7 @@ describe('ReactThenable', () => {
root.render(
);
});
});
- expect(Scheduler).toHaveYielded(['CD', 'Loading...']);
+ assertLog(['CD', 'Loading...']);
expect(root).toMatchRenderedOutput('Loading...');
});
@@ -397,7 +403,7 @@ describe('ReactThenable', () => {
root.render(
);
});
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// First attempt. The uncached promise suspends.
'Suspend! [Async]',
// Because the promise already fulfilled, we're able to unwrap the value
@@ -427,7 +433,7 @@ describe('ReactThenable', () => {
});
// @gate enableUseHook
- test('basic use(context)', () => {
+ test('basic use(context)', async () => {
const ContextA = React.createContext('');
const ContextB = React.createContext('B');
@@ -446,7 +452,7 @@ describe('ReactThenable', () => {
const root = ReactNoop.createRoot();
root.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(root).toMatchRenderedOutput('AB');
});
@@ -482,7 +488,7 @@ describe('ReactThenable', () => {
startTransition(() => {
root.render(
);
});
- expect(Scheduler).toFlushUntilNextPaint([]);
+ await waitForPaint([]);
expect(root).toMatchRenderedOutput(null);
await resolve({default:
});
@@ -492,7 +498,7 @@ describe('ReactThenable', () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Hello ', 'world!']);
+ assertLog(['Hello ', 'world!']);
expect(root).toMatchRenderedOutput(
Hello world!
);
});
@@ -547,7 +553,7 @@ describe('ReactThenable', () => {
,
);
});
- expect(Scheduler).toHaveYielded(['(empty)']);
+ assertLog(['(empty)']);
expect(root).toMatchRenderedOutput('(empty)');
await act(async () => {
@@ -559,13 +565,13 @@ describe('ReactThenable', () => {
);
});
});
- expect(Scheduler).toHaveYielded(['Async text requested [Async]']);
+ assertLog(['Async text requested [Async]']);
expect(root).toMatchRenderedOutput('(empty)');
await act(async () => {
resolveTextRequests('Async');
});
- expect(Scheduler).toHaveYielded(['Async text requested [Async]', 'Async']);
+ assertLog(['Async text requested [Async]', 'Async']);
expect(root).toMatchRenderedOutput('Async');
});
@@ -586,10 +592,7 @@ describe('ReactThenable', () => {
});
});
// Even though the initial render was a transition, it shows a fallback.
- expect(Scheduler).toHaveYielded([
- 'Async text requested [Async]',
- 'Loading...',
- ]);
+ assertLog(['Async text requested [Async]', 'Loading...']);
expect(root).toMatchRenderedOutput('Loading...');
// Resolve the original data
@@ -603,7 +606,7 @@ describe('ReactThenable', () => {
// this test, how would the developer be able to imperatively flush it if it
// wasn't initiated until the current `act` call? Can't think of a better
// strategy at the moment.
- expect(Scheduler).toHaveYielded(['Async text requested [Async]']);
+ assertLog(['Async text requested [Async]']);
expect(root).toMatchRenderedOutput('Loading...');
// Flush the second request.
@@ -611,7 +614,7 @@ describe('ReactThenable', () => {
resolveTextRequests('Async');
});
// This time it finishes because it was during a retry.
- expect(Scheduler).toHaveYielded(['Async text requested [Async]', 'Async']);
+ assertLog(['Async text requested [Async]', 'Async']);
expect(root).toMatchRenderedOutput('Async');
});
@@ -635,9 +638,7 @@ describe('ReactThenable', () => {
);
});
});
- expect(Scheduler).toHaveYielded([
- 'Async text requested [Will never resolve]',
- ]);
+ assertLog(['Async text requested [Will never resolve]']);
await act(async () => {
root.render(
@@ -646,7 +647,7 @@ describe('ReactThenable', () => {
,
);
});
- expect(Scheduler).toHaveYielded(['Something different']);
+ assertLog(['Something different']);
});
// @gate enableUseHook
@@ -669,9 +670,7 @@ describe('ReactThenable', () => {
);
});
});
- expect(Scheduler).toHaveYielded([
- 'Async text requested [Will never resolve]',
- ]);
+ assertLog(['Async text requested [Will never resolve]']);
// Calling a hook should error because we're oustide of a component.
expect(useState).toThrow(
@@ -704,7 +703,7 @@ describe('ReactThenable', () => {
ReactNoop.flushSync(() => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Hi']);
+ assertLog(['Hi']);
expect(root).toMatchRenderedOutput('Hi');
});
@@ -745,26 +744,21 @@ describe('ReactThenable', () => {
await act(() => {
root.render(
);
});
- expect(Scheduler).toHaveYielded([
- 'childShouldSuspend: false, showChild: true',
- 'Child',
- ]);
+ assertLog(['childShouldSuspend: false, showChild: true', 'Child']);
expect(root).toMatchRenderedOutput('Child');
- await act(() => {
+ await act(async () => {
// Perform an update that causes the app to suspend
startTransition(() => {
setChildShouldSuspend(true);
});
- expect(Scheduler).toFlushAndYieldThrough([
- 'childShouldSuspend: true, showChild: true',
- ]);
+ await waitFor(['childShouldSuspend: true, showChild: true']);
// While the update is in progress, schedule another update.
startTransition(() => {
setShowChild(false);
});
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Because the interleaved update is not higher priority than what we were
// already working on, it won't interrupt. The first update will continue,
// and will suspend.
@@ -827,17 +821,14 @@ describe('ReactThenable', () => {
});
});
// Suspends while we wait for the async service to respond.
- expect(Scheduler).toHaveYielded([
- 'Compute uppercase: Hello',
- 'Async text requested [HELLO!]',
- ]);
+ assertLog(['Compute uppercase: Hello', 'Async text requested [HELLO!]']);
expect(root).toMatchRenderedOutput(null);
// The data is received.
await act(async () => {
resolveTextRequests('HELLO!');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// We shouldn't run the uppercase computation again, because we can reuse
// the computation from the previous attempt.
// 'Compute uppercase: Hello',
@@ -867,15 +858,12 @@ describe('ReactThenable', () => {
root.render(
);
});
});
- expect(Scheduler).toHaveYielded(['Async text requested [apple]']);
+ assertLog(['Async text requested [apple]']);
expect(root).toMatchRenderedOutput(null);
await act(async () => {
resolveTextRequests('apple');
});
- expect(Scheduler).toHaveYielded([
- 'Async text requested [apple]',
- 'apple carrot',
- ]);
+ assertLog(['Async text requested [apple]', 'apple carrot']);
expect(root).toMatchRenderedOutput('apple carrot');
// Update the state variable after the use().
@@ -884,15 +872,12 @@ describe('ReactThenable', () => {
_setVegetable('dill');
});
});
- expect(Scheduler).toHaveYielded(['Async text requested [apple]']);
+ assertLog(['Async text requested [apple]']);
expect(root).toMatchRenderedOutput('apple carrot');
await act(async () => {
resolveTextRequests('apple');
});
- expect(Scheduler).toHaveYielded([
- 'Async text requested [apple]',
- 'apple dill',
- ]);
+ assertLog(['Async text requested [apple]', 'apple dill']);
expect(root).toMatchRenderedOutput('apple dill');
// Update the state variable before the use(). The second state is maintained.
@@ -901,15 +886,12 @@ describe('ReactThenable', () => {
_setFruit('banana');
});
});
- expect(Scheduler).toHaveYielded(['Async text requested [banana]']);
+ assertLog(['Async text requested [banana]']);
expect(root).toMatchRenderedOutput('apple dill');
await act(async () => {
resolveTextRequests('banana');
});
- expect(Scheduler).toHaveYielded([
- 'Async text requested [banana]',
- 'banana dill',
- ]);
+ assertLog(['Async text requested [banana]', 'banana dill']);
expect(root).toMatchRenderedOutput('banana dill');
});
@@ -931,15 +913,12 @@ describe('ReactThenable', () => {
root.render(
);
});
});
- expect(Scheduler).toHaveYielded(['Async text requested [aguacate]']);
+ assertLog(['Async text requested [aguacate]']);
expect(root).toMatchRenderedOutput(null);
await act(async () => {
resolveTextRequests('aguacate');
});
- expect(Scheduler).toHaveYielded([
- 'Async text requested [aguacate]',
- 'aguacate abogado',
- ]);
+ assertLog(['Async text requested [aguacate]', 'aguacate abogado']);
expect(root).toMatchRenderedOutput('aguacate abogado');
// Now update the state.
@@ -948,15 +927,12 @@ describe('ReactThenable', () => {
_setLawyer('avocat');
});
});
- expect(Scheduler).toHaveYielded(['Async text requested [aguacate]']);
+ assertLog(['Async text requested [aguacate]']);
expect(root).toMatchRenderedOutput('aguacate abogado');
await act(async () => {
resolveTextRequests('aguacate');
});
- expect(Scheduler).toHaveYielded([
- 'Async text requested [aguacate]',
- 'aguacate avocat',
- ]);
+ assertLog(['Async text requested [aguacate]', 'aguacate avocat']);
expect(root).toMatchRenderedOutput('aguacate avocat');
});
@@ -977,13 +953,13 @@ describe('ReactThenable', () => {
root.render(
);
});
});
- expect(Scheduler).toHaveYielded(['Async text requested [Hello]']);
+ assertLog(['Async text requested [Hello]']);
expect(root).toMatchRenderedOutput(null);
await act(async () => {
resolveTextRequests('Hello');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// We shouldn't request async text again, because the async function
// was memoized
// 'Async text requested [Hello]'
@@ -1015,7 +991,7 @@ describe('ReactThenable', () => {
,
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Async text requested [A]',
'Async text requested [B]',
'Async text requested [C]',
@@ -1028,19 +1004,19 @@ describe('ReactThenable', () => {
await act(async () => {
resolveTextRequests('A');
});
- expect(Scheduler).toHaveYielded(['A', '(Loading C...)', '(Loading B...)']);
+ assertLog(['A', '(Loading C...)', '(Loading B...)']);
expect(root).toMatchRenderedOutput('A(Loading B...)');
await act(async () => {
resolveTextRequests('B');
});
- expect(Scheduler).toHaveYielded(['B', '(Loading C...)']);
+ assertLog(['B', '(Loading C...)']);
expect(root).toMatchRenderedOutput('AB(Loading C...)');
await act(async () => {
resolveTextRequests('C');
});
- expect(Scheduler).toHaveYielded(['C']);
+ assertLog(['C']);
expect(root).toMatchRenderedOutput('ABC');
});
@@ -1068,7 +1044,7 @@ describe('ReactThenable', () => {
,
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Async text requested [A]',
'Async text requested [B]',
'Async text requested [C]',
@@ -1081,13 +1057,13 @@ describe('ReactThenable', () => {
await act(async () => {
resolveTextRequests('A');
});
- expect(Scheduler).toHaveYielded(['Async text requested [A]']);
+ assertLog(['Async text requested [A]']);
expect(root).toMatchRenderedOutput('(Loading A...)');
await act(async () => {
resolveTextRequests('A');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// React suspends until A finishes loading.
'Async text requested [A]',
'A',
@@ -1106,13 +1082,13 @@ describe('ReactThenable', () => {
await act(async () => {
resolveTextRequests('B');
});
- expect(Scheduler).toHaveYielded(['Async text requested [B]']);
+ assertLog(['Async text requested [B]']);
expect(root).toMatchRenderedOutput('A(Loading B...)');
await act(async () => {
resolveTextRequests('B');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// React suspends until B finishes loading.
'Async text requested [B]',
'B',
@@ -1126,13 +1102,13 @@ describe('ReactThenable', () => {
await act(async () => {
resolveTextRequests('C');
});
- expect(Scheduler).toHaveYielded(['Async text requested [C]']);
+ assertLog(['Async text requested [C]']);
expect(root).toMatchRenderedOutput('AB(Loading C...)');
await act(async () => {
resolveTextRequests('C');
});
- expect(Scheduler).toHaveYielded(['Async text requested [C]', 'C']);
+ assertLog(['Async text requested [C]', 'C']);
expect(root).toMatchRenderedOutput('ABC');
});
@@ -1162,7 +1138,7 @@ describe('ReactThenable', () => {
root.render(
);
});
});
- expect(Scheduler).toHaveYielded(['A1']);
+ assertLog(['A1']);
expect(root).toMatchRenderedOutput('A1');
});
});
diff --git a/packages/react-reconciler/src/__tests__/ReactTopLevelFragment-test.js b/packages/react-reconciler/src/__tests__/ReactTopLevelFragment-test.js
index bc015724f7958..38b0d0a52633a 100644
--- a/packages/react-reconciler/src/__tests__/ReactTopLevelFragment-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactTopLevelFragment-test.js
@@ -12,7 +12,7 @@
let React;
let ReactNoop;
-let Scheduler;
+let waitForAll;
// This is a new feature in Fiber so I put it in its own test file. It could
// probably move to one of the other test files once it is official.
@@ -21,18 +21,20 @@ describe('ReactTopLevelFragment', function () {
jest.resetModules();
React = require('react');
ReactNoop = require('react-noop-renderer');
- Scheduler = require('scheduler');
+
+ const InternalTestUtils = require('internal-test-utils');
+ waitForAll = InternalTestUtils.waitForAll;
});
- it('should render a simple fragment at the top of a component', function () {
+ it('should render a simple fragment at the top of a component', async function () {
function Fragment() {
return [
Hello
,
World
];
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
});
- it('should preserve state when switching from a single child', function () {
+ it('should preserve state when switching from a single child', async function () {
let instance = null;
class Stateful extends React.Component {
@@ -50,21 +52,21 @@ describe('ReactTopLevelFragment', function () {
);
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
const instanceA = instance;
expect(instanceA).not.toBe(null);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
const instanceB = instance;
expect(instanceB).toBe(instanceA);
});
- it('should not preserve state when switching to a nested array', function () {
+ it('should not preserve state when switching to a nested array', async function () {
let instance = null;
class Stateful extends React.Component {
@@ -82,21 +84,21 @@ describe('ReactTopLevelFragment', function () {
);
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
const instanceA = instance;
expect(instanceA).not.toBe(null);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
const instanceB = instance;
expect(instanceB).not.toBe(instanceA);
});
- it('preserves state if an implicit key slot switches from/to null', function () {
+ it('preserves state if an implicit key slot switches from/to null', async function () {
let instance = null;
class Stateful extends React.Component {
@@ -112,28 +114,28 @@ describe('ReactTopLevelFragment', function () {
: [
Hello
,
];
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
const instanceA = instance;
expect(instanceA).not.toBe(null);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
const instanceB = instance;
expect(instanceB).toBe(instanceA);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
const instanceC = instance;
expect(instanceC === instanceA).toBe(true);
});
- it('should preserve state in a reorder', function () {
+ it('should preserve state in a reorder', async function () {
let instance = null;
class Stateful extends React.Component {
@@ -149,14 +151,14 @@ describe('ReactTopLevelFragment', function () {
: [[
,
World
],
];
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
const instanceA = instance;
expect(instanceA).not.toBe(null);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
const instanceB = instance;
diff --git a/packages/react-reconciler/src/__tests__/ReactTopLevelText-test.js b/packages/react-reconciler/src/__tests__/ReactTopLevelText-test.js
index 878d3b6f51e1e..30a3fa093b4ab 100644
--- a/packages/react-reconciler/src/__tests__/ReactTopLevelText-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactTopLevelText-test.js
@@ -12,7 +12,7 @@
let React;
let ReactNoop;
-let Scheduler;
+let waitForAll;
// This is a new feature in Fiber so I put it in its own test file. It could
// probably move to one of the other test files once it is official.
@@ -21,20 +21,22 @@ describe('ReactTopLevelText', () => {
jest.resetModules();
React = require('react');
ReactNoop = require('react-noop-renderer');
- Scheduler = require('scheduler');
+
+ const InternalTestUtils = require('internal-test-utils');
+ waitForAll = InternalTestUtils.waitForAll;
});
- it('should render a component returning strings directly from render', () => {
+ it('should render a component returning strings directly from render', async () => {
const Text = ({value}) => value;
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput('foo');
});
- it('should render a component returning numbers directly from render', () => {
+ it('should render a component returning numbers directly from render', async () => {
const Text = ({value}) => value;
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput('10');
});
});
diff --git a/packages/react-reconciler/src/__tests__/ReactTransition-test.js b/packages/react-reconciler/src/__tests__/ReactTransition-test.js
index dd0b9e0d0fedc..a41670a785a6c 100644
--- a/packages/react-reconciler/src/__tests__/ReactTransition-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactTransition-test.js
@@ -20,6 +20,10 @@ let useTransition;
let startTransition;
let act;
let getCacheForType;
+let waitForAll;
+let waitFor;
+let waitForPaint;
+let assertLog;
let caches;
let seededCache;
@@ -38,6 +42,12 @@ describe('ReactTransition', () => {
getCacheForType = React.unstable_getCacheForType;
act = require('jest-react').act;
+ const InternalTestUtils = require('internal-test-utils');
+ waitForAll = InternalTestUtils.waitForAll;
+ waitFor = InternalTestUtils.waitFor;
+ waitForPaint = InternalTestUtils.waitForPaint;
+ assertLog = InternalTestUtils.assertLog;
+
caches = [];
seededCache = null;
});
@@ -178,13 +188,13 @@ describe('ReactTransition', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['(empty)']);
+ assertLog(['(empty)']);
expect(root).toMatchRenderedOutput('(empty)');
await act(async () => {
start();
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Pending...',
'(empty)',
'Suspend! [Async]',
@@ -195,7 +205,7 @@ describe('ReactTransition', () => {
await resolveText('Async');
});
- expect(Scheduler).toHaveYielded(['Async']);
+ assertLog(['Async']);
expect(root).toMatchRenderedOutput('Async');
});
@@ -239,7 +249,7 @@ describe('ReactTransition', () => {
seedNextTextCache('A content');
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A label', 'A content']);
+ assertLog(['A label', 'A content']);
expect(root).toMatchRenderedOutput(
<>
A label
A content
@@ -250,7 +260,7 @@ describe('ReactTransition', () => {
await act(async () => {
update('B');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Commit pending state
'B label (loading...)',
'A content',
@@ -271,7 +281,7 @@ describe('ReactTransition', () => {
await act(async () => {
update('C');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Commit pending state
'C label (loading...)',
'A content',
@@ -292,7 +302,7 @@ describe('ReactTransition', () => {
await act(async () => {
resolveText('B content');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Attempt to render C, but it suspends
'C label',
'Suspend! [C content]',
@@ -308,7 +318,7 @@ describe('ReactTransition', () => {
await act(async () => {
resolveText('C content');
});
- expect(Scheduler).toHaveYielded(['C label', 'C content']);
+ assertLog(['C label', 'C content']);
expect(root).toMatchRenderedOutput(
<>
C label
C content
@@ -364,7 +374,7 @@ describe('ReactTransition', () => {
seedNextTextCache('A content');
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A label', 'A content']);
+ assertLog(['A label', 'A content']);
expect(root).toMatchRenderedOutput(
<>
A label
A content
@@ -375,7 +385,7 @@ describe('ReactTransition', () => {
await act(async () => {
update('B');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Commit pending state
'B label (loading...)',
'A content',
@@ -396,7 +406,7 @@ describe('ReactTransition', () => {
await act(async () => {
update('C');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Commit pending state
'C label (loading...)',
'A content',
@@ -417,7 +427,7 @@ describe('ReactTransition', () => {
await act(async () => {
resolveText('B content');
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Attempt to render C, but it suspends
'C label',
'Suspend! [C content]',
@@ -433,7 +443,7 @@ describe('ReactTransition', () => {
await act(async () => {
resolveText('C content');
});
- expect(Scheduler).toHaveYielded(['C label', 'C content']);
+ assertLog(['C label', 'C content']);
expect(root).toMatchRenderedOutput(
<>
C label
C content
@@ -481,7 +491,7 @@ describe('ReactTransition', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(root).toMatchRenderedOutput(null);
// Switch to A.
@@ -490,7 +500,7 @@ describe('ReactTransition', () => {
setShowA(true);
});
});
- expect(Scheduler).toHaveYielded(['Suspend! [A]', 'Loading...']);
+ assertLog(['Suspend! [A]', 'Loading...']);
expect(root).toMatchRenderedOutput(null);
// Before A loads, switch to B. This should entangle A with B.
@@ -500,7 +510,7 @@ describe('ReactTransition', () => {
setShowB(true);
});
});
- expect(Scheduler).toHaveYielded(['Suspend! [B]', 'Loading...']);
+ assertLog(['Suspend! [B]', 'Loading...']);
expect(root).toMatchRenderedOutput(null);
// Before A or B loads, switch to C. This should entangle C with B, and
@@ -511,7 +521,7 @@ describe('ReactTransition', () => {
setShowC(true);
});
});
- expect(Scheduler).toHaveYielded(['Suspend! [C]', 'Loading...']);
+ assertLog(['Suspend! [C]', 'Loading...']);
expect(root).toMatchRenderedOutput(null);
// Now the data starts resolving out of order.
@@ -523,7 +533,7 @@ describe('ReactTransition', () => {
resolveText('B');
});
});
- expect(Scheduler).toHaveYielded(['Suspend! [C]', 'Loading...']);
+ assertLog(['Suspend! [C]', 'Loading...']);
expect(root).toMatchRenderedOutput(null);
// Now resolve A. Again, this will attempt to render C, since everything
@@ -533,7 +543,7 @@ describe('ReactTransition', () => {
resolveText('A');
});
});
- expect(Scheduler).toHaveYielded(['Suspend! [C]', 'Loading...']);
+ assertLog(['Suspend! [C]', 'Loading...']);
expect(root).toMatchRenderedOutput(null);
// Finally, resolve C. This time we can finish.
@@ -542,7 +552,7 @@ describe('ReactTransition', () => {
resolveText('C');
});
});
- expect(Scheduler).toHaveYielded(['C']);
+ assertLog(['C']);
expect(root).toMatchRenderedOutput('C');
},
);
@@ -559,7 +569,7 @@ describe('ReactTransition', () => {
>,
);
});
- expect(Scheduler).toHaveYielded(['Initial']);
+ assertLog(['Initial']);
expect(root).toMatchRenderedOutput('Initial');
await act(async () => {
@@ -577,7 +587,7 @@ describe('ReactTransition', () => {
});
// Partially render it.
- expect(Scheduler).toFlushAndYieldThrough([
+ await waitFor([
// Once we the update suspends, we know it's a refresh transition,
// because the Suspense boundary has already mounted.
'Suspend! [Async]',
@@ -598,7 +608,7 @@ describe('ReactTransition', () => {
// Because the first one is going to suspend regardless, we should
// immediately switch to rendering the new transition.
- expect(Scheduler).toHaveYielded(['Updated']);
+ assertLog(['Updated']);
expect(root).toMatchRenderedOutput('Updated');
});
@@ -643,12 +653,7 @@ describe('ReactTransition', () => {
await act(async () => {
root.render(
);
- expect(Scheduler).toFlushAndYield([
- 'A',
- 'shouldHideInParent: false',
- 'B',
- 'C',
- ]);
+ await waitForAll(['A', 'shouldHideInParent: false', 'B', 'C']);
expect(root).toMatchRenderedOutput('ABC');
// Schedule an update
@@ -660,14 +665,14 @@ describe('ReactTransition', () => {
// lane from the first one. At the time this was written, all transitions are worked on
// simultaneously, unless a transition was already in progress when a
// new one was scheduled. So, partially render the first transition.
- expect(Scheduler).toFlushAndYieldThrough(['A']);
+ await waitFor(['A']);
// Now schedule a second transition. We won't interrupt the first one.
React.startTransition(() => {
setShouldHideInParent(true);
});
// Continue rendering the first transition.
- expect(Scheduler).toFlushAndYieldThrough([
+ await waitFor([
'shouldHideInParent: false',
'Suspend! [Async]',
'Loading...',
@@ -683,16 +688,13 @@ describe('ReactTransition', () => {
// time we re-enter the work loop (we don't interrupt immediately, we
// just wait for the next time slice), we should throw out the
// suspended first transition and try the second one.
- expect(Scheduler).toFlushUntilNextPaint([
- 'shouldHideInParent: true',
- '(empty)',
- ]);
+ await waitForPaint(['shouldHideInParent: true', '(empty)']);
expect(root).toMatchRenderedOutput('A(empty)BC');
// Since the two transitions are not entangled, we then later go back
// and finish retry the first transition. Not really relevant to this
// test but I'll assert the result anyway.
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'A',
'shouldHideInParent: true',
'(empty)',
@@ -732,7 +734,7 @@ describe('ReactTransition', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A0', 'B0', 'C0']);
+ assertLog(['A0', 'B0', 'C0']);
expect(root).toMatchRenderedOutput('A0B0C0');
await act(async () => {
@@ -741,14 +743,14 @@ describe('ReactTransition', () => {
root.render(
);
});
// Flush past the root, but stop before the async component.
- expect(Scheduler).toFlushAndYieldThrough(['A1']);
+ await waitFor(['A1']);
// Schedule another transition on the root, which already completed.
startTransition(() => {
root.render(
);
});
// We'll keep working on the first update.
- expect(Scheduler).toFlushAndYieldThrough([
+ await waitFor([
// Now the async component suspends
'Suspend! [Async]',
'Loading...',
@@ -762,7 +764,7 @@ describe('ReactTransition', () => {
// TODO: This should work even if React does not yield to the main
// thread. Should use same mechanism as selective hydration to interrupt
// the render before the end of the current slice of work.
- expect(Scheduler).toFlushAndYield(['A2', 'B2', 'C2']);
+ await waitForAll(['A2', 'B2', 'C2']);
expect(root).toMatchRenderedOutput('A2B2C2');
});
@@ -798,11 +800,7 @@ describe('ReactTransition', () => {
});
// Initial render.
- expect(Scheduler).toHaveYielded([
- 'Transition pri: 0',
- 'Normal pri: 0',
- 'Commit',
- ]);
+ assertLog(['Transition pri: 0', 'Normal pri: 0', 'Commit']);
expect(root).toMatchRenderedOutput('Transition pri: 0, Normal pri: 0');
await act(async () => {
@@ -810,7 +808,7 @@ describe('ReactTransition', () => {
updateNormalPri();
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Normal update first.
'Transition pri: 0',
'Normal pri: 1',
@@ -854,14 +852,14 @@ describe('ReactTransition', () => {
});
// Initial render.
- expect(Scheduler).toHaveYielded(['(empty)', 'Normal pri: 0', 'Commit']);
+ assertLog(['(empty)', 'Normal pri: 0', 'Commit']);
expect(root).toMatchRenderedOutput('(empty), Normal pri: 0');
await act(async () => {
updateTransitionPri();
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Suspend.
'Suspend! [Async]',
'Normal pri: 0',
@@ -874,7 +872,7 @@ describe('ReactTransition', () => {
updateNormalPri();
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Normal pri update.
'(empty)',
'Normal pri: 1',
@@ -914,17 +912,13 @@ describe('ReactTransition', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded([
- 'Transition pri: 0',
- 'Normal pri: 0',
- 'Commit',
- ]);
+ assertLog(['Transition pri: 0', 'Normal pri: 0', 'Commit']);
expect(root).toMatchRenderedOutput('Transition pri: 0, Normal pri: 0');
await act(async () => {
updateTransitionPri();
- expect(Scheduler).toFlushAndYieldThrough([
+ await waitFor([
// Start transition update.
'Transition pri: 1',
]);
@@ -935,7 +929,7 @@ describe('ReactTransition', () => {
});
if (gate(flags => flags.enableUnifiedSyncLane)) {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Normal pri: 0',
'Commit',
@@ -945,7 +939,7 @@ describe('ReactTransition', () => {
'Commit',
]);
} else {
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Finish transition update.
'Normal pri: 0',
'Commit',
diff --git a/packages/react-reconciler/src/__tests__/ReactTransitionTracing-test.js b/packages/react-reconciler/src/__tests__/ReactTransitionTracing-test.js
index 417ec6fb1ca3c..8ce36f55f9847 100644
--- a/packages/react-reconciler/src/__tests__/ReactTransitionTracing-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactTransitionTracing-test.js
@@ -12,6 +12,8 @@ let React;
let ReactNoop;
let Scheduler;
let act;
+let waitForAll;
+let assertLog;
let getCacheForType;
let useState;
@@ -43,6 +45,10 @@ describe('ReactInteractionTracing', () => {
act = require('jest-react').act;
+ const InternalTestUtils = require('internal-test-utils');
+ waitForAll = InternalTestUtils.waitForAll;
+ assertLog = InternalTestUtils.assertLog;
+
useState = React.useState;
startTransition = React.startTransition;
Suspense = React.Suspense;
@@ -233,7 +239,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
await act(async () => {
startTransition(() => root.render(
));
@@ -242,12 +248,12 @@ describe('ReactInteractionTracing', () => {
await advanceTimers(1000);
// Doesn't call transition or marker code
- expect(Scheduler).toFlushAndYield(['Page Two']);
+ await waitForAll(['Page Two']);
startTransition(() => root.render(
), {
name: 'transition',
});
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page One',
'onTransitionStart(transition, 2000)',
'onTransitionComplete(transition, 2000, 2000)',
@@ -299,7 +305,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
await act(async () => {
startTransition(() => navigateToPageTwo(), {name: 'page transition'});
@@ -307,7 +313,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
'onTransitionStart(page transition, 1000)',
'onTransitionComplete(page transition, 1000, 2000)',
@@ -358,7 +364,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One: hide']);
+ await waitForAll(['Page One: hide']);
await act(async () => {
startTransition(
@@ -372,7 +378,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two: show',
'onTransitionStart(page transition, 1000)',
'onTransitionComplete(page transition, 1000, 2000)',
@@ -431,7 +437,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
});
await act(async () => {
@@ -440,7 +446,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Loading...',
'onTransitionStart(page transition, 1000)',
@@ -451,7 +457,7 @@ describe('ReactInteractionTracing', () => {
await advanceTimers(1000);
await resolveText('Page Two');
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
'onTransitionProgress(page transition, 1000, 3000, [])',
'onTransitionComplete(page transition, 1000, 3000)',
@@ -526,13 +532,13 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
});
await act(async () => {
startTransition(() => navigateToPageTwo(), {name: 'page transition'});
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Loading...',
'onTransitionStart(page transition, 1000)',
@@ -542,14 +548,14 @@ describe('ReactInteractionTracing', () => {
await resolveText('Page Two');
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
'onTransitionProgress(page transition, 1000, 2000, [])',
'onTransitionComplete(page transition, 1000, 2000)',
]);
startTransition(() => showTextFn(), {name: 'text transition'});
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Show Text]',
'Show Text Loading...',
'Page Two',
@@ -560,7 +566,7 @@ describe('ReactInteractionTracing', () => {
await resolveText('Show Text');
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Show Text',
'onTransitionProgress(text transition, 2000, 3000, [])',
'onTransitionComplete(text transition, 2000, 3000)',
@@ -633,7 +639,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
});
await act(async () => {
@@ -641,7 +647,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Loading...',
'onTransitionStart(page transition, 1000)',
@@ -652,7 +658,7 @@ describe('ReactInteractionTracing', () => {
await act(async () => {
startTransition(() => showTextFn(), {name: 'show text'});
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Show Text]',
'Show Text Loading...',
'Suspend [Page Two]',
@@ -667,7 +673,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
'onTransitionProgress(page transition, 1000, 3000, [])',
'onTransitionComplete(page transition, 1000, 3000)',
@@ -677,7 +683,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Show Text',
'onTransitionProgress(show text, 2000, 4000, [])',
'onTransitionComplete(show text, 2000, 4000)',
@@ -750,7 +756,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
});
await act(async () => {
@@ -758,7 +764,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Suspend [Show Text One]',
'Show Text One Loading...',
@@ -773,7 +779,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
'Suspend [Show Text One]',
'Show Text One Loading...',
@@ -786,7 +792,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Show Text One',
'onTransitionProgress(page transition, 1000, 4000, [show text two])',
]);
@@ -795,7 +801,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Show Text Two',
'onTransitionProgress(page transition, 1000, 5000, [])',
'onTransitionComplete(page transition, 1000, 5000)',
@@ -881,7 +887,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
});
await act(async () => {
@@ -890,7 +896,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Suspend [Show Text One]',
'Show Text One Loading...',
@@ -906,7 +912,7 @@ describe('ReactInteractionTracing', () => {
resolveText('Page Two');
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
'Suspend [Show Text One]',
'Show Text One Loading...',
@@ -920,7 +926,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
'Suspend [Show Text One]',
'Show Text One Loading...',
@@ -938,7 +944,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Show Text',
'onTransitionProgress(navigate, 1000, 5000, [show text one])',
'onTransitionProgress(show text one, 1000, 5000, [show text one])',
@@ -948,7 +954,7 @@ describe('ReactInteractionTracing', () => {
resolveText('Show Text Two');
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Show Text Two',
'onTransitionProgress(show text two, 3000, 6000, [])',
'onTransitionComplete(show text two, 3000, 6000)',
@@ -959,7 +965,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Show Text One',
'onTransitionProgress(navigate, 1000, 7000, [])',
'onTransitionProgress(show text one, 1000, 7000, [])',
@@ -1037,7 +1043,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
await act(async () => {
startTransition(() => navigateToPageTwo(), {name: 'page transition'});
@@ -1045,7 +1051,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
'onTransitionStart(page transition, 1000)',
'onMarkerComplete(page transition, marker two, 1000, 2000)',
@@ -1124,7 +1130,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
});
await act(async () => {
@@ -1133,7 +1139,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Suspend [Marker Text]',
'Loading...',
@@ -1145,7 +1151,7 @@ describe('ReactInteractionTracing', () => {
await advanceTimers(1000);
await resolveText('Page Two');
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
'Suspend [Marker Text]',
'Loading...',
@@ -1157,7 +1163,7 @@ describe('ReactInteractionTracing', () => {
await advanceTimers(1000);
await resolveText('Marker Text');
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Marker Text',
'onMarkerProgress(page transition, async marker, 1000, 4000, [])',
'onMarkerComplete(page transition, async marker, 1000, 4000)',
@@ -1244,7 +1250,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
});
await act(async () => {
@@ -1253,7 +1259,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Outer Text]',
'Suspend [Inner Text One]',
'Inner One...',
@@ -1267,12 +1273,12 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
await resolveText('Inner Text Two');
- expect(Scheduler).toFlushAndYield([]);
+ await waitForAll([]);
ReactNoop.expire(1000);
await advanceTimers(1000);
await resolveText('Outer Text');
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Outer Text',
'Suspend [Inner Text One]',
'Inner One...',
@@ -1284,7 +1290,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
await resolveText('Inner Text One');
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Inner Text One',
'onMarkerProgress(page transition, outer marker, 1000, 5000, [])',
'onMarkerComplete(page transition, marker one, 1000, 5000)',
@@ -1367,7 +1373,7 @@ describe('ReactInteractionTracing', () => {
root.render(
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
startTransition(
() => root.render(
),
@@ -1378,7 +1384,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Loading...',
'onTransitionStart(transition one, 1000)',
@@ -1400,7 +1406,7 @@ describe('ReactInteractionTracing', () => {
resolveText('Page Two');
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
'onMarkerProgress(transition one, marker one, 1000, 4000, [])',
'onTransitionProgress(transition one, 1000, 4000, [])',
@@ -1501,7 +1507,7 @@ describe('ReactInteractionTracing', () => {
root.render(
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
startTransition(
() => root.render(
),
@@ -1511,7 +1517,7 @@ describe('ReactInteractionTracing', () => {
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Loading...',
'Suspend [Sibling Text]',
@@ -1526,7 +1532,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Loading...',
'Suspend [Sibling Text]',
@@ -1539,7 +1545,7 @@ describe('ReactInteractionTracing', () => {
root.render(
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Loading...',
'Suspend [Sibling Text]',
@@ -1550,12 +1556,12 @@ describe('ReactInteractionTracing', () => {
resolveText('Page Two');
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page Two']);
+ await waitForAll(['Page Two']);
resolveText('Sibling Text');
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Sibling Text',
'onMarkerProgress(transition one, parent, 1000, 6000, [])',
'onMarkerProgress(transition one, sibling, 1000, 6000, [])',
@@ -1652,7 +1658,7 @@ describe('ReactInteractionTracing', () => {
root.render(
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
startTransition(
() => root.render(
),
@@ -1662,7 +1668,7 @@ describe('ReactInteractionTracing', () => {
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page One]',
'Loading One...',
'Suspend [Page Two]',
@@ -1677,7 +1683,7 @@ describe('ReactInteractionTracing', () => {
root.render(
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Loading Two...',
'onMarkerProgress(transition, parent, 1000, 3000, [suspense two])',
@@ -1688,7 +1694,7 @@ describe('ReactInteractionTracing', () => {
await resolveText('Page Two');
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
// Marker progress will still get called after incomplete but not marker complete
'onMarkerProgress(transition, parent, 1000, 4000, [])',
@@ -1793,7 +1799,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Page One']);
+ await waitForAll(['Page One']);
startTransition(
() => root.render(
),
@@ -1803,7 +1809,7 @@ describe('ReactInteractionTracing', () => {
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page One]',
'Suspend [Child]',
'Loading Child...',
@@ -1820,7 +1826,7 @@ describe('ReactInteractionTracing', () => {
await resolveText('Page One');
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page One',
'Suspend [Child]',
'Loading Child...',
@@ -1833,7 +1839,7 @@ describe('ReactInteractionTracing', () => {
root.render(
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Page Two]',
'Loading Two...',
// "suspense one" has unsuspended so shouldn't be included
@@ -1848,7 +1854,7 @@ describe('ReactInteractionTracing', () => {
await resolveText('Page Two');
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Page Two',
'onMarkerProgress(transition, parent, 1000, 5000, [])',
'onMarkerProgress(transition, two, 1000, 5000, [])',
@@ -1933,7 +1939,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Suspend [Child]',
'onTransitionStart(transition, 0)',
'onMarkerProgress(transition, parent, 0, 1000, [child])',
@@ -1945,23 +1951,20 @@ describe('ReactInteractionTracing', () => {
await advanceTimers(1000);
// This appended child isn't part of the transition so we
// don't call any callback
- expect(Scheduler).toFlushAndYield([
- 'Suspend [Appended child]',
- 'Suspend [Child]',
- ]);
+ await waitForAll(['Suspend [Appended child]', 'Suspend [Child]']);
// This deleted child isn't part of the transition so we
// don't call any callbacks
root.render(
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield(['Suspend [Child]']);
+ await waitForAll(['Suspend [Child]']);
await resolveText('Child');
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Child',
'onMarkerProgress(transition, parent, 0, 4000, [])',
'onMarkerComplete(transition, parent, 0, 4000)',
@@ -2056,7 +2059,7 @@ describe('ReactInteractionTracing', () => {
await advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend [Child]',
'onTransitionStart(transition one, 0)',
'onMarkerProgress(transition one, parent, 0, 1000, [child])',
@@ -2075,7 +2078,7 @@ describe('ReactInteractionTracing', () => {
await advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend [Appended child]',
'Suspend [Child]',
'onTransitionStart(transition two, 1000)',
@@ -2089,7 +2092,7 @@ describe('ReactInteractionTracing', () => {
await advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend [Child]',
'onMarkerProgress(transition two, appended child, 1000, 3000, [])',
'onMarkerIncomplete(transition two, appended child, 1000, [{endTime: 3000, name: appended child, type: suspense}])',
@@ -2101,7 +2104,7 @@ describe('ReactInteractionTracing', () => {
await advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Child',
'onMarkerProgress(transition one, parent, 0, 4000, [])',
'onMarkerComplete(transition one, parent, 0, 4000)',
@@ -2161,7 +2164,7 @@ describe('ReactInteractionTracing', () => {
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'one',
'onTransitionStart(transition one, 0)',
'onMarkerComplete(transition one, one, 0, 1000)',
@@ -2175,10 +2178,10 @@ describe('ReactInteractionTracing', () => {
);
ReactNoop.expire(1000);
await advanceTimers(1000);
- expect(() => {
+ await expect(async () => {
// onMarkerComplete shouldn't be called for transitions with
// new keys
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'two',
'onTransitionStart(transition two, 1000)',
'onTransitionComplete(transition two, 1000, 2000)',
@@ -2195,7 +2198,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
await advanceTimers(1000);
// This should not warn and onMarkerComplete should be called
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'three',
'onTransitionStart(transition three, 2000)',
'onMarkerComplete(transition three, three, 2000, 3000)',
@@ -2247,7 +2250,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend [Text]',
'Loading...',
'Suspend [Hidden Text]',
@@ -2260,7 +2263,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Text',
'onMarkerComplete(transition, marker, 0, 2000)',
'onTransitionComplete(transition, 0, 2000)',
@@ -2271,7 +2274,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded(['Hidden Text']);
+ assertLog(['Hidden Text']);
});
// @gate enableTransitionTracing
@@ -2317,7 +2320,7 @@ describe('ReactInteractionTracing', () => {
await advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend [Page Two]',
'Loading...',
'onTransitionStart(page transition, 0)',
@@ -2329,7 +2332,7 @@ describe('ReactInteractionTracing', () => {
await advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Page Two',
'onTransitionProgress(page transition, 0, 2000, [])',
'onTransitionComplete(page transition, 0, 2000)',
@@ -2387,7 +2390,7 @@ describe('ReactInteractionTracing', () => {
advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend [Text]',
'Loading...',
'Suspend [Text Two]',
@@ -2404,7 +2407,7 @@ describe('ReactInteractionTracing', () => {
ReactNoop.expire(1000);
advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Text Two',
'onTransitionProgress(transition, 0, 2000, [])',
'onTransitionComplete(transition, 0, 2000)',
@@ -2465,7 +2468,7 @@ describe('ReactInteractionTracing', () => {
advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Suspend [Text one]',
'Loading one...',
'Suspend [Text two]',
@@ -2482,7 +2485,7 @@ describe('ReactInteractionTracing', () => {
advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Text one',
'onTransitionProgress(transition one, 0, 2000, []) /root one/',
'onTransitionComplete(transition one, 0, 2000) /root one/',
@@ -2494,7 +2497,7 @@ describe('ReactInteractionTracing', () => {
advanceTimers(1000);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Text two',
'onTransitionProgress(transition two, 0, 3000, []) /root two/',
'onTransitionComplete(transition two, 0, 3000) /root two/',
diff --git a/packages/react-reconciler/src/__tests__/ReactUpdatePriority-test.js b/packages/react-reconciler/src/__tests__/ReactUpdatePriority-test.js
index 0089053c96043..8194bcd24d633 100644
--- a/packages/react-reconciler/src/__tests__/ReactUpdatePriority-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactUpdatePriority-test.js
@@ -6,6 +6,9 @@ let startTransition;
let useState;
let useEffect;
let act;
+let waitFor;
+let waitForPaint;
+let assertLog;
describe('ReactUpdatePriority', () => {
beforeEach(() => {
@@ -20,6 +23,11 @@ describe('ReactUpdatePriority', () => {
startTransition = React.startTransition;
useState = React.useState;
useEffect = React.useEffect;
+
+ const InternalTestUtils = require('internal-test-utils');
+ waitFor = InternalTestUtils.waitFor;
+ waitForPaint = InternalTestUtils.waitForPaint;
+ assertLog = InternalTestUtils.assertLog;
});
function Text({text}) {
@@ -43,9 +51,9 @@ describe('ReactUpdatePriority', () => {
root.render(
);
});
// Should not have flushed the effect update yet
- expect(Scheduler).toHaveYielded([1]);
+ assertLog([1]);
});
- expect(Scheduler).toHaveYielded([2]);
+ assertLog([2]);
});
test('setState inside passive effect triggered by idle update should have idle priority', async () => {
@@ -68,13 +76,13 @@ describe('ReactUpdatePriority', () => {
root.render(
);
});
// Should not have flushed the effect update yet
- expect(Scheduler).toFlushUntilNextPaint(['Idle: 1, Default: 1']);
+ await waitForPaint(['Idle: 1, Default: 1']);
// Schedule another update at default priority
setDefaultState(2);
// The default update flushes first, because
- expect(Scheduler).toFlushUntilNextPaint([
+ await waitForPaint([
// Idle update is scheduled
'Idle update',
@@ -83,7 +91,7 @@ describe('ReactUpdatePriority', () => {
]);
});
// Now the idle update has flushed
- expect(Scheduler).toHaveYielded(['Idle: 2, Default: 2']);
+ assertLog(['Idle: 2, Default: 2']);
});
test('continuous updates should interrupt transitions', async () => {
@@ -111,19 +119,19 @@ describe('ReactUpdatePriority', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A1', 'B1', 'C1']);
+ assertLog(['A1', 'B1', 'C1']);
expect(root).toMatchRenderedOutput('A1B1C1');
await act(async () => {
startTransition(() => {
setCounter(2);
});
- expect(Scheduler).toFlushAndYieldThrough(['A2']);
+ await waitFor(['A2']);
ReactNoop.unstable_runWithPriority(ContinuousEventPriority, () => {
setIsHidden(true);
});
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
// Because the hide update has continuous priority, it should interrupt the
// in-progress transition
'(hidden)',
diff --git a/packages/react-reconciler/src/__tests__/ReactUpdaters-test.internal.js b/packages/react-reconciler/src/__tests__/ReactUpdaters-test.internal.js
index e19bf198a9be6..d60e637b0da02 100644
--- a/packages/react-reconciler/src/__tests__/ReactUpdaters-test.internal.js
+++ b/packages/react-reconciler/src/__tests__/ReactUpdaters-test.internal.js
@@ -19,6 +19,9 @@ let allSchedulerTags;
let allSchedulerTypes;
let onCommitRootShouldYield;
let act;
+let waitFor;
+let waitForAll;
+let assertLog;
describe('updaters', () => {
beforeEach(() => {
@@ -91,6 +94,11 @@ describe('updaters', () => {
Scheduler = require('scheduler');
act = require('jest-react').act;
+
+ const InternalTestUtils = require('internal-test-utils');
+ waitFor = InternalTestUtils.waitFor;
+ waitForAll = InternalTestUtils.waitForAll;
+ assertLog = InternalTestUtils.assertLog;
});
it('should report the (host) root as the scheduler for root-level render', async () => {
@@ -210,10 +218,7 @@ describe('updaters', () => {
const root = ReactDOMClient.createRoot(document.createElement('div'));
await act(async () => {
root.render(
);
- expect(Scheduler).toFlushAndYieldThrough([
- 'CascadingChild 0',
- 'onCommitRoot',
- ]);
+ await waitFor(['CascadingChild 0', 'onCommitRoot']);
});
expect(triggerActiveCascade).not.toBeNull();
expect(triggerPassiveCascade).not.toBeNull();
@@ -221,7 +226,7 @@ describe('updaters', () => {
await act(async () => {
triggerActiveCascade();
- expect(Scheduler).toFlushAndYieldThrough([
+ await waitFor([
'CascadingChild 0',
'onCommitRoot',
'CascadingChild 1',
@@ -236,7 +241,7 @@ describe('updaters', () => {
await act(async () => {
triggerPassiveCascade();
- expect(Scheduler).toFlushAndYieldThrough([
+ await waitFor([
'CascadingChild 1',
'onCommitRoot',
'CascadingChild 2',
@@ -252,7 +257,7 @@ describe('updaters', () => {
]);
// Verify no outstanding flushes
- Scheduler.unstable_flushAll();
+ await waitForAll([]);
});
it('should cover suspense pings', async () => {
@@ -291,7 +296,7 @@ describe('updaters', () => {
await act(async () => {
ReactDOM.render(
, document.createElement('div'));
- expect(Scheduler).toHaveYielded(['onCommitRoot']);
+ assertLog(['onCommitRoot']);
});
expect(setShouldSuspend).not.toBeNull();
expect(allSchedulerTypes).toEqual([[null]]);
@@ -299,7 +304,7 @@ describe('updaters', () => {
await act(async () => {
setShouldSuspend(true);
});
- expect(Scheduler).toHaveYielded(['onCommitRoot']);
+ assertLog(['onCommitRoot']);
expect(allSchedulerTypes).toEqual([[null], [Suspender]]);
expect(resolver).not.toBeNull();
@@ -307,11 +312,11 @@ describe('updaters', () => {
resolver('abc');
return promise;
});
- expect(Scheduler).toHaveYielded(['onCommitRoot']);
+ assertLog(['onCommitRoot']);
expect(allSchedulerTypes).toEqual([[null], [Suspender], [Suspender]]);
// Verify no outstanding flushes
- Scheduler.unstable_flushAll();
+ await waitForAll([]);
});
it('should cover error handling', async () => {
@@ -354,7 +359,7 @@ describe('updaters', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['initial', 'onCommitRoot']);
+ assertLog(['initial', 'onCommitRoot']);
expect(triggerError).not.toBeNull();
allSchedulerTypes.splice(0);
@@ -363,11 +368,11 @@ describe('updaters', () => {
await act(async () => {
triggerError();
});
- expect(Scheduler).toHaveYielded(['onCommitRoot', 'error', 'onCommitRoot']);
+ assertLog(['onCommitRoot', 'error', 'onCommitRoot']);
expect(allSchedulerTypes).toEqual([[Parent], [ErrorBoundary]]);
// Verify no outstanding flushes
- Scheduler.unstable_flushAll();
+ await waitForAll([]);
});
it('should distinguish between updaters in the case of interleaved work', async () => {
@@ -409,7 +414,7 @@ describe('updaters', () => {
);
// Render everything initially.
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'SyncPriorityUpdater 0',
'Yield HighPriority 0',
'LowPriorityUpdater 0',
@@ -421,14 +426,14 @@ describe('updaters', () => {
expect(allSchedulerTags).toEqual([[HostRoot]]);
// Render a partial update, but don't finish.
- act(() => {
+ await act(async () => {
triggerLowPriorityUpdate();
- expect(Scheduler).toFlushAndYieldThrough(['LowPriorityUpdater 1']);
+ await waitFor(['LowPriorityUpdater 1']);
expect(allSchedulerTags).toEqual([[HostRoot]]);
// Interrupt with higher priority work.
ReactDOM.flushSync(triggerSyncPriorityUpdate);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'SyncPriorityUpdater 1',
'Yield HighPriority 1',
'onCommitRoot',
@@ -437,7 +442,7 @@ describe('updaters', () => {
// Finish the initial partial update
triggerLowPriorityUpdate();
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'LowPriorityUpdater 2',
'Yield LowPriority 2',
'onCommitRoot',
@@ -455,6 +460,6 @@ describe('updaters', () => {
]);
// Verify no outstanding flushes
- Scheduler.unstable_flushAll();
+ await waitForAll([]);
});
});
diff --git a/packages/react-reconciler/src/__tests__/StrictEffectsMode-test.js b/packages/react-reconciler/src/__tests__/StrictEffectsMode-test.js
index aceb7d05d2d1e..8dbf746e8160c 100644
--- a/packages/react-reconciler/src/__tests__/StrictEffectsMode-test.js
+++ b/packages/react-reconciler/src/__tests__/StrictEffectsMode-test.js
@@ -13,6 +13,7 @@ let React;
let ReactTestRenderer;
let Scheduler;
let act;
+let assertLog;
describe('StrictEffectsMode', () => {
beforeEach(() => {
@@ -21,6 +22,9 @@ describe('StrictEffectsMode', () => {
ReactTestRenderer = require('react-test-renderer');
Scheduler = require('scheduler');
act = require('jest-react').act;
+
+ const InternalTestUtils = require('internal-test-utils');
+ assertLog = InternalTestUtils.assertLog;
});
function supportsDoubleInvokeEffects() {
@@ -51,10 +55,7 @@ describe('StrictEffectsMode', () => {
ReactTestRenderer.create(
);
});
- expect(Scheduler).toHaveYielded([
- 'useLayoutEffect mount',
- 'useEffect mount',
- ]);
+ assertLog(['useLayoutEffect mount', 'useEffect mount']);
});
it('double invoking for effects works properly', () => {
@@ -80,7 +81,7 @@ describe('StrictEffectsMode', () => {
});
if (supportsDoubleInvokeEffects()) {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect mount',
'useEffect mount',
'useLayoutEffect unmount',
@@ -89,17 +90,14 @@ describe('StrictEffectsMode', () => {
'useEffect mount',
]);
} else {
- expect(Scheduler).toHaveYielded([
- 'useLayoutEffect mount',
- 'useEffect mount',
- ]);
+ assertLog(['useLayoutEffect mount', 'useEffect mount']);
}
act(() => {
renderer.update(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect unmount',
'useLayoutEffect mount',
'useEffect unmount',
@@ -110,10 +108,7 @@ describe('StrictEffectsMode', () => {
renderer.unmount();
});
- expect(Scheduler).toHaveYielded([
- 'useLayoutEffect unmount',
- 'useEffect unmount',
- ]);
+ assertLog(['useLayoutEffect unmount', 'useEffect unmount']);
});
it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
@@ -139,7 +134,7 @@ describe('StrictEffectsMode', () => {
});
if (supportsDoubleInvokeEffects()) {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useEffect One mount',
'useEffect Two mount',
'useEffect One unmount',
@@ -148,17 +143,14 @@ describe('StrictEffectsMode', () => {
'useEffect Two mount',
]);
} else {
- expect(Scheduler).toHaveYielded([
- 'useEffect One mount',
- 'useEffect Two mount',
- ]);
+ assertLog(['useEffect One mount', 'useEffect Two mount']);
}
act(() => {
renderer.update(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useEffect One unmount',
'useEffect Two unmount',
'useEffect One mount',
@@ -169,10 +161,7 @@ describe('StrictEffectsMode', () => {
renderer.unmount(null);
});
- expect(Scheduler).toHaveYielded([
- 'useEffect One unmount',
- 'useEffect Two unmount',
- ]);
+ assertLog(['useEffect One unmount', 'useEffect Two unmount']);
});
it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
@@ -200,7 +189,7 @@ describe('StrictEffectsMode', () => {
});
if (supportsDoubleInvokeEffects()) {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect One mount',
'useLayoutEffect Two mount',
'useLayoutEffect One unmount',
@@ -209,17 +198,14 @@ describe('StrictEffectsMode', () => {
'useLayoutEffect Two mount',
]);
} else {
- expect(Scheduler).toHaveYielded([
- 'useLayoutEffect One mount',
- 'useLayoutEffect Two mount',
- ]);
+ assertLog(['useLayoutEffect One mount', 'useLayoutEffect Two mount']);
}
act(() => {
renderer.update(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect One unmount',
'useLayoutEffect Two unmount',
'useLayoutEffect One mount',
@@ -230,10 +216,7 @@ describe('StrictEffectsMode', () => {
renderer.unmount();
});
- expect(Scheduler).toHaveYielded([
- 'useLayoutEffect One unmount',
- 'useLayoutEffect Two unmount',
- ]);
+ assertLog(['useLayoutEffect One unmount', 'useLayoutEffect Two unmount']);
});
it('useEffect and useLayoutEffect is called twice when there is no unmount', () => {
@@ -257,33 +240,27 @@ describe('StrictEffectsMode', () => {
});
if (supportsDoubleInvokeEffects()) {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect mount',
'useEffect mount',
'useLayoutEffect mount',
'useEffect mount',
]);
} else {
- expect(Scheduler).toHaveYielded([
- 'useLayoutEffect mount',
- 'useEffect mount',
- ]);
+ assertLog(['useLayoutEffect mount', 'useEffect mount']);
}
act(() => {
renderer.update(
);
});
- expect(Scheduler).toHaveYielded([
- 'useLayoutEffect mount',
- 'useEffect mount',
- ]);
+ assertLog(['useLayoutEffect mount', 'useEffect mount']);
act(() => {
renderer.unmount();
});
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
});
it('passes the right context to class component lifecycles', () => {
@@ -315,13 +292,13 @@ describe('StrictEffectsMode', () => {
});
if (supportsDoubleInvokeEffects()) {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'componentDidMount',
'componentWillUnmount',
'componentDidMount',
]);
} else {
- expect(Scheduler).toHaveYielded(['componentDidMount']);
+ assertLog(['componentDidMount']);
}
});
@@ -352,26 +329,26 @@ describe('StrictEffectsMode', () => {
});
if (supportsDoubleInvokeEffects()) {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'componentDidMount',
'componentWillUnmount',
'componentDidMount',
]);
} else {
- expect(Scheduler).toHaveYielded(['componentDidMount']);
+ assertLog(['componentDidMount']);
}
act(() => {
renderer.update(
);
});
- expect(Scheduler).toHaveYielded(['componentDidUpdate']);
+ assertLog(['componentDidUpdate']);
act(() => {
renderer.unmount();
});
- expect(Scheduler).toHaveYielded(['componentWillUnmount']);
+ assertLog(['componentWillUnmount']);
});
it('should not double invoke class lifecycles in legacy mode', () => {
@@ -397,7 +374,7 @@ describe('StrictEffectsMode', () => {
ReactTestRenderer.create(
);
});
- expect(Scheduler).toHaveYielded(['componentDidMount']);
+ assertLog(['componentDidMount']);
});
it('double flushing passive effects only results in one double invoke', () => {
@@ -427,7 +404,7 @@ describe('StrictEffectsMode', () => {
});
if (supportsDoubleInvokeEffects()) {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'mount',
'useLayoutEffect mount',
'useEffect mount',
@@ -442,7 +419,7 @@ describe('StrictEffectsMode', () => {
'useEffect mount',
]);
} else {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'mount',
'useLayoutEffect mount',
'useEffect mount',
@@ -492,7 +469,7 @@ describe('StrictEffectsMode', () => {
});
if (supportsDoubleInvokeEffects()) {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'App useLayoutEffect mount',
'App useEffect mount',
'App useLayoutEffect unmount',
@@ -501,10 +478,7 @@ describe('StrictEffectsMode', () => {
'App useEffect mount',
]);
} else {
- expect(Scheduler).toHaveYielded([
- 'App useLayoutEffect mount',
- 'App useEffect mount',
- ]);
+ assertLog(['App useLayoutEffect mount', 'App useEffect mount']);
}
act(() => {
@@ -512,7 +486,7 @@ describe('StrictEffectsMode', () => {
});
if (supportsDoubleInvokeEffects()) {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'App useLayoutEffect unmount',
'Child useLayoutEffect mount',
'App useLayoutEffect mount',
@@ -525,7 +499,7 @@ describe('StrictEffectsMode', () => {
'Child useEffect mount',
]);
} else {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'App useLayoutEffect unmount',
'Child useLayoutEffect mount',
'App useLayoutEffect mount',
@@ -580,7 +554,7 @@ describe('StrictEffectsMode', () => {
});
if (supportsDoubleInvokeEffects()) {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'componentDidMount',
'useLayoutEffect mount',
'useEffect mount',
@@ -592,7 +566,7 @@ describe('StrictEffectsMode', () => {
'useEffect mount',
]);
} else {
- expect(Scheduler).toHaveYielded([
+ assertLog([
'componentDidMount',
'useLayoutEffect mount',
'useEffect mount',
@@ -603,7 +577,7 @@ describe('StrictEffectsMode', () => {
renderer.update(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect unmount',
'useLayoutEffect mount',
'useEffect unmount',
@@ -614,7 +588,7 @@ describe('StrictEffectsMode', () => {
renderer.unmount();
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'componentWillUnmount',
'useLayoutEffect unmount',
'useEffect unmount',
diff --git a/packages/react-reconciler/src/__tests__/StrictEffectsModeDefaults-test.internal.js b/packages/react-reconciler/src/__tests__/StrictEffectsModeDefaults-test.internal.js
index 7a7603d3d9283..365adea441e38 100644
--- a/packages/react-reconciler/src/__tests__/StrictEffectsModeDefaults-test.internal.js
+++ b/packages/react-reconciler/src/__tests__/StrictEffectsModeDefaults-test.internal.js
@@ -13,6 +13,10 @@ let React;
let ReactNoop;
let Scheduler;
let act;
+let assertLog;
+let waitFor;
+let waitForAll;
+let waitForPaint;
describe('StrictEffectsMode defaults', () => {
beforeEach(() => {
@@ -23,6 +27,12 @@ describe('StrictEffectsMode defaults', () => {
Scheduler = require('scheduler');
act = require('jest-react').act;
+ const InternalTestUtils = require('internal-test-utils');
+ waitFor = InternalTestUtils.waitFor;
+ waitForAll = InternalTestUtils.waitForAll;
+ waitForPaint = InternalTestUtils.waitForPaint;
+ assertLog = InternalTestUtils.assertLog;
+
const ReactFeatureFlags = require('shared/ReactFeatureFlags');
ReactFeatureFlags.createRootStrictEffectsByDefault = __DEV__;
});
@@ -46,10 +56,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.renderLegacySyncRoot(
);
});
- expect(Scheduler).toHaveYielded([
- 'useLayoutEffect mount',
- 'useEffect mount',
- ]);
+ assertLog(['useLayoutEffect mount', 'useEffect mount']);
});
it('should not double invoke class lifecycles in legacy mode', () => {
@@ -75,11 +82,11 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.renderLegacySyncRoot(
);
});
- expect(Scheduler).toHaveYielded(['componentDidMount']);
+ assertLog(['componentDidMount']);
});
if (__DEV__) {
- it('should flush double-invoked effects within the same frame as layout effects if there are no passive effects', () => {
+ it('should flush double-invoked effects within the same frame as layout effects if there are no passive effects', async () => {
function ComponentWithEffects({label}) {
React.useLayoutEffect(() => {
Scheduler.unstable_yieldValue(`useLayoutEffect mount "${label}"`);
@@ -90,21 +97,21 @@ describe('StrictEffectsMode defaults', () => {
return label;
}
- act(() => {
+ await act(async () => {
ReactNoop.render(
<>
>,
);
- expect(Scheduler).toFlushUntilNextPaint([
+ await waitForPaint([
'useLayoutEffect mount "one"',
'useLayoutEffect unmount "one"',
'useLayoutEffect mount "one"',
]);
});
- act(() => {
+ await act(async () => {
ReactNoop.render(
<>
@@ -112,8 +119,8 @@ describe('StrictEffectsMode defaults', () => {
>,
);
- expect(Scheduler).toHaveYielded([]);
- expect(Scheduler).toFlushUntilNextPaint([
+ assertLog([]);
+ await waitForPaint([
// Cleanup and re-run "one" (and "two") since there is no dependencies array.
'useLayoutEffect unmount "one"',
'useLayoutEffect mount "one"',
@@ -128,7 +135,7 @@ describe('StrictEffectsMode defaults', () => {
// This test also verifies that double-invoked effects flush synchronously
// within the same frame as passive effects.
- it('should double invoke effects only for newly mounted components', () => {
+ it('should double invoke effects only for newly mounted components', async () => {
function ComponentWithEffects({label}) {
React.useEffect(() => {
Scheduler.unstable_yieldValue(`useEffect mount "${label}"`);
@@ -145,14 +152,14 @@ describe('StrictEffectsMode defaults', () => {
return label;
}
- act(() => {
+ await act(async () => {
ReactNoop.render(
<>
>,
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'useLayoutEffect mount "one"',
'useEffect mount "one"',
'useLayoutEffect unmount "one"',
@@ -162,7 +169,7 @@ describe('StrictEffectsMode defaults', () => {
]);
});
- act(() => {
+ await act(async () => {
ReactNoop.render(
<>
@@ -170,13 +177,13 @@ describe('StrictEffectsMode defaults', () => {
>,
);
- expect(Scheduler).toFlushAndYieldThrough([
+ await waitFor([
// Cleanup and re-run "one" (and "two") since there is no dependencies array.
'useLayoutEffect unmount "one"',
'useLayoutEffect mount "one"',
'useLayoutEffect mount "two"',
]);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'useEffect unmount "one"',
'useEffect mount "one"',
'useEffect mount "two"',
@@ -208,7 +215,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect mount',
'useEffect mount',
'useLayoutEffect unmount',
@@ -221,7 +228,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect unmount',
'useLayoutEffect mount',
'useEffect unmount',
@@ -232,10 +239,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(null);
});
- expect(Scheduler).toHaveYielded([
- 'useLayoutEffect unmount',
- 'useEffect unmount',
- ]);
+ assertLog(['useLayoutEffect unmount', 'useEffect unmount']);
});
it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
@@ -257,7 +261,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useEffect One mount',
'useEffect Two mount',
'useEffect One unmount',
@@ -270,7 +274,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useEffect One unmount',
'useEffect Two unmount',
'useEffect One mount',
@@ -281,10 +285,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(null);
});
- expect(Scheduler).toHaveYielded([
- 'useEffect One unmount',
- 'useEffect Two unmount',
- ]);
+ assertLog(['useEffect One unmount', 'useEffect Two unmount']);
});
it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
@@ -308,7 +309,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect One mount',
'useLayoutEffect Two mount',
'useLayoutEffect One unmount',
@@ -321,7 +322,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect One unmount',
'useLayoutEffect Two unmount',
'useLayoutEffect One mount',
@@ -332,10 +333,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(null);
});
- expect(Scheduler).toHaveYielded([
- 'useLayoutEffect One unmount',
- 'useLayoutEffect Two unmount',
- ]);
+ assertLog(['useLayoutEffect One unmount', 'useLayoutEffect Two unmount']);
});
it('useEffect and useLayoutEffect is called twice when there is no unmount', () => {
@@ -355,7 +353,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect mount',
'useEffect mount',
'useLayoutEffect mount',
@@ -366,16 +364,13 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
- 'useLayoutEffect mount',
- 'useEffect mount',
- ]);
+ assertLog(['useLayoutEffect mount', 'useEffect mount']);
act(() => {
ReactNoop.render(null);
});
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
});
//@gate useModernStrictMode
@@ -430,7 +425,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'componentDidMount',
'componentWillUnmount',
'componentDidMount',
@@ -460,7 +455,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'componentDidMount',
'componentWillUnmount',
'componentDidMount',
@@ -470,13 +465,13 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded(['componentDidUpdate']);
+ assertLog(['componentDidUpdate']);
act(() => {
ReactNoop.render(null);
});
- expect(Scheduler).toHaveYielded(['componentWillUnmount']);
+ assertLog(['componentWillUnmount']);
});
it('double flushing passive effects only results in one double invoke', () => {
@@ -503,7 +498,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'mount',
'useLayoutEffect mount',
'useEffect mount',
@@ -555,7 +550,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'App useLayoutEffect mount',
'App useEffect mount',
'App useLayoutEffect unmount',
@@ -568,7 +563,7 @@ describe('StrictEffectsMode defaults', () => {
_setShowChild(true);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'App useLayoutEffect unmount',
'Child useLayoutEffect mount',
'App useLayoutEffect mount',
@@ -622,7 +617,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'componentDidMount',
'useLayoutEffect mount',
'useEffect mount',
@@ -638,7 +633,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'useLayoutEffect unmount',
'useLayoutEffect mount',
'useEffect unmount',
@@ -649,7 +644,7 @@ describe('StrictEffectsMode defaults', () => {
ReactNoop.render(null);
});
- expect(Scheduler).toHaveYielded([
+ assertLog([
'componentWillUnmount',
'useLayoutEffect unmount',
'useEffect unmount',
diff --git a/packages/react-reconciler/src/__tests__/useEffectEvent-test.js b/packages/react-reconciler/src/__tests__/useEffectEvent-test.js
index c2f58292deb65..3a470a7a465cc 100644
--- a/packages/react-reconciler/src/__tests__/useEffectEvent-test.js
+++ b/packages/react-reconciler/src/__tests__/useEffectEvent-test.js
@@ -26,6 +26,8 @@ describe('useEffectEvent', () => {
let useEffect;
let useLayoutEffect;
let useMemo;
+ let waitForAll;
+ let assertLog;
beforeEach(() => {
React = require('react');
@@ -40,6 +42,10 @@ describe('useEffectEvent', () => {
useEffect = React.useEffect;
useLayoutEffect = React.useLayoutEffect;
useMemo = React.useMemo;
+
+ const InternalTestUtils = require('internal-test-utils');
+ waitForAll = InternalTestUtils.waitForAll;
+ assertLog = InternalTestUtils.assertLog;
});
function Text(props) {
@@ -48,7 +54,7 @@ describe('useEffectEvent', () => {
}
// @gate enableUseEffectEventHook
- it('memoizes basic case correctly', () => {
+ it('memoizes basic case correctly', async () => {
class IncrementButton extends React.PureComponent {
increment = () => {
this.props.onClick();
@@ -72,7 +78,7 @@ describe('useEffectEvent', () => {
const button = React.createRef(null);
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Increment', 'Count: 0']);
+ await waitForAll(['Increment', 'Count: 0']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -81,7 +87,7 @@ describe('useEffectEvent', () => {
);
act(button.current.increment);
- expect(Scheduler).toHaveYielded(['Increment', 'Count: 1']);
+ assertLog(['Increment', 'Count: 1']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -90,7 +96,7 @@ describe('useEffectEvent', () => {
);
act(button.current.increment);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Increment',
// Event should use the updated callback function closed over the new value.
'Count: 2',
@@ -104,7 +110,7 @@ describe('useEffectEvent', () => {
// Increase the increment prop amount
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Increment', 'Count: 2']);
+ await waitForAll(['Increment', 'Count: 2']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -114,7 +120,7 @@ describe('useEffectEvent', () => {
// Event uses the new prop
act(button.current.increment);
- expect(Scheduler).toHaveYielded(['Increment', 'Count: 12']);
+ assertLog(['Increment', 'Count: 12']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -124,7 +130,7 @@ describe('useEffectEvent', () => {
});
// @gate enableUseEffectEventHook
- it('can be defined more than once', () => {
+ it('can be defined more than once', async () => {
class IncrementButton extends React.PureComponent {
increment = () => {
this.props.onClick();
@@ -158,7 +164,7 @@ describe('useEffectEvent', () => {
const button = React.createRef(null);
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Increment', 'Count: 0']);
+ await waitForAll(['Increment', 'Count: 0']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -167,7 +173,7 @@ describe('useEffectEvent', () => {
);
act(button.current.increment);
- expect(Scheduler).toHaveYielded(['Increment', 'Count: 5']);
+ assertLog(['Increment', 'Count: 5']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -176,7 +182,7 @@ describe('useEffectEvent', () => {
);
act(button.current.multiply);
- expect(Scheduler).toHaveYielded(['Increment', 'Count: 25']);
+ assertLog(['Increment', 'Count: 25']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -186,7 +192,7 @@ describe('useEffectEvent', () => {
});
// @gate enableUseEffectEventHook
- it('does not preserve `this` in event functions', () => {
+ it('does not preserve `this` in event functions', async () => {
class GreetButton extends React.PureComponent {
greet = () => {
this.props.onClick();
@@ -217,7 +223,7 @@ describe('useEffectEvent', () => {
const button = React.createRef(null);
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Say hej', 'Greeting: Seb says hej']);
+ await waitForAll(['Say hej', 'Greeting: Seb says hej']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -226,10 +232,7 @@ describe('useEffectEvent', () => {
);
act(button.current.greet);
- expect(Scheduler).toHaveYielded([
- 'Say hej',
- 'Greeting: undefined says hej',
- ]);
+ assertLog(['Say hej', 'Greeting: undefined says hej']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -272,11 +275,11 @@ describe('useEffectEvent', () => {
// If something throws, we try one more time synchronously in case the error was
// caused by a data race. See recoverFromConcurrentError
- expect(Scheduler).toHaveYielded(['Count: 0', 'Count: 0']);
+ assertLog(['Count: 0', 'Count: 0']);
});
// @gate enableUseEffectEventHook
- it("useLayoutEffect shouldn't re-fire when event handlers change", () => {
+ it("useLayoutEffect shouldn't re-fire when event handlers change", async () => {
class IncrementButton extends React.PureComponent {
increment = () => {
this.props.onClick();
@@ -307,8 +310,8 @@ describe('useEffectEvent', () => {
const button = React.createRef(null);
ReactNoop.render(
);
- expect(Scheduler).toHaveYielded([]);
- expect(Scheduler).toFlushAndYield([
+ assertLog([]);
+ await waitForAll([
'Increment',
'Count: 0',
'Effect: by 2',
@@ -323,7 +326,7 @@ describe('useEffectEvent', () => {
);
act(button.current.increment);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Increment',
// Effect should not re-run because the dependency hasn't changed.
'Count: 3',
@@ -336,7 +339,7 @@ describe('useEffectEvent', () => {
);
act(button.current.increment);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Increment',
// Event should use the updated callback function closed over the new value.
'Count: 4',
@@ -350,7 +353,7 @@ describe('useEffectEvent', () => {
// Increase the increment prop amount
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Increment',
'Count: 4',
'Effect: by 20',
@@ -366,7 +369,7 @@ describe('useEffectEvent', () => {
// Event uses the new prop
act(button.current.increment);
- expect(Scheduler).toHaveYielded(['Increment', 'Count: 34']);
+ assertLog(['Increment', 'Count: 34']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -376,7 +379,7 @@ describe('useEffectEvent', () => {
});
// @gate enableUseEffectEventHook
- it("useEffect shouldn't re-fire when event handlers change", () => {
+ it("useEffect shouldn't re-fire when event handlers change", async () => {
class IncrementButton extends React.PureComponent {
increment = () => {
this.props.onClick();
@@ -407,7 +410,7 @@ describe('useEffectEvent', () => {
const button = React.createRef(null);
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Increment',
'Count: 0',
'Effect: by 2',
@@ -422,7 +425,7 @@ describe('useEffectEvent', () => {
);
act(button.current.increment);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Increment',
// Effect should not re-run because the dependency hasn't changed.
'Count: 3',
@@ -435,7 +438,7 @@ describe('useEffectEvent', () => {
);
act(button.current.increment);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Increment',
// Event should use the updated callback function closed over the new value.
'Count: 4',
@@ -449,7 +452,7 @@ describe('useEffectEvent', () => {
// Increase the increment prop amount
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Increment',
'Count: 4',
'Effect: by 20',
@@ -465,7 +468,7 @@ describe('useEffectEvent', () => {
// Event uses the new prop
act(button.current.increment);
- expect(Scheduler).toHaveYielded(['Increment', 'Count: 34']);
+ assertLog(['Increment', 'Count: 34']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -475,7 +478,7 @@ describe('useEffectEvent', () => {
});
// @gate enableUseEffectEventHook
- it('is stable in a custom hook', () => {
+ it('is stable in a custom hook', async () => {
class IncrementButton extends React.PureComponent {
increment = () => {
this.props.onClick();
@@ -512,7 +515,7 @@ describe('useEffectEvent', () => {
const button = React.createRef(null);
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Increment',
'Count: 0',
'Effect: by 2',
@@ -527,7 +530,7 @@ describe('useEffectEvent', () => {
);
act(button.current.increment);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Increment',
// Effect should not re-run because the dependency hasn't changed.
'Count: 3',
@@ -540,7 +543,7 @@ describe('useEffectEvent', () => {
);
act(button.current.increment);
- expect(Scheduler).toHaveYielded([
+ assertLog([
'Increment',
// Event should use the updated callback function closed over the new value.
'Count: 4',
@@ -554,7 +557,7 @@ describe('useEffectEvent', () => {
// Increase the increment prop amount
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'Increment',
'Count: 4',
'Effect: by 20',
@@ -570,7 +573,7 @@ describe('useEffectEvent', () => {
// Event uses the new prop
act(button.current.increment);
- expect(Scheduler).toHaveYielded(['Increment', 'Count: 34']);
+ assertLog(['Increment', 'Count: 34']);
expect(ReactNoop).toMatchRenderedOutput(
<>
@@ -580,7 +583,7 @@ describe('useEffectEvent', () => {
});
// @gate enableUseEffectEventHook
- it('is mutated before all other effects', () => {
+ it('is mutated before all other effects', async () => {
function Counter({value}) {
useInsertionEffect(() => {
Scheduler.unstable_yieldValue('Effect value: ' + value);
@@ -597,14 +600,14 @@ describe('useEffectEvent', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['Effect value: 1', 'Event value: 1']);
+ await waitForAll(['Effect value: 1', 'Event value: 1']);
act(() => ReactNoop.render(
));
- expect(Scheduler).toHaveYielded(['Effect value: 2', 'Event value: 2']);
+ assertLog(['Effect value: 2', 'Event value: 2']);
});
// @gate enableUseEffectEventHook
- it("doesn't provide a stable identity", () => {
+ it("doesn't provide a stable identity", async () => {
function Counter({shouldRender, value}) {
const onClick = useEffectEvent(() => {
Scheduler.unstable_yieldValue(
@@ -627,16 +630,16 @@ describe('useEffectEvent', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'onClick, shouldRender=true, value=0',
'onClick, shouldRender=true, value=0',
]);
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['onClick, shouldRender=true, value=1']);
+ await waitForAll(['onClick, shouldRender=true, value=1']);
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'onClick, shouldRender=false, value=2',
'onClick, shouldRender=false, value=2',
]);
@@ -676,7 +679,7 @@ describe('useEffectEvent', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Commit new event handler']);
+ assertLog(['Commit new event handler']);
expect(root).toMatchRenderedOutput('Latest rendered value 1');
expect(committedEventHandler()).toBe('Value seen by useEffectEvent: 1');
@@ -686,14 +689,14 @@ describe('useEffectEvent', () => {
});
// No new event handler should be committed, because it was omitted from
// the dependency array.
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
// But the event handler should still be able to see the latest value.
expect(root).toMatchRenderedOutput('Latest rendered value 2');
expect(committedEventHandler()).toBe('Value seen by useEffectEvent: 2');
});
// @gate enableUseEffectEventHook
- it('integration: implements docs chat room example', () => {
+ it('integration: implements docs chat room example', async () => {
function createConnection() {
let connectedCallback;
let timeout;
@@ -738,47 +741,47 @@ describe('useEffectEvent', () => {
}
act(() => ReactNoop.render(
));
- expect(Scheduler).toHaveYielded(['Welcome to the general room!']);
+ assertLog(['Welcome to the general room!']);
expect(ReactNoop).toMatchRenderedOutput(
,
);
jest.advanceTimersByTime(100);
Scheduler.unstable_advanceTime(100);
- expect(Scheduler).toHaveYielded(['Connected! theme: light']);
+ assertLog(['Connected! theme: light']);
// change roomId only
act(() => ReactNoop.render(
));
- expect(Scheduler).toHaveYielded(['Welcome to the music room!']);
+ assertLog(['Welcome to the music room!']);
expect(ReactNoop).toMatchRenderedOutput(
,
);
jest.advanceTimersByTime(100);
Scheduler.unstable_advanceTime(100);
// should trigger a reconnect
- expect(Scheduler).toHaveYielded(['Connected! theme: light']);
+ assertLog(['Connected! theme: light']);
// change theme only
act(() => ReactNoop.render(
));
- expect(Scheduler).toHaveYielded(['Welcome to the music room!']);
+ assertLog(['Welcome to the music room!']);
expect(ReactNoop).toMatchRenderedOutput(
,
);
jest.advanceTimersByTime(100);
Scheduler.unstable_advanceTime(100);
// should not trigger a reconnect
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
// change roomId only
act(() => ReactNoop.render(
));
- expect(Scheduler).toHaveYielded(['Welcome to the travel room!']);
+ assertLog(['Welcome to the travel room!']);
expect(ReactNoop).toMatchRenderedOutput(
,
);
jest.advanceTimersByTime(100);
Scheduler.unstable_advanceTime(100);
// should trigger a reconnect
- expect(Scheduler).toHaveYielded(['Connected! theme: dark']);
+ assertLog(['Connected! theme: dark']);
});
// @gate enableUseEffectEventHook
@@ -837,12 +840,9 @@ describe('useEffectEvent', () => {
,
),
);
- expect(Scheduler).toHaveYielded([
- 'Add to cart',
- 'url: /shop/1, numberOfItems: 0',
- ]);
+ assertLog(['Add to cart', 'url: /shop/1, numberOfItems: 0']);
act(button.current.addToCart);
- expect(Scheduler).toHaveYielded(['Add to cart']);
+ assertLog(['Add to cart']);
act(() =>
ReactNoop.render(
@@ -851,9 +851,6 @@ describe('useEffectEvent', () => {
,
),
);
- expect(Scheduler).toHaveYielded([
- 'Add to cart',
- 'url: /shop/2, numberOfItems: 1',
- ]);
+ assertLog(['Add to cart', 'url: /shop/2, numberOfItems: 1']);
});
});