How test a function that return JSX.Element and contains API request?

62 Views Asked by At

I have a custom function that show a user's card (returns JSX.Element) when the pointer is over the user's name. This component request user information using React Query, which I use for data-fetching in my app.

I'm trying to write a test for this function using Jest, react-test-renderer or @testing-library/react.

Function:

const link = (href: string, text: ReactNode[]): JSX.Element => {
  return match(getServiceUrl(href))
    .with({ service: 'users' }, (serviceUrl) => (
      <UserCard href={recoverUrlFromInternal(href)} userId={serviceUrl.id} text={text.toString()} />
    ))
    //.with(... some other cases
    .exhaustive()
} 

Component:

const UserCard = (props: { href: string; userId: string; text: string }) => {
  const { href, userId, text } = props

  const response = useGetApiV1UsersP1(userId)

  return <PopoverCard input={response} />
}

I want to write a test for the link function and test all cases including displaying the UserCard component.

I found two ways to do this:

  1. Make a snapshot using renderer from react-test-renderer, but I can't figure out how to wait for the request to complete. So my snapshot is:
<span>
  Still loading. 0
</span>
  1. Use the render from @testing-library/react, but the problem is the same:
<span xmlns="http://www.w3.org/1999/xhtml">Still loading. 0</span>

In this case I can't figure out how to use the waitFor() function with render. In the hook case it's more simply:

const { result } = renderHook(() => useGetApiV1UsersP1('userId'), { wrapper })
await waitFor(() => {
  expect(result.current.isSuccess).toBe(true)
})

Is it correct to use snapshots etc. to test functions like link? Maybe there is another way to test this function?

Or should I find a way how to wait for the request to complete?

Please let me know if you have any ideas or maybe you've tested something similar.

Test file:

//general part:
const queryClient = new QueryClient()
const Wrapper = (props: { children: any }) => (
  <QueryClientProvider client={queryClient}>{props.children}</QueryClientProvider>
)

const expectation = nock('http://localhost')
  .get('/api/v1/users/userId')
  .reply(200, {
    person: {
      firstName: 'Bruce',
      lastName: 'Lee',
    }
  })

//1st case:
describe('renderer test', () => {
  describe('link', () => {
    test('users', async () => {
      const usersLink = renderer
        .create(<Wrapper children={link(`#/v1/users/userId`, ['text'])} />)
        .toJSON()

       expect(usersLink).toMatchSnapshot()
    })
  })
})

//2nd case:
describe('renderer test', () => {
  describe('link', () => {
    test('users', async () => {
      const serializer = new XMLSerializer()
      const { asFragment } = render(link(`#/v1/users/userId`, ['text']), { wrapper })
      await waitFor(() => {
        //compare serializer.serializeToString(asFragment()) with ...?
      })
    })
  })
})
0

There are 0 best solutions below