Одной из распространенных задач при тестировании интерфейсов является фильтрация элементов на странице. Это может быть фильтрация элементов списка по какому-то критерию, скрытие или отображение отдельных элементов в зависимости от состояния компонента. В React Testing Library процесс взаимодействия с DOM должен максимально соответствовать поведению реального пользователя. Рассмотрим, как можно эффективно фильтровать элементы списка с использованием возможностей этой библиотеки.
React Testing Library ориентирована на тестирование компонентов так, как это делает пользователь. Вместо того чтобы манипулировать с внутренним состоянием компонента или его свойствами напрямую, тесты должны фокусироваться на том, как компонент отображается и как с ним взаимодействует пользователь. Для фильтрации элементов списка это означает работу с элементами через доступные в интерфейсе текстовые метки, атрибуты и другие видимые характеристики.
Для поиска элементов списка в React Testing Library можно использовать несколько ключевых методов:
getByText()getByRole()getByLabelText()queryByText()queryByRole()findByText() (асинхронный)Каждый из этих методов имеет свои особенности и подходит для разных
сценариев. Для фильтрации списка часто используют комбинацию
queryBy или getBy с дополнительными
параметрами или фильтрами.
getByRole и
queryByRoleМетод getByRole позволяет находить элементы на основе их
семантической роли. Это полезно, когда в интерфейсе присутствуют
элементы, связанные с интерактивными действиями, такими как кнопки,
ссылки, поля ввода. Например, если требуется фильтровать элементы списка
по роли кнопки, можно использовать:
import { render, screen } from '@testing-library/react';
test('фильтрация элементов списка по кнопке', () => {
render(<List items={['Apple', 'Banana', 'Orange']} />);
// Нажатие на кнопку фильтрации
const filterButton = screen.getByRole('button', { name: /filter/i });
fireEvent.click(filterButton);
// Проверка, что отфильтрованные элементы отображаются
expect(screen.queryByText('Apple')).toBeNull();
expect(screen.queryByText('Banana')).not.toBeNull();
});
В данном примере осуществляется проверка кнопки фильтрации по роли, и после её активации проверяется, что элемент «Apple» исчезает, а «Banana» остаётся на странице.
getByText и queryByTextМетод getByText является наиболее универсальным для
поиска текста в компоненте. Он позволяет искать текст, связанный с
конкретным элементом списка. В случаях, когда нужно отфильтровать
элементы по тексту, этот метод особенно полезен. Например, если список
продуктов нужно отфильтровать по названию, то следующий пример покажет,
как это можно сделать:
import { render, screen, fireEvent } from '@testing-library/react';
test('фильтрация по названию продукта', () => {
render(<ProductList items={['Apple', 'Banana', 'Cherry']} />);
// Ввод текста в фильтрующее поле
const input = screen.getByPlaceholderText('Search products');
fireEvent.change(input, { target: { value: 'Banana' } });
// Проверка, что только элемент "Banana" отображается
expect(screen.queryByText('Apple')).toBeNull();
expect(screen.queryByText('Banana')).not.toBeNull();
expect(screen.queryByText('Cherry')).toBeNull();
});
В данном примере мы взаимодействуем с полем ввода, имитируя ввод текста для фильтрации, и проверяем, что элементы, не соответствующие запросу, исчезают.
findByTextКогда элементы загружаются асинхронно, например, при запросах к
серверу, метод findByText может быть полезен. Он позволяет
ожидать появления элементов на странице после асинхронных операций. Этот
метод работает так же, как и getByText, но в случае, если
элемент не найден сразу, он будет ожидать его появления в течение
определенного времени.
Пример с асинхронной фильтрацией:
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
test('асинхронная фильтрация списка', async () => {
render(<AsyncList />);
// Нажатие на кнопку фильтрации
const filterButton = screen.getByRole('button', { name: /load items/i });
fireEvent.click(filterButton);
// Ожидание появления элементов
await waitFor(() => screen.findByText('Item 1'));
// Проверка фильтрации
expect(screen.getByText('Item 1')).toBeInTheDocument();
expect(screen.queryByText('Item 2')).toBeNull();
});
В этом примере элементы списка загружаются асинхронно, и с помощью
waitFor тест ожидает их появления. Метод
findByText используется для проверки появления нужных
элементов после загрузки.
Кроме текстового контента, элементы можно фильтровать и по другим
атрибутам, таким как data-testid, классы или другие
специфичные для интерфейса атрибуты. Это позволяет легко осуществлять
поиск, даже если текст не является уникальным или изменяется в
зависимости от состояния.
Пример фильтрации по data-testid:
import { render, screen, fireEvent } from '@testing-library/react';
test('фильтрация по data-testid', () => {
render(<List items={['Item 1', 'Item 2']} />);
// Нажатие на кнопку фильтрации
const button = screen.getByTestId('filter-button');
fireEvent.click(button);
// Проверка, что нужный элемент отобразился
expect(screen.getByTestId('item-1')).toBeInTheDocument();
expect(screen.queryByTestId('item-2')).toBeNull();
});
В данном случае поиск осуществляется с использованием
data-testid, который является полезным для уникальной
идентификации элементов, особенно в случае сложных или динамичных
интерфейсов.
В некоторых случаях фильтрация может быть более сложной и требовать комбинированного подхода. Например, нужно отфильтровать элементы списка по нескольким критериям одновременно или взаимодействовать с несколькими фильтрами на странице.
Пример комбинированной фильтрации по нескольким критериям:
import { render, screen, fireEvent } from '@testing-library/react';
test('фильтрация по нескольким критериям', () => {
render(<ProductFilter />);
// Выбор фильтра по категории
fireEvent.change(screen.getByLabelText(/category/i), { target: { value: 'Fruit' } });
// Ввод фильтра по названию
fireEvent.change(screen.getByPlaceholderText('Search products'), { target: { value: 'Apple' } });
// Проверка, что только элементы, соответствующие обоим фильтрам, отображаются
expect(screen.queryByText('Apple')).toBeInTheDocument();
expect(screen.queryByText('Banana')).toBeNull();
});
Здесь осуществляется фильтрация по двум критериям: категория и название. После применения фильтров на странице остаются только те элементы, которые соответствуют обоим условиям.
Фильтрация элементов списка в React Testing Library позволяет эффективно имитировать действия пользователя, ориентируясь на текст, атрибуты и другие свойства элементов. При этом библиотека предоставляет множество методов для поиска и фильтрации, что позволяет писать тесты, максимально приближенные к реальным сценариям использования. Важно помнить, что для достижения наилучших результатов нужно всегда стремиться к тестированию взаимодействия с интерфейсом таким образом, как это делает конечный пользователь.