Testing Error State of Mutation is throwing Global Error
See original GitHub issueI want to reopen https://github.com/apollographql/react-apollo/issues/2614 from the old repo as I ran into the exact same Issue today with @apollo/client": "3.2.2
.
I have a component that uses the useMutation hook and renders differently when useMutation returns an error
export const DELETE_DOG_MUTATION = gql`
mutation deleteDog($name: String!) {
deleteDog(name: $name) {
id
name
breed
}
}
`;
export function DeleteButton() {
const [mutate, { loading, error, data }] = useMutation(DELETE_DOG_MUTATION);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error!</p>;
if (data) return <p>Deleted!</p>;
return (
<button onClick={() => mutate({ variables: { name: 'Buck' } })}>
Click me to Delete Buck!
</button>
);
}
I want to Test this behaviour as described in the Docs
it('should show error UI', async () => {
const deleteDog = { name: 'Buck', breed: 'Poodle', id: 1 };
const mocks = [
{
request: {
query: DELETE_DOG_MUTATION,
variables: { name: 'Buck' },
},
error: new Error('aw shucks'),
},
];
const component = renderer.create(
<MockedProvider mocks={mocks} addTypename={false}>
<DeleteButton />
</MockedProvider>,
);
// find the button and simulate a click
const button = component.root.findByType('button');
button.props.onClick(); // fires the mutation
await new Promise(resolve => setTimeout(resolve, 0)); // wait for response
const tree = component.toJSON();
expect(tree.children).toContain('Error!');
});
Intended outcome:
The Test should pass without throwing an error.
Actual outcome:
Passing mocks with an Error to <MockedProvider />
does actually throw a global Error
aw shucks
at new ApolloError (node_modules/@apollo/client/errors/index.js:26:28)
at Object.error (node_modules/@apollo/client/core/QueryManager.js:146:48)
at notifySubscription (node_modules/zen-observable/lib/Observable.js:140:18)
at onNotify (node_modules/zen-observable/lib/Observable.js:179:3)
at SubscriptionObserver.error (node_modules/zen-observable/lib/Observable.js:240:7)
at node_modules/@apollo/client/utilities/observables/iteration.js:4:68
at Array.forEach (<anonymous>)
at iterateObserversSafely (node_modules/@apollo/client/utilities/observables/iteration.js:4:25)
at Object.error (node_modules/@apollo/client/utilities/observables/Concast.js:33:21)
at notifySubscription (node_modules/zen-observable/lib/Observable.js:140:18)
I figured out that when I add an onError
option to useMutation
my test runs as expected but I guess this is just a workaround.
const [mutate, { loading, error, data }] = useMutation(DELETE_DOG_MUTATION, {onError: () => {}});
How to reproduce the issue:
I cant share the code of the application I am working on but I can try to create a Codesandbox if neccessary but I hope my explanation is detailed enough.
Versions System: OS: macOS Mojave 10.14.6 Binaries: Node: 10.16.0 - /usr/local/bin/node npm: 6.11.2 - /usr/local/bin/npm Browsers: Chrome: 86.0.4240.80 Firefox: 81.0.1 Safari: 12.1.2 npmPackages: @apollo/client: ^3.2.2 => 3.2.2 “jest”: “^24.9.0”,
Issue Analytics
- State:
- Created 3 years ago
- Reactions:16
- Comments:11 (2 by maintainers)
Top GitHub Comments
This comment managed to get around it using errorPolicy:
You can then target to find the element rendered by
if (error) return <p>Error!</p>;
Just got bitten by this … wasted a couple of hours. If there’s no appetite to change behaviour by the Apollo team, then this behaviour really needs to be highlighted in the documentation. I guess my expectation was any errors would be passed back in the
error
property, without ALSO throwing.Seems the best way to handle this is by adding a empty
onError
handler in the options in anyuseQuery
oruseMutation
- but it would be great if there was an option to suppress the error also being thrown and just handle it in theerror
property if needed.