React Aria предоставляет набор хуков и утилит для создания доступных
компонентов пользовательского интерфейса. Тестирование этих компонентов
требует особого внимания к взаимодействиям, которые реализуются через
хуки useButton, useCheckbox,
useMenu, useSlider и другие. Основной целью
тестирования является не только проверка визуального рендеринга, но и
корректное поведение с точки зрения доступности (accessibility,
a11y).
Проверка событий клавиатуры Большинство компонентов React Aria должны корректно реагировать на стандартные клавиши:
Enter и Space для активации кнопок или
элементов списка.ArrowUp/ArrowDown для перемещения
по элементам меню или слайдера.Tab и Shift+Tab для навигации между
фокусируемыми элементами.При тестировании необходимо использовать утилиты вроде
@testing-library/user-event для симуляции этих событий.
Например:
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Button } from './Button';
test('кнопка активируется по Enter', async () => {
render(<Button>Нажми меня</Button>);
const btn = screen.getByRole('button');
btn.focus();
await userEvent.keyboard('{Enter}');
expect(btn).toHaveAttribute('aria-pressed', 'true');
});
Этот подход гарантирует, что компонент правильно обрабатывает события клавиатуры, а атрибуты ARIA обновляются корректно.
Тестирование состояния компонентов React Aria
часто управляет состоянием через хуки вроде useToggleState
или useSelectableCollection. Тесты должны проверять:
checked для
чекбокса),aria-checked, aria-selected).Пример для чекбокса:
import { Checkbox } from './Checkbox';
test('чекбокс переключается по клику', async () => {
render(<Checkbox>Согласен</Checkbox>);
const checkbox = screen.getByRole('checkbox');
expect(checkbox).not.toBeChecked();
await userEvent.click(checkbox);
expect(checkbox).toBeChecked();
});
Такой тест проверяет не только визуальное поведение, но и корректность ARIA-свойств.
Фокус и порядок табуляции Для доступных интерфейсов критично, чтобы фокус перемещался по логическому порядку. Тестирование фокуса включает:
Tab и
Shift+Tab,Пример теста модального диалога:
import { Dialog } from './Dialog';
test('фокус возвращается после закрытия диалога', async () => {
render(<Dialog isOpen={true}><button>Закрыть</button></Dialog>);
const closeBtn = screen.getByRole('button', { name: /закрыть/i });
closeBtn.focus();
await userEvent.keyboard('{Escape}');
expect(document.activeElement).toBe(document.body);
});React Aria предоставляет хуки для управляемых коллекций
(useListState, useSelectionManager). Основные
сценарии тестирования:
singleSelect), так и множественного выбора
(multiSelect).aria-selected, aria-activedescendant.Пример теста для списка с множественным выбором:
import { ListBox } from './ListBox';
test('мультивыбор элементов через клавиатуру', async () => {
render(<ListBox multiSelect options={['A', 'B', 'C']} />);
const items = screen.getAllByRole('option');
items[0].focus();
await userEvent.keyboard('{Space}');
items[1].focus();
await userEvent.keyboard('{Space}');
expect(items[0]).toHaveAttribute('aria-selected', 'true');
expect(items[1]).toHaveAttribute('aria-selected', 'true');
});
act для асинхронных эффектовМногие хуки React Aria используют внутренние состояния и эффекты,
которые могут обновляться асинхронно. Для корректного тестирования
необходимо оборачивать события в act:
import { act } from 'react-dom/test-utils';
act(() => {
userEvent.click(button);
});
Это предотвращает предупреждения о “необработанных обновлениях состояния” и обеспечивает точные проверки DOM.
Тестирование взаимодействий тесно связано с доступностью. Основные подходы:
aria-pressed,
aria-expanded, aria-label).role="button",
role="menuitem").jest-axe для
автоматической проверки a11y.Пример интеграции jest-axe:
import { axe } from 'jest-axe';
test('кнопка соответствует требованиям доступности', async () => {
const { container } = render(<Button>Нажми</Button>);
const results = await axe(container);
expect(results).toHaveNoViolations();
});
Такой подход гарантирует, что компоненты React Aria будут надежными, предсказуемыми и полностью доступными во всех сценариях взаимодействия.