Skip to content

Instantly share code, notes, and snippets.

@bvaughn
Created September 27, 2018 16:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bvaughn/72aaa1ceda61ad0540a9623046eb0b83 to your computer and use it in GitHub Desktop.
Save bvaughn/72aaa1ceda61ad0540a9623046eb0b83 to your computer and use it in GitHub Desktop.
const jestDiff = require("jest-diff");
describe("error boundaries", () => {
let BrokenRender;
let DidCatchErrorBoundary;
let GetDerivedErrorBoundary;
let React;
let ReactNoop;
let ReactFeatureFlags;
let ReactTestRenderer;
let span;
function loadModules(useTestRenderer) {
jest.resetModules();
ReactFeatureFlags = require("shared/ReactFeatureFlags");
ReactFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
if (useTestRenderer) {
ReactTestRenderer = require("react-test-renderer");
} else {
ReactNoop = require("react-noop-renderer");
}
React = require("react");
DidCatchErrorBoundary = class extends React.Component {
state = { error: null };
componentDidCatch(error) {
this.setState({ error });
}
render() {
return this.state.error ? (
<span prop="ErrorBoundary" />
) : (
this.props.children
);
}
};
GetDerivedErrorBoundary = class extends React.Component {
state = { error: null };
static getDerivedStateFromCatch(error) {
return { error };
}
render() {
return this.state.error ? (
<span prop="ErrorBoundary" />
) : (
this.props.children
);
}
};
// Used by noop renderer
span = prop => ({ type: "span", children: [], prop });
const InvalidType = undefined;
BrokenRender = ({ fail }) =>
fail ? <InvalidType /> : <span prop="BrokenRender" />;
}
describe("react-test-renderer", () => {
beforeEach(() => {
loadModules(true);
function toMatchChildren(renderer, children) {
let actual, expected;
try {
actual = renderer.toJSON();
expected = ReactTestRenderer.create(children).toJSON();
expect(actual).toEqual(expected);
} catch (error) {
return {
message: () => jestDiff(expected, actual),
pass: false
};
}
return { pass: true };
}
expect.extend({ toMatchChildren });
});
it("componentDidCatch", () => {
const renderer = ReactTestRenderer.create(
<DidCatchErrorBoundary>
<BrokenRender fail={false} />
</DidCatchErrorBoundary>
);
expect(renderer).toMatchChildren(<span prop="BrokenRender" />);
expect(() => {
renderer.update(
<DidCatchErrorBoundary>
<BrokenRender fail={true} />
</DidCatchErrorBoundary>
);
}).toWarnDev("invalid");
expect(renderer).toMatchChildren(<span prop="ErrorBoundary" />);
});
it("getDerivedStateFromCatch", () => {
const renderer = ReactTestRenderer.create(
<GetDerivedErrorBoundary>
<BrokenRender fail={false} />
</GetDerivedErrorBoundary>
);
expect(renderer).toMatchChildren(<span prop="BrokenRender" />);
expect(() => {
renderer.update(
<GetDerivedErrorBoundary>
<BrokenRender fail={true} />
</GetDerivedErrorBoundary>
);
}).toWarnDev("invalid");
expect(renderer).toMatchChildren(<span prop="ErrorBoundary" />);
});
});
describe("react-noop", () => {
beforeEach(() => loadModules(false));
it("componentDidCatch", () => {
ReactNoop.render(
<DidCatchErrorBoundary>
<BrokenRender fail={false} />
</DidCatchErrorBoundary>
);
ReactNoop.flush();
expect(ReactNoop.getChildren()).toEqual([span("BrokenRender")]);
ReactNoop.render(
<DidCatchErrorBoundary>
<BrokenRender fail={true} />
</DidCatchErrorBoundary>
);
expect(ReactNoop.flush).toWarnDev(["invalid", "invalid"]);
expect(ReactNoop.getChildren()).toEqual([span("ErrorBoundary")]);
});
it("getDerivedStateFromCatch", () => {
ReactNoop.render(
<GetDerivedErrorBoundary>
<BrokenRender fail={false} />
</GetDerivedErrorBoundary>
);
ReactNoop.flush();
expect(ReactNoop.getChildren()).toEqual([span("BrokenRender")]);
ReactNoop.render(
<GetDerivedErrorBoundary>
<BrokenRender fail={true} />
</GetDerivedErrorBoundary>
);
expect(ReactNoop.flush).toWarnDev(["invalid", "invalid"]);
expect(ReactNoop.getChildren()).toEqual([span("ErrorBoundary")]);
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment