{/* Updated */}
@@ -1057,7 +1063,7 @@ describe('ReactIncrementalSideEffects', () => {
// However, once we render fully, we will have enough time to finish it all
// at once.
- expect(Scheduler).toFlushAndYield(['Bar', 'Bar']);
+ await waitForAll(['Bar', 'Bar']);
expect(ReactNoop.getChildrenAsJSX()).toEqual(
@@ -1074,7 +1080,7 @@ describe('ReactIncrementalSideEffects', () => {
// moves to "current" without flushing due to having lower priority. Does this
// even happen? Maybe a child doesn't get processed because it is lower prio?
- it('calls callback after update is flushed', () => {
+ it('calls callback after update is flushed', async () => {
let instance;
class Foo extends React.Component {
constructor() {
@@ -1088,18 +1094,18 @@ describe('ReactIncrementalSideEffects', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(
);
let called = false;
instance.setState({text: 'bar'}, () => {
expect(ReactNoop).toMatchRenderedOutput(
);
called = true;
});
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(called).toBe(true);
});
- it('calls setState callback even if component bails out', () => {
+ it('calls setState callback even if component bails out', async () => {
let instance;
class Foo extends React.Component {
constructor() {
@@ -1116,19 +1122,19 @@ describe('ReactIncrementalSideEffects', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ReactNoop).toMatchRenderedOutput(
);
let called = false;
instance.setState({}, () => {
called = true;
});
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(called).toBe(true);
});
// TODO: Test that callbacks are not lost if an update is preempted.
- it('calls componentWillUnmount after a deletion, even if nested', () => {
+ it('calls componentWillUnmount after a deletion, even if nested', async () => {
const ops = [];
class Bar extends React.Component {
@@ -1170,11 +1176,11 @@ describe('ReactIncrementalSideEffects', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([]);
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([
'A',
'Wrapper',
@@ -1188,7 +1194,7 @@ describe('ReactIncrementalSideEffects', () => {
]);
});
- it('calls componentDidMount/Update after insertion/update', () => {
+ it('calls componentDidMount/Update after insertion/update', async () => {
let ops = [];
class Bar extends React.Component {
@@ -1233,7 +1239,7 @@ describe('ReactIncrementalSideEffects', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([
'mount:A',
'mount:B',
@@ -1249,7 +1255,7 @@ describe('ReactIncrementalSideEffects', () => {
ops = [];
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([
'update:A',
'update:B',
@@ -1263,7 +1269,7 @@ describe('ReactIncrementalSideEffects', () => {
]);
});
- it('invokes ref callbacks after insertion/update/unmount', () => {
+ it('invokes ref callbacks after insertion/update/unmount', async () => {
let classInstance = null;
let ops = [];
@@ -1310,7 +1316,7 @@ describe('ReactIncrementalSideEffects', () => {
// Refs that switch function instances get reinvoked
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([
// detach all refs that switched handlers first.
null,
@@ -1323,7 +1329,7 @@ describe('ReactIncrementalSideEffects', () => {
ops = [];
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(ops).toEqual([
// unmount
null,
@@ -1334,7 +1340,7 @@ describe('ReactIncrementalSideEffects', () => {
// TODO: Test that mounts, updates, refs, unmounts and deletions happen in the
// expected way for aborted and resumed render life-cycles.
- it('supports string refs', () => {
+ it('supports string refs', async () => {
let fooInstance = null;
class Bar extends React.Component {
@@ -1354,8 +1360,8 @@ describe('ReactIncrementalSideEffects', () => {
}
ReactNoop.render(
);
- expect(() => {
- expect(Scheduler).toFlushWithoutYielding();
+ await expect(async () => {
+ await waitForAll([]);
}).toErrorDev([
'Warning: Component "Foo" contains the string ref "bar". ' +
'Support for string refs will be removed in a future major release. ' +
diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js b/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js
index de60712c11665..3c548469fb67a 100644
--- a/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js
@@ -15,6 +15,9 @@ let ReactNoop;
let Scheduler;
let ContinuousEventPriority;
let act;
+let waitForAll;
+let waitFor;
+let assertLog;
describe('ReactIncrementalUpdates', () => {
beforeEach(() => {
@@ -26,6 +29,11 @@ describe('ReactIncrementalUpdates', () => {
act = require('jest-react').act;
ContinuousEventPriority =
require('react-reconciler/constants').ContinuousEventPriority;
+
+ const InternalTestUtils = require('internal-test-utils');
+ waitForAll = InternalTestUtils.waitForAll;
+ waitFor = InternalTestUtils.waitFor;
+ assertLog = InternalTestUtils.assertLog;
});
function flushNextRenderIfExpired() {
@@ -37,7 +45,7 @@ describe('ReactIncrementalUpdates', () => {
ReactNoop.flushSync();
}
- it('applies updates in order of priority', () => {
+ it('applies updates in order of priority', async () => {
let state;
class Foo extends React.Component {
state = {};
@@ -58,14 +66,14 @@ describe('ReactIncrementalUpdates', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYieldThrough(['commit']);
+ await waitFor(['commit']);
expect(state).toEqual({a: 'a'});
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(state).toEqual({a: 'a', b: 'b', c: 'c'});
});
- it('applies updates with equal priority in insertion order', () => {
+ it('applies updates with equal priority in insertion order', async () => {
let state;
class Foo extends React.Component {
state = {};
@@ -82,11 +90,11 @@ describe('ReactIncrementalUpdates', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(state).toEqual({a: 'a', b: 'b', c: 'c'});
});
- it('only drops updates with equal or lesser priority when replaceState is called', () => {
+ it('only drops updates with equal or lesser priority when replaceState is called', async () => {
let instance;
class Foo extends React.Component {
state = {};
@@ -104,7 +112,7 @@ describe('ReactIncrementalUpdates', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['render', 'componentDidMount']);
+ await waitForAll(['render', 'componentDidMount']);
ReactNoop.flushSync(() => {
React.startTransition(() => {
@@ -122,14 +130,14 @@ describe('ReactIncrementalUpdates', () => {
// Even though a replaceState has been already scheduled, it hasn't been
// flushed yet because it has async priority.
expect(instance.state).toEqual({a: 'a', b: 'b'});
- expect(Scheduler).toHaveYielded(['render', 'componentDidUpdate']);
+ assertLog(['render', 'componentDidUpdate']);
- expect(Scheduler).toFlushAndYield(['render', 'componentDidUpdate']);
+ await waitForAll(['render', 'componentDidUpdate']);
// Now the rest of the updates are flushed, including the replaceState.
expect(instance.state).toEqual({c: 'c', d: 'd'});
});
- it('can abort an update, schedule additional updates, and resume', () => {
+ it('can abort an update, schedule additional updates, and resume', async () => {
let instance;
class Foo extends React.Component {
state = {};
@@ -140,7 +148,7 @@ describe('ReactIncrementalUpdates', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
function createUpdate(letter) {
return () => {
@@ -159,7 +167,7 @@ describe('ReactIncrementalUpdates', () => {
});
// Begin the updates but don't flush them yet
- expect(Scheduler).toFlushAndYieldThrough(['a', 'b', 'c']);
+ await waitFor(['a', 'b', 'c']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Schedule some more updates at different priorities
@@ -174,11 +182,11 @@ describe('ReactIncrementalUpdates', () => {
// The sync updates should have flushed, but not the async ones.
if (gate(flags => flags.enableUnifiedSyncLane)) {
- expect(Scheduler).toHaveYielded(['d', 'e', 'f']);
+ assertLog(['d', 'e', 'f']);
expect(ReactNoop).toMatchRenderedOutput(
);
} else {
// Update d was dropped and replaced by e.
- expect(Scheduler).toHaveYielded(['e', 'f']);
+ assertLog(['e', 'f']);
expect(ReactNoop).toMatchRenderedOutput(
);
}
@@ -186,7 +194,7 @@ describe('ReactIncrementalUpdates', () => {
// they should be processed again, to ensure that the terminal state
// is deterministic.
if (gate(flags => !flags.enableUnifiedSyncLane)) {
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// Since 'g' is in a transition, we'll process 'd' separately first.
// That causes us to process 'd' with 'e' and 'f' rebased.
'd',
@@ -202,7 +210,7 @@ describe('ReactIncrementalUpdates', () => {
'g',
]);
} else {
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// Then we'll re-process everything for 'g'.
'a',
'b',
@@ -216,7 +224,7 @@ describe('ReactIncrementalUpdates', () => {
expect(ReactNoop).toMatchRenderedOutput(
);
});
- it('can abort an update, schedule a replaceState, and resume', () => {
+ it('can abort an update, schedule a replaceState, and resume', async () => {
let instance;
class Foo extends React.Component {
state = {};
@@ -227,7 +235,7 @@ describe('ReactIncrementalUpdates', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
function createUpdate(letter) {
return () => {
@@ -246,7 +254,7 @@ describe('ReactIncrementalUpdates', () => {
});
// Begin the updates but don't flush them yet
- expect(Scheduler).toFlushAndYieldThrough(['a', 'b', 'c']);
+ await waitFor(['a', 'b', 'c']);
expect(ReactNoop).toMatchRenderedOutput(
);
// Schedule some more updates at different priorities
@@ -264,10 +272,10 @@ describe('ReactIncrementalUpdates', () => {
// The sync updates should have flushed, but not the async ones.
if (gate(flags => flags.enableUnifiedSyncLane)) {
- expect(Scheduler).toHaveYielded(['d', 'e', 'f']);
+ assertLog(['d', 'e', 'f']);
} else {
// Update d was dropped and replaced by e.
- expect(Scheduler).toHaveYielded(['e', 'f']);
+ assertLog(['e', 'f']);
}
expect(ReactNoop).toMatchRenderedOutput(
);
@@ -275,7 +283,7 @@ describe('ReactIncrementalUpdates', () => {
// they should be processed again, to ensure that the terminal state
// is deterministic.
if (gate(flags => !flags.enableUnifiedSyncLane)) {
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// Since 'g' is in a transition, we'll process 'd' separately first.
// That causes us to process 'd' with 'e' and 'f' rebased.
'd',
@@ -291,7 +299,7 @@ describe('ReactIncrementalUpdates', () => {
'g',
]);
} else {
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// Then we'll re-process everything for 'g'.
'a',
'b',
@@ -305,7 +313,7 @@ describe('ReactIncrementalUpdates', () => {
expect(ReactNoop).toMatchRenderedOutput(
);
});
- it('passes accumulation of previous updates to replaceState updater function', () => {
+ it('passes accumulation of previous updates to replaceState updater function', async () => {
let instance;
class Foo extends React.Component {
state = {};
@@ -315,7 +323,7 @@ describe('ReactIncrementalUpdates', () => {
}
}
ReactNoop.render(
);
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
instance.setState({a: 'a'});
instance.setState({b: 'b'});
@@ -324,11 +332,11 @@ describe('ReactIncrementalUpdates', () => {
instance.updater.enqueueReplaceState(instance, previousState => ({
previousState,
}));
- expect(Scheduler).toFlushWithoutYielding();
+ await waitForAll([]);
expect(instance.state).toEqual({previousState: {a: 'a', b: 'b'}});
});
- it('does not call callbacks that are scheduled by another callback until a later commit', () => {
+ it('does not call callbacks that are scheduled by another callback until a later commit', async () => {
class Foo extends React.Component {
state = {};
componentDidMount() {
@@ -347,7 +355,7 @@ describe('ReactIncrementalUpdates', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
'render',
'did mount',
'render',
@@ -357,7 +365,7 @@ describe('ReactIncrementalUpdates', () => {
]);
});
- it('gives setState during reconciliation the same priority as whatever level is currently reconciling', () => {
+ it('gives setState during reconciliation the same priority as whatever level is currently reconciling', async () => {
let instance;
class Foo extends React.Component {
@@ -373,7 +381,7 @@ describe('ReactIncrementalUpdates', () => {
}
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield(['render']);
+ await waitForAll(['render']);
ReactNoop.flushSync(() => {
instance.setState({a: 'a'});
@@ -384,17 +392,13 @@ describe('ReactIncrementalUpdates', () => {
expect(instance.state).toEqual({a: 'a', b: 'b'});
if (gate(flags => flags.deferRenderPhaseUpdateToNextBatch)) {
- expect(Scheduler).toHaveYielded([
- 'componentWillReceiveProps',
- 'render',
- 'render',
- ]);
+ assertLog(['componentWillReceiveProps', 'render', 'render']);
} else {
- expect(Scheduler).toHaveYielded(['componentWillReceiveProps', 'render']);
+ assertLog(['componentWillReceiveProps', 'render']);
}
});
- it('updates triggered from inside a class setState updater', () => {
+ it('updates triggered from inside a class setState updater', async () => {
let instance;
class Foo extends React.Component {
state = {};
@@ -406,7 +410,7 @@ describe('ReactIncrementalUpdates', () => {
}
ReactNoop.render(
);
- expect(Scheduler).toFlushAndYield([
+ await waitForAll([
// Initial render
'render',
]);
@@ -451,7 +455,7 @@ describe('ReactIncrementalUpdates', () => {
this.setState({a: 'a'});
return {b: 'b'};
});
- expect(Scheduler).toFlushAndYield(
+ await waitForAll(
gate(flags =>
flags.deferRenderPhaseUpdateToNextBatch
? // In the new reconciler, updates inside the render phase are
@@ -529,24 +533,20 @@ describe('ReactIncrementalUpdates', () => {
return null;
}
- act(() => {
+ act(async () => {
React.startTransition(() => {
ReactNoop.render(
);
});
flushNextRenderIfExpired();
- expect(Scheduler).toHaveYielded([]);
- expect(Scheduler).toFlushAndYield([
- 'Render: 0',
- 'Commit: 0',
- 'Render: 1',
- ]);
+ assertLog([]);
+ await waitForAll(['Render: 0', 'Commit: 0', 'Render: 1']);
Scheduler.unstable_advanceTime(10000);
React.startTransition(() => {
setCount(2);
});
flushNextRenderIfExpired();
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
});
});
@@ -559,7 +559,7 @@ describe('ReactIncrementalUpdates', () => {
ReactNoop.flushSync(() => {
ReactNoop.render(
);
});
- expect(Scheduler).toHaveYielded(['A']);
+ assertLog(['A']);
Scheduler.unstable_advanceTime(10000);
@@ -567,7 +567,7 @@ describe('ReactIncrementalUpdates', () => {
ReactNoop.render(
);
});
flushNextRenderIfExpired();
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
});
it('regression: does not expire soon due to previous expired work', () => {
@@ -581,7 +581,7 @@ describe('ReactIncrementalUpdates', () => {
});
Scheduler.unstable_advanceTime(10000);
flushNextRenderIfExpired();
- expect(Scheduler).toHaveYielded(['A']);
+ assertLog(['A']);
Scheduler.unstable_advanceTime(10000);
@@ -589,7 +589,7 @@ describe('ReactIncrementalUpdates', () => {
ReactNoop.render(
);
});
flushNextRenderIfExpired();
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
});
it('when rebasing, does not exclude updates that were already committed, regardless of priority', async () => {
@@ -620,7 +620,7 @@ describe('ReactIncrementalUpdates', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['Committed: ']);
+ assertLog(['Committed: ']);
expect(root).toMatchRenderedOutput(null);
await act(async () => {
@@ -633,13 +633,9 @@ describe('ReactIncrementalUpdates', () => {
);
});
if (gate(flags => flags.enableUnifiedSyncLane)) {
- expect(Scheduler).toHaveYielded([
- 'Committed: B',
- 'Committed: BCD',
- 'Committed: ABCD',
- ]);
+ assertLog(['Committed: B', 'Committed: BCD', 'Committed: ABCD']);
} else {
- expect(Scheduler).toHaveYielded([
+ assertLog([
// A and B are pending. B is higher priority, so we'll render that first.
'Committed: B',
// Because A comes first in the queue, we're now in rebase mode. B must
@@ -685,7 +681,7 @@ describe('ReactIncrementalUpdates', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded([]);
+ assertLog([]);
expect(root).toMatchRenderedOutput(null);
await act(async () => {
@@ -697,13 +693,9 @@ describe('ReactIncrementalUpdates', () => {
);
});
if (gate(flags => flags.enableUnifiedSyncLane)) {
- expect(Scheduler).toHaveYielded([
- 'Committed: B',
- 'Committed: BCD',
- 'Committed: ABCD',
- ]);
+ assertLog(['Committed: B', 'Committed: BCD', 'Committed: ABCD']);
} else {
- expect(Scheduler).toHaveYielded([
+ assertLog([
// A and B are pending. B is higher priority, so we'll render that first.
'Committed: B',
// Because A comes first in the queue, we're now in rebase mode. B must
diff --git a/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js b/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js
index 89d9de5226d9e..709a30e6b035d 100644
--- a/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js
@@ -5,6 +5,9 @@ let startTransition;
let useState;
let useEffect;
let act;
+let assertLog;
+let waitFor;
+let waitForPaint;
describe('ReactInterleavedUpdates', () => {
beforeEach(() => {
@@ -17,6 +20,11 @@ describe('ReactInterleavedUpdates', () => {
startTransition = React.startTransition;
useState = React.useState;
useEffect = React.useEffect;
+
+ const InternalTestUtils = require('internal-test-utils');
+ assertLog = InternalTestUtils.assertLog;
+ waitFor = InternalTestUtils.waitFor;
+ waitForPaint = InternalTestUtils.waitForPaint;
});
function Text({text}) {
@@ -53,7 +61,7 @@ describe('ReactInterleavedUpdates', () => {
>,
);
});
- expect(Scheduler).toHaveYielded([0, 0, 0]);
+ assertLog([0, 0, 0]);
expect(root).toMatchRenderedOutput('000');
await act(async () => {
@@ -61,7 +69,7 @@ describe('ReactInterleavedUpdates', () => {
updateChildren(1);
});
// Partially render the children. Only the first one.
- expect(Scheduler).toFlushAndYieldThrough([1]);
+ await waitFor([1]);
// In an interleaved event, schedule an update on each of the children.
// Including the two that haven't rendered yet.
@@ -70,11 +78,11 @@ describe('ReactInterleavedUpdates', () => {
});
// We should continue rendering without including the interleaved updates.
- expect(Scheduler).toFlushUntilNextPaint([1, 1]);
+ await waitForPaint([1, 1]);
expect(root).toMatchRenderedOutput('111');
});
// The interleaved updates flush in a separate render.
- expect(Scheduler).toHaveYielded([2, 2, 2]);
+ assertLog([2, 2, 2]);
expect(root).toMatchRenderedOutput('222');
});
@@ -96,7 +104,7 @@ describe('ReactInterleavedUpdates', () => {
await act(async () => {
root.render(
);
});
- expect(Scheduler).toHaveYielded(['A0', 'B0', 'C0']);
+ assertLog(['A0', 'B0', 'C0']);
expect(root).toMatchRenderedOutput('A0B0C0');
await act(async () => {
@@ -104,7 +112,7 @@ describe('ReactInterleavedUpdates', () => {
startTransition(() => {
setStep(1);
});
- expect(Scheduler).toFlushAndYieldThrough(['A1', 'B1']);
+ await waitFor(['A1', 'B1']);
// Schedule an interleaved update. This gets placed on a special queue.
startTransition(() => {
@@ -112,7 +120,7 @@ describe('ReactInterleavedUpdates', () => {
});
// Finish rendering the first update.
- expect(Scheduler).toFlushUntilNextPaint(['C1']);
+ await waitForPaint(['C1']);
// Schedule another update. (In the regression case, this was treated
// as a normal, non-interleaved update and it was inserted into the queue
@@ -122,7 +130,7 @@ describe('ReactInterleavedUpdates', () => {
});
});
// The last update should win.
- expect(Scheduler).toHaveYielded(['A3', 'B3', 'C3']);
+ assertLog(['A3', 'B3', 'C3']);
expect(root).toMatchRenderedOutput('A3B3C3');
});
});
diff --git a/packages/react/src/__tests__/ReactProfiler-test.internal.js b/packages/react/src/__tests__/ReactProfiler-test.internal.js
index bd7f13afac8d9..5635f2d61bf31 100644
--- a/packages/react/src/__tests__/ReactProfiler-test.internal.js
+++ b/packages/react/src/__tests__/ReactProfiler-test.internal.js
@@ -1874,7 +1874,7 @@ describe(`onPostCommit`, () => {
loadModules();
});
- it('should report time spent in passive effects', () => {
+ it('should report time spent in passive effects', async () => {
const callback = jest.fn();
const ComponentWithEffects = () => {
@@ -1910,7 +1910,7 @@ describe(`onPostCommit`, () => {
,
);
});
- Scheduler.unstable_flushAll();
+ await waitForAll([]);
expect(callback).toHaveBeenCalledTimes(1);
@@ -1931,7 +1931,7 @@ describe(`onPostCommit`, () => {
,
);
});
- Scheduler.unstable_flushAll();
+ await waitForAll([]);
expect(callback).toHaveBeenCalledTimes(2);
@@ -1950,7 +1950,7 @@ describe(`onPostCommit`, () => {
,
);
});
- Scheduler.unstable_flushAll();
+ await waitForAll([]);
expect(callback).toHaveBeenCalledTimes(3);