Формы в React часто являются центром взаимодействия пользователя с приложением. Тестирование форм включает проверку корректной работы полей ввода, валидации, обработки сабмитов и взаимодействия с асинхронными процессами. React Testing Library (RTL) фокусируется на тестировании поведения, а не реализации, что делает тесты более стабильными и приближенными к реальному использованию приложения.
Ключевые моменты при тестировании форм:
getByRole, getByLabelText,
getByPlaceholderText.fireEvent.change,
userEvent.type. UserEvent предпочтительнее, так как
имитирует поведение пользователя более реалистично.queryByText, findByText. Асинхронные проверки
требуют использования async/await с RTL.React Hook Form (RHF) использует хуки для управления состоянием формы. Основные компоненты тестирования:
register для привязки полей.handleSubmit для обработки сабмита.formState.errors для отображения ошибок валидации.Пример теста поля ввода и валидации:
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { FormProvider, useForm } from 'react-hook-form';
import MyForm from './MyForm';
test('отображение ошибки при пустом поле email', async () => {
render(<MyForm />);
const submitButton = screen.getByRole('button', { name: /отправить/i });
await userEvent.click(submitButton);
expect(await screen.findByText(/email обязателен/i)).toBeInTheDocument();
});
test('ввод валидного email убирает ошибку', async () => {
render(<MyForm />);
const emailInput = screen.getByLabelText(/email/i);
await userEvent.type(emailInput, 'user@example.com');
const submitButton = screen.getByRole('button', { name: /отправить/i });
await userEvent.click(submitButton);
expect(screen.queryByText(/email обязателен/i)).not.toBeInTheDocument();
});
Особенности тестирования RHF:
FormProvider и
useFormContext позволяет тестировать вложенные
компоненты.resolver) нужно оборачивать
тест в async/await.Formik управляет состоянием формы через компонент Formik
или хук useFormik. Важные элементы:
initialValues задаёт начальные значения.onSubmit обрабатывает сабмит.errors и touched используются для
валидации.Пример теста формы с Formik:
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import MyFormikForm from './MyFormikForm';
test('валидация обязательного поля password', async () => {
render(<MyFormikForm />);
const submitButton = screen.getByRole('button', { name: /войти/i });
await userEvent.click(submitButton);
expect(await screen.findByText(/пароль обязателен/i)).toBeInTheDocument();
});
test('правильный ввод вызывает onSubmit', async () => {
const handleSubmit = jest.fn();
render(<MyFormikForm onSub mit={handleSubmit} />);
const emailInput = screen.getByLabelText(/email/i);
const passwordInput = screen.getByLabelText(/пароль/i);
await userEvent.type(emailInput, 'test@example.com');
await userEvent.type(passwordInput, '123456');
const submitButton = screen.getByRole('button', { name: /войти/i });
await userEvent.click(submitButton);
expect(handleSubmit).toHaveBeenCalledWith(
{ email: 'test@example.com', password: '123456' },
expect.any(Object)
);
});
Особенности тестирования Formik:
touched). При тестировании важно вызвать blur
для поля, чтобы активировать ошибку.validationSchema требуют ожидания
появления ошибок через findByText.formik.setFieldValue упрощает программное
изменение значений для сложных компонентов.| Характеристика | React Hook Form | Formik |
|---|---|---|
| Стейт формы | Хуки (useForm) |
Компонент/хук (Formik) |
| Валидация | Синхронная и асинхронная, resolver |
Yup или функции валидации |
| Тестирование ошибок | Через текст ошибок, formState.errors |
Через текст ошибок, errors и touched |
| Имитация пользовательского ввода | userEvent.type / fireEvent.change |
userEvent.type / fireEvent.change |
| Асинхронные проверки | await для сабмита или resolver |
await для сабмита или validationSchema |
screen.getByRole и
screen.getByLabelText для поиска элементов.await findBy... или waitFor.queryBy... для проверки отсутствия
элементов.При использовании UI-библиотек (Material-UI, Ant Design) важно учитывать:
role или
labelText.waitFor или findBy*.Controller в RHF, Field в
Formik).Тестирование форм с React Hook Form и Formik в React Testing Library должно фокусироваться на поведении пользователя: ввод, ошибки, сабмит, а не на внутренней реализации. Такой подход делает тесты устойчивыми к изменениям кода и улучшает качество приложения.