Одной из важных составляющих тестирования в Jest является проверка корректности рендеринга компонентов. Тестирование рендеринга помогает убедиться, что компонент отрисовывается правильно, а его структура соответствует ожиданиям, что особенно важно в контексте UI-тестирования.
@testing-library/reactДля рендеринга компонентов в Jest чаще всего используется библиотека
@testing-library/react. Этот инструмент предоставляет
удобные методы для работы с DOM-элементами и их проверки. Модуль
предназначен для того, чтобы тесты были максимально приближены к
реальной работе с приложением, а значит, способствует более эффективному
выявлению ошибок и дефектов интерфейса.
npm install --save-dev @testing-library/react
Основной метод для рендеринга компонента в
@testing-library/react — это функция render().
Она позволяет отрисовать компонент в виртуальном DOM и получить доступ к
различным вспомогательным функциям для взаимодействия с результатом
рендеринга.
import { render } from '@testing-library/react';
import MyComponent from './MyComponent';
test('renders component correctly', () => {
const { container } = render(<MyComponent />);
expect(container).toMatchSnapshot();
});
В приведенном примере происходит рендеринг компонента
MyComponent, и результат помещается в объект
container. С помощью этого объекта можно проверить
структуру DOM, что и будет предметом дальнейших тестов.
Одним из мощных инструментов для проверки рендеринга является функциональность “снимков” (snapshots). Снимок позволяет зафиксировать текущую структуру компонента и сравнивать её с предыдущими версиями. Такой подход позволяет быстро выявлять изменения в разметке и устранять непреднамеренные баги, связанные с рендерингом.
Для создания снимка используется функция
toMatchSnapshot(), которая сохраняет текущее состояние DOM
в виде снимка:
test('matches snapshot', () => {
const { asFragment } = render(<MyComponent />);
expect(asFragment()).toMatchSnapshot();
});
При последующих запусках тестов Jest будет сравнивать текущий рендер с сохраненным снимком. В случае, если рендер компонента изменится, тест завершится неудачно, и разработчик сможет либо обновить снимок (если изменение было ожидаемым), либо исправить ошибку.
После рендеринга компонента в тестах необходимо взаимодействовать с
его элементами. Для этого @testing-library/react
предоставляет различные методы для поиска элементов в DOM. Например,
можно использовать getByText(), getByRole(),
getByTestId() и другие.
Пример использования getByText():
test('displays correct text', () => {
const { getByText } = render(<MyComponent />);
expect(getByText('Hello, World!')).toBeInTheDocument();
});
Этот тест проверяет, что на странице отображается текст “Hello, World!”.
Для поиска элементов также можно использовать более сложные
селекторы, такие как getByRole() или
getByTestId(). Эти методы позволяют находить элементы по
ролям или тестовым идентификаторам, что дает больше гибкости в написании
тестов.
Иногда необходимо не только рендерить компонент, но и проверить его
реакцию на изменения состояния (state) или действия пользователя. В
таких случаях можно использовать методы, которые имитируют события,
например, fireEvent.
Пример тестирования клика по кнопке:
import { fireEvent } from '@testing-library/react';
test('button click updates state', () => {
const { getByText } = render(<MyComponent />);
const button = getByText('Click me');
fireEvent.click(button);
expect(getByText('Button clicked')).toBeInTheDocument();
});
Здесь происходит клик по кнопке, и затем проверяется, что после клика в документе появляется текст “Button clicked”. Такое тестирование полезно для проверки, что компонент правильно обновляет состояние при взаимодействии с пользователем.
Часто компоненты зависят от внешних данных, таких как API-запросы или
состояния родительских компонентов. В таких случаях необходимо
замокировать эти данные, чтобы тесты не зависели от внешних систем. Для
этого можно использовать библиотеки для мокирования, такие как
jest.mock().
Пример мокирования API-запроса:
jest.mock('./api', () => ({
fetchData: jest.fn().mockResolvedValue({ data: 'some data' }),
}));
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
import { fetchData } from './api';
test('displays fetched data', async () => {
render(<MyComponent />);
const data = await screen.findByText('some data');
expect(data).toBeInTheDocument();
});
В данном примере мокируется функция fetchData, которая
обычно выполняет асинхронный запрос. Вместо реального запроса мы
возвращаем замокированные данные, что позволяет сосредоточиться на
тестировании компонента без зависимости от реальных данных.
Компоненты могут выполнять асинхронные операции, такие как запросы к
серверу или задержки, и необходимо проверять, как они ведут себя в таких
случаях. Для работы с асинхронностью Jest предоставляет такие функции,
как waitFor() и findBy....
Пример теста с асинхронным рендерингом:
import { waitFor } from '@testing-library/react';
test('fetches and displays data', async () => {
const { findByText } = render(<MyComponent />);
await waitFor(() => findByText('some data'));
expect(screen.getByText('some data')).toBeInTheDocument();
});
Здесь используется waitFor(), чтобы дождаться, пока
элемент с данными появится в DOM, после чего выполняется проверка.
Для того чтобы тесты не влияли друг на друга, важно правильно очищать
состояние компонентов после их выполнения. Jest предоставляет встроенную
функцию cleanup(), которая автоматически очищает DOM после
каждого теста. Однако в некоторых случаях может понадобиться вручную
вызвать очистку, если компоненты не освобождают ресурсы должным
образом.
import { cleanup } from '@testing-library/react';
afterEach(cleanup);
Эта функция обеспечит, что после каждого теста состояние будет очищено, и каждый тест будет начинаться с чистого листа.
Рендеринг компонентов в Jest — это ключевая часть процесса
тестирования UI, которая помогает проверять правильность отображения и
взаимодействия компонентов. Используя возможности
@testing-library/react, можно эффективно тестировать
компоненты, включая работу с состоянием, асинхронностью и внешними
зависимостями. Важно также помнить о правильной очистке и изоляции
тестов, чтобы каждый тест был независим от предыдущих.