Jest является популярным инструментом для тестирования JavaScript-программ, включая работу с DOM. Тестирование манипуляций с DOM важно для обеспечения правильности работы веб-приложений, особенно когда взаимодействие с элементами страницы является основным функционалом. В этой статье рассматриваются основные подходы и методы тестирования DOM в Jest.
Перед тем как начать тестирование, необходимо настроить тестовую
среду. Jest сам по себе не предоставляет полного API для манипуляций с
DOM, однако в комбинации с библиотеками, такими как
@testing-library/react, можно легко тестировать компоненты,
взаимодействующие с DOM.
Для начала нужно установить необходимые пакеты:
npm install --save-dev @testing-library/react @testing-library/jest-dom
@testing-library/react предоставляет утилиты для работы
с React-компонентами и их рендеринга, а
@testing-library/jest-dom добавляет полезные матчеры для
проверки DOM-элементов.
Для тестирования манипуляций с DOM, первым шагом будет рендеринг
компонента. Jest использует ReactDOM.render() или
альтернативу, предоставляемую библиотеками, для рендеринга компонентов в
виртуальный DOM. После этого можно выполнять тесты, проверяя, как
изменения DOM влияют на отображение и поведение страницы.
Пример рендеринга компонента с использованием
@testing-library/react:
import { render } from '@testing-library/react';
import MyComponent from './MyComponent';
test('renders component with text', () => {
const { getByText } = render(<MyComponent />);
const element = getByText(/Hello, World!/i);
expect(element).toBeInTheDocument();
});
В этом примере мы рендерим компонент MyComponent и
проверяем, что текст «Hello, World!» существует в DOM.
Тестирование манипуляций с DOM часто включает симуляцию
пользовательских действий, таких как клики, ввод текста и другие
события. Для этого можно использовать утилиты из библиотеки
@testing-library/react.
Для симуляции кликов или ввода данных применяются методы, такие как
fireEvent. Рассмотрим пример, где мы тестируем кнопку,
меняющую текст при клике:
import { render, fireEvent } from '@testing-library/react';
import Button from './Button';
test('changes text on click', () => {
const { getByText } = render(<Button />);
const button = getByText(/Click me/i);
fireEvent.click(button);
const newText = getByText(/Clicked!/i);
expect(newText).toBeInTheDocument();
});
В этом примере мы симулируем клик по кнопке, что должно изменить текст на странице. После клика мы проверяем, что новый текст отображается в DOM.
Часто в реальных приложениях взаимодействие с DOM асинхронное,
например, при загрузке данных с сервера. Для таких случаев используется
findBy из @testing-library/react, который
позволяет ожидать появления элемента через асинхронное событие.
Пример теста с асинхронным запросом:
import { render, screen, waitFor } from '@testing-library/react';
import UserProfile from './UserProfile';
test('loads and displays user data', async () => {
render(<UserProfile />);
// Ожидаем, что загрузка данных завершится и элемент появится
const user = await screen.findByText(/John Doe/i);
expect(user).toBeInTheDocument();
});
В этом примере мы тестируем компонент, который загружает данные о
пользователе. Метод findByText ожидает появления элемента с
текстом “John Doe” после асинхронной загрузки данных.
Для корректной работы тестов важно очищать DOM после каждого теста,
чтобы избежать конфликтов и утечек памяти. Jest автоматически очищает
все изменения в DOM между тестами, но это можно также настроить вручную
с помощью функции cleanup, которая вызывается после каждого
теста.
import { render, cleanup } from '@testing-library/react';
afterEach(cleanup);
test('should render element correctly', () => {
const { getByText } = render(<MyComponent />);
const element = getByText(/Sample Text/i);
expect(element).toBeInTheDocument();
});
Этот код позволяет гарантировать, что DOM очищается после каждого теста, предотвращая влияние одного теста на другой.
Jest DOM предоставляет набор матчеров, которые помогают проверять состояние DOM, такие как:
toBeInTheDocument(): проверяет, что элемент
присутствует в DOM.toHaveClass(): проверяет, что элемент имеет указанный
CSS класс.toHaveTextContent(): проверяет, что элемент содержит
определённый текст.toHaveAttribute(): проверяет наличие атрибута у
элемента.Пример использования матчеров:
import { render } from '@testing-library/react';
import Button from './Button';
test('button has correct text and class', () => {
const { getByRole } = render(<Button />);
const button = getByRole('button');
expect(button).toHaveTextContent(/Click me/i);
expect(button).toHaveClass('btn-primary');
});
В этом примере мы проверяем, что кнопка имеет правильный текст и класс.
В некоторых случаях важно протестировать обработку событий, таких как клик, изменение поля ввода и другие. Для этого часто используют мокирование функций. Jest позволяет замещать или отслеживать поведение функций через моки, что даёт возможность проверять, как компонент реагирует на различные события.
Пример тестирования обработчика клика с использованием моков:
import { render, fireEvent } from '@testing-library/react';
import Button from './Button';
test('calls handler on click', () => {
const handleClick = jest.fn();
const { getByText } = render(<Button onCl ick={handleClick} />);
fireEvent.click(getByText(/Click me/i));
expect(handleClick).toHaveBeenCalledTimes(1);
});
В этом примере мы тестируем, что функция обработчика клика была вызвана при нажатии на кнопку.
Веб-приложения часто имеют динамически изменяющиеся элементы, такие как раскрывающиеся меню, модальные окна, всплывающие подсказки и другие UI-элементы. Для таких случаев важно тестировать, как состояние компонента влияет на отображение DOM.
Пример теста динамического компонента:
import { render, fireEvent } from '@testing-library/react';
import Dropdown from './Dropdown';
test('toggles dropdown visibility', () => {
const { getByText, queryByText } = render(<Dropdown />);
const button = getByText(/Toggle dropdown/i);
fireEvent.click(button);
const dropdownMenu = getByText(/Option 1/i);
expect(dropdownMenu).toBeInTheDocument();
fireEvent.click(button);
expect(queryByText(/Option 1/i)).not.toBeInTheDocument();
});
Здесь проверяется, что при клике на кнопку скрывается и появляется выпадающее меню, что является частым элементом динамических изменений DOM.
Тестирование манипуляций с DOM с использованием Jest и сопутствующих библиотек позволяет создавать надёжные и поддерживаемые тесты для веб-приложений. Основные принципы включают рендеринг компонентов, симуляцию событий, работу с асинхронными операциями и использование различных матчеров для проверки состояния DOM. Важно помнить о необходимости очистки DOM между тестами, а также о правильном мокировании функций для проверки событий.