Тестирование доступности

React Aria — это библиотека, предоставляющая низкоуровневые хуки для создания доступных компонентов в React. Тестирование доступности является неотъемлемой частью разработки, поскольку обеспечивает соответствие интерфейса стандартам WCAG и удобство для пользователей с особыми потребностями.


Основные подходы к тестированию доступности

1. Автоматизированное тестирование с помощью инструментов React Aria можно интегрировать с библиотеками автоматизированного тестирования, такими как:

  • axe-core Позволяет выявлять ошибки доступности на уровне DOM. В сочетании с jest-axe можно создавать unit-тесты для компонентов React Aria.

    import { render } from '@testing-library/react';
    import { axe } from 'jest-axe';
    import { useButton } from '@react-aria/button';
    import React from 'react';
    
    function Button(props) {
      let ref = React.useRef();
      let { buttonProps } = useButton(props, ref);
      return <button {...buttonProps} ref={ref}>{props.children}</button>;
    }
    
    test('Button должен быть доступен', async () => {
      const { container } = render(<Button>Click me</Button>);
      const results = await axe(container);
      expect(results).toHaveNoViolations();
    });

    Здесь проверяется, что компонент корректно рендерится с атрибутами ARIA и не содержит ошибок доступности.

  • Testing Library @testing-library/react и @testing-library/user-event позволяют симулировать пользовательские взаимодействия с компонентами, что важно для проверки интерактивности и фокусного управления.

    import { render, screen } from '@testing-library/react';
    import userEvent from '@testing-library/user-event';
    import { useCheckbox } from '@react-aria/checkbox';
    
    function Checkbox(props) {
      let ref = React.useRef();
      let { inputProps } = useCheckbox(props, ref);
      return <input type="checkbox" {...inputProps} ref={ref} />;
    }
    
    test('Checkbox можно переключить с клавиатуры', async () => {
      render(<Checkbox />);
      const checkbox = screen.getByRole('checkbox');
      checkbox.focus();
      await userEvent.keyboard('{Space}');
      expect(checkbox).toBeChecked();
    });

2. Ручное тестирование с помощью вспомогательных технологий React Aria обеспечивает правильное управление фокусом, атрибутами aria-* и семантикой элементов, что облегчает тестирование с:

  • Экранными читалками (NVDA, VoiceOver)
  • Навигацией с клавиатуры
  • Псевдоустройствами для проверки контрастности и масштабирования текста

Проверка ARIA-атрибутов

React Aria автоматически добавляет большинство необходимых атрибутов. Основные моменты для тестирования:

  • role — корректное определение роли компонента (button, checkbox, menu, dialog)
  • aria-checked — синхронизация состояния для чекбоксов и радиокнопок
  • aria-disabled — блокировка элементов
  • aria-expanded / aria-controls — контроль раскрывающихся списков и меню
  • aria-label / aria-labelledby — текстовое описание элементов

Автоматические тесты могут проверять наличие этих атрибутов и соответствие их значения текущему состоянию компонента.

import { render, screen } from '@testing-library/react';
import { useToggleButton } from '@react-aria/button';

function ToggleButton({ isSelected, onChange }) {
  let ref = React.useRef();
  let { buttonProps } = useToggleButton({ isSelected, onChange }, ref);
  return <button {...buttonProps} ref={ref}>Toggle</button>;
}

test('ToggleButton корректно обновляет aria-pressed', () => {
  const { rerender } = render(<ToggleButton isSelected={false} onCha nge={() => {}} />);
  let button = screen.getByRole('button');
  expect(button).toHaveAttribute('aria-pressed', 'false');

  rerender(<ToggleButton isSelected={true} onCha nge={() => {}} />);
  button = screen.getByRole('button');
  expect(button).toHaveAttribute('aria-pressed', 'true');
});

Тестирование фокусного управления

React Aria обеспечивает автоматическое управление фокусом и навигацией с клавиатуры. Важно проверять:

  • Порядок табуляции (tabIndex)
  • Правильный перенос фокуса при открытии модальных окон или меню
  • Возможность управления элементами с помощью стрелок, пробела и Enter
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { useMenu } from '@react-aria/menu';
import { useMenuItem } from '@react-aria/menu';

function MenuItem({ children }) {
  let ref = React.useRef();
  let { menuItemProps } = useMenuItem({}, ref);
  return <div {...menuItemProps} ref={ref}>{children}</div>;
}

function Menu() {
  let ref = React.useRef();
  let { menuProps } = useMenu({}, ref);
  return (
    <div {...menuProps} ref={ref}>
      <MenuItem>Option 1</MenuItem>
      <MenuItem>Option 2</MenuItem>
    </div>
  );
}

test('Меню поддерживает навигацию с клавиатуры', async () => {
  render(<Menu />);
  const items = screen.getAllByRole('menuitem');
  items[0].focus();
  await userEvent.keyboard('{ArrowDown}');
  expect(items[1]).toHaveFocus();
});

Интеграция с CI/CD

Автоматические проверки доступности можно интегрировать в пайплайн CI/CD:

  • Выполнение jest-axe тестов при каждом pull request
  • Линтинг с использованием eslint-plugin-jsx-a11y
  • Генерация отчетов для отслеживания прогресса в исправлении нарушений доступности

Практические советы

  • Проверять компоненты на разных браузерах и устройствах, включая мобильные
  • Использовать Storybook вместе с @storybook/addon-a11y для визуального тестирования доступности
  • Не ограничиваться проверкой атрибутов ARIA: проверять также поведение и интерактивность

React Aria формирует основу доступного интерфейса, но полная проверка требует сочетания автоматических тестов, ручного тестирования и интеграции с пайплайном разработки.