Cypress и axe-core

Библиотека axe-core является стандартным инструментом для автоматической проверки доступности веб-приложений. Она реализует рекомендации WCAG (Web Content Accessibility Guidelines) и позволяет выявлять нарушения, связанные с цветовым контрастом, семантикой HTML, фокусом клавиатуры и другими аспектами доступности.

Cypress, как фреймворк для end-to-end тестирования, обеспечивает удобную среду для запуска тестов в браузере. Совмещение Cypress с axe-core позволяет интегрировать автоматическую проверку доступности в процессы CI/CD.


Установка и настройка

Для использования axe-core с Cypress требуется установка двух пакетов:

npm install --save-dev cypress
npm install --save-dev cypress-axe
  • cypress – основной фреймворк для тестирования.
  • cypress-axe – обертка для интеграции axe-core с Cypress.

После установки необходимо подключить cypress-axe в файле cypress/support/e2e.js:

import 'cypress-axe';

Это позволяет использовать команды injectAxe и checkA11y в тестах.


Основные команды

cy.injectAxe()

Эта команда внедряет скрипт axe-core в текущую страницу. Она должна вызываться после того, как страница полностью загружена:

cy.visit('/login');
cy.injectAxe();
  • Важно: скрипт axe-core должен быть внедрен после загрузки всех динамических компонентов, иначе проверки будут неполными.

cy.checkA11y(context, options, violationCallback)

Команда выполняет проверку доступности. Параметры:

  • context (необязательный) – селектор или DOM-элемент, для которого проводится проверка. Если не указан, проверяется весь документ.
  • options (необязательный) – объект конфигурации axe-core, например, для отключения отдельных правил.
  • violationCallback (необязательный) – функция обратного вызова, вызываемая при обнаружении нарушений.

Пример:

cy.checkA11y(null, {
  runOnly: {
    type: 'tag',
    values: ['wcag2a', 'wcag2aa']
  }
}, (violations) => {
  if (violations.length) {
    cy.log(`${violations.length} нарушений доступности обнаружено`);
    violations.forEach(v => {
      cy.log(`Элемент: ${v.nodes.map(n => n.target).join(', ')} - ${v.help}`);
    });
  }
});
  • runOnly позволяет ограничить проверку конкретными категориями WCAG.
  • violations содержит подробную информацию о каждом нарушении: целевой элемент, описание ошибки, рекомендации по исправлению.

Настройка фильтрации и исключений

Для сложных интерфейсов может потребоваться исключить определённые элементы из проверки:

cy.checkA11y('.main-content', {
  exclude: ['.advertisement', '#promo-banner']
});
  • exclude – массив селекторов, которые будут пропущены.
  • Можно комбинировать с include, чтобы проверять только конкретные части страницы.

Также можно отключать отдельные правила:

cy.checkA11y(null, {
  rules: {
    'color-contrast': { enabled: false },
    'label': { enabled: true }
  }
});

Интеграция с Cypress-тестами

Рекомендуется вызывать cy.injectAxe() в блоке beforeEach, чтобы скрипт axe-core был внедрён перед каждой проверкой:

describe('Тестирование доступности страницы логина', () => {
  beforeEach(() => {
    cy.visit('/login');
    cy.injectAxe();
  });

  it('Страница соответствует стандартам WCAG 2.1', () => {
    cy.checkA11y();
  });
});
  • Это обеспечивает автоматическую проверку после каждой загрузки страницы.
  • Легко масштабируется на многостраничные приложения.

Настройка отчётности

violationCallback можно использовать для генерации детализированных отчётов. Например, для CI/CD удобно выводить результаты в консоль в структурированном виде или сохранять в файл JSON:

cy.checkA11y(null, {}, (violations) => {
  const results = violations.map(v => ({
    id: v.id,
    impact: v.impact,
    description: v.description,
    elements: v.nodes.map(n => n.target)
  }));
  cy.writeFile('cypress/reports/accessibility.json', results);
});
  • Сохранённый JSON позволяет интегрировать данные с внешними системами отчётности.
  • Можно фильтровать по impact (critical, serious, moderate, minor) для приоритизации исправлений.

Отладка и локальное тестирование

Для визуальной отладки удобно использовать команду cy.checkA11y с выделением нарушений на странице:

cy.checkA11y(null, {}, (violations) => {
  violations.forEach(v => {
    v.nodes.forEach(n => {
      Cypress.$(n.target).css('outline', '3px solid red');
    });
  });
});
  • Подсветка элементов помогает быстро определить проблемные зоны интерфейса.
  • Можно временно включать только на локальном окружении, исключая из CI/CD.

Поддержка динамического контента

Для компонентов, которые загружаются асинхронно (React, Vue, Angular), необходимо вызывать cy.checkA11y после завершения рендеринга:

cy.get('#dynamic-component').should('be.visible');
cy.checkA11y('#dynamic-component');
  • should('be.visible') гарантирует, что axe-core проверяет окончательное состояние DOM.
  • Позволяет избегать ложных срабатываний на незагруженные элементы.

Расширенные возможности

  • Тестирование отдельных правил: можно проверять только color-contrast или aria-roles.
  • Локальные конфигурации axe-core: позволяют сохранять набор правил для конкретного проекта.
  • Интеграция с CI/CD: Cypress + axe-core легко подключаются к GitHub Actions, GitLab CI, Jenkins для автоматической проверки на каждом пуше.

Использование axe-core совместно с Cypress обеспечивает системный подход к проверке доступности, позволяет выявлять ошибки на ранних этапах и поддерживать соответствие стандартам WCAG в масштабных веб-приложениях.