apollo-client
apollo-client copied to clipboard
onError is not called when using testing-library/react-hooks
Intended outcome:
I am writing a custom hook using Apollo React hooks, setting onError to do console.error if an error occurs, but otherwise only dealing with successful data. I then want to test the error state of the custom hook using renderHook from @testing-library/react-hooks and MockedProvider. I would expect onError to be called if an error occurs, with the same value as the error key in the useQuery result.
Actual outcome:
onError is never actually called
How to reproduce the issue:
The following jest test fails on the last assertion on onErrorData
import { useQuery } from '@apollo/react-hooks'
import { MockedProvider } from '@apollo/react-testing'
import { act, renderHook } from '@testing-library/react-hooks'
import gql from 'graphql-tag'
import _ from 'lodash'
import React, { useState } from 'react'
type MyQuery = {
name: string
}
const MyQueryDocument = gql`
query {
name
}
`
const useFoo = () => {
const [onErrorData, setOnErrorData] = useState()
const { data, error } = useQuery<MyQuery>(MyQueryDocument, {
onError: setOnErrorData
})
return { data, error, onErrorData }
}
test('onError should be called', async () => {
const mocks = [
{
request: {
query: MyQueryDocument,
},
error: new Error('this is an error'),
},
]
const { result } = renderHook(() => useFoo(), {
wrapper: ({ children }) => (
<MockedProvider mocks={mocks}>
<>{children}</>
</MockedProvider>
)
})
await act(() => new Promise(_.defer))
expect(result.current.data).toBeUndefined()
expect(result.current.error?.message).toBe('Network error: this is an error')
expect(result.current.onErrorData?.message).toBe('Network error: this is an error')
})
Versions
System:
OS: macOS Mojave 10.14.6
Binaries:
Node: 13.11.0 - /usr/local/bin/node
Yarn: 1.22.4 - ~/leapyear/lyalpha/node_modules/.bin/yarn
npm: 6.13.7 - /usr/local/bin/npm
Browsers:
Chrome: 80.0.3987.163
Firefox: 72.0.2
Safari: 13.1
i am facing a similar issue, did you manage to find a fix?
No, we just have a skipped test with a link to this issue :(
same issue here
I can also reproduce this
+1
Spent the last 3 hours ripping my hair off and finally found this.
Wondering why it keeps going to onCompleted callback instead of onError.
Even tried just having only onError callback, and it's still not doing it.
Any updates on this?
any updates on this?
any update?
This is not working also, it's not triggering the onError of useQuery
jest.spyOn(axios, 'get').mockImplementation(() => {
return Promise.reject('error');
});
solution found tannerlinsley/react-query#2196 (comment)
Does apollo-client also have retries? I dont recall that being a default configuration
For everyone still looking for an answer. This works for me. Make sure to NOT include the error inside of the result key in the mock.
So instead of writing:
export const mock = (errorMessage: string) => {
return {
request: {
...
},
result: {
errors: [new GraphQLError(errorMessage)],
},
};
};
Turn it to:
export const mock = (errorMessage: string) => {
return {
request: {
...
},
errors: [new GraphQLError(errorMessage)],
};
};
Then, and only then, your onError callback will get invoked during the tests.
Cheers! 🥳
☝️ ☝️ ☝️ This may not be ideal for your test cases.
You're setting the network response error when some may want to test graphql errors
It results in an error like:
graphQLErrors: [],
networkError: GraphQLError [Object] {
message: 'my error message',
extensions: [Object]
},
This makes my implementation for onError not work because I want to handle graphql errors, not network errors
function onError(error?: ApolloError) {
if (!error?.graphQLErrors.length) {
return;
}
const err = error.graphQLErrors[0];
if (err.extensions?.code === "CONFLICT") {
setErrors(...);
}
}
That's a good call out, @zebapy -- here's an example of a test that calls onError when a GraphQL error is returned from our Apollo Client test suite: https://github.com/apollographql/apollo-client/blob/router-subs/src/react/hooks/tests/useQuery.test.tsx#L1847:L1888
Since the original issue was opened several years ago and this seems to no longer be a problem (and, I might add, since testing-library/react-hooks is deprecated and renderHook has been moved inside of @testing-libary/react), I'm going to close this out. Thanks!
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. For general questions, we recommend using StackOverflow or our discord server.