Accessibility тесты

Radix UI — библиотека компонентов для React, ориентированная на создание доступных интерфейсов (accessible UI). Одним из ключевых преимуществ Radix является встроенная поддержка ARIA-атрибутов, правильного фокусирования и управления клавиатурой. Это делает компоненты удобными для тестирования на соответствие стандартам доступности, таким как WCAG и WAI-ARIA.


Основные принципы тестирования доступности

  1. ARIA-атрибуты Компоненты Radix автоматически включают необходимые ARIA-атрибуты, например:

    • role="dialog" для модальных окон
    • aria-expanded и aria-controls для выпадающих списков
    • aria-checked для чекбоксов и радио-кнопок

    Тесты должны проверять наличие этих атрибутов и их корректное обновление при взаимодействии пользователя.

  2. Управление фокусом Radix заботится о правильной навигации с клавиатуры:

    • Tab перемещает фокус по интерактивным элементам
    • Escape закрывает диалоговые окна и меню
    • ArrowUp/ArrowDown управляют выбором в списках

    Тесты должны эмулировать нажатия клавиш и проверять, что фокус перемещается корректно.

  3. Состояние компонентов Важно проверять, что визуальные изменения компонентов сопровождаются соответствующими ARIA-состояниями. Например:

    • В выпадающем списке DropdownMenu.Item при выборе элемента aria-selected устанавливается в true
    • В Toggle состояние on/off отражается в aria-pressed

Инструменты для accessibility тестов

Jest + React Testing Library Radix UI прекрасно интегрируется с React Testing Library (RTL). Примеры:

import { render, screen, fireEvent } from '@testing-library/react';
import { Dialog, DialogTrigger, DialogContent } from '@radix-ui/react-dialog';

test('Dialog открывается и закрывается с клавиатуры', () => {
  render(
    <Dialog>
      <DialogTrigger>Открыть диалог</DialogTrigger>
      <DialogContent>Содержимое диалога</DialogContent>
    </Dialog>
  );

  const trigger = screen.getByText('Открыть диалог');
  fireEvent.click(trigger);

  const content = screen.getByText('Содержимое диалога');
  expect(content).toHaveAttribute('role', 'dialog');

  fireEvent.keyDown(content, { key: 'Escape' });
  expect(content).not.toBeInTheDocument();
});

axe-core / jest-axe Для автоматизированной проверки доступности часто используют axe-core:

import { render } from '@testing-library/react';
import { axe } from 'jest-axe';
import { Checkbox } from '@radix-ui/react-checkbox';

test('Checkbox соответствует стандартам доступности', async () => {
  const { container } = render(<Checkbox />);
  const results = await axe(container);
  expect(results).toHaveNoViolations();
});

Эти инструменты позволяют находить пропущенные ARIA-атрибуты, проблемы с фокусом и контрастностью.


Тестирование клавиатурной навигации

Radix UI предоставляет предсказуемые схемы навигации, которые легко тестировать:

  1. Списки и меню

    • ArrowDown/ArrowUp для перемещения между элементами
    • Home/End для быстрого перехода к началу или концу списка

    Тест проверяет корректность установки фокуса и изменения состояний элементов.

  2. Модальные окна

    • При открытии диалога фокус автоматически переносится на первый интерактивный элемент
    • Закрытие возвращает фокус к элементу-триггеру

    Тестирование включает последовательное эмулирование нажатий клавиш Tab, Shift+Tab и Escape.

  3. Тогглы и чекбоксы

    • Space или Enter переключают состояние компонента
    • Проверка правильного отражения состояния через ARIA (aria-checked, aria-pressed)

Интеграционные и end-to-end тесты

Для комплексной проверки можно использовать Cypress или Playwright:

describe('DropdownMenu accessibility', () => {
  it('allows keyboard navigation', () => {
    cy.visit('/dropdown-page');
    cy.get('[data-radix-dropdown-trigger]').focus().type('{enter}');
    cy.get('[role="menuitem"]').first().should('have.focus');
    cy.focused().type('{downarrow}');
    cy.focused().should('contain.text', 'Второй элемент');
  });
});

Такие тесты проверяют реальное поведение компонентов в браузере и гарантируют, что доступность сохраняется не только на уровне DOM, но и при взаимодействии пользователя.


Контроль изменений при обновлениях

Radix UI активно развивается, поэтому важно включать accessibility тесты в CI/CD-пайплайн. Это позволяет автоматически выявлять регрессии, когда новые версии компонентов могут изменить ARIA-атрибуты или поведение клавиатурной навигации.

Советы по поддержанию тестов:

  • Использовать отдельный тестовый файл для accessibility каждого компонента
  • Автоматически запускать axe на всех рендеренных компонентах
  • Проверять фокус и состояния после каждой интерактивной операции

Особенности тестирования динамических компонентов

Некоторые компоненты Radix UI, такие как Popover, Tooltip и Toast, появляются и исчезают динамически. Для них важно:

  1. Проверка рендера в DOM после открытия
  2. Проверка атрибутов ARIA (aria-hidden, role)
  3. Проверка доступности контента для скринридеров
  4. Эмуляция клавиатурных событий, чтобы убедиться, что закрытие и открытие корректно управляют фокусом

Выводы по практическому подходу

Radix UI обеспечивает высокий уровень доступности “из коробки”, но для гарантии соответствия стандартам необходимо:

  • Проверять ARIA-атрибуты и состояния интерактивных элементов
  • Тестировать фокус и клавиатурную навигацию
  • Использовать инструменты вроде axe, React Testing Library и Cypress
  • Интегрировать accessibility тесты в CI/CD

Правильная комбинация unit-, integration- и end-to-end тестов позволяет уверенно использовать Radix UI для создания доступных интерфейсов, минимизируя риск ошибок в доступности при обновлениях или расширении функциональности.