getByText для поиска текстового контента

getByText является одним из ключевых методов поиска элементов в React Testing Library, позволяя находить DOM-узлы по их текстовому содержимому. Этот метод возвращает первый найденный элемент, который соответствует заданному тексту, и выбрасывает ошибку, если такой элемент отсутствует.

Пример базового использования:

import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';

test('отображает текст Hello World', () => {
  render(<MyComponent />);
  const element = screen.getByText('Hello World');
  expect(element).toBeInTheDocument();
});

В этом примере getByText ищет элемент с точным текстом "Hello World". Если элемент не найден, тест завершится с ошибкой, что делает getByText удобным для строгих проверок наличия контента.


Точный поиск vs частичное совпадение

По умолчанию getByText ищет строгое совпадение текста. Для случаев, когда необходимо проверить наличие части текста, можно использовать регулярные выражения:

const element = screen.getByText(/Hello/i); // регистр не важен

Ключевые моменты:

  • /Hello/i — регулярное выражение, ищет текст независимо от регистра.
  • Можно использовать флаги i для игнорирования регистра и g для глобального поиска, хотя глобальный флаг обычно не применяется с getByText.

Функция в качестве аргумента

getByText позволяет передавать функцию, которая получает текстовый контент каждого элемента и возвращает true для совпадения. Это полезно при динамическом содержимом или сложной разметке:

const element = screen.getByText((content, element) => {
  return content.startsWith('Hello') && element.tagName.toLowerCase() === 'h1';
});

Преимущества использования функции:

  • Возможность фильтровать элементы по тегам.
  • Гибкость при работе с длинными текстовыми блоками или динамически генерируемым контентом.

Настройки поиска текста

Метод getByText поддерживает опции для тонкой настройки поиска:

screen.getByText('Hello World', { exact: false, collapseWhitespace: true });
  • exact: false — позволяет искать текст не строго, то есть элемент может содержать дополнительные символы.
  • collapseWhitespace: true — убирает лишние пробелы и переносы строк при сравнении текста.

Это особенно важно при работе с текстом из Markdown, JSX с переносами строк или текстом, содержащим пробелы для форматирования.


Обработка нескольких совпадений

getByText выбрасывает ошибку, если найдено несколько элементов, соответствующих критериям. Для случаев, когда ожидается несколько совпадений, используются:

  • getAllByText — возвращает массив элементов.
  • queryAllByText — возвращает массив или пустой массив, не выбрасывая ошибку.

Пример:

const elements = screen.getAllByText(/Click/i);
expect(elements.length).toBe(2);

Взаимодействие с вложенной разметкой

getByText ищет текст внутри дочерних элементов, игнорируя HTML-теги. Это позволяет находить элементы даже при вложенных структурах:

<div>
  <span>Hello</span> <strong>World</strong>
</div>
screen.getByText('Hello World'); // успешно находит элемент

Для сложных случаев можно использовать опцию selector для фильтрации по типу тега:

screen.getByText('Hello World', { selector: 'div' });

Рекомендации по использованию

  • Использовать getByText для проверки видимого текста, а не для тестирования структуры DOM.
  • При работе с динамическим содержимым рекомендуется регулярные выражения или функции, чтобы тесты не ломались при изменении пробелов или регистра.
  • Предпочтительно комбинировать getByText с toBeInTheDocument() для явного утверждения наличия элемента.
  • Для элементов, которые могут отсутствовать, лучше использовать queryByText, чтобы избежать ненужного выброса ошибок.

Примеры практического применения

Тестирование кнопки с текстом:

render(<button>Submit Form</button>);
const button = screen.getByText(/submit/i);
expect(button).toBeEnabled();

Тестирование ошибок формы:

render(<Form />);
fireEvent.click(screen.getByText('Отправить'));
expect(screen.getByText('Поле обязательно')).toBeVisible();

Фильтрация по тегу и содержимому:

render(
  <div>
    <p>Info message</p>
    <span>Info message</span>
  </div>
);

const paragraph = screen.getByText('Info message', { selector: 'p' });
expect(paragraph.tagName).toBe('P');

getByText является мощным инструментом для проверки видимого текстового контента, обеспечивая точность и гибкость тестов в React-приложениях.