React Testing Library предоставляет богатый набор инструментов для работы с компонентами React в тестах. Однако часто в процессе написания тестов возникает необходимость в дополнительных функциях и утилитах, которые могут упростить код тестов и повысить их читаемость. В этой части рассматриваются несколько таких утилит, а также общие рекомендации по их использованию.
Тесты, использующие асинхронный код, — это обычная практика при работе с React-компонентами, особенно если в приложении используется данные из API или другие асинхронные действия. В таких случаях важно правильно обрабатывать ожидания, чтобы избежать ошибок и сделать тесты более устойчивыми.
waitFor Одна из часто используемых
функций — это waitFor, предназначенная для ожидания
определённых изменений в компоненте. Эта утилита позволяет дождаться,
пока условие, например, элемент на странице или состояние, станет
истинным.
Пример использования:
import { render, screen, waitFor } from '@testing-library/react';
import MyComponent from './MyComponent';
test('отображение данных после асинхронного запроса', async () => {
render(<MyComponent />);
await waitFor(() => expect(screen.getByText('Данные загружены')).toBeInTheDocument());
});
Здесь waitFor гарантирует, что условие (в данном случае
наличие текста “Данные загружены”) будет проверяться до тех пор, пока не
выполнится или не истечёт таймаут. Это особенно важно для асинхронных
операций, когда элемент может появиться на экране с задержкой.
findBy Метод findBy
является еще одной удобной утилитой для работы с асинхронными
элементами. В отличие от getBy, который сразу вызывает
ошибку, если элемент не найден, findBy автоматически будет
ожидать появления элемента в течение заданного времени.
Пример:
test('должен отобразить кнопку после загрузки данных', async () => {
render(<MyComponent />);
const button = await screen.findByRole('button', { name: /загрузить/i });
expect(button).toBeInTheDocument();
});
Здесь findByRole выполняет поиск кнопки с определённым
названием и ожидает её появления, что делает тесты более устойчивыми к
асинхронным задержкам.
React Testing Library предоставляет различные утилиты для имитации взаимодействий с элементами UI. Эти утилиты облегчают тестирование компонентов, которые реагируют на действия пользователя.
fireEvent Функция
fireEvent позволяет инициировать различные события, такие
как клики, изменение текста в полях ввода и другие взаимодействия.
Пример:
import { render, screen, fireEvent } from '@testing-library/react';
import MyComponent from './MyComponent';
test('клик по кнопке вызывает нужную функцию', () => {
const mockFunction = jest.fn();
render(<MyComponent onCl ick={mockFunction} />);
const button = screen.getByRole('button');
fireEvent.click(button);
expect(mockFunction).toHaveBeenCalledTimes(1);
});
Здесь fireEvent.click симулирует клик по кнопке и
проверяет, что функция mockFunction была вызвана. Этот
метод подходит для большинства стандартных событий.
userEvent Библиотека также включает
userEvent, которая предлагает более высокоуровневую
абстракцию для имитации действий пользователя, таких как клики, ввод
текста, выбор опций в выпадающих списках и другие.
Пример использования:
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import MyComponent from './MyComponent';
test('ввод текста в поле ввода', async () => {
render(<MyComponent />);
const input = screen.getByRole('textbox');
await userEvent.type(input, 'Пример текста');
expect(input).toHaveValue('Пример текста');
});
userEvent.type моделирует ввод текста с задержками, как
это делает пользователь. Это помогает сделать тесты более естественными
и близкими к реальному поведению пользователя.
React Testing Library в сочетании с хуками React предоставляет
возможности для тестирования состояния и логики, используя такие
утилиты, как renderHook из библиотеки
@testing-library/react-hooks.
renderHook Функция
renderHook позволяет тестировать хуки отдельно от
компонентов, что полезно для тестирования кастомных хуков или логики,
которая используется в компонентах.
Пример:
import { renderHook } from '@testing-library/react-hooks';
import useCounter from './useCounter';
test('должен увеличивать счётчик', () => {
const { result } = renderHook(() => useCounter());
expect(result.current.count).toBe(0);
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
Здесь renderHook позволяет протестировать хук
useCounter без необходимости рендерить компонент, что
ускоряет тестирование логики.
React Testing Library предоставляет несколько полезных методов для поиска элементов в DOM, что упрощает взаимодействие с компонентами и их проверку в тестах.
screen Объект screen
является основным инструментом для поиска элементов в тестах. Он
предоставляет методы для поиска элементов по роли, тексту, тегу, и
другим аттрибутам.
Пример:
test('поиск элемента по роли', () => {
render(<MyComponent />);
const button = screen.getByRole('button', { name: /submit/i });
expect(button).toBeInTheDocument();
});
Метод getByRole ищет элементы с определённой ролью, что
помогает следить за семантическим HTML и доступностью.
within Иногда требуется искать элементы
внутри других элементов, например, внутри модальных окон или списков. В
таких случаях можно использовать утилиту within.
Пример:
import { render, screen, within } from '@testing-library/react';
test('поиск кнопки внутри модального окна', () => {
render(<MyComponent />);
const modal = screen.getByRole('dialog');
const button = within(modal).getByRole('button', { name: /close/i });
expect(button).toBeInTheDocument();
});
Метод within позволяет ограничить область поиска, что
полезно для работы с вложенными компонентами.
Для тестирования сложных взаимодействий с API или сторонними библиотеками часто требуется мокирование. React Testing Library совместно с Jest позволяет использовать моки и шпионов для симуляции внешних зависимостей.
jest.fn() Функция
jest.fn() используется для создания мок-функций, которые
могут отслеживать, сколько раз они были вызваны, с какими аргументами и
т.д.
Пример:
test('должен вызывать колбэк при клике', () => {
const mockCallback = jest.fn();
render(<MyComponent onCl ick={mockCallback} />);
const button = screen.getByRole('button');
fireEvent.click(button);
expect(mockCallback).toHaveBeenCalledTimes(1);
});
Этот подход позволяет проверить взаимодействие компонентов с внешними функциями или сервисами, не выполняя реальные вызовы.
В React Testing Library имеется множество полезных утилит и вспомогательных функций, которые позволяют писать удобные и надёжные тесты. Использование асинхронных функций, моков, утилит для событий и поиска элементов помогает создать удобный и эффективный процесс тестирования React-приложений.