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
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
})
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)
Amazing article! I just found a typo.
const { container ) -> const { container }