Браузерные расширения

Axe-core — это библиотека для автоматизированного тестирования доступности веб-приложений на стороне клиента. Она написана на JavaScript и интегрируется с браузером, предоставляя точные и стандартизированные проверки по критериям WCAG (Web Content Accessibility Guidelines). Основная цель библиотеки — выявление проблем доступности до их попадания в продакшн, что позволяет улучшить UX для людей с ограниченными возможностями.

Библиотека поддерживает работу как в браузере, так и в средах для автоматизированного тестирования, таких как Jest, Cypress, Puppeteer и Playwright. В контексте браузерных расширений Axe-core предоставляет возможность анализа DOM без необходимости внедрения дополнительных скриптов на страницу.


Установка и подключение

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

  1. Через npm:
npm install axe-core

После установки скрипт можно подключить в контентном скрипте расширения:

import axe from 'axe-core';

axe.run(document, {}, (err, results) => {
  if (err) throw err;
  console.log(results.violations);
});
  1. Через CDN:
<script src="https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.7.0/axe.min.js"></script>
<script>
  axe.run(document, {}, (err, results) => {
    if (err) throw err;
    console.log(results.violations);
  });
</script>

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


Основные концепции Axe-core

1. Контекст (Context) Контекст определяет область DOM для анализа. По умолчанию Axe-core проверяет весь документ:

axe.run(document, options, callback);

Можно указать конкретный элемент или селектор:

axe.run(document.querySelector('#main'), {}, (err, results) => { ... });

2. Правила (Rules) Правила описывают конкретные проверки доступности, например:

  • наличие альтернативного текста для изображений,
  • правильная структура заголовков,
  • контраст текста и фона,
  • корректное использование ARIA-атрибутов.

Каждое правило имеет id, категорию, уровень серьезности (critical, serious, moderate, minor) и подробное описание.

3. Опции (Options) Опции позволяют управлять поведением сканера:

  • runOnly — ограничение проверки конкретными правилами или категориями:
axe.run(document, {
  runOnly: ['color-contrast', 'image-alt']
}, callback);
  • rules — включение или отключение отдельных правил:
axe.run(document, {
  rules: {
    'color-contrast': { enabled: true },
    'image-alt': { enabled: false }
  }
}, callback);

Работа с результатами

Метод axe.run возвращает объект results, содержащий:

  • violations — массив нарушений с описанием проблемы, рекомендациями и списком элементов DOM, где обнаружено нарушение.
  • passes — массив элементов, которые прошли проверку.
  • incomplete — проверки, которые не были завершены, например, из-за динамически загружаемого контента.
  • inapplicable — правила, неприменимые к текущему контексту.

Пример обработки:

axe.run(document, {}, (err, results) => {
  if (err) throw err;
  results.violations.forEach(v => {
    console.log(`Нарушение: ${v.id}`);
    console.log(`Описание: ${v.description}`);
    console.log(`Элементы:`, v.nodes.map(n => n.html));
  });
});

Интеграция в браузерное расширение

Для браузерного расширения важно учитывать:

  1. Контентные скрипты — Axe-core запускается непосредственно на странице, анализируя DOM.
  2. Разрешения — необходимо разрешение "activeTab" или "tabs" в манифесте расширения для доступа к DOM.
  3. Асинхронная обработка — результаты сканирования нужно передавать из контентного скрипта в popup или background script через chrome.runtime.sendMessage.

Пример отправки результатов в popup:

// content.js
axe.run(document, {}, (err, results) => {
  if (!err) {
    chrome.runtime.sendMessage({ type: 'axe-results', data: results });
  }
});

// popup.js
chrome.runtime.onMessage.addListener((msg) => {
  if (msg.type === 'axe-results') {
    displayViolations(msg.data.violations);
  }
});

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

Axe-core поддерживает кастомные правила. Пользователь может добавить проверку, специфичную для своего приложения:

axe.registerRule({
  id: 'custom-heading-check',
  selector: 'h2',
  enabled: true,
  evaluate: (node) => {
    return node.textContent.trim().length > 0;
  },
  meta: {
    description: 'Заголовки второго уровня должны быть непустыми',
    impact: 'moderate'
  }
});

Это позволяет создавать собственные политики доступности, выходящие за рамки стандартных WCAG.


Автоматизация тестирования

Axe-core легко интегрируется с тестовыми фреймворками:

  • Jest:
import axe from 'axe-core';
import { render } from '@testing-library/react';

test('доступность компонента', async () => {
  const { container } = render(<MyComponent />);
  const results = await axe.run(container);
  expect(results.violations).toHaveLength(0);
});
  • Cypress:
cy.visit('/page');
cy.injectAxe();
cy.checkA11y(null, { includedImpacts: ['critical'] });

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


Практические советы при использовании в расширениях

  • Локальная модификация DOM: при изменении страниц через content script рекомендуется повторно запускать axe.run, чтобы проверять динамический контент.
  • Фильтрация результатов: важно отображать только критические и серьезные нарушения для удобства анализа.
  • Совместимость с фреймворками: React, Angular, Vue — Axe-core корректно работает со всеми, анализируя финальный DOM.
  • Отложенный запуск: на страницах с динамическим контентом полезно использовать MutationObserver, чтобы запускать проверку после появления новых элементов.

Визуализация результатов

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

  • Группировка по типу нарушения (critical, serious, moderate, minor).
  • Подсветка элементов на странице с помощью временной рамки или выделения цвета.
  • Сортировка по селекторам и тегам для быстрого исправления проблем.

Пример подсветки:

results.violations.forEach(v => {
  v.nodes.forEach(n => {
    const el = document.querySelector(n.target[0]);
    if (el) el.style.outline = '3px solid red';
  });
});

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