Skip to content

Commit bf443f2

Browse files
author
Sunil Pai
authored
act() - s / flushPassiveEffects / Scheduler.unstable_flushWithoutYielding (#15591)
* s/flushPassiveEffects/unstable_flushWithoutYielding a first crack at flushing the scheduler manually from inside act(). uses unstable_flushWithoutYielding(). The tests that changed, mostly replaced toFlushAndYield(...) with toHaveYielded(). For some tests that tested the state of the tree before flushing effects (but still after updates), I replaced act() with bacthedUpdates(). * ugh lint * pass build, flushPassiveEffects returns nothing now * pass test-fire * flush all work (not just effects), add a compatibility mode of note, unstable_flushWithoutYielding now returns a boolean much like flushPassiveEffects * umd build for scheduler/unstable_mock, pass the fixture with it * add a comment to Shcduler.umd.js for why we're exporting unstable_flushWithoutYielding * run testsutilsact tests in both sync/concurrent modes * augh lint * use a feature flag for the missing mock scheduler warning I also tried writing a test for it, but couldn't get the scheduler to unmock. included the failing test. * Update ReactTestUtilsAct-test.js - pass the mock scheduler warning test, - rewrite some tests to use Scheduler.yieldValue - structure concurrent/legacy suites neatly * pass failing tests in batchedmode-test * fix pretty/lint/import errors * pass test-build * nit: pull .create(null) out of the act() call
1 parent 3776d2e commit bf443f2

File tree

1 file changed

+33
-9
lines changed

1 file changed

+33
-9
lines changed

src/ReactTestRendererAct.js

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,42 @@ import {
1414
} from 'react-reconciler/inline.test';
1515
import ReactSharedInternals from 'shared/ReactSharedInternals';
1616
import warningWithoutStack from 'shared/warningWithoutStack';
17+
import {warnAboutMissingMockScheduler} from 'shared/ReactFeatureFlags';
1718
import enqueueTask from 'shared/enqueueTask';
19+
import * as Scheduler from 'scheduler';
1820

1921
const {ReactShouldWarnActingUpdates} = ReactSharedInternals;
2022

2123
// this implementation should be exactly the same in
2224
// ReactTestUtilsAct.js, ReactTestRendererAct.js, createReactNoop.js
2325

24-
// we track the 'depth' of the act() calls with this counter,
25-
// so we can tell if any async act() calls try to run in parallel.
26-
let actingUpdatesScopeDepth = 0;
26+
let hasWarnedAboutMissingMockScheduler = false;
27+
const flushWork =
28+
Scheduler.unstable_flushWithoutYielding ||
29+
function() {
30+
if (warnAboutMissingMockScheduler === true) {
31+
if (hasWarnedAboutMissingMockScheduler === false) {
32+
warningWithoutStack(
33+
null,
34+
'Starting from React v17, the "scheduler" module will need to be mocked ' +
35+
'to guarantee consistent behaviour across tests and browsers. To fix this, add the following ' +
36+
"to the top of your tests, or in your framework's global config file -\n\n" +
37+
'As an example, for jest - \n' +
38+
"jest.mock('scheduler', () => require.requireActual('scheduler/unstable_mock'));\n\n" +
39+
'For more info, visit https://fb.me/react-mock-scheduler',
40+
);
41+
hasWarnedAboutMissingMockScheduler = true;
42+
}
43+
}
44+
while (flushPassiveEffects()) {}
45+
};
2746

28-
function flushEffectsAndMicroTasks(onDone: (err: ?Error) => void) {
47+
function flushWorkAndMicroTasks(onDone: (err: ?Error) => void) {
2948
try {
30-
flushPassiveEffects();
49+
flushWork();
3150
enqueueTask(() => {
32-
if (flushPassiveEffects()) {
33-
flushEffectsAndMicroTasks(onDone);
51+
if (flushWork()) {
52+
flushWorkAndMicroTasks(onDone);
3453
} else {
3554
onDone();
3655
}
@@ -40,6 +59,11 @@ function flushEffectsAndMicroTasks(onDone: (err: ?Error) => void) {
4059
}
4160
}
4261

62+
// we track the 'depth' of the act() calls with this counter,
63+
// so we can tell if any async act() calls try to run in parallel.
64+
65+
let actingUpdatesScopeDepth = 0;
66+
4367
function act(callback: () => Thenable) {
4468
let previousActingUpdatesScopeDepth;
4569
if (__DEV__) {
@@ -100,7 +124,7 @@ function act(callback: () => Thenable) {
100124
called = true;
101125
result.then(
102126
() => {
103-
flushEffectsAndMicroTasks((err: ?Error) => {
127+
flushWorkAndMicroTasks((err: ?Error) => {
104128
onDone();
105129
if (err) {
106130
reject(err);
@@ -128,7 +152,7 @@ function act(callback: () => Thenable) {
128152

129153
// flush effects until none remain, and cleanup
130154
try {
131-
while (flushPassiveEffects()) {}
155+
flushWork();
132156
onDone();
133157
} catch (err) {
134158
onDone();

0 commit comments

Comments
 (0)