Тестирование форм
Тестирование форм — проверка поведения форм: ввод данных, валидация, отображение ошибок и отправка данных через
@testing-library/user-eventдля симуляции реальных взаимодействий пользователя.
Зачем нужно
Формы — один из самых критичных элементов UI: регистрация, логин, оформление заказа. Ошибки в форме напрямую влияют на конверсию. Тесты форм проверяют валидацию, корректность submit-данных, обработку ошибок сервера и доступность.
Где используется
- Формы авторизации и регистрации
- Checkout и payment формы
- Профили пользователей с редактированием
- Фильтры и поисковые формы
Основной контент
Базовый тест формы
// LoginForm.test.tsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { LoginForm } from './LoginForm';
test('отправляет форму с корректными данными', async () => {
const onSubmit = jest.fn;
const user = userEvent.setup;
render(<LoginForm onSubmit={onSubmit} />);
await user.type(screen.getByLabelText('Email'), 'alice@example.com');
await user.type(screen.getByLabelText('Пароль'), 'secret123');
await user.click(screen.getByRole('button', { name: 'Войти' }));
expect(onSubmit).toHaveBeenCalledWith({
email: 'alice@example.com',
password: 'secret123',
});
});
Тестирование валидации
test('показывает ошибку при пустом email', async () => {
const user = userEvent.setup;
render(<LoginForm onSubmit={jest.fn} />);
// Отправляем без заполнения
await user.click(screen.getByRole('button', { name: 'Войти' }));
expect(screen.getByText('Email обязателен')).toBeInTheDocument;
expect(screen.getByRole('button')).toBeDisabled; // или форма не отправляется
});
test('показывает ошибку при невалидном email', async () => {
const user = userEvent.setup;
render(<LoginForm onSubmit={jest.fn} />);
await user.type(screen.getByLabelText('Email'), 'not-an-email');
await user.tab; // blur для запуска валидации
expect(screen.getByText('Введите корректный email')).toBeInTheDocument;
});
test('не показывает ошибку при валидном email', async () => {
const user = userEvent.setup;
render(<LoginForm onSubmit={jest.fn} />);
await user.type(screen.getByLabelText('Email'), 'alice@example.com');
await user.tab;
expect(screen.queryByText('Введите корректный email')).not.toBeInTheDocument;
});
Тестирование react-hook-form
// RegistrationForm.test.tsx — с react-hook-form
test('отображает ошибку при слишком коротком пароле', async () => {
const user = userEvent.setup;
render(<RegistrationForm onSubmit={jest.fn} />);
await user.type(screen.getByLabelText('Пароль'), '123');
await user.click(screen.getByRole('button', { name: 'Зарегистрироваться' }));
await screen.findByText('Минимум 8 символов');
});
Тестирование ошибки сервера
test('показывает серверную ошибку при неверных данных', async () => {
const onSubmit = jest.fn.mockRejectedValue(new Error('Неверный пароль'));
const user = userEvent.setup;
render(<LoginForm onSubmit={onSubmit} />);
await user.type(screen.getByLabelText('Email'), 'alice@example.com');
await user.type(screen.getByLabelText('Пароль'), 'wrongpass');
await user.click(screen.getByRole('button', { name: 'Войти' }));
await screen.findByText('Неверный пароль');
});
Тестирование loading-состояния
test('кнопка отключена во время отправки', async () => {
const onSubmit = jest.fn( => new Promise(() => {})); // зависает
const user = userEvent.setup;
render(<LoginForm onSubmit={onSubmit} />);
await user.type(screen.getByLabelText('Email'), 'alice@example.com');
await user.type(screen.getByLabelText('Пароль'), 'secret');
await user.click(screen.getByRole('button', { name: 'Войти' }));
expect(screen.getByRole('button', { name: /Загрузка/ })).toBeDisabled;
});
Частые ошибки
fireEvent.changeвместоuserEvent.type—fireEventне симулирует реальный ввод; react-hook-form и Formik могут не отработать correctly- Нет теста на submit без заполнения — граничный случай "пустая форма" часто забывают; это источник багов
- Тест проверяет HTML-атрибут
required— браузерная валидация не работает в jsdom; тестируй кастомную логику валидации компонента
Связанные темы
- _MOC Тестирование
- React Testing Library -- основы
- Тестирование пользовательских событий
- Тестирование рендеринга
- Тестирование ошибок и edge cases