Skip to content

Commit

Permalink
Test cleanup in response to eps1lon's PR feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Vaughn committed Apr 9, 2021
1 parent 3fdb4d3 commit 8c058c7
Showing 1 changed file with 81 additions and 164 deletions.
245 changes: 81 additions & 164 deletions packages/react-reconciler/src/__tests__/ReactUpdaters-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,12 @@ describe('updaters', () => {
await ReactTestUtils.act(async () => {
ReactDOM.render(<Parent />, container);
});
expect(allSchedulerTags).toHaveLength(1);
expect(allSchedulerTags[0]).toHaveLength(1);
expect(allSchedulerTags[0]).toContain(HostRoot);
expect(allSchedulerTags).toEqual([[HostRoot]]);

await ReactTestUtils.act(async () => {
ReactDOM.render(<Parent />, container);
});
expect(allSchedulerTags).toHaveLength(2);
expect(allSchedulerTags[1]).toHaveLength(1);
expect(allSchedulerTags[1]).toContain(HostRoot);
expect(allSchedulerTags).toEqual([[HostRoot], [HostRoot]]);
});

it('should report a function component as the scheduler for a hooks update', async () => {
Expand Down Expand Up @@ -116,21 +112,21 @@ describe('updaters', () => {
});
expect(scheduleForA).not.toBeNull();
expect(scheduleForB).not.toBeNull();
expect(allSchedulerTypes).toHaveLength(1);
expect(allSchedulerTypes).toEqual([[null]]);

await ReactTestUtils.act(async () => {
scheduleForA();
});
expect(allSchedulerTypes).toHaveLength(2);
expect(allSchedulerTypes[1]).toHaveLength(1);
expect(allSchedulerTypes[1]).toContain(SchedulingComponentA);
expect(allSchedulerTypes).toEqual([[null], [SchedulingComponentA]]);

await ReactTestUtils.act(async () => {
scheduleForB();
});
expect(allSchedulerTypes).toHaveLength(3);
expect(allSchedulerTypes[2]).toHaveLength(1);
expect(allSchedulerTypes[2]).toContain(SchedulingComponentB);
expect(allSchedulerTypes).toEqual([
[null],
[SchedulingComponentA],
[SchedulingComponentB],
]);
});

it('should report a class component as the scheduler for a setState update', async () => {
Expand All @@ -147,15 +143,13 @@ describe('updaters', () => {
await ReactTestUtils.act(async () => {
ReactDOM.render(<Parent />, document.createElement('div'));
});
expect(allSchedulerTypes).toHaveLength(1);
expect(allSchedulerTypes).toEqual([[null]]);

expect(instance).not.toBeNull();
await ReactTestUtils.act(async () => {
instance.setState({});
});
expect(allSchedulerTypes).toHaveLength(2);
expect(allSchedulerTypes[1]).toHaveLength(1);
expect(allSchedulerTypes[1]).toContain(SchedulingComponent);
expect(allSchedulerTypes).toEqual([[null], [SchedulingComponent]]);
});

// @gate experimental
Expand Down Expand Up @@ -198,7 +192,7 @@ describe('updaters', () => {
});
expect(triggerActiveCascade).not.toBeNull();
expect(triggerPassiveCascade).not.toBeNull();
expect(allSchedulerTypes).toHaveLength(1);
expect(allSchedulerTypes).toEqual([[null]]);

await ReactTestUtils.act(async () => {
triggerActiveCascade();
Expand All @@ -209,11 +203,11 @@ describe('updaters', () => {
'onCommitRoot',
]);
});
expect(allSchedulerTypes).toHaveLength(3);
expect(allSchedulerTypes[1]).toHaveLength(1);
expect(allSchedulerTypes[1]).toContain(SchedulingComponent);
expect(allSchedulerTypes[2]).toHaveLength(1);
expect(allSchedulerTypes[2]).toContain(CascadingChild);
expect(allSchedulerTypes).toEqual([
[null],
[SchedulingComponent],
[CascadingChild],
]);

await ReactTestUtils.act(async () => {
triggerPassiveCascade();
Expand All @@ -224,11 +218,13 @@ describe('updaters', () => {
'onCommitRoot',
]);
});
expect(allSchedulerTypes).toHaveLength(5);
expect(allSchedulerTypes[3]).toHaveLength(1);
expect(allSchedulerTypes[3]).toContain(SchedulingComponent);
expect(allSchedulerTypes[4]).toHaveLength(1);
expect(allSchedulerTypes[4]).toContain(CascadingChild);
expect(allSchedulerTypes).toEqual([
[null],
[SchedulingComponent],
[CascadingChild],
[SchedulingComponent],
[CascadingChild],
]);

// Verify no outstanding flushes
Scheduler.unstable_flushAll();
Expand Down Expand Up @@ -273,25 +269,21 @@ describe('updaters', () => {
expect(Scheduler).toHaveYielded(['onCommitRoot']);
});
expect(setShouldSuspend).not.toBeNull();
expect(allSchedulerTypes).toHaveLength(1);
expect(allSchedulerTypes).toEqual([[null]]);

await ReactTestUtils.act(async () => {
setShouldSuspend(true);
});
expect(Scheduler).toHaveYielded(['onCommitRoot']);
expect(allSchedulerTypes).toHaveLength(2);
expect(allSchedulerTypes[1]).toHaveLength(1);
expect(allSchedulerTypes[1]).toContain(Suspender);
expect(allSchedulerTypes).toEqual([[null], [Suspender]]);

expect(resolver).not.toBeNull();
await ReactTestUtils.act(() => {
resolver('abc');
return promise;
});
expect(Scheduler).toHaveYielded(['onCommitRoot']);
expect(allSchedulerTypes).toHaveLength(3);
expect(allSchedulerTypes[2]).toHaveLength(1);
expect(allSchedulerTypes[2]).toContain(Suspender);
expect(allSchedulerTypes).toEqual([[null], [Suspender], [Suspender]]);

// Verify no outstanding flushes
Scheduler.unstable_flushAll();
Expand All @@ -301,7 +293,10 @@ describe('updaters', () => {

// @gate experimental
it('traces interaction through hidden subtree', async () => {
const {HostRoot} = require('react-reconciler/src/ReactWorkTags');
const {
FunctionComponent,
HostRoot,
} = require('react-reconciler/src/ReactWorkTags');

// Note: This is based on a similar component we use in www. We can delete once
// the extra div wrapper is no longer necessary.
Expand Down Expand Up @@ -368,17 +363,17 @@ describe('updaters', () => {
'onCommitRoot',
'Child:update',
]);
// Initial render
expect(allSchedulerTypes).toHaveLength(4);
expect(allSchedulerTags[0]).toHaveLength(1);
expect(allSchedulerTags[0]).toContain(HostRoot);
// Offscreen update
expect(allSchedulerTypes[1]).toHaveLength(0);
// Child passive effect
expect(allSchedulerTypes[2]).toHaveLength(1);
expect(allSchedulerTypes[2]).toContain(Child);
// Offscreen update
expect(allSchedulerTypes[3]).toHaveLength(0);
expect(allSchedulerTypes).toEqual([
// Initial render
[null],
// Offscreen update
[],
// Child passive effect
[Child],
// Offscreen update
[],
]);
expect(allSchedulerTags).toEqual([[HostRoot], [], [FunctionComponent], []]);
});

// @gate experimental
Expand Down Expand Up @@ -432,25 +427,26 @@ describe('updaters', () => {
triggerError();
});
expect(Scheduler).toHaveYielded(['onCommitRoot', 'error', 'onCommitRoot']);
expect(allSchedulerTypes).toHaveLength(2);
expect(allSchedulerTypes[0]).toHaveLength(1);
expect(allSchedulerTypes[0]).toContain(Parent);
expect(allSchedulerTypes[1]).toHaveLength(1);
expect(allSchedulerTypes[1]).toContain(ErrorBoundary);
expect(allSchedulerTypes).toEqual([[Parent], [ErrorBoundary]]);

// Verify no outstanding flushes
Scheduler.unstable_flushAll();
});

// @gate experimental
it('should distinguish between updaters in the case of interleaved work', async () => {
const {
FunctionComponent,
HostRoot,
} = require('react-reconciler/src/ReactWorkTags');

let triggerLowPriorityUpdate = null;
let triggerSyncPriorityUpdate = null;

const HighPriorityUpdater = () => {
const SyncPriorityUpdater = () => {
const [count, setCount] = React.useState(0);
triggerSyncPriorityUpdate = () => setCount(prevCount => prevCount + 1);
Scheduler.unstable_yieldValue(`HighPriorityUpdater ${count}`);
Scheduler.unstable_yieldValue(`SyncPriorityUpdater ${count}`);
return <Yield value={`HighPriority ${count}`} />;
};
const LowPriorityUpdater = () => {
Expand All @@ -465,139 +461,60 @@ describe('updaters', () => {
};

const root = ReactDOM.unstable_createRoot(document.createElement('div'));
ReactTestUtils.act(() => {
root.render(
<React.Fragment>
<HighPriorityUpdater />
<LowPriorityUpdater />
</React.Fragment>,
);
expect(Scheduler).toFlushAndYieldThrough([
'HighPriorityUpdater 0',
'Yield HighPriority 0',
'LowPriorityUpdater 0',
'Yield LowPriority 0',
'onCommitRoot',
]);
});
root.render(
<React.Fragment>
<SyncPriorityUpdater />
<LowPriorityUpdater />
</React.Fragment>,
);

// Render everything initially.
expect(Scheduler).toFlushAndYield([
'SyncPriorityUpdater 0',
'Yield HighPriority 0',
'LowPriorityUpdater 0',
'Yield LowPriority 0',
'onCommitRoot',
]);
expect(triggerLowPriorityUpdate).not.toBeNull();
expect(triggerSyncPriorityUpdate).not.toBeNull();
expect(allSchedulerTypes).toHaveLength(1);
expect(allSchedulerTags).toEqual([[HostRoot]]);

// Render a partially update, but don't finish.
// Render a partial update, but don't finish.
ReactTestUtils.act(() => {
triggerLowPriorityUpdate();
expect(Scheduler).toFlushAndYieldThrough(['LowPriorityUpdater 1']);
expect(allSchedulerTypes).toHaveLength(1);
expect(allSchedulerTags).toEqual([[HostRoot]]);

// Interrupt with higher priority work.
ReactDOM.flushSync(triggerSyncPriorityUpdate);
expect(Scheduler).toHaveYielded([
'HighPriorityUpdater 1',
'SyncPriorityUpdater 1',
'Yield HighPriority 1',
'onCommitRoot',
]);
expect(allSchedulerTypes).toHaveLength(2);
expect(allSchedulerTypes[1]).toHaveLength(1);
expect(allSchedulerTypes[1]).toContain(HighPriorityUpdater);
expect(allSchedulerTypes).toEqual([[null], [SyncPriorityUpdater]]);

// Finish the initial partial update
triggerLowPriorityUpdate();
expect(Scheduler).toFlushAndYieldThrough([
expect(Scheduler).toFlushAndYield([
'LowPriorityUpdater 2',
'Yield LowPriority 2',
'onCommitRoot',
]);
});
expect(allSchedulerTypes).toHaveLength(3);
expect(allSchedulerTypes[2]).toHaveLength(1);
expect(allSchedulerTypes[2]).toContain(LowPriorityUpdater);

// Verify no outstanding flushes
Scheduler.unstable_flushAll();
});

// @gate experimental
it('should not lose track of updaters if work yields before finishing', async () => {
const {HostRoot} = require('react-reconciler/src/ReactWorkTags');

const Yield = ({renderTime}) => {
Scheduler.unstable_advanceTime(renderTime);
Scheduler.unstable_yieldValue('Yield:' + renderTime);
return null;
};

let first;
class FirstComponent extends React.Component {
state = {renderTime: 1};
render() {
first = this;
Scheduler.unstable_advanceTime(this.state.renderTime);
Scheduler.unstable_yieldValue(
'FirstComponent:' + this.state.renderTime,
);
return <Yield renderTime={4} />;
}
}
let second;
class SecondComponent extends React.Component {
state = {renderTime: 2};
render() {
second = this;
Scheduler.unstable_advanceTime(this.state.renderTime);
Scheduler.unstable_yieldValue(
'SecondComponent:' + this.state.renderTime,
);
return <Yield renderTime={7} />;
}
}

Scheduler.unstable_advanceTime(5); // 0 -> 5

const root = ReactDOM.unstable_createRoot(document.createElement('div'));
root.render(
<React.Fragment>
<FirstComponent />
<SecondComponent />
</React.Fragment>,
);

// Render everything initially.
expect(Scheduler).toFlushAndYield([
'FirstComponent:1',
'Yield:4',
'SecondComponent:2',
'Yield:7',
'onCommitRoot',
expect(allSchedulerTags).toEqual([
[HostRoot],
[FunctionComponent],
[FunctionComponent],
]);
expect(allSchedulerTags).toHaveLength(1);
expect(allSchedulerTags[0]).toHaveLength(1);
expect(allSchedulerTags[0]).toContain(HostRoot);

// Render a partial update, but don't finish.
first.setState({renderTime: 10});
expect(Scheduler).toFlushAndYieldThrough(['FirstComponent:10']);
expect(allSchedulerTypes).toHaveLength(1);

// Interrupt with higher priority work.
ReactDOM.flushSync(() => second.setState({renderTime: 30}));
expect(Scheduler).toHaveYielded([
'SecondComponent:30',
'Yield:7',
'onCommitRoot',
expect(allSchedulerTypes).toEqual([
[null],
[SyncPriorityUpdater],
[LowPriorityUpdater],
]);
expect(allSchedulerTypes).toHaveLength(2);
expect(allSchedulerTypes[1]).toHaveLength(1);
expect(allSchedulerTypes[1]).toContain(SecondComponent);

// Resume the original low priority update.
expect(Scheduler).toFlushAndYield([
'FirstComponent:10',
'Yield:4',
'onCommitRoot',
]);
expect(allSchedulerTypes).toHaveLength(3);
expect(allSchedulerTypes[2]).toHaveLength(1);
expect(allSchedulerTypes[2]).toContain(FirstComponent);
// Verify no outstanding flushes
Scheduler.unstable_flushAll();
});
});

0 comments on commit 8c058c7

Please sign in to comment.