Testing Library: компоненты глазами пользователя
Запросы по роли и подписи, get/query/find, user-event.
Обновлено
Что такое Testing Library
React Testing Library (RTL) — библиотека для тестирования компонентов так, как ими пользуется человек: вы находите элементы по тому, что видно (текст, подпись, роль), кликаете, печатаете — и проверяете, что появилось на экране. Внутреннее состояние и props вы не смотрите.
Её принцип: «Чем больше тесты похожи на то, как используется программа, тем больше уверенности они дают».
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
test('добавляет задачу', async () => {
const user = userEvent.setup()
render(<TodoApp />)
await user.type(screen.getByLabelText('Новая задача'), 'Выучить RTL')
await user.click(screen.getByRole('button', { name: 'Добавить' }))
expect(screen.getByText('Выучить RTL')).toBeInTheDocument()
})Запросы — по приоритету
Выбирайте первый из списка, который работает. Порядок отражает, насколько доступен компонент:
| Приоритет | Запрос | Находит по | Пример |
|---|---|---|---|
| 1 | getByRole |
роли + доступному имени | getByRole('button', { name: 'Сохранить' }) |
| 2 | getByLabelText |
подписи поля | getByLabelText('Email') |
| 3 | getByPlaceholderText |
placeholder | если подписи нет |
| 4 | getByText |
видимому тексту | абзацы, сообщения |
| 5 | getByDisplayValue |
значению поля | заполненные формы |
| 6 | getByAltText / getByTitle |
alt / title |
изображения |
| последний | getByTestId |
data-testid |
только когда ничего другого не работает |
Бонус: если элемент не находится через getByRole, чаще всего у компонента проблема с доступностью. Тесты подталкивают к лучшему HTML.
Варианты: get, query, find
| Префикс | Если не нашёл | Async | Когда |
|---|---|---|---|
getBy |
бросает ошибку | нет | элемент должен быть сейчас |
queryBy |
возвращает null |
нет | проверить, что элемента нет: expect(queryByText('Ошибка')).toBeNull() |
findBy |
бросает после таймаута | да | элемент появится позже (после fetch, setTimeout) |
getAllBy... / queryAllBy... / findAllBy... — для нескольких элементов.
user-event или fireEvent
userEvent |
fireEvent |
|
|---|---|---|
| Имитирует | полное взаимодействие (focus, keydown, input, keyup, click) | одно DOM-событие |
| Реалистичность | высокая | низкая |
| Когда | по умолчанию | особые случаи |
Чего не делать
- Тестировать внутреннее состояние (
component.state.count). container.querySelector('.btn-primary')— классы это детали реализации.- Огромные снапшоты, которые никто не читает.
Коротко
- RTL тестирует компоненты как пользователь: ищете по роли, подписи, тексту.
- Приоритет:
getByRole→getByLabelText→ … →getByTestId. get= должен быть,query= может отсутствовать,find= появится.