React Testing Library предоставляет разнообразные методы для поиска
элементов в DOM — queries. Основные категории включают
getBy, queryBy, findBy и их
множественные варианты (getAllBy, queryAllBy,
findAllBy). В простых случаях одного query достаточно для
проверки существования элемента. Однако реальные приложения часто
содержат сложные компоненты с множественными вложенными элементами,
динамическим рендерингом и асинхронным поведением. В таких случаях
необходимо комбинировать queries для точной и надёжной выборки.
1. Последовательная фильтрация элементов
Если требуется найти элемент, соответствующий нескольким критериям, можно использовать цепочку queries. Например:
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import TodoList from './TodoList';
test('отмечает конкретную задачу как выполненную', () => {
render(<TodoList tasks={[{ id: 1, text: 'Купить молоко' }, { id: 2, text: 'Позвонить другу' }]} />);
const taskItem = screen.getByText('Купить молоко');
const checkbox = within(taskItem).getByRole('checkbox');
userEvent.click(checkbox);
expect(checkbox).toBeChecked();
});
Здесь используется метод within(), который позволяет
ограничить область поиска элементами внутри конкретного родителя. Это
эффективный способ избежать конфликтов при наличии одинаковых текстов
или ролей в разных частях DOM.
2. Использование регулярных выражений и предикатов
Для поиска элементов по частичному совпадению текста или по пользовательским условиям применяются регулярные выражения или функции-предикаты:
const button = screen.getByRole('button', { name: /отправить/i });
Если нужно уточнить поиск ещё сильнее, можно передавать функцию:
const importantTask = screen.getAllByText((content, element) => {
return element.tagName.toLowerCase() === 'li' && content.includes('важно');
});
Такой подход особенно полезен для динамически сгенерированных списков или сложных вложенных структур.
3. Комбинирование разных типов queries
Иногда один query недостаточен. Например, элемент может не иметь уникального текста, но его можно однозначно определить через комбинацию роли и текстового содержимого:
const modal = screen.getByRole('dialog');
const confirmButton = within(modal).getByText('Подтвердить');
userEvent.click(confirmButton);
Использование комбинации getByRole +
within().getByText делает тесты более устойчивыми к
изменениям структуры DOM, чем слепой поиск по тексту.
4. Асинхронное комбинирование
Когда элементы появляются с задержкой (например, после запроса к
API), применяются findBy и findAllBy. Их можно
комбинировать с within или предикатами:
test('загружает список пользователей и выделяет активных', async () => {
render(<UserList />);
const userItems = await screen.findAllByRole('listitem');
const activeUsers = userItems.filter(item => item.textContent.includes('Активен'));
expect(activeUsers.length).toBeGreaterThan(0);
});
findBy возвращает Promise, что позволяет
корректно ожидать появления элементов перед их фильтрацией или
взаимодействием.
5. Создание утилитарных функций для повторяющихся комбинаций
Если один и тот же сложный поиск используется в нескольких тестах, имеет смысл обернуть его в функцию:
function getTaskCheckbox(taskText) {
const taskItem = screen.getByText(taskText);
return within(taskItem).getByRole('checkbox');
}
test('отмечает задачу', () => {
render(<TodoList tasks={[{ id: 1, text: 'Сделать домашку' }]} />);
const checkbox = getTaskCheckbox('Сделать домашку');
userEvent.click(checkbox);
expect(checkbox).toBeChecked();
});
Это повышает читаемость тестов и уменьшает дублирование кода.
within() для ограничения области поиска и
повышения точности.getByRole +
getByText, findAllBy + фильтры по тексту или
атрибутам.findBy, findAllBy)
всегда обрабатывать через await.Заключение по стратегии
Комбинирование queries позволяет создавать устойчивые и читаемые тесты даже для сложных интерфейсов. Вместо поиска одного уникального селектора используется последовательная фильтрация, ограничение области поиска и использование асинхронных ожиданий. Такой подход делает тесты более надёжными и облегчает сопровождение приложений с динамическим DOM.