-
Notifications
You must be signed in to change notification settings - Fork 273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
13.x: testing error states with renderHook
does not throw as expected
#1733
Comments
The only thing that really jumps out in diffing 12.9 and 13.0 is |
Could you try running again with |
Yep, confirmed, that fixes it. What do you think - should this just be documented in the migration guide, or is this really a bug? |
Is that issue occurring only when your hook throws? Are there any scenarios when the hook does not throw and the test fails? |
it's only thrown errors from hooks - all other tests work as-is. Rendering a component which throws as part of its rendering also works fine with concurrentRoot turned on: function Component({ shouldThrow }: { shouldThrow?: boolean }) {
if (shouldThrow) {
throw new Error("the error is thrown");
}
return <Text>hello</Text>;
}
it("should throw if render component throws", () => {
service.mockReturnValueOnce(undefined);
expect(() => {
render(<Component />);
}).not.toThrow();
});
it("should throw if render component throws", () => {
expect(() => {
render(<Component shouldThrow />);
}).toThrowErrorMatchingInlineSnapshot(`"the error is thrown"`);
}); |
Hmm, interesting observation. BTW it's not guaranteed that https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary |
@fastfrwrd I've done some checks and it seems that the The
Hence, the most probable answer is that Concurrent Mode renders test component (+ your hook) twice simply as a matter of regular operation. |
Spent a couple minutes testing what you said, and it definitely seems true! Has nothing to do with hooks, but rather any thrown error within a concurrent root leads to exactly one re-render, which is a difference from how things work when you turn the concurrent root off. Here's some tests which demonstrate that. import { Text } from "react-native";
import { render } from "@testing-library/react-native";
const callTracker = jest.fn();
describe("demonstrate post-throw re-rendering", () => {
function Component2({ throwOnMount }: { throwOnMount?: boolean }) {
callTracker();
if (throwOnMount) {
throw new Error(`throw on mount`);
}
return <Text>Some Component</Text>;
}
beforeEach(() => {
callTracker.mockClear();
});
it("should render once", () => {
expect(callTracker).not.toHaveBeenCalled();
render(<Component2 />);
expect(callTracker).toHaveBeenCalledTimes(1);
});
it("should throw, but then it re-renders", () => {
expect(callTracker).not.toHaveBeenCalled();
expect(() => render(<Component2 throwOnMount />)).toThrow();
expect(callTracker).toHaveBeenCalledTimes(2);
});
describe("non-concurrent", () => {
it("does not re-render following throw", () => {
expect(callTracker).not.toHaveBeenCalled();
expect(() =>
render(<Component2 throwOnMount />, { concurrentRoot: false })
).toThrow();
expect(callTracker).toHaveBeenCalledTimes(1);
});
});
}); |
Describe the bug
We found that, upon upgrading to @testing-library/react-native 13.x, a number of existing tests which tested failure cases for hooks began to fail. A simplified reproduction looks like this:
This test passes with 12.x and fails with 13.x. Specifically, the failure here is:
The following change fixes the test:
...which smells like a
StrictMode
hook issue, but I don't see anything that leads me to believe that was turned on by default, and also, this only seems to impact hooks which throw errors, so that doesn't make sense.I've tested this with both Jest and Vitest, so it seems like some kind of issue within
@testing-library/react-native
for sure.Expected behavior
When a hook that throws an error is rendered, the first failed rendered output ought to cause the
renderHook
call to throw, but only the second call to the hook can actually causerenderHook
to throw.Steps to Reproduce
See the above example. Let me know if you want me to include any other config files in this report or set up some sort of code sandbox.
Screenshots
n/a
Versions
Exclusive to 13.x.
The text was updated successfully, but these errors were encountered: