React Testing Library (RTL) предоставляет мощные инструменты для
тестирования компонентов React, ориентируясь на поведение пользователя,
а не на реализацию. Одним из таких инструментов является функция
within, позволяющая ограничивать область поиска элементов
внутри конкретного узла DOM. Это особенно важно при работе с
компонентами, содержащими повторяющиеся структуры, списки, таблицы или
вложенные элементы.
withinФункция within создает контекст поиска относительно
переданного DOM-узла. Стандартные функции поиска, такие как
getByText, getByRole,
queryByTestId и другие, обычно ищут элементы во всём дереве
DOM, начиная с корня document.body. Использование
within позволяет локализовать поиск до конкретного
контейнера, предотвращая ложные совпадения.
Синтаксис:
import { render, screen, within } from '@testing-library/react';
const { container } = render(<MyComponent />);
const section = container.querySelector('.my-section');
const { getByText } = within(section);
const element = getByText('Текст внутри секции');
В этом примере getByText ищет текст только
внутри выбранной секции .my-section. Элементы за
её пределами игнорируются.
within особенно полезен при тестировании списков и
таблиц:
import { render, screen, within } from '@testing-library/react';
import UsersTable from './UsersTable';
test('проверка данных в строках таблицы', () => {
render(<UsersTable />);
const rows = screen.getAllByRole('row');
// Пропускаем заголовок таблицы
const userRows = rows.slice(1);
userRows.forEach((row, index) => {
const { getByText } = within(row);
expect(getByText(`User ${index + 1}`)).toBeInTheDocument();
expect(getByText(`user${index + 1}@mail.com`)).toBeInTheDocument();
});
});
Здесь within обеспечивает, что поиск имени пользователя
и электронной почты выполняется строго в рамках одной строки таблицы.
Это предотвращает путаницу, если таблица содержит одинаковые данные в
других строках.
Без within код выглядел бы так:
screen.getByText('User 1');
screen.getByText('user1@mail.com');
Проблема такого подхода в том, что getByText может
вернуть неправильный элемент, если на странице есть повторяющиеся
значения. within гарантирует локальный контекст поиска и
делает тесты более точными и надежными.
Пример с карточкой товара:
const card = screen.getByTestId('product-card-1');
const { getByRole } = within(card);
expect(getByRole('button', { name: /купить/i })).toBeInTheDocument();
Здесь кнопка «Купить» ищется только внутри первой карточки товара, исключая другие карточки.
findBy и queryBywithin работает со всеми типами методов поиска RTL:
getBy... – выбросит ошибку, если элемент не
найден.queryBy... – вернет null, если элемент не
найден.findBy... – возвращает промис и ждет появления
элемента.const modal = screen.getByRole('dialog');
const { findByText } = within(modal);
await findByText('Содержимое модального окна');
Это особенно полезно при работе с динамическим контентом, который появляется после асинхронных операций.
withinwithin на уровне
корневого контейнера — это делает тесты бессмысленными.within совместно с селекторами
getAllBy для перебора повторяющихся элементов.within повышает точность и читаемость тестов в React
Testing Library. Он позволяет локализовать поиск элементов,
минимизировать ложные срабатывания и делает тесты более поддерживаемыми.
При правильном применении within значительно сокращает
вероятность ошибок, связанных с повторяющимися или вложенными элементами
DOM.