В предыдущей статье рассмотрели, как быстро настроить Cypress и axe-core для запуска автоматических тестов доступности (подробнее здесь).
Теперь время перейти к практике. Какие именно проверки стоит автоматизировать в первую очередь? На каких ошибках доступности можно поймать проблемы ещё до выхода на продакшн?
В этой статье — 5 простых, но эффективных идей для автоматизированных accessibility-тестов, которые помогают системно повышать качество интерфейсов при минимальных затратах.
1. Автоматическая проверка A11y нарушений на странице
Базовая, но мощная проверка: подключить axe-core
и запускать cy.checkA11y()
на всех страницах.
Что выявляет axe-core:
Контрастность текста и фона на соответствие минимальным требованиям контраста по стандарту 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();
});
});
2. Проверка доступности главной навигации
Навигационное меню должно быть доступным с клавиатуры, иметь корректные 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');
});
});
});
3. Проверка форм и валидации ошибок
Формы — один из самых частых источников 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)');
}
});
});
});
4. Фокус по клавиатуре
Пользователь должен иметь возможность перемещаться по всем интерактивным элементам с помощью 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');
}
});
});
5. Динамические компоненты: модальные окна, алерты, уведомления
Важно, чтобы модальные окна:
перехватывали фокус при открытии,
имели
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-атрибутов
Проверку фокусировки клавиатурой
Доступность динамических компонентов, таких как модальные окна и уведомления
Автоматизация позволяет находить большинство технических ошибок на ранних этапах, но не отменяет важность ручного тестирования скринридерами и проверки логики взаимодействия.
Начать стоит с базовых тестов для ключевых страниц, постепенно расширяя покрытие на новые фичи и сценарии. Даже один тест на доступность — вклад в создание инклюзивного интернета.