Ответ
Тестирование Toggle-компонента требует проверки функциональности, UI/UX, доступности и интеграции.
1. Функциональное тестирование
- Базовое переключение: Изменение состояния с
falseнаtrueи обратно по клику. - Управление с клавиатуры: Активация через
Tabи переключение с помощьюSpaceилиEnter. - Связь с состоянием: Корректное обновление связанного значения в состоянии приложения (например, через React
useState). - Контролируемый/неконтролируемый режим: Работа как с внешним пропсом
checked, так и с внутренним состоянием.
2. Тестирование рендера и UI
- Соответствие дизайну: Визуальная правильность в обоих состояниях (цвет, позиция ползунка, подписи).
- Анимация: Плавность перехода (если есть) и её отсутствие при первоначальном рендере.
- Состояния: Отображение disabled-состояния (opacity, курсор
not-allowed).
3. Тестирование доступности (A11y)
- Семантическая разметка: Использование правильного ARIA-роля (
role="switch"). - Атрибуты: Наличие
aria-checked,aria-labelилиaria-labelledby. - Фокус: Видимый индикатор фокуса для клавиатурной навигации.
- Screen Readers: Корректное озвучивание состояния ("on", "off").
4. Интеграционное и E2E-тестирование
- Взаимодействие с бэкендом: При переключении должен отправляться корректный API-запрос (например, PATCH /settings).
- Сохранение состояния: После перезагрузки страницы позиция тоггла должна восстанавливаться.
Пример теста на React + Jest + Testing Library:
import { render, screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Toggle from './Toggle';
describe('Toggle Component', () => {
test('toggles state on click and updates aria-checked', () => {
render(<Toggle aria-label="Enable notifications" />);
const toggle = screen.getByRole('switch', { name: /enable notifications/i });
// Начальное состояние
expect(toggle).toHaveAttribute('aria-checked', 'false');
// Клик мышью
userEvent.click(toggle);
expect(toggle).toHaveAttribute('aria-checked', 'true');
// Переключение с клавиатуры
fireEvent.keyDown(toggle, { key: ' ', code: 'Space' });
expect(toggle).toHaveAttribute('aria-checked', 'false');
});
test('is disabled when disabled prop is passed', () => {
render(<Toggle disabled />);
const toggle = screen.getByRole('switch');
expect(toggle).toBeDisabled();
expect(toggle).toHaveStyle('cursor: not-allowed');
});
});