5 идей для accessibility-тестов, которые можно автоматизировать уже сегодня
- вторник, 29 апреля 2025 г. в 00:00:04
 
В предыдущей статье рассмотрели, как быстро настроить Cypress и axe-core для запуска автоматических тестов доступности (подробнее здесь).
Теперь время перейти к практике. Какие именно проверки стоит автоматизировать в первую очередь? На каких ошибках доступности можно поймать проблемы ещё до выхода на продакшн?
В этой статье — 5 простых, но эффективных идей для автоматизированных accessibility-тестов, которые помогают системно повышать качество интерфейсов при минимальных затратах.
Базовая, но мощная проверка: подключить axe-core и запускать cy.checkA11y() на всех страницах.
Контрастность текста и фона на соответствие минимальным требованиям контраста по стандарту WCAG 2.1 (например, 4.5:1 для обычного текста).
Отсутствие альтернативного текста (alt) у изображений
Некорректное использование ARIA-атрибутов. Например: aria-labelledby, указывающий на несуществующий ID.
Ошибка семантической структуры. Например, используется div вместо кнопок без роли button
Проблемы фокусировки (tabindex, правильные фокусы).
Отсутствие описаний у интерактивных элементов ****для озвучки скринридерами.
Ошибки в использовании ролей (role).
Дублирование ID (мешает корректной навигации для скринридеров)
Недоступные элементы управления
describe('eBay - Home Page Accessibility', () => {
  it('Check for accessibility errors', () => {
    cy.visit('/');
    cy.axeAndCheck();
  });
});
Навигационное меню должно быть доступным с клавиатуры, иметь корректные role, aria-label, и быть видимым скринридеру. Проверки могут включать:
наличие nav или role="navigation"
проверку фокусировки по Tab
aria-expanded на раскрывающихся списках
describe('eBay - Navigation Accessibility', () => {
  it('Check that the main navigation is accessible', () => {
    cy.visit('/');
    // Проверяем наличие навигационного блока
    cy.get('nav, [role="navigation"]').should('exist');
    // Проверяем наличие aria-label у навигации
    cy.get('nav, [role="navigation"]')
      .should('have.attr', 'aria-label')
      .and('not.be.empty');
    // Проверяем фокусировку на первом элементе навигации через Tab
    cy.get('body').tab();
    cy.focused()
      .should('exist')
      .and(($el) => {
        const role = $el.attr('role') || '';
        expect(role === 'link' || role === 'button').to.be.true;
      });
    // Проверяем наличие aria-expanded на раскрывающихся элементах (если есть)
    cy.get('[aria-haspopup="true"]').each(($el) => {
      cy.wrap($el).should('have.attr', 'aria-expanded');
    });
  });
});Формы — один из самых частых источников A11y-багов. Автотесты могут проверить:
наличие aria-label / aria-labelledby на input'ах
aria-describedby на ошибках
role="alert" или aria-live для динамического вывода ошибок
describe('eBay - Form Fields Accessibility', () => {
  it('Check for accessibility attributes on the search input', () => {
    cy.visit('/');
    // Проверяем, что поле поиска имеет соответствующие атрибуты
    cy.get('input[placeholder="Search for anything"]')
      .should(($input) => {
        expect(
          $input.attr('aria-label') || $input.attr('aria-labelledby')
        ).to.exist;
      });
  });
  it('Check that error messages have aria-describedby or live regions', () => {
    cy.visit('/');
    // Имитируем неправильный поиск или некорректный ввод, если возможно
    cy.get('input[placeholder="Search for anything"]').type('{enter}');
    // Проверка ошибок (если есть ошибки поиска, сообщения, алерты)
    cy.get('body').then(($body) => {
      if ($body.find('[role="alert"], [aria-live]').length) {
        cy.get('[role="alert"], [aria-live]')
          .should('exist')
          .and('not.be.empty');
      } else {
        cy.log('No live error messages found (may not trigger without bad input)');
      }
    });
  });
});Пользователь должен иметь возможность перемещаться по всем интерактивным элементам с помощью Tab / Shift + Tab. Проверки могут включать:
наличие видимого фокуса (outline)
правильный порядок фокусировки
отсутствие «ловушек», где фокус застревает.
Для этих проверок нам понадобится дополнительный плагин - cypress-plugin-tab
Cypress по умолчанию не поддерживает событие нажатия клавиши Tab как пользовательскую навигацию между элементами.
Плагин cypress-plugin-tab добавляет команду .tab(), которая эмулирует реальное нажатие клавиши Tab, обеспечивая правильную навигацию по фокусируемым элементам страницы.
import 'cypress-plugin-tab';
describe('Keyboard Focus - eBay homepage', () => {
it('Check that keyboard focus moves correctly and visibly', () => {
cy.visit('/');
// Начинаем с body
cy.get('body').tab();
// Проверяем, что фокус на интерактивном элементе
cy.focused()
  .should('exist')
  .and(($el) => {
    // Проверяем, что это ссылка, кнопка или другое интерактивное
    const tag = $el.prop('tagName').toLowerCase();
    expect(['a', 'button', 'input', 'select', 'textarea']).to.include(tag);
  });
// Проверяем, что фокус визуально виден (outline)
cy.focused().should('have.css', 'outline-style').and('not.eq', 'none');
// Дополнительно: пройти Tab несколько раз и убедиться, что переход есть
for (let i = 0; i < 5; i++) {
  cy.focused().tab();
  cy.focused().should('exist');
}
});
});Важно, чтобы модальные окна:
перехватывали фокус при открытии,
имели aria-modal, aria-labelledby,
корректно скрывались и возвращали фокус.
describe('eBay - Modal Accessibility', () => {
it('Check modal accessibility and focus trapping', () => {
cy.visit('/');
// Открываем модальное окно (например, вход в аккаунт или фильтры поиска)
cy.get('[data-testid="open-modal"]').click();
// Проверяем, что модальное окно открыто и имеет aria-modal
cy.get('[role="dialog"]')
  .should('exist')
  .and('have.attr', 'aria-modal', 'true');
// Проверяем наличие заголовка для модального окна
cy.get('[role="dialog"]').should('have.attr', 'aria-labelledby');
// Проверяем, что фокус переходит внутрь модального окна
cy.focused().should('exist');
cy.get('[role="dialog"]').then(($dialog) => {
  expect($dialog[0].contains(document.activeElement)).to.be.true;
});
});
});Автоматизация доступности — это не замена ручному тестированию, а надёжный фундамент. Даже 1–2 простых проверки, встроенные в CI, уже заметно повышают качество продукта.
В этой статье рассмотрели реальные сценарии автоматизированных проверок:
Структуры и семантики страниц
Наличия альтернативного текста и корректных aria-атрибутов
Проверку фокусировки клавиатурой
Доступность динамических компонентов, таких как модальные окна и уведомления
Автоматизация позволяет находить большинство технических ошибок на ранних этапах, но не отменяет важность ручного тестирования скринридерами и проверки логики взаимодействия.
Начать стоит с базовых тестов для ключевых страниц, постепенно расширяя покрытие на новые фичи и сценарии. Даже один тест на доступность — вклад в создание инклюзивного интернета.