Навигация с клавиатуры является важным аспектом доступности
веб-приложений. Клавиша Tab позволяет пользователю
перемещаться между интерактивными элементами страницы, такими как
кнопки, ссылки, поля ввода и другие элементы формы. В React Testing
Library моделирование такого поведения позволяет проверить не только
корректность работы компонентов, но и соблюдение принципов
accessibility (a11y).
Порядок фокуса Элементы получают фокус в порядке
их появления в DOM, если явно не указано поведение через
tabIndex.
tabIndex=0 — элемент включается в естественный порядок
табуляции.tabIndex>0 — элемент получает приоритет перед
элементами с tabIndex=0.tabIndex<0 — элемент исключен из последовательности
табуляции, но может быть сфокусирован программно.Интерактивные элементы По умолчанию фокусируются:
<button><input> (включая textarea и
select)<a> с атрибутом hreftabIndex >= 0React Testing Library предоставляет утилиту
userEvent.tab() для имитации нажатия клавиши
Tab. Это позволяет проверять, как фокус перемещается между
элементами.
Пример базового теста:
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Form from './Form';
test('фокус перемещается по полям формы при Tab', async () => {
render(<Form />);
const user = userEvent.setup();
const inputName = screen.getByLabelText(/имя/i);
const inputEmail = screen.getByLabelText(/email/i);
const submitButton = screen.getByRole('button', { name: /отправить/i });
await user.tab();
expect(inputName).toHaveFocus();
await user.tab();
expect(inputEmail).toHaveFocus();
await user.tab();
expect(submitButton).toHaveFocus();
});
Ключевые моменты:
userEvent.setup() позволяет более
реалистично симулировать действия пользователя.toHaveFocus() подтверждает правильность
последовательности табуляции.Иногда порядок элементов в DOM не совпадает с ожидаемой
последовательностью. Для тестирования используется
tabIndex:
<div tabIndex={2}>Элемент A</div>
<div tabIndex={1}>Элемент B</div>
В тесте:
await user.tab();
expect(screen.getByText('Элемент B')).toHaveFocus();
await user.tab();
expect(screen.getByText('Элемент A')).toHaveFocus();
Это гарантирует, что фокус следует заданной последовательности, а не естественному порядку DOM.
При открытии модального окна фокус должен автоматически перемещаться внутрь модалки и быть замкнутым. Проверка Tab-навигации в модальных компонентах включает:
Tab и проверка циклического
обхода элементов внутри модалки.Пример:
const firstInput = screen.getByLabelText(/логин/i);
const lastButton = screen.getByRole('button', { name: /отмена/i });
await user.tab();
expect(firstInput).toHaveFocus();
await user.tab();
expect(lastButton).toHaveFocus();
await user.tab();
expect(firstInput).toHaveFocus(); // фокус замкнулся
Для проверки обратного обхода используется
user.tab({ shift: true }):
await user.tab({ shift: true });
expect(lastButton).toHaveFocus();
Это критично для доступности, чтобы пользователь мог перемещаться по элементам как вперед, так и назад.
display: none и visibility: hidden
исключают элемент из последовательности Tab.disabled не получают фокус.user.tab() только если они доступны в DOM и имеют
tabIndex.Для компонентов типа таблиц, списков с динамическим содержимым или кастомных кнопок важно:
Пример для кастомного компонента кнопок:
const buttons = screen.getAllByRole('button');
await user.tab();
expect(buttons[0]).toHaveFocus();
await user.tab();
expect(buttons[1]).toHaveFocus();
beforeEach для рендеринга компонента и
инициализации userEvent.Навигация с помощью клавиши Tab в тестах React Testing Library является мощным инструментом для проверки доступности и корректной работы интерфейсов. Она позволяет гарантировать, что пользовательский опыт будет одинаково качественным как при мыши, так и при клавиатуре.