Автоматизированные тесты a11y

React Aria предоставляет набор хуков и утилит для создания доступных компонентов интерфейса. Одним из ключевых аспектов работы с доступностью является автоматизированное тестирование a11y — проверка компонентов на соответствие стандартам доступности без ручного вмешательства.

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

Автоматизированные тесты a11y делятся на три уровня:

  1. Статический анализ разметки (Linting) Используются линтеры, такие как eslint-plugin-jsx-a11y. Они анализируют JSX и предупреждают о потенциальных нарушениях доступности, например:

    • отсутствующие aria-label для интерактивных элементов,
    • использование <div> вместо семантических кнопок,
    • некорректное сочетание role и дочерних элементов.

    Пример конфигурации ESLint:

    {
      "plugins": ["jsx-a11y"],
      "extends": ["plugin:jsx-a11y/recommended"]
    }
  2. Тестирование через утилиты для рендеринга компонентов Библиотеки @testing-library/react и @testing-library/jest-dom позволяют рендерить компоненты в тестовой среде и проверять их на наличие атрибутов доступности, таких как:

    • aria-label,
    • aria-hidden,
    • aria-labelledby,
    • фокусируемость элементов.

    Пример теста для кнопки с React Aria:

    import { render, screen } from '@testing-library/react';
    import { useButton } from '@react-aria/button';
    
    function MyButton(props) {
      let ref = React.useRef();
      let { buttonProps } = useButton(props, ref);
      return <button {...buttonProps} ref={ref}>{props.children}</button>;
    }
    
    test('кнопка имеет правильный aria-атрибут', () => {
      render(<MyButton aria-label="Отправить форму">Отправить</MyButton>);
      const button = screen.getByRole('button', { name: 'Отправить форму' });
      expect(button).toBeInTheDocument();
    });
  3. Использование специализированных a11y-сканеров Инструменты вроде axe-core или jest-axe позволяют интегрировать автоматическую проверку доступности в CI/CD:

    import { render } from '@testing-library/react';
    import { axe, toHaveNoViolations } from 'jest-axe';
    import MyButton from './MyButton';
    
    expect.extend(toHaveNoViolations);
    
    test('компонент не имеет нарушений доступности', async () => {
      const { container } = render(<MyButton>Отправить</MyButton>);
      const results = await axe(container);
      expect(results).toHaveNoViolations();
    });

Особенности тестирования компонентов React Aria

  • Фокус и клавиатурная навигация Многие хуки React Aria управляют состоянием фокуса и обработкой клавиатурных событий (useFocus, useKeyboard). Автоматизированные тесты должны имитировать события клавиатуры и проверять правильность управления фокусом:

    import { fireEvent } from '@testing-library/react';
    
    test('фокус переходит на кнопку по Tab', () => {
      render(<MyButton>Отправить</MyButton>);
      const button = screen.getByRole('button');
      button.focus();
      expect(document.activeElement).toBe(button);
      fireEvent.keyDown(button, { key: 'Enter', code: 'Enter' });
      // проверка реакции на Enter
    });
  • ARIA состояния и свойства React Aria динамически управляет состояниями, такими как aria-checked, aria-expanded, aria-selected. Тесты должны проверять их корректное обновление при взаимодействии:

    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}>{isSelected ? 'Вкл' : 'Выкл'}</button>;
    }
    
    test('кнопка toggle меняет aria-checked', () => {
      const handleChange = jest.fn();
      render(<ToggleButton isSelected={false} onCha nge={handleChange} />);
      const button = screen.getByRole('button');
      expect(button).toHaveAttribute('aria-checked', 'false');
      fireEvent.click(button);
      expect(handleChange).toHaveBeenCalled();
    });

Интеграция a11y-тестов в CI/CD

  • Подключение jest-axe или cypress-axe позволяет запускать проверку доступности на каждом этапе сборки.
  • Создание отдельных тестов a11y помогает поддерживать стандарты доступности при добавлении новых компонентов.
  • Настройка линтеров и автоматических проверок предотвращает появление ошибок ещё на этапе разработки.

Рекомендации по повышению эффективности тестов

  • Использовать семантические элементы и минимизировать кастомные контейнеры, чтобы автоматические проверки были более точными.
  • Проверять все интерактивные элементы, включая модальные окна, панели навигации и кастомные списки.
  • Включать сценарии клавиатурной навигации и управления фокусом.
  • Регулярно обновлять библиотеки axe-core и @testing-library/react для поддержки последних стандартов доступности.

Автоматизированные тесты a11y в связке с React Aria позволяют не только выявлять нарушения, но и гарантировать, что компоненты остаются доступными на всех этапах разработки и в сложных интерфейсах.