Почему важно тестировать события пользователя?
Наши приложения — это не скучный статичный HTML. Их оживляют клики, набор текста, фокус. Поэтому важно убедиться, что всё это работает корректно, иначе пользователь, не получив ожидаемого результата, просто закроет вкладку и уйдёт.
Представьте: вы создали кнопку "Удалить всё", но из-за ошибки нажатие на неё делает что-то совершенно непредсказуемое, например, заказывает пиццу вашему начальнику. Тестируя пользовательские события, мы убеждаемся, что наше приложение реагирует на действия так, как задумано, без сюрпризов.
Основные инструменты: React Testing Library и fireEvent
Для тестирования взаимодействий мы будем использовать библиотеку React Testing Library и её инструмент fireEvent. React Testing Library предоставляет простую и понятную абстракцию для симуляции пользовательских действий, а fireEvent позволяет "прикидываться" пользователем, который кликает, вводит текст или перемещает фокус.
Мы будем использовать такие етоды из fireEvent:
fireEvent.click— симулирует клик по элементу.fireEvent.change— имитирует ввод данных в инпут или textarea.fireEvent.focusиfireEvent.blur— для проверки реакций на установку или потерю фокуса.
Давайте начнём с простого компонента для тестирования пользовательских взаимодействий:
// components/UserForm.tsx
import React, { useState } from "react";
interface UserFormProps {
onSubmit: (name: string) => void;
}
export const UserForm: React.FC<UserFormProps> = ({ onSubmit }) => {
const [name, setName] = useState("");
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSubmit(name);
};
return (
<form onSubmit={handleSubmit}>
<label htmlFor="name">Name:</label>
<input
id="name"
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
data-testid="name-input"
/>
<button type="submit" data-testid="submit-button">
Submit
</button>
</form>
);
};
Этот компонент состоит из текстового поля, кнопки и простого обработчика формы. При нажатии на кнопку вызывается переданная через пропс onSubmit функция.
Тестирование кликов
Начнём с тестирования кликов по кнопке в нашей форме.
// tests/UserForm.test.tsx
import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import { UserForm } from "../components/UserForm";
test("отправка формы при клике на кнопку", () => {
const mockOnSubmit = jest.fn(); // имитация переданной функции
render(<UserForm onSubmit={mockOnSubmit} />);
const button = screen.getByTestId("submit-button");
fireEvent.click(button);
expect(mockOnSubmit).toHaveBeenCalled(); // проверяем, что функция была вызвана
});
В этом тесте мы проверяем, вызывается ли переданная функция onSubmit при клике на кнопку. Для этого используем jest.fn() — мок-функцию, которая позволяет отслеживать вызовы.
Тестирование ввода текста
Теперь протестируем, как наш компонент обрабатывает ввод текста в поле. Мы будем использовать fireEvent.change.
test("обновление состояния при вводе текста", () => {
const mockOnSubmit = jest.fn();
render(<UserForm onSubmit={mockOnSubmit} />);
const input = screen.getByTestId("name-input");
fireEvent.change(input, { target: { value: "John Doe" } });
expect(input).toHaveValue("John Doe"); // проверяем, что значение обновилось
});
В данном тесте fireEvent.change имитирует ввод текста "John Doe". После этого мы проверяем, что значение инпута действительно изменилось, используя метод toHaveValue.
Тестирование фокуса
Фокусировка элементов интерфейса играет большую роль в доступности приложения. Проверим, корректно ли компонент реагирует на установку и потерю фокуса.
Мы добавим простую визуальную реакцию на фокус в компонент:
// Update in UserForm.tsx
const [isFocused, setIsFocused] = useState(false);
return (
<form onSubmit={handleSubmit}>
<label htmlFor="name">Name:</label>
<input
id="name"
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
data-testid="name-input"
/>
{isFocused && <p data-testid="focus-message">Input is focused</p>}
<button type="submit" data-testid="submit-button">
Submit
</button>
</form>
);
Новый тест на проверку фокуса:
test("проверка установки и потери фокуса", () => {
const mockOnSubmit = jest.fn();
render(<UserForm onSubmit={mockOnSubmit} />);
const input = screen.getByTestId("name-input");
fireEvent.focus(input);
expect(screen.getByTestId("focus-message")).toBeInTheDocument();
fireEvent.blur(input);
expect(screen.queryByTestId("focus-message")).not.toBeInTheDocument();
});
Мы используем fireEvent.focus, чтобы проверить появление текста "Input is focused". Затем, применяя fireEvent.blur, убеждаемся, что текст исчезает.
Типичные ошибки при тестировании событий
Тестирование событий пользователя может столкнуться с рядом подводных камней. Например, если вы забудете явно указать значения в объекте target при изменении данных с помощью fireEvent.change, то тест будет вести себя странно и не отразит реальных результатов.
Ещё одна ошибка — неверная цель. Убедитесь, что вы используете корректные селекторы, такие как getByTestId, чтобы находить нужные элементы. Например, использование getByText для элементов, которые могут изменять своё текстовое содержимое в процессе теста, не всегда надёжно.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ