Проверка после событий

Библиотека Axe-core обеспечивает мощные средства для автоматизированного тестирования доступности веб-приложений. Одной из ключевых особенностей является возможность выполнения проверок после событий, что позволяет анализировать состояние страницы после динамических изменений, таких как открытие модальных окон, изменение контента через JavaScript или реакцию на пользовательские действия.


Подключение и инициализация

Для работы с Axe-core в JavaScript проекте используется пакет axe-core, который можно подключить через npm:

import axe from 'axe-core';

// или для Node.js с require
const axe = require('axe-core');

Инициализация проводится обычно на корневом элементе документа:

const context = document.body; // Контекст проверки — вся страница
const options = {
  runOnly: ['wcag2a', 'wcag2aa'], // Ограничение правил
  rules: {
    'color-contrast': { enabled: true }
  }
};

axe.run(context, options).then(results => {
  console.log(results.violations);
});

Основы проверки после событий

Проверка после событий подразумевает два этапа:

  1. Вызов события – симуляция пользовательского действия или ожидание события на странице.
  2. Выполнение сканирования Axe-core – анализ DOM после внесённых изменений.

Пример: открытие модального окна и проверка его доступности:

// Триггер события открытия модального окна
const modalButton = document.querySelector('#openModal');
modalButton.click();

// Использование setTimeout или MutationObserver для ожидания изменений
setTimeout(() => {
  axe.run(document.getElementById('modal'), {}, (err, results) => {
    if (err) throw err;
    console.log(results.violations);
  });
}, 500);

Ключевой момент: Axe-core проверяет текущий DOM, поэтому важно дождаться полного рендеринга элементов, появившихся после события.


Использование MutationObserver для динамических изменений

Для отслеживания изменения DOM и автоматического запуска проверок удобно использовать MutationObserver:

const targetNode = document.body;
const config = { childList: true, subtree: true };

const callback = (mutationsList) => {
  for (const mutation of mutationsList) {
    if (mutation.addedNodes.length) {
      axe.run(document.body).then(results => {
        console.log(results.violations);
      });
    }
  }
};

const observer = new MutationObserver(callback);
observer.observe(targetNode, config);

Преимущество такого подхода — проверка запускается автоматически при добавлении новых элементов в DOM, без необходимости ручного тайм-аута.


Асинхронная интеграция с фреймворками

В современных фронтенд-фреймворках (React, Vue, Angular) изменения DOM часто происходят асинхронно. В таких случаях проверка после события должна учитывать промисы и рендер циклы:

import { act } from '@testing-library/react';
import axe from 'axe-core';

test('проверка модального окна после открытия', async () => {
  const { getByText } = render(<ModalComponent />);
  
  act(() => {
    getByText('Открыть модальное окно').click();
  });

  await new Promise(resolve => setTimeout(resolve, 100)); // ожидание рендера

  const results = await axe.run(document.body);
  expect(results.violations).toHaveLength(0);
});

Использование act() гарантирует завершение всех синхронных и асинхронных обновлений компонентов перед проверкой доступности.


Настройка правил и исключений

При проверке после событий часто требуется временно отключить правила, которые некорректно срабатывают на динамические элементы:

const options = {
  rules: {
    'region': { enabled: false }, // отключение конкретного правила
    'color-contrast': { enabled: true }
  }
};

axe.run(document.body, options).then(results => {
  console.log(results.violations);
});

Также можно использовать фильтрацию по селекторам для ограничения проверки только к новым или изменённым элементам:

const context = document.querySelector('#modal');
axe.run(context).then(results => {
  console.log(results.violations);
});

Логирование и визуализация результатов

Для удобства анализа после событий рекомендуется использовать структурированное логирование:

axe.run(document.body).then(results => {
  results.violations.forEach(v => {
    console.group(`Нарушение: ${v.id}`);
    console.log('Описание:', v.description);
    console.log('Элементы:', v.nodes.map(n => n.target.join(', ')));
    console.groupEnd();
  });
});

Это позволяет быстро определить, какие элементы появились динамически и вызывают нарушения доступности.


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

Axe-core может быть включён в тестовые пайплайны для автоматической проверки доступности после событий:

  • Cypress с cypress-axe для интерактивного тестирования пользовательских сценариев.
  • Jest + Axe-core для unit-тестов динамических компонентов.
  • GitHub Actions или GitLab CI для прогонки тестов на staging-среде после деплоя.

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

  • Всегда учитывать асинхронность рендера при проверке после событий.
  • Использовать контекстные селекторы для проверки только нужной части DOM.
  • Сочетать Axe-core с MutationObserver для автоматической проверки новых элементов.
  • В логах фиксировать конкретные селекторы и типы нарушений для облегчения исправления.
  • Настраивать правила под проект, чтобы исключить ложные срабатывания на динамические элементы.

Эти подходы позволяют строить стабильные автоматизированные проверки доступности в сложных интерактивных приложениях, минимизируя вероятность пропуска нарушений после динамических изменений страницы.