From 8e25ed20bd27d126f670d04680db85209f779056 Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Mon, 25 Feb 2019 19:01:45 -0800 Subject: [PATCH] Unify noop and test renderer assertion APIs (#14952) * 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. * 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 | 143 +++---- .../ReactExpiration-test.internal.js | 24 +- .../src/__tests__/ReactFragment-test.js | 104 +++--- ...eactHooksWithNoopRenderer-test.internal.js | 351 +++++++++--------- .../ReactIncremental-test.internal.js | 202 +++++----- ...tIncrementalErrorHandling-test.internal.js | 118 +++--- .../ReactIncrementalErrorLogging-test.js | 8 +- .../ReactIncrementalErrorReplay-test.js | 4 +- .../ReactIncrementalPerf-test.internal.js | 63 ++-- ...eactIncrementalReflection-test.internal.js | 48 ++- ...eactIncrementalScheduling-test.internal.js | 84 +++-- ...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 | 222 +++++------ .../__tests__/ReactTopLevelFragment-test.js | 20 +- .../src/__tests__/ReactTopLevelText-test.js | 8 +- ...ReactIncrementalPerf-test.internal.js.snap | 14 +- .../ReactTestRenderer-test.internal.js | 2 +- .../__tests__/ReactProfiler-test.internal.js | 24 +- .../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 +- 30 files changed, 1072 insertions(+), 1004 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 cbbb34979a33c..39969ac4bd9d4 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 a9e0e7486fe06..f7115c556c0d5 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 985493ea47132..714141ccd18c8 100644 --- a/packages/react-noop-renderer/src/createReactNoop.js +++ b/packages/react-noop-renderer/src/createReactNoop.js @@ -534,55 +534,71 @@ 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 { + 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 { + 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 childToJSX(child, text) { if (text !== null) { return text; @@ -747,53 +763,14 @@ 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; - }, - // 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; - }, - - 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; - } - } - } - expect(actual).toEqual(expected); - }, + unstable_flushWithoutYielding: flushAll, + unstable_flushNumberOfYields: flushNumberOfYields, + unstable_clearYields: clearYields, 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( @@ -811,7 +788,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) { hostUpdateCounter = 0; hostCloneCounter = 0; try { - ReactNoop.flush(); + flushAll(); return useMutation ? { hostDiffCounter, @@ -838,28 +815,10 @@ 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; - }, - - yield(value: mixed) { - if (yieldedValues === null) { - yieldedValues = [value]; - } else { - yieldedValues.push(value); - } + return flushNumberOfYields(0); }, - clearYields() { - const values = yieldedValues; - yieldedValues = null; - return values; - }, + yield: yieldValue, hasScheduledCallback() { return !!scheduledCallback; @@ -1038,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 65f06b6dc3f51..c397d01b34562 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(null); + 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(null); + 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 d6b8b41fc0f2a..c72b395eb27c3 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 bb8e033623f3e..adca4cbc6de8d 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,9 +583,10 @@ describe('ReactHooksWithNoopRenderer', () => { ReactNoop.flushSync(() => { counter.current.dispatch(INCREMENT); }); + 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')]); }); }); @@ -599,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', () => { @@ -627,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'), @@ -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).toHaveYielded(['Passive effect']); + expect(ReactNoop).toFlushAndYield([]); expect(ReactNoop.getChildren()).toEqual([span('Passive')]); // (No effects are left to flush.) ReactNoop.flushPassiveEffects(); - expect(ReactNoop.clearYields()).toEqual(null); + expect(ReactNoop).toHaveYielded([]); }); it('flushes passive effects even if siblings schedule an update', () => { @@ -666,7 +668,7 @@ describe('ReactHooksWithNoopRenderer', () => { ReactNoop.render([, ]); act(() => { - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Passive', 'Layout', 'Layout effect 0', @@ -698,7 +700,7 @@ describe('ReactHooksWithNoopRenderer', () => { return ; } ReactNoop.render([, ]); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'Passive', 'Layout', 'Layout effect', @@ -732,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.flush()).toEqual([ + expect(ReactNoop).toHaveYielded([ // The previous effect flushes before the reconciliation 'Committed state when effect was fired: 0', - 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', ]); }, @@ -764,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', () => { @@ -791,22 +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(); - ReactNoop.flushThrough(['Schedule update [0]', '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.flush()).toEqual(['Schedule update [1]', 'Count: 1']); + expect(ReactNoop).toHaveYielded(['Schedule update [1]']); + expect(ReactNoop).toFlushAndYield(['Count: 1']); expect(ReactNoop.getChildren()).toEqual([span('Count: 1')]); }); @@ -823,13 +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.flush()).toEqual(['Will set count to 1', 'Count: 2']); + expect(ReactNoop).toHaveYielded(['Will set count to 1']); + expect(ReactNoop).toFlushAndYield(['Count: 2']); expect(ReactNoop.getChildren()).toEqual([span('Count: 2')]); }); @@ -867,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); @@ -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).toHaveYielded(['Will set count to 1']); + expect(ReactNoop).toFlushAndYield(['Count: 2']); expect(ReactNoop.getChildren()).toEqual([span('Count: 2')]); expect(onInteractionScheduledWorkCompleted).toHaveBeenCalledTimes(1); @@ -905,13 +911,13 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.renderLegacySyncRoot(); // Even in sync mode, effects are deferred until after paint - expect(ReactNoop.flush()).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')]); }, ); @@ -931,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(() => { @@ -950,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', () => { @@ -976,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([]); }); @@ -997,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(null); + expect(ReactNoop).toHaveYielded([]); ReactNoop.render(null); - expect(ReactNoop.flush()).toEqual(['Did destroy [0]']); + expect(ReactNoop).toFlushAndYield(['Did destroy [0]']); expect(ReactNoop.getChildren()).toEqual([]); }); @@ -1025,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([]); }); @@ -1056,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(null); + 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]', ]); @@ -1100,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', () => { @@ -1135,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]', @@ -1172,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 @@ -1206,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]', @@ -1248,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]', @@ -1277,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([]); }); }); @@ -1293,7 +1290,9 @@ describe('ReactHooksWithNoopRenderer', () => { describe('useLayoutEffect', () => { it('fires layout effects after the host has been mutated', () => { function getCommittedText() { + const yields = ReactNoop.unstable_clearYields(); const children = ReactNoop.getChildren(); + ReactNoop.yield(yields); if (children === null) { return null; } @@ -1308,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)]); }); @@ -1340,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.flush()).toEqual([ - 'Mount normal [current: 0]', + 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]', ]); @@ -1385,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', @@ -1404,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', @@ -1416,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'), @@ -1439,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')]); }); @@ -1472,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', () => { @@ -1502,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']); }); }); @@ -1546,17 +1545,17 @@ describe('ReactHooksWithNoopRenderer', () => { } ReactNoop.render(); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toFlushAndYield([]); ping(1); ping(2); ping(3); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toHaveYielded([]); jest.advanceTimersByTime(100); - expect(ReactNoop.flush()).toEqual(['ping: 3']); + expect(ReactNoop).toHaveYielded(['ping: 3']); ping(4); jest.advanceTimersByTime(20); @@ -1564,10 +1563,10 @@ describe('ReactHooksWithNoopRenderer', () => { ping(6); jest.advanceTimersByTime(80); - expect(ReactNoop.flush()).toEqual([]); + expect(ReactNoop).toHaveYielded([]); jest.advanceTimersByTime(20); - expect(ReactNoop.flush()).toEqual(['ping: 6']); + expect(ReactNoop).toHaveYielded(['ping: 6']); }); it('should return the same ref during re-renders', () => { @@ -1588,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']); }); }); @@ -1612,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); @@ -1642,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); }); @@ -1678,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); @@ -1686,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 @@ -1723,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]'), ]); @@ -1733,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')]); }); @@ -1775,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.', ); @@ -1813,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 1f65fc6ec3d90..1ae63e690e774 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 f4a24cfc0ae42..fe09a682cb45b 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,14 @@ 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 'RethrowErrorBoundary render', 'BrokenRender', @@ -709,7 +711,7 @@ describe('ReactIncrementalErrorHandling', () => { throw new Error('Hello'); }); }).toThrow('Hello'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([span('a:3')]); }); @@ -726,7 +728,7 @@ describe('ReactIncrementalErrorHandling', () => { }); }); }).toThrow('Hello'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([span('a:5')]); }); @@ -759,7 +761,7 @@ describe('ReactIncrementalErrorHandling', () => { ReactNoop.render(); expect(() => { - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); }).toThrow('Hello'); expect(ops).toEqual([ 'BrokenRender', @@ -769,7 +771,7 @@ describe('ReactIncrementalErrorHandling', () => { ]); ops = []; ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Foo']); }); @@ -790,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', @@ -806,7 +808,7 @@ describe('ReactIncrementalErrorHandling', () => { ops = []; ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['Foo']); }); @@ -828,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']); }); @@ -871,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', @@ -910,7 +912,7 @@ describe('ReactIncrementalErrorHandling', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); ReactNoop.flushSync(() => { ReactNoop.render(); @@ -944,7 +946,7 @@ describe('ReactIncrementalErrorHandling', () => { 'a', ); ReactNoop.renderToRootWithID(, 'b'); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren('a')).toEqual([ span('Caught an error: Hello.'), ]); @@ -958,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([]); @@ -974,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([]); @@ -983,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([]); @@ -995,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')]); @@ -1010,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')]); @@ -1025,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); @@ -1086,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}, @@ -1119,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', @@ -1161,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', @@ -1192,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__ @@ -1202,7 +1204,7 @@ describe('ReactIncrementalErrorHandling', () => { ); ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([span('hi')]); }); @@ -1241,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([ @@ -1283,7 +1285,7 @@ describe('ReactIncrementalErrorHandling', () => { } ReactNoop.render(); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual(['barRef attach']); expect(ReactNoop.getChildren()).toEqual([div(span('Bar'))]); @@ -1291,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 @@ -1303,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', () => { @@ -1357,7 +1359,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ops).toEqual([ 'ErrorBoundary (try)', @@ -1428,7 +1430,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - expect(ReactNoop.flush()).toEqual([ + expect(ReactNoop).toFlushAndYield([ 'ErrorBoundary (try)', 'throw', // Continue rendering siblings after BadRender throws @@ -1478,7 +1480,7 @@ describe('ReactIncrementalErrorHandling', () => { } ReactNoop.render(); - ReactNoop.flushThrough([ + expect(ReactNoop).toFlushAndYieldThrough([ 'render', 'throw', 'render', @@ -1520,7 +1522,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushAndYield(['render error message']); expect(ReactNoop.getChildren()).toEqual([ span( 'Caught an error:\n' + @@ -1556,7 +1558,7 @@ describe('ReactIncrementalErrorHandling', () => { , ); - ReactNoop.flush(); + expect(ReactNoop).toFlushWithoutYielding(); expect(ReactNoop.getChildren()).toEqual([span('Caught an error: Hello')]); }); @@ -1580,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 4394b2822e79d..16b0393d3ddcc 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 1474d012e67ec..0b4d20c4a56e8 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 c3b18696380bf..cab786974244e 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,7 +652,8 @@ describe('ReactDebugFiberPerf', () => { ReactNoop.flushSync(() => { ReactNoop.render(); }); - ReactNoop.flush(); + expect(ReactNoop).toHaveYielded(['Foo']); + expect(ReactNoop).toFlushWithoutYielding(); expect(getFlameChart()).toMatchSnapshot(); }); @@ -663,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 c82b2f990ef25..0f67ff943c190 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 353a20ce65b28..b1896b97b37a5 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,27 +243,31 @@ describe('ReactIncrementalScheduling', () => { ReactNoop.render(); }); // The cDM update should not have flushed yet because it has async priority. - expect(ReactNoop.getChildren()).toEqual([span(0)]); + expect(ReactNoop).toHaveYielded([ + 'render: 0', + 'componentDidMount (before setState): 0', + 'componentDidMount (after setState): 0', + ]); + expect(ReactNoop).toMatchRenderedOutput(); // Now flush the cDM update. - ReactNoop.clearYields(); - 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', () => { @@ -286,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', () => { @@ -305,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', () => { @@ -331,7 +335,7 @@ describe('ReactIncrementalScheduling', () => { // in unbatchedUpdates. this.setState({step: 2}); }); - expect(ReactNoop.getChildren()).toEqual([span(1)]); + expect(ReactNoop).toMatchRenderedOutput(); } } render() { @@ -341,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', @@ -376,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 9e14dd202fb59..e96f61f88b7c4 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(