DEV Community

Sławek Kołodziej
Sławek Kołodziej

Posted on • Edited on • Originally published at slawkolodziej.com

Guide: Unit Testing React Apollo Components with React Testing Library

In this post I will present you a quick guide how to test React components which use Apollo.

At first let's see how our component looks like:

import React from 'react'
import gql from 'graphql-tag'
import { useQuery } from '@apollo/react-hooks'

export const POSTS_QUERY = gql`
  query Post($id: String!) {
    {
      post(id: $id) {
        title
        author
        description
      }
    }
  }
`

const Post = ({ postId )} => {
  const { loading, error, data } = useQuery(POSTS_QUERY, {
    variables: { id: postId },
  })

  if (loading) return null
  if (error) return `Error: ${error}`

  return (
    <div>
      <h3 data-testId="post-title">{data.post.title}</h3>
      <h4 data-testId="post-author">{data.post.author}</h4>
      <p data-testId="post-description">{data.post.description}</p>
    </div>
  )
}

export default Post
Enter fullscreen mode Exit fullscreen mode

I always had issues with testing components which do not render desired value immediately. In our case Post component at first won't render anything, because it is in loading state.

Fortunately react-testing-library solves this problem for us. It allows us to wait for some element to be rendered.

On the other hand, Apollo has very useful MockedProvider component. Thanks to this component you can mock result of your queries. Let's take a look at the code.

import React from 'react'
import { render, cleanup, findByTestId, findByText } from '@testing-library/react'
import { MockedProvider } from '@apollo/react-testing'

import Post, { POSTS_QUERY } from './Post'

const mocks = [
  {
    request: {
      query: POSTS_QUERY,
      variables: {
        id: 'postId',
      }
    },
    result: {
      data: {
        post: {
          title: 'title',
          author: 'author',
          description: 'description',
        }
      }
    }
  }
]

describe('Post', () => {
  afterEach(cleanup)

  it('should render post title', async () => {
    const { container ) = render(
      <MockedProvider mocks={mocks} addTypename={false}>
        <Post postId="postId" />
      </MockedProvider>
    )

    const titleElement = await findByTestId(container, 'post-title')
    const titleContent = await findByText(titleElement, 'title')

    expect(titleElement).toBeTruthy()
    expect(titleContent).toBeTruthy()
  })

  ...tests for author and description
})
Enter fullscreen mode Exit fullscreen mode

At first we create mocked query response for POSTS_QUERY. We pass the mocks variable to MockedProvider when rendering our component.

To get title element we use findByTestId function. When you go back to component code you can see we added data-testId to h3 element.
When we finally find this element we check whether it has expected text using findByText.

Additional resources

Apollo Docs - Testing React components
React Testing Library Docs


I'm regularly publishing my insights on web development.
Consider subscribing to my newsletter.
Visit my blog at slawkolodziej.com to find out more interesting content.
Follow me on Twitter.

Top comments (1)

Collapse
 
valeriafurin profile image
Valeria Furin

Amazing article! I just found a typo.

const { container ) -> const { container }