Skip to content

Commit

Permalink
act() - s / flushPassiveEffects / Scheduler.unstable_flushWithoutYi…
Browse files Browse the repository at this point in the history
…elding (#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
  • Loading branch information
Sunil Pai committed May 16, 2019
1 parent 3776d2e commit bf443f2
Showing 1 changed file with 33 additions and 9 deletions.
42 changes: 33 additions & 9 deletions src/ReactTestRendererAct.js
Expand Up @@ -14,23 +14,42 @@ import {
} from 'react-reconciler/inline.test';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import warningWithoutStack from 'shared/warningWithoutStack';
import {warnAboutMissingMockScheduler} from 'shared/ReactFeatureFlags';
import enqueueTask from 'shared/enqueueTask';
import * as Scheduler from 'scheduler';

const {ReactShouldWarnActingUpdates} = ReactSharedInternals;

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

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

function flushEffectsAndMicroTasks(onDone: (err: ?Error) => void) {
function flushWorkAndMicroTasks(onDone: (err: ?Error) => void) {
try {
flushPassiveEffects();
flushWork();
enqueueTask(() => {
if (flushPassiveEffects()) {
flushEffectsAndMicroTasks(onDone);
if (flushWork()) {
flushWorkAndMicroTasks(onDone);
} else {
onDone();
}
Expand All @@ -40,6 +59,11 @@ function flushEffectsAndMicroTasks(onDone: (err: ?Error) => void) {
}
}

// we track the 'depth' of the act() calls with this counter,
// so we can tell if any async act() calls try to run in parallel.

let actingUpdatesScopeDepth = 0;

function act(callback: () => Thenable) {
let previousActingUpdatesScopeDepth;
if (__DEV__) {
Expand Down Expand Up @@ -100,7 +124,7 @@ function act(callback: () => Thenable) {
called = true;
result.then(
() => {
flushEffectsAndMicroTasks((err: ?Error) => {
flushWorkAndMicroTasks((err: ?Error) => {
onDone();
if (err) {
reject(err);
Expand Down Expand Up @@ -128,7 +152,7 @@ function act(callback: () => Thenable) {

// flush effects until none remain, and cleanup
try {
while (flushPassiveEffects()) {}
flushWork();
onDone();
} catch (err) {
onDone();
Expand Down

0 comments on commit bf443f2

Please sign in to comment.