Testing Library для Vue: тесты с позиции пользователя
↑ 4.1 Vue 3: основы, компоненты, Composition API · ← Предыдущая · → Следующая
Зачем это на собесе
Подход «тестируйте как пользователь»: доступные селекторы и устойчивость к рефакторингу.
Объяснение
@testing-library/vue — обёртка над VTU с принципом: тесты должны напоминать то, как пользователь работает с интерфейсом. Ищем элементы по роли, тексту, label — а не по классам и внутренней структуре.
import { render, screen, within, waitFor } from "@testing-library/vue";
import userEvent from "@testing-library/user-event";
it("добавляет заказ через форму", async () => {
const user = userEvent.setup();
const onSubmit = vi.fn();
render(OrderForm, { props: { onSubmit }, global: { plugins: [pinia] } });
await user.type(screen.getByLabelText("Клиент"), "Иванов");
await user.selectOptions(screen.getByRole("combobox", { name: "Статус" }), "paid");
await user.click(screen.getByRole("button", { name: /сохранить/i }));
expect(onSubmit).toHaveBeenCalledWith(expect.objectContaining({ customer: "Иванов" }));
expect(await screen.findByText("Сохранено")).toBeInTheDocument(); // findBy = ожидание появления
expect(screen.queryByRole("alert")).not.toBeInTheDocument(); // queryBy = отсутствие
});Приоритет запросов (от предпочтительных):
| Запрос | Когда |
|---|---|
getByRole(role, { name }) | всё, что имеет роль (кнопки, поля, заголовки): проверяет и доступность |
getByLabelText | поля форм |
getByPlaceholderText, getByText | текстовое содержимое |
getByDisplayValue, getByAltText, getByTitle | специфические случаи |
getByTestId | последнее средство |
Варианты запросов: getBy (сразу, бросает при отсутствии), queryBy (для проверки отсутствия), findBy (асинхронно с ожиданием), *AllBy. waitFor — повторные проверки; within(el) — поиск внутри области. Матчеры @testing-library/jest-dom: toBeInTheDocument, toBeVisible, toBeDisabled, toHaveValue, toHaveAccessibleName.
Плюсы: тесты устойчивы к рефакторингу, побочно проверяют доступность (роли и label); минус — нужны доступные разметка и названия.
Нюансы и подводные камни
userEvent(реалистичные последовательности событий) предпочтительнееfireEvent.- Не запрашивайте по классам и структуре DOM.
- Не используйте
waitForдля синхронных проверок. - Для дат/таймеров — фейковые таймеры и
advanceTimersвuserEvent.setup. - Много
getByTestId— признак недоступной разметки.
Практика
- Перепишите тест формы с VTU на Testing Library.
- Проверьте доступность через
getByRoleи name. - Протестируйте асинхронное появление уведомления через
findBy.
Вопросы с ответами
В чём философия Testing Library?
Тестировать поведение с позиции пользователя, используя доступные селекторы, а не детали реализации.
getBy,queryBy,findBy— разница?
getByсразу и бросает,queryByвозвращаетnull(для отсутствия),findByждёт появления.