Skip to content

Commit

Permalink
Update error recovery test to match new semantics
Browse files Browse the repository at this point in the history
  • Loading branch information
acdlite committed Sep 10, 2019
1 parent fd253c9 commit 052ee96
Showing 1 changed file with 87 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,20 @@ describe('ReactIncrementalErrorHandling', () => {
// This update is in a separate batch
ReactNoop.render(<App isBroken={false} />, onCommit);

expect(Scheduler).toFlushAndYield([
expect(Scheduler).toFlushAndYieldThrough([
// The first render fails. But because there's a lower priority pending
// update, it doesn't throw.
'error',
// Now we retry at the lower priority. This time it succeeds.
]);

// React will try to recover by rendering all the pending updates in a
// single batch, synchronously. This time it succeeds.
//
// This tells Scheduler to render a single unit of work. Because the render
// to recover from the error is synchronous, this should be enough to
// finish the rest of the work.
Scheduler.unstable_flushNumberOfYields(1);
expect(Scheduler).toHaveYielded([
'success',
// Nothing commits until the second update completes.
'commit',
Expand All @@ -256,6 +265,82 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.getChildren()).toEqual([span('Everything is fine.')]);
});

it('does not include offscreen work when retrying after an error', () => {
function App(props) {
if (props.isBroken) {
Scheduler.unstable_yieldValue('error');
throw new Error('Oops!');
}
Scheduler.unstable_yieldValue('success');
return (
<>
Everything is fine
<div hidden={true}>
<div>Offscreen content</div>
</div>
</>
);
}

function onCommit() {
Scheduler.unstable_yieldValue('commit');
}

function interrupt() {
ReactNoop.flushSync(() => {
ReactNoop.renderToRootWithID(null, 'other-root');
});
}

ReactNoop.render(<App isBroken={true} />, onCommit);
Scheduler.unstable_advanceTime(1000);
expect(Scheduler).toFlushAndYieldThrough(['error']);
interrupt();

expect(ReactNoop).toMatchRenderedOutput(null);

// This update is in a separate batch
ReactNoop.render(<App isBroken={false} />, onCommit);

expect(Scheduler).toFlushAndYieldThrough([
// The first render fails. But because there's a lower priority pending
// update, it doesn't throw.
'error',
]);

// React will try to recover by rendering all the pending updates in a
// single batch, synchronously. This time it succeeds.
//
// This tells Scheduler to render a single unit of work. Because the render
// to recover from the error is synchronous, this should be enough to
// finish the rest of the work.
Scheduler.unstable_flushNumberOfYields(1);
expect(Scheduler).toHaveYielded([
'success',
// Nothing commits until the second update completes.
'commit',
'commit',
]);
// This should not include the offscreen content
expect(ReactNoop).toMatchRenderedOutput(
<>
Everything is fine
<div hidden={true} />
</>,
);

// The offscreen content finishes in a subsequent render
expect(Scheduler).toFlushAndYield([]);
expect(ReactNoop).toMatchRenderedOutput(
<>
Everything is fine
<div hidden={true}>
<div>Offscreen content</div>
</div>
</>,
);
});

it('retries one more time before handling error', () => {
function BadRender() {
Scheduler.unstable_yieldValue('BadRender');
Expand Down Expand Up @@ -296,10 +381,6 @@ describe('ReactIncrementalErrorHandling', () => {
expect(ReactNoop.getChildren()).toEqual([]);
});

// TODO: This is currently unobservable, but will be once we lift renderRoot
// and commitRoot into the renderer.
// it("does not retry synchronously if there's an update between complete and commit");

it('calls componentDidCatch multiple times for multiple errors', () => {
let id = 0;
class BadMount extends React.Component {
Expand Down

0 comments on commit 052ee96

Please sign in to comment.