Тестирование форм в веб-приложениях является важной частью обеспечения их качества и надежности. Формы часто содержат пользовательский ввод, который должен быть проверен на корректность, а также обрабатывать различные типы данных. Использование Jest для тестирования форм позволяет создавать надежные тесты, проверяющие как саму логику работы формы, так и правильность валидации данных.
Первым шагом в тестировании формы является проверка ее рендеринга. Чтобы удостовериться, что компоненты формы правильно отображаются, можно использовать методы тестирования Jest в связке с React Testing Library (если используется React).
import { render, screen } from '@testing-library/react';
import MyForm from './MyForm';
test('форма рендерится правильно', () => {
render(<MyForm />);
expect(screen.getByLabelText(/Имя/i)).toBeInTheDocument();
expect(screen.getByLabelText(/Электронная почта/i)).toBeInTheDocument();
expect(screen.getByRole('button', { name: /Отправить/i })).toBeInTheDocument();
});
Этот тест проверяет, что компоненты формы (например, поля ввода и кнопка) отображаются на странице.
Валидация является важной частью работы формы, так как она гарантирует, что введенные пользователем данные соответствуют необходимым требованиям (например, формат электронной почты или обязательность поля). В Jest можно проверить валидацию с помощью моков и утверждений на основе состояния формы.
Пример тестирования обязательности поля:
import { render, screen, fireEvent } from '@testing-library/react';
import MyForm from './MyForm';
test('проверка обязательности поля "Имя"', () => {
render(<MyForm />);
fireEvent.click(screen.getByRole('button', { name: /Отправить/i }));
expect(screen.getByText(/Поле "Имя" обязательно для заполнения/i)).toBeInTheDocument();
});
В данном примере происходит клик по кнопке формы без ввода данных в обязательное поле, что должно вызвать ошибку валидации.
В большинстве форм необходимо проверять правильность введенных данных. Например, проверка формата электронной почты или номера телефона. Для тестирования таких проверок создаются моки, которые симулируют пользовательский ввод.
Пример теста для проверки формата электронной почты:
test('проверка правильности формата электронной почты', () => {
render(<MyForm />);
const emailInput = screen.getByLabelText(/Электронная почта/i);
const submitButton = screen.getByRole('button', { name: /Отправить/i });
fireEvent.change(emailInput, { target: { value: 'invalid-email' } });
fireEvent.click(submitButton);
expect(screen.getByText(/Неверный формат электронной почты/i)).toBeInTheDocument();
});
Здесь проверяется, что при вводе неверного формата электронной почты появляется соответствующее сообщение об ошибке.
Иногда валидация формы включает асинхронные операции, такие как
проверка на уникальность логина или электронного адреса через API. Для
таких случаев Jest предоставляет возможность работать с асинхронным
кодом с использованием async/await.
Пример теста для асинхронной проверки доступности email:
test('проверка доступности email через API', async () => {
render(<MyForm />);
const emailInput = screen.getByLabelText(/Электронная почта/i);
const submitButton = screen.getByRole('button', { name: /Отправить/i });
fireEvent.change(emailInput, { target: { value: 'test@example.com' } });
fireEvent.click(submitButton);
const emailTakenMessage = await screen.findByText(/Этот email уже занят/i);
expect(emailTakenMessage).toBeInTheDocument();
});
Здесь мы моделируем ввод уже занятый email и проверяем, что форма возвращает правильное сообщение об ошибке после асинхронной проверки.
После того как все поля прошли валидацию, необходимо проверить сам процесс отправки формы. В Jest для этого можно использовать мок-функции, которые будут симулировать успешную или неудачную отправку данных.
Пример теста для успешной отправки формы:
test('успешная отправка формы', async () => {
const mockSubmit = jest.fn().mockResolvedValue({ success: true });
render(<MyForm onSub mit={mockSubmit} />);
const nameInput = screen.getByLabelText(/Имя/i);
const emailInput = screen.getByLabelText(/Электронная почта/i);
const submitButton = screen.getByRole('button', { name: /Отправить/i });
fireEvent.change(nameInput, { target: { value: 'John Doe' } });
fireEvent.change(emailInput, { target: { value: 'john.doe@example.com' } });
fireEvent.click(submitButton);
expect(mockSubmit).toHaveBeenCalledWith({ name: 'John Doe', email: 'john.doe@example.com' });
expect(await screen.findByText(/Форма успешно отправлена/i)).toBeInTheDocument();
});
Этот тест проверяет, что после заполнения формы и отправки она вызывает правильную функцию с нужными данными, а также показывает сообщение об успешной отправке.
Важно проверять, как форма реагирует на изменения состояний, например, показывается ли индикатор загрузки, когда форма отправляется, или правильно ли отключается кнопка отправки, если форма невалидна.
Пример теста для проверки кнопки отправки в зависимости от состояния формы:
test('кнопка отправки отключена при невалидных данных', () => {
render(<MyForm />);
const submitButton = screen.getByRole('button', { name: /Отправить/i });
expect(submitButton).toBeDisabled();
const nameInput = screen.getByLabelText(/Имя/i);
fireEvent.change(nameInput, { target: { value: 'John Doe' } });
expect(submitButton).toBeDisabled();
const emailInput = screen.getByLabelText(/Электронная почта/i);
fireEvent.change(emailInput, { target: { value: 'john.doe@example.com' } });
expect(submitButton).toBeEnabled();
});
Здесь проверяется, что кнопка отправки остается отключенной до тех пор, пока все обязательные поля не будут заполнены корректно.
Для улучшения тестов и работы с асинхронными функциями можно
использовать шпионов (jest.fn()), которые позволяют
отслеживать вызовы функций. Это полезно, например, для проверки,
вызывается ли функция валидации, отправки данных и т.д.
Пример использования шпиона:
test('проверка вызова функции валидации', () => {
const validateEmail = jest.fn();
render(<MyForm validateEmail={validateEmail} />);
const emailInput = screen.getByLabelText(/Электронная почта/i);
fireEvent.change(emailInput, { target: { value: 'invalid-email' } });
expect(validateEmail).toHaveBeenCalledWith('invalid-email');
});
Такой подход позволяет точно отслеживать, какие функции и когда были вызваны, что помогает в тестировании сложных взаимодействий.
При тестировании форм важным моментом является имитация реальных
пользовательских действий, таких как изменение значений в полях, клик по
кнопкам и т.д. Использование методов fireEvent и
userEvent позволяет точно воспроизводить поведение
пользователя.
Пример использования userEvent:
import userEvent from '@testing-library/user-event';
test('проверка ввода в поле и отправки формы', async () => {
render(<MyForm />);
const nameInput = screen.getByLabelText(/Имя/i);
const emailInput = screen.getByLabelText(/Электронная почта/i);
const submitButton = screen.getByRole('button', { name: /Отправить/i });
await userEvent.type(nameInput, 'Jane Doe');
await userEvent.type(emailInput, 'jane.doe@example.com');
await userEvent.click(submitButton);
expect(await screen.findByText(/Форма успешно отправлена/i)).toBeInTheDocument();
});
Использование userEvent помогает симулировать реальные
действия пользователя с большей точностью по сравнению с
fireEvent, что делает тесты более реалистичными.
Тестирование форм с использованием Jest требует внимательности к деталям, так как необходимо проверять не только рендеринг и валидацию, но и асинхронные операции, взаимодействие с сервером и состояние UI. Использование Jest вместе с React Testing Library и других ут