Skip to content

onError is not called when using testing-library/react-hooks #6137

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

Closed
brandon-leapyear opened this issue Apr 10, 2020 · 13 comments
Closed

onError is not called when using testing-library/react-hooks #6137

brandon-leapyear opened this issue Apr 10, 2020 · 13 comments

Comments

@brandon-leapyear
Copy link

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
@waldinho
Copy link

i am facing a similar issue, did you manage to find a fix?

@brandon-leapyear
Copy link
Author

No, we just have a skipped test with a link to this issue :(

@adnanfajlur
Copy link

same issue here

@afonsoduarte
Copy link

I can also reproduce this

@ghost
Copy link

ghost commented Sep 23, 2020

+1

@ardok
Copy link

ardok commented Nov 12, 2020

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?

@ahmadelgabrii
Copy link

any updates on this?

@emil45
Copy link

emil45 commented Apr 22, 2021

any update?

This is not working also, it's not triggering the onError of useQuery

jest.spyOn(axios, 'get').mockImplementation(() => {
		return Promise.reject('error');
	});

@brandonchinn178
Copy link

solution found tannerlinsley/react-query#2196 (comment)

Does apollo-client also have retries? I dont recall that being a default configuration

@jonathanfilbert
Copy link

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! 🥳

@zebapy
Copy link

zebapy commented Aug 12, 2022

☝️ ☝️ ☝️ 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(...);
    } 

  }

@alessbell
Copy link
Contributor

alessbell commented Mar 8, 2023

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!

@github-actions
Copy link
Contributor

github-actions bot commented Apr 8, 2023

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests