From 805d96253755725c3a434d2d14918b13e1993bda Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Sat, 23 Feb 2019 19:15:44 -0800 Subject: [PATCH 1/2] Throw in tests if work is done before emptying log Test renderer already does this. Makes it harder to miss unexpected behavior by forcing you to assert on every logged value. --- .../src/createReactNoop.js | 146 ++++++++---------- .../ReactExpiration-test.internal.js | 4 +- ...eactHooksWithNoopRenderer-test.internal.js | 44 +++--- ...tIncrementalErrorHandling-test.internal.js | 2 + .../ReactIncrementalPerf-test.internal.js | 1 + ...eactIncrementalScheduling-test.internal.js | 6 +- .../ReactIncrementalUpdates-test.internal.js | 4 +- ...tSuspenseWithNoopRenderer-test.internal.js | 82 +++++----- ...ReactIncrementalPerf-test.internal.js.snap | 14 +- .../__tests__/ReactProfiler-test.internal.js | 7 +- 10 files changed, 151 insertions(+), 159 deletions(-) diff --git a/packages/react-noop-renderer/src/createReactNoop.js b/packages/react-noop-renderer/src/createReactNoop.js index 985493ea471..743a24fcc12 100644 --- a/packages/react-noop-renderer/src/createReactNoop.js +++ b/packages/react-noop-renderer/src/createReactNoop.js @@ -22,6 +22,7 @@ import {createPortal} from 'shared/ReactPortal'; import expect from 'expect'; import {REACT_FRAGMENT_TYPE, REACT_ELEMENT_TYPE} from 'shared/ReactSymbols'; import warningWithoutStack from 'shared/warningWithoutStack'; +import invariant from 'shared/invariant'; // for .act's return value type Thenable = { @@ -534,55 +535,81 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { const roots = new Map(); const DEFAULT_ROOT_ID = ''; - let yieldedValues = null; - - let didYield; - let unitsRemaining; + let yieldedValues: Array = []; + let didStop: boolean = false; + let expectedNumberOfYields: number = -1; function shouldYield() { - // Check if we already yielded - if (didYield || yieldedValues !== null) { - return true; - } - - // If there are no remaining units of work, and we haven't timed out, then - // we should yield. if ( - unitsRemaining-- <= 0 && + expectedNumberOfYields !== -1 && + yieldedValues.length >= expectedNumberOfYields && (scheduledCallbackTimeout === -1 || elapsedTimeInMs < scheduledCallbackTimeout) ) { - didYield = true; + // We yielded at least as many values as expected. Stop rendering. + didStop = true; return true; } - - // Otherwise, keep working. + // Keep rendering. return false; } - function* flushUnitsOfWork(n: number): Generator, void, void> { - unitsRemaining = n; - didYield = false; + function flushAll(): Array { + assertYieldsWereCleared(); + yieldedValues = []; + while (scheduledCallback !== null) { + const cb = scheduledCallback; + scheduledCallback = null; + const didTimeout = + scheduledCallbackTimeout !== -1 && + scheduledCallbackTimeout < elapsedTimeInMs; + cb(didTimeout); + } + const values = yieldedValues; + yieldedValues = []; + return values; + } + + function flushNumberOfYields(count: number): Array { + assertYieldsWereCleared(); + expectedNumberOfYields = count; + didStop = false; + yieldedValues = []; try { - while (!didYield && scheduledCallback !== null) { - let cb = scheduledCallback; + while (scheduledCallback !== null && !didStop) { + const cb = scheduledCallback; scheduledCallback = null; const didTimeout = scheduledCallbackTimeout !== -1 && scheduledCallbackTimeout < elapsedTimeInMs; cb(didTimeout); - if (yieldedValues !== null) { - const values = yieldedValues; - yieldedValues = null; - yield values; - } } + return yieldedValues; } finally { - unitsRemaining = -1; - didYield = false; + expectedNumberOfYields = -1; + didStop = false; + yieldedValues = []; } } + function yieldValue(value: mixed): void { + yieldedValues.push(value); + } + + function clearYields(): Array { + const values = yieldedValues; + yieldedValues = []; + return values; + } + + function assertYieldsWereCleared() { + invariant( + yieldedValues.length === 0, + 'Log of yielded values is not empty. ' + + 'Call ReactNoop.clearYields(...) first.', + ); + } + function childToJSX(child, text) { if (text !== null) { return text; @@ -638,6 +665,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { const ReactNoop = { getChildren(rootID: string = DEFAULT_ROOT_ID) { + assertYieldsWereCleared(); const container = rootContainers.get(rootID); if (container) { return container.children; @@ -747,53 +775,19 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { return NoopRenderer.findHostInstance(component); }, - flush(): Array { - let values = yieldedValues || []; - yieldedValues = null; - // eslint-disable-next-line no-for-of-loops/no-for-of-loops - for (const value of flushUnitsOfWork(Infinity)) { - values.push(...value); - } - return values; - }, + flush: flushAll, // TODO: Should only be used via a Jest plugin (like we do with the // test renderer). - unstable_flushNumberOfYields(n: number): Array { - let values = yieldedValues || []; - yieldedValues = null; - // eslint-disable-next-line no-for-of-loops/no-for-of-loops - for (const value of flushUnitsOfWork(Infinity)) { - values.push(...value); - if (values.length >= n) { - break; - } - } - return values; - }, + unstable_flushNumberOfYields: flushNumberOfYields, flushThrough(expected: Array): void { - let actual = []; - if (expected.length !== 0) { - // eslint-disable-next-line no-for-of-loops/no-for-of-loops - for (const value of flushUnitsOfWork(Infinity)) { - actual.push(...value); - if (actual.length >= expected.length) { - break; - } - } - } + const actual = flushNumberOfYields(expected.length); expect(actual).toEqual(expected); }, flushNextYield(): Array { - let actual = null; - // eslint-disable-next-line no-for-of-loops/no-for-of-loops - for (const value of flushUnitsOfWork(Infinity)) { - actual = value; - break; - } - return actual !== null ? actual : []; + return flushNumberOfYields(1); }, flushWithHostCounters( @@ -838,28 +832,12 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { }, flushExpired(): Array { - let values = yieldedValues || []; - yieldedValues = null; - // eslint-disable-next-line no-for-of-loops/no-for-of-loops - for (const value of flushUnitsOfWork(0)) { - values.push(...value); - } - return values; + return flushNumberOfYields(0); }, - yield(value: mixed) { - if (yieldedValues === null) { - yieldedValues = [value]; - } else { - yieldedValues.push(value); - } - }, + yield: yieldValue, - clearYields() { - const values = yieldedValues; - yieldedValues = null; - return values; - }, + clearYields, hasScheduledCallback() { return !!scheduledCallback; diff --git a/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js b/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js index 65f06b6dc3f..2d6742af907 100644 --- a/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js @@ -88,7 +88,7 @@ describe('ReactExpiration', () => { // haven't entered an idle callback, the scheduler must assume that we're // inside the same event. ReactNoop.advanceTime(2000); - expect(ReactNoop.clearYields()).toEqual(null); + expect(ReactNoop.clearYields()).toEqual([]); expect(ReactNoop.getChildren()).toEqual([span('B')]); // Schedule another update. ReactNoop.render(); @@ -142,7 +142,7 @@ describe('ReactExpiration', () => { // haven't entered an idle callback, the scheduler must assume that we're // inside the same event. ReactNoop.advanceTime(2000); - expect(ReactNoop.clearYields()).toEqual(null); + expect(ReactNoop.clearYields()).toEqual([]); expect(ReactNoop.getChildren()).toEqual([span('B')]); // Perform some synchronous work. Again, the scheduler must assume we're diff --git a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js index bb8e033623f..b2d2da8683e 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js @@ -583,6 +583,7 @@ describe('ReactHooksWithNoopRenderer', () => { ReactNoop.flushSync(() => { counter.current.dispatch(INCREMENT); }); + expect(ReactNoop.clearYields()).toEqual(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); ReactNoop.flush(); @@ -636,12 +637,13 @@ describe('ReactHooksWithNoopRenderer', () => { // Destroying the first child shouldn't prevent the passive effect from // being executed ReactNoop.render([passive]); - expect(ReactNoop.flush()).toEqual(['Passive effect']); + expect(ReactNoop.clearYields()).toEqual(['Passive effect']); + expect(ReactNoop.flush()).toEqual([]); expect(ReactNoop.getChildren()).toEqual([span('Passive')]); // (No effects are left to flush.) ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(null); + expect(ReactNoop.clearYields()).toEqual([]); }); it('flushes passive effects even if siblings schedule an update', () => { @@ -737,11 +739,11 @@ describe('ReactHooksWithNoopRenderer', () => { // Before the effects have a chance to flush, schedule another update ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop.clearYields()).toEqual([ // The previous effect flushes before the reconciliation 'Committed state when effect was fired: 0', - 1, ]); + expect(ReactNoop.flush()).toEqual([1]); expect(ReactNoop.getChildren()).toEqual([span(1)]); ReactNoop.flushPassiveEffects(); @@ -796,7 +798,8 @@ describe('ReactHooksWithNoopRenderer', () => { // Rendering again should flush the previous commit's effects ReactNoop.render(); - ReactNoop.flushThrough(['Schedule update [0]', 'Count: 0']); + expect(ReactNoop.clearYields()).toEqual(['Schedule update [0]']); + ReactNoop.flushThrough(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]); ReactNoop.batchedUpdates(() => { @@ -806,7 +809,8 @@ describe('ReactHooksWithNoopRenderer', () => { expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.flush()).toEqual(['Schedule update [1]', 'Count: 1']); + expect(ReactNoop.clearYields()).toEqual(['Schedule update [1]']); + expect(ReactNoop.flush()).toEqual(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); }); @@ -829,7 +833,8 @@ describe('ReactHooksWithNoopRenderer', () => { // Enqueuing this update forces the passive effect to be flushed -- // updateCount(1) happens first, so 2 wins. act(() => _updateCount(2)); - expect(ReactNoop.flush()).toEqual(['Will set count to 1', 'Count: 2']); + expect(ReactNoop.clearYields()).toEqual(['Will set count to 1']); + expect(ReactNoop.flush()).toEqual(['Count: 2']); expect(ReactNoop.getChildren()).toEqual([span('Count: 2')]); }); @@ -875,7 +880,8 @@ describe('ReactHooksWithNoopRenderer', () => { // Enqueuing this update forces the passive effect to be flushed -- // updateCount(1) happens first, so 2 wins. act(() => _updateCount(2)); - expect(ReactNoop.flush()).toEqual(['Will set count to 1', 'Count: 2']); + expect(ReactNoop.clearYields()).toEqual(['Will set count to 1']); + expect(ReactNoop.flush()).toEqual(['Count: 2']); expect(ReactNoop.getChildren()).toEqual([span('Count: 2')]); expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1); @@ -905,7 +911,7 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.renderLegacySyncRoot(); // Even in sync mode, effects are deferred until after paint - expect(ReactNoop.flush()).toEqual(['Count: (empty)']); + expect(ReactNoop.clearYields()).toEqual(['Count: (empty)']); expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]); // Now fire the effects ReactNoop.flushPassiveEffects(); @@ -1006,7 +1012,7 @@ describe('ReactHooksWithNoopRenderer', () => { expect(ReactNoop.flush()).toEqual(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(null); + expect(ReactNoop.clearYields()).toEqual([]); ReactNoop.render(null); expect(ReactNoop.flush()).toEqual(['Did destroy [0]']); @@ -1075,7 +1081,7 @@ describe('ReactHooksWithNoopRenderer', () => { // Nothing changed, so no effect should have fired expect(ReactNoop.flush()).toEqual(['Count: 1']); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(null); + expect(ReactNoop.clearYields()).toEqual([]); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); ReactNoop.render(); @@ -1293,7 +1299,9 @@ describe('ReactHooksWithNoopRenderer', () => { describe('useLayoutEffect', () => { it('fires layout effects after the host has been mutated', () => { function getCommittedText() { + const yields = ReactNoop.clearYields(); const children = ReactNoop.getChildren(); + ReactNoop.yield(yields); if (children === null) { return null; } @@ -1308,11 +1316,11 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([0, 'Current: 0']); + expect(ReactNoop.flush()).toEqual([[0], 'Current: 0']); expect(ReactNoop.getChildren()).toEqual([span(0)]); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([1, 'Current: 1']); + expect(ReactNoop.flush()).toEqual([[1], 'Current: 1']); expect(ReactNoop.getChildren()).toEqual([span(1)]); }); @@ -1344,8 +1352,8 @@ describe('ReactHooksWithNoopRenderer', () => { expect(committedText).toEqual('0'); ReactNoop.render(); + expect(ReactNoop.clearYields()).toEqual(['Mount normal [current: 0]']); expect(ReactNoop.flush()).toEqual([ - 'Mount normal [current: 0]', 'Unmount layout [current: 0]', 'Mount layout [current: 1]', ]); @@ -1552,11 +1560,11 @@ describe('ReactHooksWithNoopRenderer', () => { ping(2); ping(3); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop.clearYields()).toEqual([]); jest.advanceTimersByTime(100); - expect(ReactNoop.flush()).toEqual(['ping: 3']); + expect(ReactNoop.clearYields()).toEqual(['ping: 3']); ping(4); jest.advanceTimersByTime(20); @@ -1564,10 +1572,10 @@ describe('ReactHooksWithNoopRenderer', () => { ping(6); jest.advanceTimersByTime(80); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop.clearYields()).toEqual([]); jest.advanceTimersByTime(20); - expect(ReactNoop.flush()).toEqual(['ping: 6']); + expect(ReactNoop.clearYields()).toEqual(['ping: 6']); }); it('should return the same ref during re-renders', () => { diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js index f4a24cfc0ae..97959aa53e1 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js @@ -615,6 +615,8 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.flush(); }).toThrow('Hello'); expect(ReactNoop.clearYields()).toEqual([ + 'BrokenRender', + // React retries one more time 'RethrowErrorBoundary render', 'BrokenRender', diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js index c3b18696380..90501df0fb1 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js @@ -652,6 +652,7 @@ describe('ReactDebugFiberPerf', () => { ReactNoop.flushSync(() => { ReactNoop.render(); }); + expect(ReactNoop.clearYields()).toEqual(['Foo']); ReactNoop.flush(); expect(getFlameChart()).toMatchSnapshot(); }); diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.internal.js index 353a20ce65b..4f23c2d599a 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.internal.js @@ -243,10 +243,14 @@ describe('ReactIncrementalScheduling', () => { ReactNoop.render(); }); // The cDM update should not have flushed yet because it has async priority. + expect(ReactNoop.clearYields()).toEqual([ + 'render: 0', + 'componentDidMount (before setState): 0', + 'componentDidMount (after setState): 0', + ]); expect(ReactNoop.getChildren()).toEqual([span(0)]); // Now flush the cDM update. - ReactNoop.clearYields(); expect(ReactNoop.flush()).toEqual(['render: 1', 'componentDidUpdate: 1']); expect(ReactNoop.getChildren()).toEqual([span(1)]); diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.internal.js index 80a1e0ae5fc..5b87cbe02a9 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.internal.js @@ -173,12 +173,12 @@ describe('ReactIncrementalUpdates', () => { instance.setState(createUpdate('g')); // The sync updates should have flushed, but not the async ones + expect(ReactNoop.clearYields()).toEqual(['e', 'f']); expect(ReactNoop.getChildren()).toEqual([span('ef')]); // Now flush the remaining work. Even though e and f were already processed, // they should be processed again, to ensure that the terminal state // is deterministic. - ReactNoop.clearYields(); expect(ReactNoop.flush()).toEqual([ 'a', 'b', @@ -247,12 +247,12 @@ describe('ReactIncrementalUpdates', () => { // The sync updates should have flushed, but not the async ones. Update d // was dropped and replaced by e. + expect(ReactNoop.clearYields()).toEqual(['e', 'f']); expect(ReactNoop.getChildren()).toEqual([span('f')]); // Now flush the remaining work. Even though e and f were already processed, // they should be processed again, to ensure that the terminal state // is deterministic. - ReactNoop.clearYields(); expect(ReactNoop.flush()).toEqual([ 'a', 'b', diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js index daf898c6dfd..d8712812328 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js @@ -126,13 +126,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { // Flush the promise completely await advanceTimers(50); // Renders successfully - expect(ReactNoop.flush()).toEqual([ - 'Promise resolved [A]', - 'Foo', - 'Bar', - 'A', - 'B', - ]); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [A]']); + expect(ReactNoop.flush()).toEqual(['Foo', 'Bar', 'A', 'B']); expect(ReactNoop.getChildren()).toEqual([span('A'), span('B')]); }); @@ -172,7 +167,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { ReactNoop.expire(1000); await advanceTimers(1000); - expect(ReactNoop.flush()).toEqual(['Promise resolved [A]', 'A']); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [A]']); + expect(ReactNoop.flush()).toEqual(['A']); expect(ReactNoop.getChildren()).toEqual([span('A'), span('Loading B...')]); // Advance time by enough that the second Suspense's promise resolves @@ -180,7 +176,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { ReactNoop.expire(1000); await advanceTimers(1000); - expect(ReactNoop.flush()).toEqual(['Promise resolved [B]', 'B']); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [B]']); + expect(ReactNoop.flush()).toEqual(['B']); expect(ReactNoop.getChildren()).toEqual([span('A'), span('B')]); }); @@ -207,13 +204,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { // Wait for data to resolve await advanceTimers(100); // Renders successfully - expect(ReactNoop.flush()).toEqual([ - 'Promise resolved [B]', - 'A', - 'B', - 'C', - 'D', - ]); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [B]']); + expect(ReactNoop.flush()).toEqual(['A', 'B', 'C', 'D']); expect(ReactNoop.getChildren()).toEqual([ span('A'), span('B'), @@ -259,8 +251,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { await advanceTimers(1000); textResourceShouldFail = false; + expect(ReactNoop.clearYields()).toEqual(['Promise rejected [Result]']); + expect(ReactNoop.flush()).toEqual([ - 'Promise rejected [Result]', 'Error! [Result]', // React retries one more time @@ -316,8 +309,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { await advanceTimers(1000); textResourceShouldFail = false; + expect(ReactNoop.clearYields()).toEqual(['Promise rejected [Result]']); expect(ReactNoop.flush()).toEqual([ - 'Promise rejected [Result]', 'Error! [Result]', // React retries one more time @@ -346,6 +339,7 @@ describe('ReactSuspenseWithNoopRenderer', () => { ReactNoop.render(); ReactNoop.flush(); await advanceTimers(0); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [1]']); ReactNoop.flush(); expect(ReactNoop.getChildren()).toEqual([span('A'), span('1')]); @@ -363,12 +357,12 @@ describe('ReactSuspenseWithNoopRenderer', () => { ReactNoop.flushSync(() => { ReactNoop.render(); }); - expect(ReactNoop.flush()).toEqual(['B', '1']); + expect(ReactNoop.clearYields()).toEqual(['B', '1']); expect(ReactNoop.getChildren()).toEqual([span('B'), span('1')]); // Unblock the low-pri text and finish await advanceTimers(0); - expect(ReactNoop.flush()).toEqual(['Promise resolved [2]']); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [2]']); expect(ReactNoop.getChildren()).toEqual([span('B'), span('1')]); }); @@ -393,7 +387,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { expect(ReactNoop.getChildren()).toEqual([]); await advanceTimers(0); - expect(ReactNoop.flush()).toEqual(['Promise resolved [A]', 'A', 'B']); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [A]']); + expect(ReactNoop.flush()).toEqual(['A', 'B']); expect(ReactNoop.getChildren()).toEqual([span('A'), span('B')]); }); @@ -460,7 +455,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { // Once the promise resolves, we render the suspended view await advanceTimers(10000); - expect(ReactNoop.flush()).toEqual(['Promise resolved [Async]', 'Async']); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [Async]']); + expect(ReactNoop.flush()).toEqual(['Async']); expect(ReactNoop.getChildren()).toEqual([span('Async'), span('Sync')]); }); @@ -509,8 +505,10 @@ describe('ReactSuspenseWithNoopRenderer', () => { // timed out at 1.5 seconds. So, 2 seconds have elapsed since the // placeholder timed out. That means we still haven't reached the 2.5 second // threshold of the inner placeholder. - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop.clearYields()).toEqual([ 'Promise resolved [Outer content]', + ]); + expect(ReactNoop.flush()).toEqual([ 'Outer content', 'Suspend! [Inner content]', 'Loading inner...', @@ -535,10 +533,10 @@ describe('ReactSuspenseWithNoopRenderer', () => { // Finally, flush the inner promise. We should see the complete screen. ReactNoop.expire(1000); await advanceTimers(1000); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop.clearYields()).toEqual([ 'Promise resolved [Inner content]', - 'Inner content', ]); + expect(ReactNoop.flush()).toEqual(['Inner content']); expect(ReactNoop.getChildren()).toEqual([ span('Sync'), span('Outer content'), @@ -571,7 +569,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { // Once the promise resolves, we render the suspended view await advanceTimers(0); - expect(ReactNoop.flush()).toEqual(['Promise resolved [Async]', 'Async']); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [Async]']); + expect(ReactNoop.flush()).toEqual(['Async']); expect(ReactNoop.getChildren()).toEqual([span('Async'), span('Sync')]); }); @@ -628,7 +627,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { // Once the promise resolves, we render the suspended view await advanceTimers(1000); - expect(ReactNoop.flush()).toEqual(['Promise resolved [Async]', 'Async']); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [Async]']); + expect(ReactNoop.flush()).toEqual(['Async']); expect(ReactNoop.getChildren()).toEqual([span('Async'), span('Sync')]); }); @@ -672,12 +672,11 @@ describe('ReactSuspenseWithNoopRenderer', () => { await advanceTimers(100); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop.clearYields()).toEqual([ 'Promise resolved [A]', 'Promise resolved [B]', - 'A', - 'B', ]); + expect(ReactNoop.flush()).toEqual(['A', 'B']); expect(ReactNoop.getChildren()).toEqual([span('A'), span('B')]); }); @@ -701,7 +700,8 @@ describe('ReactSuspenseWithNoopRenderer', () => { // Resolve the promise await advanceTimers(1); // We can now resume rendering - expect(ReactNoop.flush()).toEqual(['Promise resolved [Async]', 'Async']); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [Async]']); + expect(ReactNoop.flush()).toEqual(['Async']); expect(ReactNoop.getChildren()).toEqual([span('Async')]); }); @@ -747,10 +747,12 @@ describe('ReactSuspenseWithNoopRenderer', () => { await advanceTimers(10000); // Flush the remaining work. - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop.clearYields()).toEqual([ 'Promise resolved [A]', 'Promise resolved [B]', ]); + // Nothing else to render. + expect(ReactNoop.flush()).toEqual([]); expect(ReactNoop.getChildren()).toEqual([span('C')]); }); @@ -863,8 +865,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { ]); expect(ReactNoop.getChildren()).toEqual([span('Loading...')]); + ReactNoop.expire(100); await advanceTimers(100); - expect(ReactNoop.expire(100)).toEqual([ + expect(ReactNoop.clearYields()).toEqual([ 'Promise resolved [Result]', 'Result', ]); @@ -945,7 +948,7 @@ describe('ReactSuspenseWithNoopRenderer', () => { ); await advanceTimers(100); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop.clearYields()).toEqual([ 'Promise resolved [Step: 2]', 'Step: 2', ]); @@ -1289,8 +1292,9 @@ describe('ReactSuspenseWithNoopRenderer', () => { , ); + ReactNoop.expire(1000); await advanceTimers(1000); - expect(ReactNoop.expire(1000)).toEqual(['Promise resolved [B]', 'B']); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [B]', 'B']); expect(ReactNoop.getChildrenAsJSX()).toEqual( @@ -1377,8 +1381,16 @@ describe('ReactSuspenseWithNoopRenderer', () => { } ReactNoop.renderLegacySyncRoot(); + + expect(ReactNoop.clearYields()).toEqual([ + 'Suspend! [Hi]', + 'Loading...', + // Re-render due to lifecycle update + 'Loading...', + ]); expect(ReactNoop.getChildren()).toEqual([span('Loading...')]); await advanceTimers(100); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [Hi]', 'Hi']); expect(ReactNoop.getChildren()).toEqual([span('Hi')]); }); diff --git a/packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap b/packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap index 8312adf89c5..3f5f23c5a9b 100644 --- a/packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap +++ b/packages/react-reconciler/src/__tests__/__snapshots__/ReactIncrementalPerf-test.internal.js.snap @@ -212,12 +212,6 @@ exports[`ReactDebugFiberPerf measures deferred work in chunks 1`] = ` "⚛ (Waiting for async callback... will force flush in 5250 ms) // Start rendering through B -⚛ (React Tree Reconciliation: Yielded) - ⚛ Parent [mount] - ⚛ A [mount] - -⚛ (Waiting for async callback... will force flush in 5250 ms) - ⚛ (React Tree Reconciliation: Yielded) ⚛ Parent [mount] ⚛ A [mount] @@ -227,17 +221,11 @@ exports[`ReactDebugFiberPerf measures deferred work in chunks 1`] = ` ⚛ (Waiting for async callback... will force flush in 5250 ms) // Complete the rest -⚛ (React Tree Reconciliation: Yielded) +⚛ (React Tree Reconciliation: Completed Root) ⚛ Parent [mount] ⚛ B [mount] ⚛ Child [mount] ⚛ C [mount] - -⚛ (Waiting for async callback... will force flush in 5250 ms) - -⚛ (React Tree Reconciliation: Completed Root) - ⚛ Parent [mount] - ⚛ C [mount] ⚛ Child [mount] ⚛ (Committing Changes) diff --git a/packages/react/src/__tests__/ReactProfiler-test.internal.js b/packages/react/src/__tests__/ReactProfiler-test.internal.js index f98c7fbfa33..987d71f3ef3 100644 --- a/packages/react/src/__tests__/ReactProfiler-test.internal.js +++ b/packages/react/src/__tests__/ReactProfiler-test.internal.js @@ -1254,6 +1254,7 @@ describe('Profiler', () => { ReactNoop.advanceTime(200); + expect(ReactNoop.clearYields()).toEqual(['Parent:componentDidMount:one']); ReactNoop.flush(); expect(ReactNoop.getRoot('two').current.actualDuration).toBe(14); @@ -2273,10 +2274,8 @@ describe('Profiler', () => { // Once the promise resolves, we render the suspended view await awaitableAdvanceTimers(10000); - expect(ReactNoop.flush()).toEqual([ - 'Promise resolved [Async]', - 'AsyncText [Async]', - ]); + expect(ReactNoop.clearYields()).toEqual(['Promise resolved [Async]']); + expect(ReactNoop.flush()).toEqual(['AsyncText [Async]']); expect(ReactNoop.getChildrenAsJSX()).toEqual('AsyncSync'); expect(onRender).toHaveBeenCalledTimes(3); From ce0d4bbe1b88adabd48beb14f8a7ab875022651a Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Mon, 25 Feb 2019 11:43:37 -0800 Subject: [PATCH 2/2] Convert ReactNoop tests to use jest matchers The matchers warn if work is flushed while the log is empty. This is the pattern we already follow for test renderer. I've used the same APIs as test renderer, so it should be easy to switch between the two. --- .../createSubscription-test.internal.js | 56 +-- .../react-art/src/__tests__/ReactART-test.js | 4 +- .../src/createReactNoop.js | 27 +- .../ReactExpiration-test.internal.js | 24 +- .../src/__tests__/ReactFragment-test.js | 104 ++--- ...eactHooksWithNoopRenderer-test.internal.js | 357 +++++++++--------- .../ReactIncremental-test.internal.js | 202 +++++----- ...tIncrementalErrorHandling-test.internal.js | 116 +++--- .../ReactIncrementalErrorLogging-test.js | 8 +- .../ReactIncrementalErrorReplay-test.js | 4 +- .../ReactIncrementalPerf-test.internal.js | 64 ++-- ...eactIncrementalReflection-test.internal.js | 48 ++- ...eactIncrementalScheduling-test.internal.js | 80 ++-- ...actIncrementalSideEffects-test.internal.js | 122 +++--- .../ReactIncrementalTriangle-test.internal.js | 6 +- .../ReactIncrementalUpdates-test.internal.js | 48 +-- .../src/__tests__/ReactMemo-test.internal.js | 58 +-- .../ReactNewContext-test.internal.js | 146 +++---- .../src/__tests__/ReactPersistent-test.js | 18 +- ...tSuspenseWithNoopRenderer-test.internal.js | 214 +++++------ .../__tests__/ReactTopLevelFragment-test.js | 20 +- .../src/__tests__/ReactTopLevelText-test.js | 8 +- .../ReactTestRenderer-test.internal.js | 2 +- .../__tests__/ReactProfiler-test.internal.js | 23 +- .../src/__tests__/forwardRef-test.internal.js | 16 +- .../react/src/__tests__/forwardRef-test.js | 40 +- scripts/jest/matchers/reactTestMatchers.js | 105 ++++++ scripts/jest/setupTests.js | 9 +- .../spec-equivalence-reporter/setupTests.js | 9 +- 29 files changed, 1007 insertions(+), 931 deletions(-) create mode 100644 scripts/jest/matchers/reactTestMatchers.js diff --git a/packages/create-subscription/src/__tests__/createSubscription-test.internal.js b/packages/create-subscription/src/__tests__/createSubscription-test.internal.js index cbbb34979a3..39969ac4bd9 100644 --- a/packages/create-subscription/src/__tests__/createSubscription-test.internal.js +++ b/packages/create-subscription/src/__tests__/createSubscription-test.internal.js @@ -65,16 +65,16 @@ describe('createSubscription', () => { ); // Updates while subscribed should re-render the child component - expect(ReactNoop.flush()).toEqual(['default']); + expect(ReactNoop).toFlushAndYield(['default']); observable.next(123); - expect(ReactNoop.flush()).toEqual([123]); + expect(ReactNoop).toFlushAndYield([123]); observable.next('abc'); - expect(ReactNoop.flush()).toEqual(['abc']); + expect(ReactNoop).toFlushAndYield(['abc']); // Unmounting the subscriber should remove listeners ReactNoop.render(
); observable.next(456); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toFlushAndYield([]); }); it('should support observable types like RxJS ReplaySubject', () => { @@ -102,13 +102,13 @@ describe('createSubscription', () => { const observable = createReplaySubject('initial'); ReactNoop.render({render}); - expect(ReactNoop.flush()).toEqual(['initial']); + expect(ReactNoop).toFlushAndYield(['initial']); observable.next('updated'); - expect(ReactNoop.flush()).toEqual(['updated']); + expect(ReactNoop).toFlushAndYield(['updated']); // Unsetting the subscriber prop should reset subscribed values ReactNoop.render({render}); - expect(ReactNoop.flush()).toEqual(['default']); + expect(ReactNoop).toFlushAndYield(['default']); }); describe('Promises', () => { @@ -141,19 +141,19 @@ describe('createSubscription', () => { // Test a promise that resolves after render ReactNoop.render({render}); - expect(ReactNoop.flush()).toEqual(['loading']); + expect(ReactNoop).toFlushAndYield(['loading']); resolveA(true); await promiseA; - expect(ReactNoop.flush()).toEqual(['finished']); + expect(ReactNoop).toFlushAndYield(['finished']); // Test a promise that resolves before render // Note that this will require an extra render anyway, // Because there is no way to synchronously get a Promise's value rejectB(false); ReactNoop.render({render}); - expect(ReactNoop.flush()).toEqual(['loading']); + expect(ReactNoop).toFlushAndYield(['loading']); await promiseB.catch(() => true); - expect(ReactNoop.flush()).toEqual(['failed']); + expect(ReactNoop).toFlushAndYield(['failed']); }); it('should still work if unsubscription is managed incorrectly', async () => { @@ -177,9 +177,9 @@ describe('createSubscription', () => { // Subscribe first to Promise A then Promise B ReactNoop.render({render}); - expect(ReactNoop.flush()).toEqual(['default']); + expect(ReactNoop).toFlushAndYield(['default']); ReactNoop.render({render}); - expect(ReactNoop.flush()).toEqual(['default']); + expect(ReactNoop).toFlushAndYield(['default']); // Resolve both Promises resolveB(123); @@ -187,7 +187,7 @@ describe('createSubscription', () => { await Promise.all([promiseA, promiseB]); // Ensure that only Promise B causes an update - expect(ReactNoop.flush()).toEqual([123]); + expect(ReactNoop).toFlushAndYield([123]); }); it('should not call setState for a Promise that resolves after unmount', async () => { @@ -211,11 +211,11 @@ describe('createSubscription', () => { }); ReactNoop.render({render}); - expect(ReactNoop.flush()).toEqual(['rendered']); + expect(ReactNoop).toFlushAndYield(['rendered']); // Unmount ReactNoop.render(null); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); // Resolve Promise should not trigger a setState warning resolvePromise(true); @@ -245,21 +245,21 @@ describe('createSubscription', () => { ); // Updates while subscribed should re-render the child component - expect(ReactNoop.flush()).toEqual(['a-0']); + expect(ReactNoop).toFlushAndYield(['a-0']); // Unsetting the subscriber prop should reset subscribed values ReactNoop.render( {render}, ); - expect(ReactNoop.flush()).toEqual(['b-0']); + expect(ReactNoop).toFlushAndYield(['b-0']); // Updates to the old subscribable should not re-render the child component observableA.next('a-1'); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toFlushAndYield([]); // Updates to the bew subscribable should re-render the child component observableB.next('b-1'); - expect(ReactNoop.flush()).toEqual(['b-1']); + expect(ReactNoop).toFlushAndYield(['b-1']); }); it('should ignore values emitted by a new subscribable until the commit phase', () => { @@ -315,12 +315,12 @@ describe('createSubscription', () => { const observableB = createBehaviorSubject('b-0'); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Subscriber: a-0', 'Child: a-0']); + expect(ReactNoop).toFlushAndYield(['Subscriber: a-0', 'Child: a-0']); expect(log).toEqual(['Parent.componentDidMount']); // Start React update, but don't finish ReactNoop.render(); - ReactNoop.flushThrough(['Subscriber: b-0']); + expect(ReactNoop).toFlushAndYieldThrough(['Subscriber: b-0']); expect(log).toEqual(['Parent.componentDidMount']); // Emit some updates from the uncommitted subscribable @@ -335,7 +335,7 @@ describe('createSubscription', () => { // We expect the last emitted update to be rendered (because of the commit phase value check) // But the intermediate ones should be ignored, // And the final rendered output should be the higher-priority observable. - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Child: b-0', 'Subscriber: b-3', 'Child: b-3', @@ -402,12 +402,12 @@ describe('createSubscription', () => { const observableB = createBehaviorSubject('b-0'); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Subscriber: a-0', 'Child: a-0']); + expect(ReactNoop).toFlushAndYield(['Subscriber: a-0', 'Child: a-0']); expect(log).toEqual(['Parent.componentDidMount']); // Start React update, but don't finish ReactNoop.render(); - ReactNoop.flushThrough(['Subscriber: b-0']); + expect(ReactNoop).toFlushAndYieldThrough(['Subscriber: b-0']); expect(log).toEqual(['Parent.componentDidMount']); // Emit some updates from the old subscribable @@ -420,7 +420,7 @@ describe('createSubscription', () => { // Flush everything and ensure that the correct subscribable is used // We expect the new subscribable to finish rendering, // But then the updated values from the old subscribable should be used. - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Child: b-0', 'Subscriber: a-2', 'Child: a-2', @@ -433,7 +433,7 @@ describe('createSubscription', () => { // Updates from the new subscribable should be ignored. observableB.next('b-1'); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toFlushAndYield([]); expect(log).toEqual([ 'Parent.componentDidMount', 'Parent.componentDidUpdate', @@ -479,7 +479,7 @@ describe('createSubscription', () => { {value => null}, ); - expect(ReactNoop.flush).toThrow( + expect(ReactNoop).toFlushAndThrow( 'A subscription must return an unsubscribe function.', ); }); diff --git a/packages/react-art/src/__tests__/ReactART-test.js b/packages/react-art/src/__tests__/ReactART-test.js index a9e0e7486fe..f7115c556c0 100644 --- a/packages/react-art/src/__tests__/ReactART-test.js +++ b/packages/react-art/src/__tests__/ReactART-test.js @@ -385,7 +385,7 @@ describe('ReactART', () => { , ); - ReactNoop.flushThrough(['A']); + expect(ReactNoop).toFlushAndYieldThrough(['A']); ReactDOM.render( @@ -400,7 +400,7 @@ describe('ReactART', () => { expect(ops).toEqual([null, 'ART']); ops = []; - expect(ReactNoop.flush()).toEqual(['B', 'C']); + expect(ReactNoop).toFlushAndYield(['B', 'C']); expect(ops).toEqual(['Test']); }); diff --git a/packages/react-noop-renderer/src/createReactNoop.js b/packages/react-noop-renderer/src/createReactNoop.js index 743a24fcc12..714141ccd18 100644 --- a/packages/react-noop-renderer/src/createReactNoop.js +++ b/packages/react-noop-renderer/src/createReactNoop.js @@ -22,7 +22,6 @@ import {createPortal} from 'shared/ReactPortal'; import expect from 'expect'; import {REACT_FRAGMENT_TYPE, REACT_ELEMENT_TYPE} from 'shared/ReactSymbols'; import warningWithoutStack from 'shared/warningWithoutStack'; -import invariant from 'shared/invariant'; // for .act's return value type Thenable = { @@ -555,7 +554,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { } function flushAll(): Array { - assertYieldsWereCleared(); yieldedValues = []; while (scheduledCallback !== null) { const cb = scheduledCallback; @@ -571,7 +569,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { } function flushNumberOfYields(count: number): Array { - assertYieldsWereCleared(); expectedNumberOfYields = count; didStop = false; yieldedValues = []; @@ -602,14 +599,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { return values; } - function assertYieldsWereCleared() { - invariant( - yieldedValues.length === 0, - 'Log of yielded values is not empty. ' + - 'Call ReactNoop.clearYields(...) first.', - ); - } - function childToJSX(child, text) { if (text !== null) { return text; @@ -665,7 +654,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { const ReactNoop = { getChildren(rootID: string = DEFAULT_ROOT_ID) { - assertYieldsWereCleared(); const container = rootContainers.get(rootID); if (container) { return container.children; @@ -775,16 +763,11 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { return NoopRenderer.findHostInstance(component); }, - flush: flushAll, - // TODO: Should only be used via a Jest plugin (like we do with the // test renderer). + unstable_flushWithoutYielding: flushAll, unstable_flushNumberOfYields: flushNumberOfYields, - - flushThrough(expected: Array): void { - const actual = flushNumberOfYields(expected.length); - expect(actual).toEqual(expected); - }, + unstable_clearYields: clearYields, flushNextYield(): Array { return flushNumberOfYields(1); @@ -805,7 +788,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { hostUpdateCounter = 0; hostCloneCounter = 0; try { - ReactNoop.flush(); + flushAll(); return useMutation ? { hostDiffCounter, @@ -837,8 +820,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { yield: yieldValue, - clearYields, - hasScheduledCallback() { return !!scheduledCallback; }, @@ -1016,7 +997,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { _next: null, }; root.firstBatch = batch; - const actual = ReactNoop.flush(); + const actual = flushAll(); expect(actual).toEqual(expectedFlush); return (expectedCommit: Array) => { batch._defer = false; diff --git a/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js b/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js index 2d6742af907..c397d01b345 100644 --- a/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactExpiration-test.internal.js @@ -73,7 +73,7 @@ describe('ReactExpiration', () => { ReactNoop.render(); // The updates should flush in separate batches, since sufficient time // passed in between them *and* they occurred in separate events. - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'A [render]', 'A [commit]', 'B [render]', @@ -88,13 +88,13 @@ describe('ReactExpiration', () => { // haven't entered an idle callback, the scheduler must assume that we're // inside the same event. ReactNoop.advanceTime(2000); - expect(ReactNoop.clearYields()).toEqual([]); + expect(ReactNoop).toHaveYielded([]); expect(ReactNoop.getChildren()).toEqual([span('B')]); // Schedule another update. ReactNoop.render(); // The updates should flush in the same batch, since as far as the scheduler // knows, they may have occurred inside the same event. - expect(ReactNoop.flush()).toEqual(['B [render]', 'B [commit]']); + expect(ReactNoop).toFlushAndYield(['B [render]', 'B [commit]']); }); it( @@ -127,7 +127,7 @@ describe('ReactExpiration', () => { ReactNoop.render(); // The updates should flush in separate batches, since sufficient time // passed in between them *and* they occurred in separate events. - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'A [render]', 'A [commit]', 'B [render]', @@ -142,7 +142,7 @@ describe('ReactExpiration', () => { // haven't entered an idle callback, the scheduler must assume that we're // inside the same event. ReactNoop.advanceTime(2000); - expect(ReactNoop.clearYields()).toEqual([]); + expect(ReactNoop).toHaveYielded([]); expect(ReactNoop.getChildren()).toEqual([span('B')]); // Perform some synchronous work. Again, the scheduler must assume we're @@ -156,7 +156,7 @@ describe('ReactExpiration', () => { ReactNoop.render(); // The updates should flush in the same batch, since as far as the scheduler // knows, they may have occurred inside the same event. - expect(ReactNoop.flush()).toEqual(['B [render]', 'B [commit]']); + expect(ReactNoop).toFlushAndYield(['B [render]', 'B [commit]']); }, ); @@ -191,7 +191,7 @@ describe('ReactExpiration', () => { // Initial mount ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'initial [A] [render]', 'initial [B] [render]', 'initial [C] [render]', @@ -204,12 +204,18 @@ describe('ReactExpiration', () => { // Partial update subscribers.forEach(s => s.setState({text: '1'})); - ReactNoop.flushThrough(['1 [A] [render]', '1 [B] [render]']); + expect(ReactNoop).toFlushAndYieldThrough([ + '1 [A] [render]', + '1 [B] [render]', + ]); // Before the update can finish, update again. Even though no time has // advanced, this update should be given a different expiration time than // the currently rendering one. So, C and D should render with 1, not 2. subscribers.forEach(s => s.setState({text: '2'})); - ReactNoop.flushThrough(['1 [C] [render]', '1 [D] [render]']); + expect(ReactNoop).toFlushAndYieldThrough([ + '1 [C] [render]', + '1 [D] [render]', + ]); }); }); diff --git a/packages/react-reconciler/src/__tests__/ReactFragment-test.js b/packages/react-reconciler/src/__tests__/ReactFragment-test.js index d6b8b41fc0f..c72b395eb27 100644 --- a/packages/react-reconciler/src/__tests__/ReactFragment-test.js +++ b/packages/react-reconciler/src/__tests__/ReactFragment-test.js @@ -43,7 +43,7 @@ describe('ReactFragment', () => { ); ReactNoop.render(element); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([span()]); }); @@ -52,7 +52,7 @@ describe('ReactFragment', () => { const element = ; ReactNoop.render(element); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([]); }); @@ -65,7 +65,7 @@ describe('ReactFragment', () => { ); ReactNoop.render(element); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([text('hello '), span()]); }); @@ -78,7 +78,7 @@ describe('ReactFragment', () => { ); ReactNoop.render(element); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([span(), span()]); }); @@ -108,16 +108,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div(), div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful', 'Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -149,16 +149,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful', 'Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -199,16 +199,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div(), div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful', 'Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -242,16 +242,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -283,16 +283,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -325,16 +325,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div(), div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -364,16 +364,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful', 'Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -403,16 +403,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful', 'Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -444,16 +444,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -481,16 +481,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -522,16 +522,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful', 'Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -564,16 +564,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div(), span()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -605,16 +605,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div()]); @@ -658,16 +658,16 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div(span(), div(div()), span())]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Update Stateful', 'Update Stateful']); expect(ReactNoop.getChildren()).toEqual([div(span(), div(div()), span())]); @@ -705,10 +705,10 @@ describe('ReactFragment', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Each child in a list should have a unique "key" prop.', ); @@ -716,7 +716,7 @@ describe('ReactFragment', () => { expect(ReactNoop.getChildren()).toEqual([div(div(), span())]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([]); expect(ReactNoop.getChildren()).toEqual([div(div(), span())]); @@ -752,12 +752,12 @@ describe('ReactFragment', () => { } ReactNoop.render(); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Each child in a list should have a unique "key" prop.', ); ReactNoop.render(); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Each child in a list should have a unique "key" prop.', ); @@ -765,7 +765,7 @@ describe('ReactFragment', () => { expect(ReactNoop.getChildren()).toEqual([span(), div()]); ReactNoop.render(); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Each child in a list should have a unique "key" prop.', ); diff --git a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js index b2d2da8683e..adca4cbc6de 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.internal.js @@ -74,7 +74,7 @@ describe('ReactHooksWithNoopRenderer', () => { // Initial mount const counter = React.createRef(null); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); // Schedule some updates @@ -84,17 +84,17 @@ describe('ReactHooksWithNoopRenderer', () => { }); // Partially flush without committing - ReactNoop.flushThrough(['Count: 11']); + expect(ReactNoop).toFlushAndYieldThrough(['Count: 11']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); // Interrupt with a high priority update ReactNoop.flushSync(() => { ReactNoop.render(); }); - expect(ReactNoop.clearYields()).toEqual(['Total: 0']); + expect(ReactNoop).toHaveYielded(['Total: 0']); // Resume rendering - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Total: 11']); expect(ReactNoop.getChildren()).toEqual([span('Total: 11')]); }); @@ -107,7 +107,7 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(() => ReactNoop.flush()).toThrow( + expect(ReactNoop).toFlushAndThrow( 'Hooks can only be called inside the body of a function component.', ); @@ -117,7 +117,7 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([10]); + expect(ReactNoop).toFlushAndYield([10]); }); it('throws inside module-style components', () => { @@ -130,7 +130,7 @@ describe('ReactHooksWithNoopRenderer', () => { }; } ReactNoop.render(); - expect(() => ReactNoop.flush()).toThrow( + expect(ReactNoop).toFlushAndThrow( 'Hooks can only be called inside the body of a function component.', ); @@ -140,7 +140,7 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([10]); + expect(ReactNoop).toFlushAndYield([10]); }); it('throws when called outside the render phase', () => { @@ -159,15 +159,15 @@ describe('ReactHooksWithNoopRenderer', () => { Counter = forwardRef(Counter); const counter = React.createRef(null); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); act(() => counter.current.updateCount(1)); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); act(() => counter.current.updateCount(count => count + 10)); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 11']); expect(ReactNoop.getChildren()).toEqual([span('Count: 11')]); }); @@ -183,11 +183,11 @@ describe('ReactHooksWithNoopRenderer', () => { Counter = forwardRef(Counter); const counter = React.createRef(null); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['getInitialState', 'Count: 42']); + expect(ReactNoop).toFlushAndYield(['getInitialState', 'Count: 42']); expect(ReactNoop.getChildren()).toEqual([span('Count: 42')]); act(() => counter.current.updateCount(7)); - expect(ReactNoop.flush()).toEqual(['Count: 7']); + expect(ReactNoop).toFlushAndYield(['Count: 7']); expect(ReactNoop.getChildren()).toEqual([span('Count: 7')]); }); @@ -201,14 +201,14 @@ describe('ReactHooksWithNoopRenderer', () => { Counter = forwardRef(Counter); const counter = React.createRef(null); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); act(() => counter.current.updateCount(7)); - expect(ReactNoop.flush()).toEqual(['Count: 7']); + expect(ReactNoop).toFlushAndYield(['Count: 7']); act(() => counter.current.updateLabel('Total')); - expect(ReactNoop.flush()).toEqual(['Total: 7']); + expect(ReactNoop).toFlushAndYield(['Total: 7']); }); it('returns the same updater function every time', () => { @@ -219,15 +219,15 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); act(() => updaters[0](1)); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); act(() => updaters[0](count => count + 10)); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 11']); expect(ReactNoop.getChildren()).toEqual([span('Count: 11')]); expect(updaters).toEqual([updaters[0], updaters[0], updaters[0]]); @@ -242,9 +242,9 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(null); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(() => act(() => _updateCount(1))).toWarnDev( "Warning: Can't perform a React state update on an unmounted " + 'component. This is a no-op, but it indicates a memory leak in your ' + @@ -264,15 +264,15 @@ describe('ReactHooksWithNoopRenderer', () => { Counter = memo(Counter); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toFlushAndYield([]); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); act(() => _updateCount(1)); - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); }); }); @@ -293,27 +293,27 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Scrolling down: false']); expect(ReactNoop.getChildren()).toEqual([span('Scrolling down: false')]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Scrolling down: true']); expect(ReactNoop.getChildren()).toEqual([span('Scrolling down: true')]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Scrolling down: true']); expect(ReactNoop.getChildren()).toEqual([span('Scrolling down: true')]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Scrolling down: true']); expect(ReactNoop.getChildren()).toEqual([span('Scrolling down: true')]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Scrolling down: false']); expect(ReactNoop.getChildren()).toEqual([span('Scrolling down: false')]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Scrolling down: false']); expect(ReactNoop.getChildren()).toEqual([span('Scrolling down: false')]); }); @@ -328,7 +328,7 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Render: 0', 'Render: 1', 'Render: 2', @@ -351,7 +351,7 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ // Should increase by three each time 'Render: 0', 'Render: 3', @@ -371,7 +371,7 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(() => ReactNoop.flush()).toThrow( + expect(ReactNoop).toFlushAndThrow( 'Too many re-renders. React limits the number of renders to prevent ' + 'an infinite loop.', ); @@ -391,7 +391,7 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Render: 0', 'Render: 1', 'Render: 2', @@ -441,7 +441,7 @@ describe('ReactHooksWithNoopRenderer', () => { Counter = forwardRef(Counter); const counter = React.createRef(null); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ // The count should increase by alternating amounts of 10 and 1 // until we reach 21. 'Render: 0', @@ -458,7 +458,7 @@ describe('ReactHooksWithNoopRenderer', () => { counter.current.dispatch('reset'); }); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Render: 0', 'Render: 1', 'Render: 11', @@ -494,11 +494,11 @@ describe('ReactHooksWithNoopRenderer', () => { Counter = forwardRef(Counter); const counter = React.createRef(null); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); act(() => counter.current.dispatch(INCREMENT)); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); act(() => { counter.current.dispatch(DECREMENT); @@ -506,7 +506,7 @@ describe('ReactHooksWithNoopRenderer', () => { counter.current.dispatch(DECREMENT); }); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: -2']); expect(ReactNoop.getChildren()).toEqual([span('Count: -2')]); }); @@ -536,11 +536,11 @@ describe('ReactHooksWithNoopRenderer', () => { Counter = forwardRef(Counter); const counter = React.createRef(null); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Init', 'Count: 10']); + expect(ReactNoop).toFlushAndYield(['Init', 'Count: 10']); expect(ReactNoop.getChildren()).toEqual([span('Count: 10')]); act(() => counter.current.dispatch(INCREMENT)); - expect(ReactNoop.flush()).toEqual(['Count: 11']); + expect(ReactNoop).toFlushAndYield(['Count: 11']); expect(ReactNoop.getChildren()).toEqual([span('Count: 11')]); act(() => { @@ -549,7 +549,7 @@ describe('ReactHooksWithNoopRenderer', () => { counter.current.dispatch(DECREMENT); }); - expect(ReactNoop.flush()).toEqual(['Count: 8']); + expect(ReactNoop).toFlushAndYield(['Count: 8']); expect(ReactNoop.getChildren()).toEqual([span('Count: 8')]); }); @@ -571,7 +571,7 @@ describe('ReactHooksWithNoopRenderer', () => { const counter = React.createRef(null); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); act(() => { @@ -583,10 +583,10 @@ describe('ReactHooksWithNoopRenderer', () => { ReactNoop.flushSync(() => { counter.current.dispatch(INCREMENT); }); - expect(ReactNoop.clearYields()).toEqual(['Count: 1']); + expect(ReactNoop).toHaveYielded(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 4']); expect(ReactNoop.getChildren()).toEqual([span('Count: 4')]); }); }); @@ -600,17 +600,17 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Did commit [0]']); + expect(ReactNoop).toHaveYielded(['Did commit [0]']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); // Effects are deferred until after the commit ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Did commit [1]']); + expect(ReactNoop).toHaveYielded(['Did commit [1]']); }); it('flushes passive effects even with sibling deletions', () => { @@ -628,7 +628,7 @@ describe('ReactHooksWithNoopRenderer', () => { } let passive = ; ReactNoop.render([, passive]); - expect(ReactNoop.flush()).toEqual(['Layout', 'Passive', 'Layout effect']); + expect(ReactNoop).toFlushAndYield(['Layout', 'Passive', 'Layout effect']); expect(ReactNoop.getChildren()).toEqual([ span('Layout'), span('Passive'), @@ -637,13 +637,13 @@ describe('ReactHooksWithNoopRenderer', () => { // Destroying the first child shouldn't prevent the passive effect from // being executed ReactNoop.render([passive]); - expect(ReactNoop.clearYields()).toEqual(['Passive effect']); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toHaveYielded(['Passive effect']); + expect(ReactNoop).toFlushAndYield([]); expect(ReactNoop.getChildren()).toEqual([span('Passive')]); // (No effects are left to flush.) ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual([]); + expect(ReactNoop).toHaveYielded([]); }); it('flushes passive effects even if siblings schedule an update', () => { @@ -668,7 +668,7 @@ describe('ReactHooksWithNoopRenderer', () => { ReactNoop.render([, ]); act(() => { - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Passive', 'Layout', 'Layout effect 0', @@ -700,7 +700,7 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render([, ]); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Passive', 'Layout', 'Layout effect', @@ -734,20 +734,20 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([0]); + expect(ReactNoop).toFlushAndYield([0]); expect(ReactNoop.getChildren()).toEqual([span(0)]); // Before the effects have a chance to flush, schedule another update ReactNoop.render(); - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ // The previous effect flushes before the reconciliation 'Committed state when effect was fired: 0', ]); - expect(ReactNoop.flush()).toEqual([1]); + expect(ReactNoop).toFlushAndYield([1]); expect(ReactNoop.getChildren()).toEqual([span(1)]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ 'Committed state when effect was fired: 1', ]); }, @@ -766,18 +766,18 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: (empty)']); + expect(ReactNoop).toFlushAndYield(['Count: (empty)']); expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Schedule update [0]']); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toHaveYielded(['Schedule update [0]']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Schedule update [1]']); - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toHaveYielded(['Schedule update [1]']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); }); it('updates have async priority even if effects are flushed early', () => { @@ -793,24 +793,24 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: (empty)']); + expect(ReactNoop).toFlushAndYield(['Count: (empty)']); expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]); // Rendering again should flush the previous commit's effects ReactNoop.render(); - expect(ReactNoop.clearYields()).toEqual(['Schedule update [0]']); - ReactNoop.flushThrough(['Count: 0']); + expect(ReactNoop).toHaveYielded(['Schedule update [0]']); + expect(ReactNoop).toFlushAndYieldThrough(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]); ReactNoop.batchedUpdates(() => { - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toFlushAndYield([]); }); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Schedule update [1]']); - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toHaveYielded(['Schedule update [1]']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); }); @@ -827,14 +827,14 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); // Enqueuing this update forces the passive effect to be flushed -- // updateCount(1) happens first, so 2 wins. act(() => _updateCount(2)); - expect(ReactNoop.clearYields()).toEqual(['Will set count to 1']); - expect(ReactNoop.flush()).toEqual(['Count: 2']); + expect(ReactNoop).toHaveYielded(['Will set count to 1']); + expect(ReactNoop).toFlushAndYield(['Count: 2']); expect(ReactNoop.getChildren()).toEqual([span('Count: 2')]); }); @@ -872,7 +872,7 @@ describe('ReactHooksWithNoopRenderer', () => { ReactNoop.render(); }, ); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(0); @@ -880,8 +880,8 @@ describe('ReactHooksWithNoopRenderer', () => { // Enqueuing this update forces the passive effect to be flushed -- // updateCount(1) happens first, so 2 wins. act(() => _updateCount(2)); - expect(ReactNoop.clearYields()).toEqual(['Will set count to 1']); - expect(ReactNoop.flush()).toEqual(['Count: 2']); + expect(ReactNoop).toHaveYielded(['Will set count to 1']); + expect(ReactNoop).toFlushAndYield(['Count: 2']); expect(ReactNoop.getChildren()).toEqual([span('Count: 2')]); expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1); @@ -911,13 +911,13 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.renderLegacySyncRoot(); // Even in sync mode, effects are deferred until after paint - expect(ReactNoop.clearYields()).toEqual(['Count: (empty)']); + expect(ReactNoop).toHaveYielded(['Count: (empty)']); expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]); // Now fire the effects ReactNoop.flushPassiveEffects(); // There were multiple updates, but there should only be a // single render - expect(ReactNoop.clearYields()).toEqual(['Count: 0']); + expect(ReactNoop).toHaveYielded(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); }, ); @@ -937,7 +937,7 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: (empty)']); + expect(ReactNoop).toFlushAndYield(['Count: (empty)']); expect(ReactNoop.getChildren()).toEqual([span('Count: (empty)')]); expect(() => { @@ -956,19 +956,16 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Did create [0]']); + expect(ReactNoop).toHaveYielded(['Did create [0]']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual([ - 'Did destroy [0]', - 'Did create [1]', - ]); + expect(ReactNoop).toHaveYielded(['Did destroy [0]', 'Did create [1]']); }); it('unmounts on deletion', () => { @@ -982,13 +979,13 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Did create [0]']); + expect(ReactNoop).toHaveYielded(['Did create [0]']); ReactNoop.render(null); - expect(ReactNoop.flush()).toEqual(['Did destroy [0]']); + expect(ReactNoop).toFlushAndYield(['Did destroy [0]']); expect(ReactNoop.getChildren()).toEqual([]); }); @@ -1003,19 +1000,19 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Did create [0]']); + expect(ReactNoop).toHaveYielded(['Did create [0]']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual([]); + expect(ReactNoop).toHaveYielded([]); ReactNoop.render(null); - expect(ReactNoop.flush()).toEqual(['Did destroy [0]']); + expect(ReactNoop).toFlushAndYield(['Did destroy [0]']); expect(ReactNoop.getChildren()).toEqual([]); }); @@ -1031,19 +1028,19 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Did create']); + expect(ReactNoop).toHaveYielded(['Did create']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Did destroy', 'Did create']); + expect(ReactNoop).toHaveYielded(['Did destroy', 'Did create']); ReactNoop.render(null); - expect(ReactNoop.flush()).toEqual(['Did destroy']); + expect(ReactNoop).toFlushAndYield(['Did destroy']); expect(ReactNoop.getChildren()).toEqual([]); }); @@ -1062,34 +1059,34 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Did create [Count: 0]']); + expect(ReactNoop).toHaveYielded(['Did create [Count: 0]']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.render(); // Count changed - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ 'Did destroy [Count: 0]', 'Did create [Count: 1]', ]); ReactNoop.render(); // Nothing changed, so no effect should have fired - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual([]); + expect(ReactNoop).toHaveYielded([]); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); ReactNoop.render(); // Label changed - expect(ReactNoop.flush()).toEqual(['Total: 1']); + expect(ReactNoop).toFlushAndYield(['Total: 1']); expect(ReactNoop.getChildren()).toEqual([span('Total: 1')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ 'Did destroy [Count: 1]', 'Did create [Total: 1]', ]); @@ -1106,22 +1103,16 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual([ - 'Did commit 1 [0]', - 'Did commit 2 [0]', - ]); + expect(ReactNoop).toHaveYielded(['Did commit 1 [0]', 'Did commit 2 [0]']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual([ - 'Did commit 1 [1]', - 'Did commit 2 [1]', - ]); + expect(ReactNoop).toHaveYielded(['Did commit 1 [1]', 'Did commit 2 [1]']); }); it('unmounts all previous effects before creating any new ones', () => { @@ -1141,16 +1132,16 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Mount A [0]', 'Mount B [0]']); + expect(ReactNoop).toHaveYielded(['Mount A [0]', 'Mount B [0]']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ 'Unmount A [0]', 'Unmount B [0]', 'Mount A [1]', @@ -1178,10 +1169,10 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); expect(() => ReactNoop.flushPassiveEffects()).toThrow('Oops'); - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ 'Mount A [0]', 'Oops!', // Clean up effect A. There's no effect B to clean-up, because it @@ -1212,17 +1203,17 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Mount A [0]', 'Mount B [0]']); + expect(ReactNoop).toHaveYielded(['Mount A [0]', 'Mount B [0]']); // This update will trigger an errror ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); expect(() => ReactNoop.flushPassiveEffects()).toThrow('Oops'); - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ 'Unmount A [0]', 'Unmount B [0]', 'Mount A [1]', @@ -1254,17 +1245,17 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Mount A [0]', 'Mount B [0]']); + expect(ReactNoop).toHaveYielded(['Mount A [0]', 'Mount B [0]']); // This update will trigger an errror ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); expect(() => ReactNoop.flushPassiveEffects()).toThrow('Oops'); - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ 'Oops!', // B unmounts even though an error was thrown in the previous effect 'Unmount B [0]', @@ -1283,15 +1274,15 @@ describe('ReactHooksWithNoopRenderer', () => { Counter = memo(Counter); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 0', 'Mount: 0']); + expect(ReactNoop).toFlushAndYield(['Count: 0', 'Mount: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Count: 1', 'Unmount: 0', 'Mount: 1']); + expect(ReactNoop).toFlushAndYield(['Count: 1', 'Unmount: 0', 'Mount: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); ReactNoop.render(null); - expect(ReactNoop.flush()).toEqual(['Unmount: 1']); + expect(ReactNoop).toFlushAndYield(['Unmount: 1']); expect(ReactNoop.getChildren()).toEqual([]); }); }); @@ -1299,7 +1290,7 @@ describe('ReactHooksWithNoopRenderer', () => { describe('useLayoutEffect', () => { it('fires layout effects after the host has been mutated', () => { function getCommittedText() { - const yields = ReactNoop.clearYields(); + const yields = ReactNoop.unstable_clearYields(); const children = ReactNoop.getChildren(); ReactNoop.yield(yields); if (children === null) { @@ -1316,11 +1307,11 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([[0], 'Current: 0']); + expect(ReactNoop).toFlushAndYield([[0], 'Current: 0']); expect(ReactNoop.getChildren()).toEqual([span(0)]); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([[1], 'Current: 1']); + expect(ReactNoop).toFlushAndYield([[1], 'Current: 1']); expect(ReactNoop.getChildren()).toEqual([span(1)]); }); @@ -1348,19 +1339,19 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Mount layout [current: 0]']); + expect(ReactNoop).toFlushAndYield(['Mount layout [current: 0]']); expect(committedText).toEqual('0'); ReactNoop.render(); - expect(ReactNoop.clearYields()).toEqual(['Mount normal [current: 0]']); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toHaveYielded(['Mount normal [current: 0]']); + expect(ReactNoop).toFlushAndYield([ 'Unmount layout [current: 0]', 'Mount layout [current: 1]', ]); expect(committedText).toEqual('1'); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ 'Unmount normal [current: 1]', 'Mount normal [current: 1]', ]); @@ -1393,14 +1384,14 @@ describe('ReactHooksWithNoopRenderer', () => { const button = React.createRef(null); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Increment', 'Count: 0']); + expect(ReactNoop).toFlushAndYield(['Increment', 'Count: 0']); expect(ReactNoop.getChildren()).toEqual([ span('Increment'), span('Count: 0'), ]); act(button.current.increment); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ // Button should not re-render, because its props haven't changed // 'Increment', 'Count: 1', @@ -1412,7 +1403,7 @@ describe('ReactHooksWithNoopRenderer', () => { // Increase the increment amount ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ // Inputs did change this time 'Increment', 'Count: 1', @@ -1424,7 +1415,7 @@ describe('ReactHooksWithNoopRenderer', () => { // Callback should have updated act(button.current.increment); - expect(ReactNoop.flush()).toEqual(['Count: 11']); + expect(ReactNoop).toFlushAndYield(['Count: 11']); expect(ReactNoop.getChildren()).toEqual([ span('Increment'), span('Count: 11'), @@ -1447,19 +1438,19 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(["Capitalize 'hello'", 'HELLO']); + expect(ReactNoop).toFlushAndYield(["Capitalize 'hello'", 'HELLO']); expect(ReactNoop.getChildren()).toEqual([span('HELLO')]); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(["Capitalize 'hi'", 'HI']); + expect(ReactNoop).toFlushAndYield(["Capitalize 'hi'", 'HI']); expect(ReactNoop.getChildren()).toEqual([span('HI')]); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['HI']); + expect(ReactNoop).toFlushAndYield(['HI']); expect(ReactNoop.getChildren()).toEqual([span('HI')]); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(["Capitalize 'goodbye'", 'GOODBYE']); + expect(ReactNoop).toFlushAndYield(["Capitalize 'goodbye'", 'GOODBYE']); expect(ReactNoop.getChildren()).toEqual([span('GOODBYE')]); }); @@ -1480,16 +1471,16 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['compute A', 'A']); + expect(ReactNoop).toFlushAndYield(['compute A', 'A']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['compute A', 'A']); + expect(ReactNoop).toFlushAndYield(['compute A', 'A']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['compute A', 'A']); + expect(ReactNoop).toFlushAndYield(['compute A', 'A']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['compute B', 'B']); + expect(ReactNoop).toFlushAndYield(['compute B', 'B']); }); it('should not invoke memoized function during re-renders unless inputs change', () => { @@ -1510,13 +1501,13 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['compute A', 'A']); + expect(ReactNoop).toFlushAndYield(['compute A', 'A']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['A']); + expect(ReactNoop).toFlushAndYield(['A']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['compute B', 'B']); + expect(ReactNoop).toFlushAndYield(['compute B', 'B']); }); }); @@ -1554,17 +1545,17 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toFlushAndYield([]); ping(1); ping(2); ping(3); - expect(ReactNoop.clearYields()).toEqual([]); + expect(ReactNoop).toHaveYielded([]); jest.advanceTimersByTime(100); - expect(ReactNoop.clearYields()).toEqual(['ping: 3']); + expect(ReactNoop).toHaveYielded(['ping: 3']); ping(4); jest.advanceTimersByTime(20); @@ -1572,10 +1563,10 @@ describe('ReactHooksWithNoopRenderer', () => { ping(6); jest.advanceTimersByTime(80); - expect(ReactNoop.clearYields()).toEqual([]); + expect(ReactNoop).toHaveYielded([]); jest.advanceTimersByTime(20); - expect(ReactNoop.clearYields()).toEqual(['ping: 6']); + expect(ReactNoop).toHaveYielded(['ping: 6']); }); it('should return the same ref during re-renders', () => { @@ -1596,10 +1587,10 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['val']); + expect(ReactNoop).toFlushAndYield(['val']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['val']); + expect(ReactNoop).toFlushAndYield(['val']); }); }); @@ -1620,14 +1611,14 @@ describe('ReactHooksWithNoopRenderer', () => { Counter = forwardRef(Counter); const counter = React.createRef(null); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); expect(counter.current.count).toBe(0); act(() => { counter.current.dispatch(INCREMENT); }); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); // Intentionally not updated because of [] deps: expect(counter.current.count).toBe(0); @@ -1650,14 +1641,14 @@ describe('ReactHooksWithNoopRenderer', () => { Counter = forwardRef(Counter); const counter = React.createRef(null); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); expect(counter.current.count).toBe(0); act(() => { counter.current.dispatch(INCREMENT); }); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); expect(counter.current.count).toBe(1); }); @@ -1686,7 +1677,7 @@ describe('ReactHooksWithNoopRenderer', () => { Counter = forwardRef(Counter); const counter = React.createRef(null); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 0']); expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]); expect(counter.current.count).toBe(0); expect(totalRefUpdates).toBe(1); @@ -1694,14 +1685,14 @@ describe('ReactHooksWithNoopRenderer', () => { act(() => { counter.current.dispatch(INCREMENT); }); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); expect(counter.current.count).toBe(1); expect(totalRefUpdates).toBe(2); // Update that doesn't change the ref dependencies ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); expect(counter.current.count).toBe(1); expect(totalRefUpdates).toBe(2); // Should not increase since last time @@ -1731,7 +1722,7 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['A: 0, B: 0, C: [not loaded]']); + expect(ReactNoop).toFlushAndYield(['A: 0, B: 0, C: [not loaded]']); expect(ReactNoop.getChildren()).toEqual([ span('A: 0, B: 0, C: [not loaded]'), ]); @@ -1741,21 +1732,21 @@ describe('ReactHooksWithNoopRenderer', () => { updateB(3); }); - expect(ReactNoop.flush()).toEqual(['A: 2, B: 3, C: [not loaded]']); + expect(ReactNoop).toFlushAndYield(['A: 2, B: 3, C: [not loaded]']); expect(ReactNoop.getChildren()).toEqual([ span('A: 2, B: 3, C: [not loaded]'), ]); ReactNoop.render(); expect(() => { - expect(ReactNoop.flush()).toEqual(['A: 2, B: 3, C: 0']); + expect(ReactNoop).toFlushAndYield(['A: 2, B: 3, C: 0']); }).toThrow('Rendered more hooks than during the previous render'); // Uncomment if/when we support this again // expect(ReactNoop.getChildren()).toEqual([span('A: 2, B: 3, C: 0')]); // updateC(4); - // expect(ReactNoop.flush()).toEqual(['A: 2, B: 3, C: 4']); + // expect(ReactNoop).toFlushAndYield(['A: 2, B: 3, C: 4']); // expect(ReactNoop.getChildren()).toEqual([span('A: 2, B: 3, C: 4')]); }); @@ -1783,17 +1774,17 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['A: 0, B: 0, C: 0']); + expect(ReactNoop).toFlushAndYield(['A: 0, B: 0, C: 0']); expect(ReactNoop.getChildren()).toEqual([span('A: 0, B: 0, C: 0')]); act(() => { updateA(2); updateB(3); updateC(4); }); - expect(ReactNoop.flush()).toEqual(['A: 2, B: 3, C: 4']); + expect(ReactNoop).toFlushAndYield(['A: 2, B: 3, C: 4']); expect(ReactNoop.getChildren()).toEqual([span('A: 2, B: 3, C: 4')]); ReactNoop.render(); - expect(() => ReactNoop.flush()).toThrow( + expect(ReactNoop).toFlushAndThrow( 'Rendered fewer hooks than expected. This may be caused by an ' + 'accidental early return statement.', ); @@ -1821,21 +1812,21 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toFlushAndYield([]); ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(['Mount A']); + expect(ReactNoop).toHaveYielded(['Mount A']); ReactNoop.render(); expect(() => { - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toFlushAndYield([]); }).toThrow('Rendered more hooks than during the previous render'); // Uncomment if/when we support this again // ReactNoop.flushPassiveEffects(); - // expect(ReactNoop.clearYields()).toEqual(['Mount B']); + // expect(ReactNoop).toHaveYielded(['Mount B']); // ReactNoop.render(); - // expect(() => ReactNoop.flush()).toThrow( + // expect(ReactNoop).toFlushAndThrow( // 'Rendered fewer hooks than expected. This may be caused by an ' + // 'accidental early return statement.', // ); diff --git a/packages/react-reconciler/src/__tests__/ReactIncremental-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncremental-test.internal.js index 1f65fc6ec3d..1ae63e690e7 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncremental-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncremental-test.internal.js @@ -35,7 +35,7 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }); it('should render a simple component, in steps if needed', () => { @@ -58,7 +58,7 @@ describe('ReactIncremental', () => { expect(ReactNoop.flushNextYield()).toEqual(['Foo']); // Do the rest of the work. - expect(ReactNoop.flush()).toEqual(['Bar', 'Bar', 'callback']); + expect(ReactNoop).toFlushAndYield(['Bar', 'Bar', 'callback']); }); it('updates a previous render', () => { @@ -96,7 +96,7 @@ describe('ReactIncremental', () => { ReactNoop.render(, () => ops.push('renderCallbackCalled'), ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ 'Foo', @@ -114,7 +114,7 @@ describe('ReactIncremental', () => { ReactNoop.render(, () => ops.push('secondRenderCallbackCalled'), ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); // TODO: Test bail out of host components. This is currently unobservable. @@ -146,21 +146,21 @@ describe('ReactIncremental', () => { // Init ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Foo', 'Bar', 'Bar']); ReactNoop.render(); // Flush part of the work - ReactNoop.flushThrough(['Foo', 'Bar']); + expect(ReactNoop).toFlushAndYieldThrough(['Foo', 'Bar']); // This will abort the previous work and restart ReactNoop.flushSync(() => ReactNoop.render(null)); ReactNoop.render(); // Flush part of the new work - ReactNoop.flushThrough(['Foo', 'Bar']); + expect(ReactNoop).toFlushAndYieldThrough(['Foo', 'Bar']); // Flush the rest of the work which now includes the low priority - expect(ReactNoop.flush()).toEqual(['Bar']); + expect(ReactNoop).toFlushAndYield(['Bar']); }); it('should call callbacks even if updates are aborted', () => { @@ -186,7 +186,7 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); inst.setState( () => { @@ -197,7 +197,7 @@ describe('ReactIncremental', () => { ); // Flush part of the work - ReactNoop.flushThrough(['setState1']); + expect(ReactNoop).toFlushAndYieldThrough(['setState1']); // This will abort the previous work and restart ReactNoop.flushSync(() => ReactNoop.render()); @@ -210,7 +210,7 @@ describe('ReactIncremental', () => { ); // Flush the rest of the work which now includes the low priority - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'setState1', 'setState2', 'callback1', @@ -248,7 +248,7 @@ describe('ReactIncremental', () => { // Init ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Foo', 'Bar', 'Bar', @@ -259,9 +259,9 @@ describe('ReactIncremental', () => { // Render part of the work. This should be enough to flush everything except // the middle which has lower priority. ReactNoop.render(); - ReactNoop.flushThrough(['Foo', 'Bar', 'Bar']); + expect(ReactNoop).toFlushAndYieldThrough(['Foo', 'Bar', 'Bar']); // Flush only the remaining work - expect(ReactNoop.flush()).toEqual(['Middle', 'Middle']); + expect(ReactNoop).toFlushAndYield(['Middle', 'Middle']); }); it('can deprioritize a tree from without dropping work', () => { @@ -297,7 +297,7 @@ describe('ReactIncremental', () => { ReactNoop.flushSync(() => { ReactNoop.render(); }); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Foo', 'Bar', 'Bar', 'Middle', 'Middle']); ops = []; @@ -312,7 +312,7 @@ describe('ReactIncremental', () => { // The hidden content was deprioritized from high to low priority. A low // priority callback should have been scheduled. Flush it now. - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Middle', 'Middle']); }); @@ -375,7 +375,7 @@ describe('ReactIncremental', () => { ops = []; // Flush the rest to make sure that the bailout didn't block this work. - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Middle']); }); @@ -455,7 +455,7 @@ describe('ReactIncremental', () => { // as a single batch. Therefore, it is correct that Middle should be in the // middle. If it occurs after the two "Bar" components then it was flushed // after them which is not correct. - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Bar', 'Middle', 'Bar']); ops = []; @@ -473,7 +473,7 @@ describe('ReactIncremental', () => { // it. If the priority levels aren't down-prioritized correctly this may // abort rendering of the down-prioritized content. ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Foo', 'Bar', 'Bar']); }); @@ -514,7 +514,7 @@ describe('ReactIncremental', () => { foo.setState({value: 'bar'}); ops = []; - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Foo', 'Bar']); }); @@ -577,7 +577,7 @@ describe('ReactIncremental', () => { foo.setState({value: 'bar'}); ops = []; - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(constructorCount).toEqual(1); expect(ops).toEqual([ 'componentWillMount: foo', @@ -639,7 +639,7 @@ describe('ReactIncremental', () => { // Interrupt the rendering with a quick update. This should not touch the // middle content. ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); // We've now rendered the entire tree but we didn't have to redo the work // done by the first Middle and Bar already. @@ -674,7 +674,7 @@ describe('ReactIncremental', () => { // Since we did nothing to the middle subtree during the interruption, // we should be able to reuse the reconciliation work that we already did // without restarting. - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Middle']); }); @@ -727,7 +727,7 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ops = []; // Begin working on a low priority update to Child, but stop before @@ -747,7 +747,7 @@ describe('ReactIncremental', () => { // Continue the low pri work. The work on Child and GrandChild was memoized // so they should not be worked on again. ops = []; - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ // No Child // No Grandchild @@ -803,7 +803,7 @@ describe('ReactIncremental', () => { // Init ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Foo', 'Bar', 'Content', 'Middle', 'Bar', 'Middle']); @@ -836,7 +836,7 @@ describe('ReactIncremental', () => { // Since we did nothing to the middle subtree during the interruption, // we should be able to reuse the reconciliation work that we already did // without restarting. - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Middle']); }); @@ -857,16 +857,16 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ops = []; ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['shouldComponentUpdate: false']); ops = []; ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ // If the memoized props were not updated during last bail out, sCU will // keep returning false. @@ -897,10 +897,10 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(instance.state).toEqual({a: 'a'}); instance.setState({b: 'b'}); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(instance.state).toEqual({a: 'a', b: 'b'}); }); @@ -926,12 +926,12 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); // Call setState multiple times before flushing instance.setState({b: 'b'}); instance.setState({c: 'c'}); instance.setState({d: 'd'}); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(instance.state).toEqual({a: 'a', b: 'b', c: 'c', d: 'd'}); }); @@ -961,15 +961,15 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(instance.state.num).toEqual(1); instance.setState(updater); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(instance.state.num).toEqual(2); instance.setState(updater); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(instance.state.num).toEqual(6); }); @@ -1003,10 +1003,10 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); instance.setState(updater); instance.setState(updater, callback); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(instance.state.num).toEqual(4); expect(instance.state.called).toEqual(true); }); @@ -1030,11 +1030,11 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); instance.setState({b: 'b'}); instance.setState({c: 'c'}); instance.updater.enqueueReplaceState(instance, {d: 'd'}); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(instance.state).toEqual({d: 'd'}); }); @@ -1071,10 +1071,10 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Foo', 'Bar', 'Baz']); instance.forceUpdate(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Foo', 'Bar', 'Baz', 'Bar', 'Baz']); }); @@ -1091,14 +1091,14 @@ describe('ReactIncremental', () => { const foo = React.createRef(null); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['A: 0, B: 0']); + expect(ReactNoop).toFlushAndYield(['A: 0, B: 0']); a = 1; foo.current.forceUpdate(); - expect(ReactNoop.flush()).toEqual(['A: 1, B: 0']); + expect(ReactNoop).toFlushAndYield(['A: 1, B: 0']); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toFlushAndYield([]); }); xit('can call sCU while resuming a partly mounted component', () => { @@ -1193,7 +1193,7 @@ describe('ReactIncremental', () => {
, ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ops = []; @@ -1214,7 +1214,7 @@ describe('ReactIncremental', () => { ops = []; - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Bar:A-1', 'Baz']); }); @@ -1263,7 +1263,7 @@ describe('ReactIncremental', () => { ops = []; ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ 'App', @@ -1311,7 +1311,7 @@ describe('ReactIncremental', () => { ops = []; ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ 'App', @@ -1366,7 +1366,7 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ 'App', @@ -1394,7 +1394,7 @@ describe('ReactIncremental', () => { ops = []; ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ 'App', @@ -1432,7 +1432,7 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['getDerivedStateFromProps', 'render']); expect(instance.state).toEqual({foo: 'foo'}); @@ -1440,7 +1440,7 @@ describe('ReactIncremental', () => { ops = []; instance.changeState(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ 'getDerivedStateFromProps', @@ -1472,7 +1472,7 @@ describe('ReactIncremental', () => { const child = React.createRef(null); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'getDerivedStateFromProps', 'Parent', 'Child', @@ -1480,7 +1480,7 @@ describe('ReactIncremental', () => { // Schedule an update on the child. The parent should not re-render. child.current.setState({}); - expect(ReactNoop.flush()).toEqual(['Child']); + expect(ReactNoop).toFlushAndYield(['Child']); }); xit('does not call componentWillReceiveProps for state-only updates', () => { @@ -1553,7 +1553,7 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ 'App', @@ -1584,7 +1584,7 @@ describe('ReactIncremental', () => { // LifeCycle instances[1].tick(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ // no componentWillReceiveProps @@ -1617,7 +1617,7 @@ describe('ReactIncremental', () => { // Next we will update LifeCycle directly but not with new props. instances[1].tick(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ // This should not trigger another componentWillReceiveProps because @@ -1672,7 +1672,7 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ 'componentWillMount', @@ -1685,7 +1685,7 @@ describe('ReactIncremental', () => { // Update to same props ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ 'componentWillReceiveProps', @@ -1715,7 +1715,7 @@ describe('ReactIncremental', () => { // ...but we'll interrupt it to rerender the same props. ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); // We can bail out this time, but we must call componentDidUpdate. expect(ops).toEqual([ @@ -1741,7 +1741,7 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ops = []; ReactNoop.flushSync(() => { @@ -1783,7 +1783,7 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ops = []; function updater({n}) { @@ -1798,7 +1798,7 @@ describe('ReactIncremental', () => { instance.setState(updater, () => ops.push('third callback')); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('callback error'); // The third callback isn't called because the second one throws @@ -1897,7 +1897,7 @@ describe('ReactIncremental', () => { , ); expect(() => - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Intl {}', 'ShowLocale {"locale":"fr"}', 'ShowBoth {"locale":"fr"}', @@ -1916,7 +1916,7 @@ describe('ReactIncremental', () => { , ); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Intl {}', 'ShowLocale {"locale":"de"}', 'ShowBoth {"locale":"de"}', @@ -1930,7 +1930,7 @@ describe('ReactIncremental', () => { , ); - ReactNoop.flushThrough(['Intl {}']); + expect(ReactNoop).toFlushAndYieldThrough(['Intl {}']); ReactNoop.render( @@ -1942,7 +1942,7 @@ describe('ReactIncremental', () => { , ); expect(() => - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'ShowLocale {"locale":"sv"}', 'ShowBoth {"locale":"sv"}', 'Intl {}', @@ -1986,7 +1986,7 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: Recurse', {withoutStack: true}, @@ -2023,7 +2023,7 @@ describe('ReactIncremental', () => { }; ReactNoop.render(); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: Recurse', {withoutStack: true}, @@ -2074,14 +2074,14 @@ describe('ReactIncremental', () => { , ); - ReactNoop.flushThrough([ + expect(ReactNoop).toFlushAndYieldThrough([ 'Intl {}', 'ShowLocale {"locale":"fr"}', 'ShowLocale {"locale":"fr"}', ]); expect(() => - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'ShowLocale {"locale":"fr"}', 'Intl {}', 'ShowLocale {"locale":"ru"}', @@ -2165,7 +2165,7 @@ describe('ReactIncremental', () => { , ); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: Intl, ShowLocaleClass, ShowLocaleFn', {withoutStack: true}, @@ -2181,7 +2181,7 @@ describe('ReactIncremental', () => { ops.length = 0; statefulInst.setState({x: 1}); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); // All work has been memoized because setState() // happened below the context and could not have affected it. expect(ops).toEqual([]); @@ -2257,7 +2257,7 @@ describe('ReactIncremental', () => { , ); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: Intl, ShowLocaleClass, ShowLocaleFn', {withoutStack: true}, @@ -2273,7 +2273,7 @@ describe('ReactIncremental', () => { ops.length = 0; statefulInst.setState({locale: 'gr'}); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ // Intl is below setState() so it might have been // affected by it. Therefore we re-render and recompute @@ -2326,7 +2326,7 @@ describe('ReactIncremental', () => { // Init ReactNoop.render(); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: Child', {withoutStack: true}, @@ -2334,7 +2334,7 @@ describe('ReactIncremental', () => { // Trigger an update in the middle of the tree instance.setState({}); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }); it('maintains the correct context when unwinding due to an error in render', () => { @@ -2376,7 +2376,7 @@ describe('ReactIncremental', () => { // Init ReactNoop.render(); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: ContextProvider', {withoutStack: true}, @@ -2387,7 +2387,7 @@ describe('ReactIncremental', () => { instance.setState({ throwError: true, }); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Error boundaries should implement getDerivedStateFromError()', {withoutStack: true}, ); @@ -2425,7 +2425,7 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( [ 'componentWillReceiveProps: Please update the following components ' + 'to use static getDerivedStateFromProps instead: MyComponent', @@ -2496,7 +2496,7 @@ describe('ReactIncremental', () => { // Initial render of the entire tree. // Renders: Root, Middle, FirstChild, SecondChild ReactNoop.render(A); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(renderCounter).toBe(1); @@ -2518,7 +2518,7 @@ describe('ReactIncremental', () => { // The in-progress child content will bailout. // Renders: Root, Middle, FirstChild, SecondChild ReactNoop.render(B); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); // At this point the higher priority render has completed. // Since FirstChild props didn't change, sCU returned false. @@ -2575,14 +2575,14 @@ describe('ReactIncremental', () => { , ); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: Child, TopContextProvider', {withoutStack: true}, ); expect(rendered).toEqual(['count:0']); instance.updateCount(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(rendered).toEqual(['count:0', 'count:1']); }); @@ -2637,14 +2637,14 @@ describe('ReactIncremental', () => { , ); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: Child, MiddleContextProvider, TopContextProvider', {withoutStack: true}, ); expect(rendered).toEqual(['count:0']); instance.updateCount(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(rendered).toEqual(['count:0', 'count:1']); }); @@ -2708,14 +2708,14 @@ describe('ReactIncremental', () => { , ); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: Child, MiddleContextProvider, TopContextProvider', {withoutStack: true}, ); expect(rendered).toEqual(['count:0']); instance.updateCount(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(rendered).toEqual(['count:0']); }); @@ -2789,17 +2789,17 @@ describe('ReactIncremental', () => { , ); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: Child, MiddleContextProvider, TopContextProvider', {withoutStack: true}, ); expect(rendered).toEqual(['count:0, name:brian']); topInstance.updateCount(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(rendered).toEqual(['count:0, name:brian']); middleInstance.updateName('not brian'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(rendered).toEqual([ 'count:0, name:brian', 'count:1, name:not brian', @@ -2818,12 +2818,12 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flushThrough(['Parent: 1']); + expect(ReactNoop).toFlushAndYieldThrough(['Parent: 1']); // Interrupt at same priority ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Child: 1', 'Parent: 2', 'Child: 2']); + expect(ReactNoop).toFlushAndYield(['Child: 1', 'Parent: 2', 'Child: 2']); }); it('does not interrupt for update at lower priority', () => { @@ -2838,13 +2838,13 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flushThrough(['Parent: 1']); + expect(ReactNoop).toFlushAndYieldThrough(['Parent: 1']); // Interrupt at lower priority ReactNoop.expire(2000); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Child: 1', 'Parent: 2', 'Child: 2']); + expect(ReactNoop).toFlushAndYield(['Child: 1', 'Parent: 2', 'Child: 2']); }); it('does interrupt for update at higher priority', () => { @@ -2859,15 +2859,15 @@ describe('ReactIncremental', () => { } ReactNoop.render(); - ReactNoop.flushThrough(['Parent: 1']); + expect(ReactNoop).toFlushAndYieldThrough(['Parent: 1']); // Interrupt at higher priority expect( ReactNoop.flushSync(() => ReactNoop.render()), ).toEqual(['Parent: 2', 'Child: 2']); - ReactNoop.clearYields(); + expect(ReactNoop).toHaveYielded(['Parent: 2', 'Child: 2']); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toFlushAndYield([]); }); // We don't currently use fibers as keys. Re-enable this test if we @@ -2889,7 +2889,7 @@ describe('ReactIncremental', () => { } } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); } // First, verify that this code path normally receives Fibers as keys, diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js index 97959aa53e1..fe09a682cb4 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js @@ -86,7 +86,7 @@ describe('ReactIncrementalErrorHandling', () => { ); // Start rendering asynchronously - ReactNoop.flushThrough([ + expect(ReactNoop).toFlushAndYieldThrough([ 'ErrorBoundary (try)', 'Indirection', 'Indirection', @@ -96,9 +96,9 @@ describe('ReactIncrementalErrorHandling', () => { ]); // Still rendering async... - ReactNoop.flushThrough(['Indirection']); + expect(ReactNoop).toFlushAndYieldThrough(['Indirection']); - ReactNoop.flushThrough([ + expect(ReactNoop).toFlushAndYieldThrough([ 'Indirection', // Call getDerivedStateFromError and re-render the error boundary, this @@ -179,7 +179,7 @@ describe('ReactIncrementalErrorHandling', () => { ); // Start rendering asynchronously - ReactNoop.flushThrough([ + expect(ReactNoop).toFlushAndYieldThrough([ 'ErrorBoundary (try)', 'Indirection', 'Indirection', @@ -189,9 +189,9 @@ describe('ReactIncrementalErrorHandling', () => { ]); // Still rendering async... - ReactNoop.flushThrough(['Indirection']); + expect(ReactNoop).toFlushAndYieldThrough(['Indirection']); - ReactNoop.flushThrough([ + expect(ReactNoop).toFlushAndYieldThrough([ 'Indirection', // Now that the tree is complete, and there's no remaining work, React // reverts to sync mode to retry one more time before handling the error. @@ -230,7 +230,7 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.expire(2000); ReactNoop.render(, onCommit); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ // The first render fails. But because there's a lower priority pending // update, it doesn't throw. 'error', @@ -270,7 +270,7 @@ describe('ReactIncrementalErrorHandling', () => { // Initial mount const parent = React.createRef(null); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual(['Child']); + expect(ReactNoop).toFlushAndYield(['Child']); expect(ReactNoop.getChildren()).toEqual([span('Child')]); // Schedule a low priority update to hide the child @@ -281,7 +281,7 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.flushSync(() => { ReactNoop.render(); }); - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ // First the sync update triggers an error 'Error!', // Because there's a pending low priority update, we restart at the @@ -321,10 +321,10 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.render(, () => ReactNoop.yield('commit')); // Render the bad component asynchronously - ReactNoop.flushThrough(['Parent', 'BadRender']); + expect(ReactNoop).toFlushAndYieldThrough(['Parent', 'BadRender']); // Finish the rest of the async work - ReactNoop.flushThrough(['Sibling']); + expect(ReactNoop).toFlushAndYieldThrough(['Sibling']); // React retries once, synchronously, before throwing. ops = []; @@ -371,7 +371,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'ErrorBoundary', 'BadMount', 'BadMount', @@ -408,7 +408,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([span('Caught an error: Hello.')]); }); @@ -442,10 +442,10 @@ describe('ReactIncrementalErrorHandling', () => { , ); - ReactNoop.flushThrough(['ErrorBoundary render success']); + expect(ReactNoop).toFlushAndYieldThrough(['ErrorBoundary render success']); expect(ReactNoop.getChildren()).toEqual([]); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'BrokenRender', // React retries one more time 'ErrorBoundary render success', @@ -570,7 +570,7 @@ describe('ReactIncrementalErrorHandling', () => { ); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); expect(ops).toEqual([ 'RethrowErrorBoundary render', @@ -609,12 +609,12 @@ describe('ReactIncrementalErrorHandling', () => { , ); - ReactNoop.flushThrough(['RethrowErrorBoundary render']); + expect(ReactNoop).toFlushAndYieldThrough(['RethrowErrorBoundary render']); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ 'BrokenRender', // React retries one more time @@ -711,7 +711,7 @@ describe('ReactIncrementalErrorHandling', () => { throw new Error('Hello'); }); }).toThrow('Hello'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([span('a:3')]); }); @@ -728,7 +728,7 @@ describe('ReactIncrementalErrorHandling', () => { }); }); }).toThrow('Hello'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([span('a:5')]); }); @@ -761,7 +761,7 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.render(); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); expect(ops).toEqual([ 'BrokenRender', @@ -771,7 +771,7 @@ describe('ReactIncrementalErrorHandling', () => { ]); ops = []; ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Foo']); }); @@ -792,12 +792,12 @@ describe('ReactIncrementalErrorHandling', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ops = []; expect(() => { ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); expect(ops).toEqual([ 'BrokenRender', @@ -808,7 +808,7 @@ describe('ReactIncrementalErrorHandling', () => { ops = []; ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Foo']); }); @@ -830,16 +830,16 @@ describe('ReactIncrementalErrorHandling', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(() => { ReactNoop.render(
); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); ops = []; ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Foo']); }); @@ -873,9 +873,9 @@ describe('ReactIncrementalErrorHandling', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(null); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ // Parent unmounts before the error is thrown. 'Parent componentWillUnmount', 'ThrowsOnUnmount componentWillUnmount', @@ -912,7 +912,7 @@ describe('ReactIncrementalErrorHandling', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.flushSync(() => { ReactNoop.render(); @@ -946,7 +946,7 @@ describe('ReactIncrementalErrorHandling', () => { 'a', ); ReactNoop.renderToRootWithID(, 'b'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren('a')).toEqual([ span('Caught an error: Hello.'), ]); @@ -960,14 +960,14 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.renderToRootWithID(, 'a'); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); expect(ReactNoop.getChildren('a')).toEqual([]); ReactNoop.renderToRootWithID(, 'a'); ReactNoop.renderToRootWithID(, 'b'); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); expect(ReactNoop.getChildren('a')).toEqual([]); @@ -976,7 +976,7 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.renderToRootWithID(, 'a'); ReactNoop.renderToRootWithID(, 'b'); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); expect(ReactNoop.getChildren('a')).toEqual([span('a:3')]); expect(ReactNoop.getChildren('b')).toEqual([]); @@ -985,7 +985,7 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.renderToRootWithID(, 'b'); ReactNoop.renderToRootWithID(, 'c'); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); expect(ReactNoop.getChildren('a')).toEqual([span('a:4')]); expect(ReactNoop.getChildren('b')).toEqual([]); @@ -997,7 +997,7 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.renderToRootWithID(, 'd'); ReactNoop.renderToRootWithID(, 'e'); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); expect(ReactNoop.getChildren('a')).toEqual([span('a:5')]); expect(ReactNoop.getChildren('b')).toEqual([span('b:5')]); @@ -1012,7 +1012,7 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.renderToRootWithID(, 'e'); ReactNoop.renderToRootWithID(, 'f'); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); expect(ReactNoop.getChildren('a')).toEqual([]); expect(ReactNoop.getChildren('b')).toEqual([span('b:6')]); @@ -1027,7 +1027,7 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.unmountRootWithID('d'); ReactNoop.unmountRootWithID('e'); ReactNoop.unmountRootWithID('f'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren('a')).toEqual(null); expect(ReactNoop.getChildren('b')).toEqual(null); expect(ReactNoop.getChildren('c')).toEqual(null); @@ -1088,7 +1088,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: Connector, Provider', {withoutStack: true}, @@ -1121,7 +1121,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - expect(ReactNoop.flush).toWarnDev([ + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev([ 'Warning: React.createElement: type is invalid -- expected a string', // React retries once on error 'Warning: React.createElement: type is invalid -- expected a string', @@ -1163,14 +1163,14 @@ describe('ReactIncrementalErrorHandling', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render( , ); - expect(ReactNoop.flush).toWarnDev([ + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev([ 'Warning: React.createElement: type is invalid -- expected a string', // React retries once on error 'Warning: React.createElement: type is invalid -- expected a string', @@ -1194,7 +1194,7 @@ describe('ReactIncrementalErrorHandling', () => { 'Warning: React.createElement: type is invalid -- expected a string', {withoutStack: true}, ); - expect(ReactNoop.flush).toThrowError( + expect(ReactNoop).toFlushAndThrow( 'Element type is invalid: expected a string (for built-in components) or ' + 'a class/function (for composite components) but got: undefined.' + (__DEV__ @@ -1204,7 +1204,7 @@ describe('ReactIncrementalErrorHandling', () => { ); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([span('hi')]); }); @@ -1243,11 +1243,11 @@ describe('ReactIncrementalErrorHandling', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); inst.setState({fail: true}); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrowError('Hello.'); expect(ops).toEqual([ @@ -1285,7 +1285,7 @@ describe('ReactIncrementalErrorHandling', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['barRef attach']); expect(ReactNoop.getChildren()).toEqual([div(span('Bar'))]); @@ -1293,7 +1293,7 @@ describe('ReactIncrementalErrorHandling', () => { // Unmount ReactNoop.render(); - expect(() => ReactNoop.flush()).toThrow('Detach error'); + expect(ReactNoop).toFlushAndThrow('Detach error'); expect(ops).toEqual([ 'barRef detach', // Bar should unmount even though its ref threw an error while detaching @@ -1305,14 +1305,14 @@ describe('ReactIncrementalErrorHandling', () => { it('handles error thrown by host config while working on failed root', () => { ReactNoop.render(); - expect(() => ReactNoop.flush()).toThrow('Error in host config.'); + expect(ReactNoop).toFlushAndThrow('Error in host config.'); }); it('handles error thrown by top-level callback', () => { ReactNoop.render(
, () => { throw new Error('Error!'); }); - expect(() => ReactNoop.flush()).toThrow('Error!'); + expect(ReactNoop).toFlushAndThrow('Error!'); }); it('error boundaries capture non-errors', () => { @@ -1359,7 +1359,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ 'ErrorBoundary (try)', @@ -1430,7 +1430,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'ErrorBoundary (try)', 'throw', // Continue rendering siblings after BadRender throws @@ -1480,7 +1480,7 @@ describe('ReactIncrementalErrorHandling', () => { } ReactNoop.render(); - ReactNoop.flushThrough([ + expect(ReactNoop).toFlushAndYieldThrough([ 'render', 'throw', 'render', @@ -1522,7 +1522,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['render error message']); expect(ReactNoop.getChildren()).toEqual([ span( 'Caught an error:\n' + @@ -1558,7 +1558,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([span('Caught an error: Hello')]); }); @@ -1582,7 +1582,7 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.render(); expect(() => { - expect(() => ReactNoop.flush()).toThrow('Oops!'); + expect(ReactNoop).toFlushAndThrow('Oops!'); }).toWarnDev( 'Legacy context API has been detected within a strict-mode tree: \n\n' + 'Please update the following components: Provider', diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorLogging-test.js b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorLogging-test.js index 4394b2822e7..16b0393d3dd 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorLogging-test.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorLogging-test.js @@ -50,7 +50,7 @@ describe('ReactIncrementalErrorLogging', () => {
, ); - expect(() => ReactNoop.flush()).toThrowError('constructor error'); + expect(ReactNoop).toFlushAndThrow('constructor error'); expect(console.error).toHaveBeenCalledTimes(1); expect(console.error).toHaveBeenCalledWith( __DEV__ @@ -86,7 +86,7 @@ describe('ReactIncrementalErrorLogging', () => {
, ); - expect(() => ReactNoop.flush()).toThrowError('componentDidMount error'); + expect(ReactNoop).toFlushAndThrow('componentDidMount error'); expect(console.error).toHaveBeenCalledTimes(1); expect(console.error).toHaveBeenCalledWith( __DEV__ @@ -125,7 +125,7 @@ describe('ReactIncrementalErrorLogging', () => { , ); - expect(() => ReactNoop.flush()).toThrow('render error'); + expect(ReactNoop).toFlushAndThrow('render error'); expect(logCapturedErrorCalls.length).toBe(1); expect(logCapturedErrorCalls[0]).toEqual( __DEV__ @@ -181,7 +181,7 @@ describe('ReactIncrementalErrorLogging', () => { , ); - expect(ReactNoop.flush()).toEqual( + expect(ReactNoop).toFlushAndYield( [ 'render: 0', __DEV__ && 'render: 0', // replay diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorReplay-test.js b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorReplay-test.js index 1474d012e67..0b4d20c4a56 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalErrorReplay-test.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalErrorReplay-test.js @@ -22,7 +22,7 @@ describe('ReactIncrementalErrorReplay', () => { it('should fail gracefully on error in the host environment', () => { ReactNoop.render(); - expect(() => ReactNoop.flush()).toThrow('Error in host config.'); + expect(ReactNoop).toFlushAndThrow('Error in host config.'); }); it("should ignore error if it doesn't throw on retry", () => { @@ -43,6 +43,6 @@ describe('ReactIncrementalErrorReplay', () => { } } ReactNoop.render(); - expect(() => ReactNoop.flush()).not.toThrow(); + expect(ReactNoop).toFlushWithoutYielding(); }); }); diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js index 90501df0fb1..cab78697424 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalPerf-test.internal.js @@ -144,7 +144,7 @@ describe('ReactDebugFiberPerf', () => {
, ); addComment('Mount'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render( @@ -152,11 +152,11 @@ describe('ReactDebugFiberPerf', () => { , ); addComment('Update'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(null); addComment('Unmount'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -182,7 +182,7 @@ describe('ReactDebugFiberPerf', () => {
, ); addComment('Mount'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -200,7 +200,7 @@ describe('ReactDebugFiberPerf', () => { , ); addComment('Mount'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -216,7 +216,7 @@ describe('ReactDebugFiberPerf', () => { , ); addComment('Mount'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -248,13 +248,13 @@ describe('ReactDebugFiberPerf', () => {
, ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); resetFlamechart(); a.setState({}); b.setState({}); addComment('Should include just A and B, no Parents'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -274,7 +274,7 @@ describe('ReactDebugFiberPerf', () => {
, ); addComment('Should print a warning'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -283,7 +283,7 @@ describe('ReactDebugFiberPerf', () => { componentDidMount() { ReactNoop.renderToRootWithID(, 'b'); addComment('Scheduling another root from componentDidMount'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); } render() { return
{this.props.children}
; @@ -292,7 +292,7 @@ describe('ReactDebugFiberPerf', () => { ReactNoop.renderToRootWithID(, 'a'); addComment('Rendering the first root'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -315,7 +315,7 @@ describe('ReactDebugFiberPerf', () => {
, ); addComment('Should not print a warning'); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( [ 'componentWillMount: Please update the following components ' + 'to use componentDidMount instead: NotCascading' + @@ -330,7 +330,7 @@ describe('ReactDebugFiberPerf', () => {
, ); addComment('Should not print a warning'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -357,7 +357,7 @@ describe('ReactDebugFiberPerf', () => { } ReactNoop.render(); addComment('Mount'); - expect(ReactNoop.flush).toWarnDev( + expect(() => expect(ReactNoop).toFlushWithoutYielding()).toWarnDev( [ 'componentWillMount: Please update the following components ' + 'to use componentDidMount instead: AllLifecycles' + @@ -372,10 +372,10 @@ describe('ReactDebugFiberPerf', () => { ); ReactNoop.render(); addComment('Update'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render(null); addComment('Unmount'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -391,7 +391,7 @@ describe('ReactDebugFiberPerf', () => { ); }); addComment('Flush the child'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -431,9 +431,9 @@ describe('ReactDebugFiberPerf', () => {
, ); addComment('Start rendering through B'); - ReactNoop.flushThrough(['A', 'B']); + expect(ReactNoop).toFlushAndYieldThrough(['A', 'B']); addComment('Complete the rest'); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['C']); expect(getFlameChart()).toMatchSnapshot(); }); @@ -449,7 +449,7 @@ describe('ReactDebugFiberPerf', () => { ); try { addComment('Will fatal'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); } catch (err) { expect(err.message).toBe('Game over'); } @@ -459,7 +459,7 @@ describe('ReactDebugFiberPerf', () => {
, ); addComment('Will reconcile from a clean state'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -495,7 +495,7 @@ describe('ReactDebugFiberPerf', () => {
, ); addComment('Stop on Baddie and restart from Boundary'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -526,7 +526,7 @@ describe('ReactDebugFiberPerf', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); resetFlamechart(); ReactNoop.render( @@ -538,7 +538,7 @@ describe('ReactDebugFiberPerf', () => { , ); addComment('The commit phase should mention A and B just once'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.render( @@ -549,7 +549,7 @@ describe('ReactDebugFiberPerf', () => { ); addComment("Because of deduplication, we don't know B was cascading,"); addComment('but we should still see the warning for the commit phase.'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -562,7 +562,7 @@ describe('ReactDebugFiberPerf', () => { {ReactNoop.createPortal(, portalContainer, null)} , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -575,7 +575,7 @@ describe('ReactDebugFiberPerf', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -603,7 +603,7 @@ describe('ReactDebugFiberPerf', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); resolve( @@ -621,7 +621,7 @@ describe('ReactDebugFiberPerf', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -652,8 +652,8 @@ describe('ReactDebugFiberPerf', () => { ReactNoop.flushSync(() => { ReactNoop.render(); }); - expect(ReactNoop.clearYields()).toEqual(['Foo']); - ReactNoop.flush(); + expect(ReactNoop).toHaveYielded(['Foo']); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -664,7 +664,7 @@ describe('ReactDebugFiberPerf', () => { ReactNoop.render(); ReactNoop.expire(6000); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); }); diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.internal.js index c82b2f990ef..0f67ff943c1 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.internal.js @@ -23,6 +23,17 @@ describe('ReactIncrementalReflection', () => { ReactNoop = require('react-noop-renderer'); }); + function div(...children) { + children = children.map( + c => (typeof c === 'string' ? {text: c, hidden: false} : c), + ); + return {type: 'div', children, prop: undefined, hidden: false}; + } + + function span(prop) { + return {type: 'span', children: [], prop, hidden: false}; + } + it('handles isMounted even when the initial render is deferred', () => { const instances = []; @@ -51,13 +62,13 @@ describe('ReactIncrementalReflection', () => { ReactNoop.render(); // Render part way through but don't yet commit the updates. - ReactNoop.flushThrough(['componentWillMount: false']); + expect(ReactNoop).toFlushAndYieldThrough(['componentWillMount: false']); expect(instances[0]._isMounted()).toBe(false); // Render the rest and commit the updates. expect(() => - expect(ReactNoop.flush()).toEqual(['componentDidMount: true']), + expect(ReactNoop).toFlushAndYield(['componentDidMount: true']), ).toWarnDev( 'componentWillMount: Please update the following components ' + 'to use componentDidMount instead: Component', @@ -96,7 +107,7 @@ describe('ReactIncrementalReflection', () => { } ReactNoop.render(); - expect(() => expect(ReactNoop.flush()).toEqual(['Component'])).toWarnDev( + expect(() => expect(ReactNoop).toFlushAndYield(['Component'])).toWarnDev( 'componentWillMount: Please update the following components ' + 'to use componentDidMount instead: Component', {withoutStack: true}, @@ -107,12 +118,12 @@ describe('ReactIncrementalReflection', () => { ReactNoop.render(); // Render part way through but don't yet commit the updates so it is not // fully unmounted yet. - ReactNoop.flushThrough(['Other']); + expect(ReactNoop).toFlushAndYieldThrough(['Other']); expect(instances[0]._isMounted()).toBe(true); // Finish flushing the unmount. - expect(ReactNoop.flush()).toEqual(['componentWillUnmount: true']); + expect(ReactNoop).toFlushAndYield(['componentWillUnmount: true']); expect(instances[0]._isMounted()).toBe(false); }); @@ -174,7 +185,7 @@ describe('ReactIncrementalReflection', () => { ReactNoop.render(); // Flush past Component but don't complete rendering everything yet. - ReactNoop.flushThrough([ + expect(ReactNoop).toFlushAndYieldThrough([ ['componentWillMount', null], 'render', 'render sibling', @@ -186,9 +197,7 @@ describe('ReactIncrementalReflection', () => { expect(findInstance(classInstance)).toBe(null); expect(() => - expect(ReactNoop.flush()).toEqual([ - ['componentDidMount', classInstance.span], - ]), + expect(ReactNoop).toFlushAndYield([['componentDidMount', span()]]), ).toWarnDev( 'componentWillMount: Please update the following components ' + 'to use componentDidMount instead: Component' + @@ -205,7 +214,7 @@ describe('ReactIncrementalReflection', () => { // Flush next step which will cause an update but not yet render a new host // node. ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ ['componentWillUpdate', hostSpan], 'render', 'render sibling', @@ -217,7 +226,7 @@ describe('ReactIncrementalReflection', () => { // The next step will render a new host node but won't get committed yet. // We expect this to mutate the original Fiber. ReactNoop.render(); - ReactNoop.flushThrough([ + expect(ReactNoop).toFlushAndYieldThrough([ ['componentWillUpdate', hostSpan], 'render', 'render sibling', @@ -227,9 +236,7 @@ describe('ReactIncrementalReflection', () => { expect(ReactNoop.findInstance(classInstance)).toBe(hostSpan); // When we finally flush the tree it will get committed. - expect(ReactNoop.flush()).toEqual([ - ['componentDidUpdate', classInstance.div], - ]); + expect(ReactNoop).toFlushAndYield([['componentDidUpdate', div()]]); const hostDiv = classInstance.div; expect(hostDiv).toBeDefined(); @@ -240,7 +247,7 @@ describe('ReactIncrementalReflection', () => { // Render to null but don't commit it yet. ReactNoop.render(); - ReactNoop.flushThrough([ + expect(ReactNoop).toFlushAndYieldThrough([ ['componentWillUpdate', hostDiv], 'render', 'render sibling', @@ -249,17 +256,22 @@ describe('ReactIncrementalReflection', () => { // This should still be the host div since the deletion is not committed. expect(ReactNoop.findInstance(classInstance)).toBe(hostDiv); - expect(ReactNoop.flush()).toEqual([['componentDidUpdate', null]]); + expect(ReactNoop).toFlushAndYield([['componentDidUpdate', null]]); // This should still be the host div since the deletion is not committed. expect(ReactNoop.findInstance(classInstance)).toBe(null); // Render a div again ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield([ + ['componentWillUpdate', null], + 'render', + 'render sibling', + ['componentDidUpdate', div()], + ]); // Unmount the component. ReactNoop.render([]); - expect(ReactNoop.flush()).toEqual([['componentWillUnmount', hostDiv]]); + expect(ReactNoop).toFlushAndYield([['componentWillUnmount', hostDiv]]); }); }); diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.internal.js index 4f23c2d599a..b1896b97b37 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.internal.js @@ -31,8 +31,8 @@ describe('ReactIncrementalScheduling', () => { ReactNoop.render(); expect(ReactNoop.getChildren()).toEqual([]); - ReactNoop.flush(); - expect(ReactNoop.getChildren()).toEqual([span('1')]); + expect(ReactNoop).toFlushWithoutYielding(); + expect(ReactNoop).toMatchRenderedOutput(); }); it('searches for work on other roots once the current root completes', () => { @@ -40,7 +40,7 @@ describe('ReactIncrementalScheduling', () => { ReactNoop.renderToRootWithID(, 'b'); ReactNoop.renderToRootWithID(, 'c'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren('a')).toEqual([span('a:1')]); expect(ReactNoop.getChildren('b')).toEqual([span('b:1')]); @@ -50,8 +50,8 @@ describe('ReactIncrementalScheduling', () => { it('schedules top-level updates in order of priority', () => { // Initial render. ReactNoop.render(); - ReactNoop.flush(); - expect(ReactNoop.getChildren()).toEqual([span(1)]); + expect(ReactNoop).toFlushWithoutYielding(); + expect(ReactNoop).toMatchRenderedOutput(); ReactNoop.batchedUpdates(() => { ReactNoop.render(); @@ -62,27 +62,27 @@ describe('ReactIncrementalScheduling', () => { }); }); // The sync updates flush first. - expect(ReactNoop.getChildren()).toEqual([span(4)]); + expect(ReactNoop).toMatchRenderedOutput(); // The terminal value should be the last update that was scheduled, // regardless of priority. In this case, that's the last sync update. - ReactNoop.flush(); - expect(ReactNoop.getChildren()).toEqual([span(4)]); + expect(ReactNoop).toFlushWithoutYielding(); + expect(ReactNoop).toMatchRenderedOutput(); }); it('schedules top-level updates with same priority in order of insertion', () => { // Initial render. ReactNoop.render(); - ReactNoop.flush(); - expect(ReactNoop.getChildren()).toEqual([span(1)]); + expect(ReactNoop).toFlushWithoutYielding(); + expect(ReactNoop).toMatchRenderedOutput(); ReactNoop.render(); ReactNoop.render(); ReactNoop.render(); ReactNoop.render(); - ReactNoop.flush(); - expect(ReactNoop.getChildren()).toEqual([span(5)]); + expect(ReactNoop).toFlushWithoutYielding(); + expect(ReactNoop).toMatchRenderedOutput(); }); it('works on deferred roots in the order they were scheduled', () => { @@ -102,7 +102,7 @@ describe('ReactIncrementalScheduling', () => { ReactNoop.renderToRootWithID(, 'b'); ReactNoop.renderToRootWithID(, 'c'); }); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['a:1', 'b:1', 'c:1']); expect(ReactNoop.getChildrenAsJSX('a')).toEqual('a:1'); expect(ReactNoop.getChildrenAsJSX('b')).toEqual('b:1'); @@ -114,7 +114,7 @@ describe('ReactIncrementalScheduling', () => { ReactNoop.renderToRootWithID(, 'b'); }); // Ensure it starts in the order it was scheduled - ReactNoop.flushThrough(['c:2']); + expect(ReactNoop).toFlushAndYieldThrough(['c:2']); expect(ReactNoop.getChildrenAsJSX('a')).toEqual('a:1'); expect(ReactNoop.getChildrenAsJSX('b')).toEqual('b:1'); @@ -124,12 +124,12 @@ describe('ReactIncrementalScheduling', () => { ReactNoop.renderToRootWithID(, 'a'); }); // Keep performing work in the order it was scheduled - ReactNoop.flushThrough(['b:2']); + expect(ReactNoop).toFlushAndYieldThrough(['b:2']); expect(ReactNoop.getChildrenAsJSX('a')).toEqual('a:1'); expect(ReactNoop.getChildrenAsJSX('b')).toEqual('b:2'); expect(ReactNoop.getChildrenAsJSX('c')).toEqual('c:2'); - ReactNoop.flushThrough(['a:2']); + expect(ReactNoop).toFlushAndYieldThrough(['a:2']); expect(ReactNoop.getChildrenAsJSX('a')).toEqual('a:2'); expect(ReactNoop.getChildrenAsJSX('b')).toEqual('b:2'); expect(ReactNoop.getChildrenAsJSX('c')).toEqual('c:2'); @@ -175,7 +175,7 @@ describe('ReactIncrementalScheduling', () => { ReactNoop.render(); // Render without committing - ReactNoop.flushThrough(['render: 0']); + expect(ReactNoop).toFlushAndYieldThrough(['render: 0']); // Do one more unit of work to commit expect(ReactNoop.flushNextYield()).toEqual([ @@ -188,7 +188,7 @@ describe('ReactIncrementalScheduling', () => { ]); instance.setState({tick: 2}); - ReactNoop.flushThrough(['render: 2']); + expect(ReactNoop).toFlushAndYieldThrough(['render: 2']); expect(ReactNoop.flushNextYield()).toEqual([ 'componentDidUpdate: 2', 'componentDidUpdate (before setState): 2', @@ -243,31 +243,31 @@ describe('ReactIncrementalScheduling', () => { ReactNoop.render(); }); // The cDM update should not have flushed yet because it has async priority. - expect(ReactNoop.clearYields()).toEqual([ + expect(ReactNoop).toHaveYielded([ 'render: 0', 'componentDidMount (before setState): 0', 'componentDidMount (after setState): 0', ]); - expect(ReactNoop.getChildren()).toEqual([span(0)]); + expect(ReactNoop).toMatchRenderedOutput(); // Now flush the cDM update. - expect(ReactNoop.flush()).toEqual(['render: 1', 'componentDidUpdate: 1']); - expect(ReactNoop.getChildren()).toEqual([span(1)]); + expect(ReactNoop).toFlushAndYield(['render: 1', 'componentDidUpdate: 1']); + expect(ReactNoop).toMatchRenderedOutput(); // Increment the tick to 2. This will trigger an update inside cDU. Flush // the first update without flushing the second one. instance.setState({tick: 2}); - ReactNoop.flushThrough([ + expect(ReactNoop).toFlushAndYieldThrough([ 'render: 2', 'componentDidUpdate: 2', 'componentDidUpdate (before setState): 2', 'componentDidUpdate (after setState): 2', ]); - expect(ReactNoop.getChildren()).toEqual([span(2)]); + expect(ReactNoop).toMatchRenderedOutput(); // Now flush the cDU update. - expect(ReactNoop.flush()).toEqual(['render: 3', 'componentDidUpdate: 3']); - expect(ReactNoop.getChildren()).toEqual([span(3)]); + expect(ReactNoop).toFlushAndYield(['render: 3', 'componentDidUpdate: 3']); + expect(ReactNoop).toMatchRenderedOutput(); }); it('performs Task work even after time runs out', () => { @@ -290,13 +290,13 @@ describe('ReactIncrementalScheduling', () => { ReactNoop.render(); // This should be just enough to complete all the work, but not enough to // commit it. - ReactNoop.flushThrough(['Foo']); - expect(ReactNoop.getChildren()).toEqual([]); + expect(ReactNoop).toFlushAndYieldThrough(['Foo']); + expect(ReactNoop).toMatchRenderedOutput(null); // Do one more unit of work. ReactNoop.flushNextYield(); // The updates should all be flushed with Task priority - expect(ReactNoop.getChildren()).toEqual([span(5)]); + expect(ReactNoop).toMatchRenderedOutput(); }); it('can opt-out of batching using unbatchedUpdates', () => { @@ -309,16 +309,16 @@ describe('ReactIncrementalScheduling', () => { // updates are not batched ReactNoop.unbatchedUpdates(() => { ReactNoop.render(); - expect(ReactNoop.getChildren()).toEqual([span(1)]); + expect(ReactNoop).toMatchRenderedOutput(); ReactNoop.render(); - expect(ReactNoop.getChildren()).toEqual([span(2)]); + expect(ReactNoop).toMatchRenderedOutput(); }); ReactNoop.render(); - expect(ReactNoop.getChildren()).toEqual([span(2)]); + expect(ReactNoop).toMatchRenderedOutput(); }); // Remaining update is now flushed - expect(ReactNoop.getChildren()).toEqual([span(3)]); + expect(ReactNoop).toMatchRenderedOutput(); }); it('nested updates are always deferred, even inside unbatchedUpdates', () => { @@ -335,7 +335,7 @@ describe('ReactIncrementalScheduling', () => { // in unbatchedUpdates. this.setState({step: 2}); }); - expect(ReactNoop.getChildren()).toEqual([span(1)]); + expect(ReactNoop).toMatchRenderedOutput(); } } render() { @@ -345,13 +345,13 @@ describe('ReactIncrementalScheduling', () => { } } ReactNoop.render(); - ReactNoop.flush(); - expect(ReactNoop.getChildren()).toEqual([span(0)]); + expect(ReactNoop).toFlushWithoutYielding(); + expect(ReactNoop).toMatchRenderedOutput(); ReactNoop.flushSync(() => { instance.setState({step: 1}); }); - expect(ReactNoop.getChildren()).toEqual([span(2)]); + expect(ReactNoop).toMatchRenderedOutput(); expect(ops).toEqual([ 'render: 0', @@ -380,14 +380,16 @@ describe('ReactIncrementalScheduling', () => { } ReactNoop.render(); - expect(ReactNoop.flush).toWarnDev( + expect(() => { + expect(ReactNoop).toFlushWithoutYielding(); + }).toWarnDev( 'componentWillReceiveProps: Please update the following components ' + 'to use static getDerivedStateFromProps instead: Foo', {withoutStack: true}, ); ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'has callback before setState: false', 'has callback after setState: false', ]); diff --git a/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.internal.js b/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.internal.js index 9e14dd202fb..e96f61f88b7 100644 --- a/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.internal.js @@ -53,11 +53,11 @@ describe('ReactIncrementalSideEffects', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div(span())]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div(span(), span())]); }); @@ -81,17 +81,17 @@ describe('ReactIncrementalSideEffects', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div(span(), span('test'))]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([ div(span(), span(), div(), span('test')), ]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([ div(span(), div(), span(), span('test')), ]); @@ -114,11 +114,11 @@ describe('ReactIncrementalSideEffects', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div('Hello')]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div('World', 'World', '!')]); }); @@ -138,13 +138,13 @@ describe('ReactIncrementalSideEffects', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([ div(div(), span('Hello'), 'World'), ]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div()]); }); @@ -180,23 +180,23 @@ describe('ReactIncrementalSideEffects', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div(span('Class'), 'Trail')]); expect(unmounted).toBe(false); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div(span('Function'), 'Trail')]); expect(unmounted).toBe(true); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div('Text', 'Trail')]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div('Trail')]); }); @@ -230,19 +230,19 @@ describe('ReactIncrementalSideEffects', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div(span('Class'), 'Trail')]); expect(unmounted).toBe(false); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div(span('Function'), 'Trail')]); expect(unmounted).toBe(true); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div('Trail')]); }); @@ -267,7 +267,7 @@ describe('ReactIncrementalSideEffects', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div()]); expect(ReactNoop.getChildren('portalContainer')).toEqual([ div(), @@ -280,7 +280,7 @@ describe('ReactIncrementalSideEffects', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div()]); expect(ReactNoop.getChildren('portalContainer')).toEqual([]); @@ -289,7 +289,7 @@ describe('ReactIncrementalSideEffects', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div()]); expect(ReactNoop.getChildren('portalContainer')).toEqual([ div(), @@ -298,17 +298,17 @@ describe('ReactIncrementalSideEffects', () => { ]); ReactNoop.render(null); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren('portalContainer')).toEqual([]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren('portalContainer')).toEqual([]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren('portalContainer')).toEqual([ div(), @@ -317,7 +317,7 @@ describe('ReactIncrementalSideEffects', () => { ]); ReactNoop.render(null); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren('portalContainer')).toEqual([]); }); @@ -343,7 +343,7 @@ describe('ReactIncrementalSideEffects', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([div()]); expect(ReactNoop.getChildren('portalContainer')).toEqual([ div(), @@ -352,12 +352,12 @@ describe('ReactIncrementalSideEffects', () => { ]); ReactNoop.render(null); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren('portalContainer')).toEqual([]); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren('portalContainer')).toEqual([ div(), @@ -366,7 +366,7 @@ describe('ReactIncrementalSideEffects', () => { ]); ReactNoop.render(null); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([]); expect(ReactNoop.getChildren('portalContainer')).toEqual([]); }); @@ -391,7 +391,7 @@ describe('ReactIncrementalSideEffects', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Foo', 'Bar', 'Bar', 'Bar']); expect(ReactNoop.getChildren()).toEqual([ div(div(span('Hello'), span('Hello')), span('Yo')), ]); @@ -399,7 +399,7 @@ describe('ReactIncrementalSideEffects', () => { ReactNoop.render(); // Flush some of the work without committing - ReactNoop.flushThrough(['Foo', 'Bar']); + expect(ReactNoop).toFlushAndYieldThrough(['Foo', 'Bar']); expect(ReactNoop.getChildren()).toEqual([ div(div(span('Hello'), span('Hello')), span('Yo')), ]); @@ -423,7 +423,7 @@ describe('ReactIncrementalSideEffects', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Foo', 'Middle']); expect(ReactNoop.getChildrenAsJSX()).toEqual(
@@ -434,7 +434,7 @@ describe('ReactIncrementalSideEffects', () => { ); ReactNoop.render(, () => ReactNoop.yield('commit')); - ReactNoop.flushThrough(['Foo', 'commit']); + expect(ReactNoop).toFlushAndYieldThrough(['Foo', 'commit']); expect(ReactNoop.getChildrenAsJSX()).toEqual(
, ); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['Middle']); expect(ReactNoop.getChildrenAsJSX()).toEqual(