Тестирование форм в React требует системного подхода, учитывающего пользовательские взаимодействия, валидацию и асинхронные операции. Основная цель — проверить, что форма корректно обрабатывает ввод данных, ошибки и успешную отправку, не привязываясь к внутренней реализации компонентов.
Элементы формы должны быть доступны для тестов через публичные селекторы, а не через внутренние классы или идентификаторы. React Testing Library рекомендует ориентироваться на:
getByLabelText,
queryByLabelTextgetByPlaceholderTextgetByRole, например,
role="button" для кнопокgetByText для кнопок
или сообщений об ошибкеИспользование этих селекторов обеспечивает устойчивость тестов при изменении структуры DOM.
Пример:
const usernameInput = screen.getByLabelText(/имя пользователя/i);
const submitButton = screen.getByRole('button', { name: /отправить/i });
Ввод данных должен воспроизводить действия реального пользователя.
Для этого используются методы userEvent из пакета
@testing-library/user-event, которые позволяют:
userEvent.type(input, 'тест')userEvent.click(button)userEvent.selectOptions(select, 'значение')Пример заполнения формы:
import userEvent from '@testing-library/user-event';
await userEvent.type(usernameInput, 'john_doe');
await userEvent.type(passwordInput, 'password123');
await userEvent.click(submitButton);
Важно использовать await, так как большинство действий
асинхронные.
Формы часто содержат клиентскую и серверную валидацию. Проверка в тестах включает:
Пример проверки ошибки:
await userEvent.click(submitButton);
expect(screen.getByText(/пароль обязателен/i)).toBeInTheDocument();
После исправления данных:
await userEvent.type(passwordInput, 'password123');
expect(screen.queryByText(/пароль обязателен/i)).not.toBeInTheDocument();
Формы часто отправляют данные на сервер. Для тестирования асинхронных
процессов используется комбинация async/await и
waitFor:
import { waitFor } from '@testing-library/react';
await userEvent.click(submitButton);
await waitFor(() => {
expect(screen.getByText(/успешно сохранено/i)).toBeInTheDocument();
});
waitFor повторяет проверку до появления элемента, что
важно для симуляции реальных задержек и сетевых запросов.
Тесты форм не должны зависеть от реального сервера. Для этого используются мок-функции:
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ success: true }),
})
);
Это позволяет проверять поведение формы при различных ответах: успешном сохранении, ошибке сервера или тайм-ауте.
Каждый сценарий проверяет только внешнее поведение, а не внутренние методы компонента.
describe по типу тестируемого
функционала (валидация, успешная отправка, ошибки сервера)it('показывает сообщение об ошибке при пустом пароле'))Пример утилиты:
async function fillLoginForm({ username, password }) {
const usernameInput = screen.getByLabelText(/имя пользователя/i);
const passwordInput = screen.getByLabelText(/пароль/i);
const submitButton = screen.getByRole('button', { name: /войти/i });
await userEvent.type(usernameInput, username);
await userEvent.type(passwordInput, password);
await userEvent.click(submitButton);
}
userEvent.Такой подход позволяет создавать устойчивые, читаемые и эффективные тесты, обеспечивающие надежность формы в любых условиях использования.