Introduction to the Testing Library - coursehero/ch-react-workshop GitHub Wiki
The @testing-library family of packages helps you test UI components in a user-centric way.
The more your tests resemble the way your software is used, the more confidence they can give you.
--- from https://testing-library.com/docs/ and https://kentcdodds.com/about/
The Testing Library comes in many flavors. The following three are relevant for our workshop:
- provides utilities for querying the DOM the same way a user would:
getBy*
,getAllBy*
,queryBy*
,queryAllBy*
,findBy*
,findAllBy*
💡 Tip: use the Testing Playground to help debug your HTML for accessibility and to select the best query. |
- adds API on top of DOM Testing Library:
render
,cleanup
,act
- adds the familiar API to the
cy.
command of Cypress
Let's assume you want to test the following React component:
import * as React from 'react'
const USERS = [
{ name: 'User 1', city: 'Tokyo' },
{ name: 'User 2', city: 'Prague' },
]
export const Users = () => {
return (
<ul>
{USERS.map(({ name, city }: any) => (
<li key={name}>
{name} - {city}
</li>
))}
</ul>
)
}
Here is what it would render:
<ul>
<li>User 1 - Tokyo</li>
<li>User 2 - Prague</li>
</ul>
Try to write the test yourself!
import * as React from 'react'
import { render } from '@testing-library/react'
import { Users } from './Users'
test('Renders a list with the correct number of users', () => {
const { getByRole } = render(<Users />)
const usersList = getByRole('list')
expect(usersList.children).toHaveLength(2)
})
Check for accessibility violations:
import { axe, toHaveNoViolations } from 'jest-axe'
import 'jest-axe/extend-expect'
...
const { container } = render(<Users />)
const results = await axe(container)
expect(results).toHaveNoViolations() // or expect(results.violations).toHaveLength(0)
Mosts components will be more complicated and some will render data coming from API endpoints. Here is an example of mocking the data:
import {loadGreeting as mockLoadGreeting} from '../api'
test('loads greetings on click', () => {
mockLoadGreeting.mockResolvedValueOnce({data: {greeting: 'TEST_GREETING'}})
const {getByLabelText, getByText} = render(<GreetingLoader />)
const nameInput = getByLabelText(/name/i)
const loadButton = getByText(/load/i)
nameInput.value = 'Mary'
fireEvent.click(loadButton)
})
💡 Tip: while you can always use the basic mocking or stubbing functionality provided by jest, we recommend a more sophisticated approach to mocking described in our Guide to Mocking. |
- Learn the differences between the DOM, React and Cypress Testing Library
- See a more complete example from the RTL documentation
- Learn which query to use
- Avoid the most common mistakes with RTL