React Testing Library — это инструмент, ориентированный на тестирование компонентов React с акцентом на пользовательское взаимодействие. Вместо того чтобы проверять внутреннюю логику компонентов, библиотека предлагает подход, при котором тесты имитируют поведение реального пользователя, работая с компонентами через доступные элементы интерфейса. Два важнейших аспекта взаимодействия с компонентами — это actions (действия) и selectors (селектора), которые играют ключевую роль при тестировании.
Действия (actions) — это те операции, которые могут быть выполнены
пользователем в интерфейсе, такие как клики, ввод текста, наведение мыши
и другие взаимодействия с элементами UI. React Testing Library
предоставляет набор утилит для имитации этих действий. Например, для
кликов используется функция fireEvent, а для ввода текста —
fireEvent.change.
Клик по элементу — одно из самых распространённых действий, которое
необходимо протестировать. Для имитации клика используется метод
fireEvent.click.
Пример:
import { render, screen, fireEvent } from '@testing-library/react';
import MyButton from './MyButton';
test('Button click triggers action', () => {
render(<MyButton />);
const button = screen.getByRole('button');
fireEvent.click(button);
// Пример проверок после клика
expect(screen.getByText(/Кнопка нажата!/)).toBeInTheDocument();
});
В данном примере мы рендерим компонент MyButton, находим
кнопку с помощью getByRole('button') и инициируем клик с
помощью fireEvent.click. После клика проверяется, что текст
на странице изменился.
Для имитации ввода текста в поля формы используется событие
fireEvent.change. Это событие позволяет симулировать
изменения значения в элементе input.
Пример:
import { render, screen, fireEvent } from '@testing-library/react';
import MyForm from './MyForm';
test('Input changes on user typing', () => {
render(<MyForm />);
const input = screen.getByLabelText('Введите текст');
fireEvent.change(input, { target: { value: 'Hello, world!' } });
expect(input.value).toBe('Hello, world!');
});
Здесь имитируется изменение значения в input. Метод
fireEvent.change позволяет задать новое значение для поля
формы. В тесте проверяется, что значение в поле изменилось.
Для тестирования эффектов наведения используется событие
fireEvent.mouseOver. Это может быть полезно для проверки
функциональности всплывающих подсказок, меню или других интерфейсных
элементов, зависящих от наведения.
Пример:
import { render, screen, fireEvent } from '@testing-library/react';
import Tooltip from './Tooltip';
test('Tooltip appears on hover', () => {
render(<Tooltip />);
const element = screen.getByText('Наведи на меня');
fireEvent.mouseOver(element);
expect(screen.getByText('Подсказка')).toBeInTheDocument();
});
Здесь проверяется, что при наведении мыши на элемент появляется всплывающее окно с подсказкой.
Селекторами называют методы, с помощью которых можно найти элементы на странице. React Testing Library предлагает множество способов поиска элементов: по роли, по тексту, по меткам, по тестовым ID и другим признакам. Важно выбрать подходящий способ в зависимости от контекста, так как каждый из них имеет свои особенности и области применения.
getByRoleМетод getByRole является одним из самых мощных
инструментов для поиска элементов, так как он ориентирован на
доступность. Он ищет элементы по их роли (например, кнопка, поле ввода,
ссылка и т.д.). Каждый элемент в веб-странице имеет определённую роль,
которая определяется атрибутами ARIA или HTML5 тегами.
Пример:
import { render, screen } from '@testing-library/react';
import MyButton from './MyButton';
test('Find button by role', () => {
render(<MyButton />);
const button = screen.getByRole('button');
expect(button).toBeInTheDocument();
});
В этом примере метод getByRole используется для поиска
кнопки. Важно помнить, что getByRole ищет только те
элементы, которые соответствуют стандартам доступности, и это помогает
создавать более доступные интерфейсы.
getByTextМетод getByText используется для поиска элементов по их
текстовому содержимому. Этот способ полезен для поиска элементов,
отображающих текст, такой как кнопки, заголовки, параграфы и другие
текстовые блоки.
Пример:
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
test('Text content is displayed', () => {
render(<MyComponent />);
const textElement = screen.getByText(/Привет мир!/);
expect(textElement).toBeInTheDocument();
});
В данном случае мы ищем элемент, содержащий текст “Привет мир!”.
Метод getByText позволяет гибко искать текстовые элементы с
учётом регистрозависимости или с использованием регулярных
выражений.
getByLabelTextМетод getByLabelText позволяет находить элементы формы
(например, input) по связанным с ними меткам (label). Это особенно важно
для тестирования доступности и обеспечения правильной ассоциации между
меткой и полем ввода.
Пример:
import { render, screen } from '@testing-library/react';
import MyForm from './MyForm';
test('Find input by label', () => {
render(<MyForm />);
const input = screen.getByLabelText('Имя');
expect(input).toBeInTheDocument();
});
Здесь поиск осуществляется через текст, связанный с меткой элемента формы. Это важный момент для обеспечения доступности и соответствия стандартам.
getByTestIdМетод getByTestId используется для поиска элементов по
атрибуту data-testid. Это удобный способ для поиска
элементов в тестах, но его следует использовать с осторожностью,
поскольку он может нарушать принципы доступности.
Пример:
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
test('Find element by test ID', () => {
render(<MyComponent />);
const element = screen.getByTestId('unique-element');
expect(element).toBeInTheDocument();
});
В этом случае поиск осуществляется по значению атрибута
data-testid. Этот метод полезен, если другие способы поиска
элементов не подходят или если необходимо избежать изменения структуры
документа.
С помощью комбинации методов можно создавать более сложные селекторы
для поиска элементов. Например, можно использовать
getByRole вместе с name или
hidden для получения более точных результатов, учитывая
контекст интерфейса.
Пример:
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
test('Complex selector usage', () => {
render(<MyComponent />);
const button = screen.getByRole('button', { name: /Отправить/i });
expect(button).toBeInTheDocument();
});
Здесь используется комбинация getByRole и
name, что позволяет точнее указать, какой именно элемент
должен быть найден (в данном случае — кнопка с текстом “Отправить”).
Тестирование действий и селекторов является важной частью работы с
React Testing Library. Правильное использование методов для симуляции
пользовательских действий и поиска элементов помогает создавать
стабильные и надежные тесты, которые ориентированы на реальное поведение
пользователя. Эффективное использование таких утилит, как
fireEvent и screen, позволяет имитировать
широкий спектр взаимодействий и находить элементы на странице с учётом
доступности, контекста и структуры компонентов.