Библиотека ally.js предоставляет мощный набор инструментов для проверки доступности веб-приложений и эмуляции поведения скринридеров. Основная цель — выявление потенциальных проблем в интерфейсе до того, как их заметят пользователи с ограничениями зрения. ally.js не заменяет полноценное тестирование с реальными скринридерами, но позволяет автоматизировать большую часть проверок на уровне DOM.
В ядре библиотеки реализованы методы для определения фокуса, ролей элементов, видимости контента, а также для проверки состояния aria-атрибутов. Эти функции особенно полезны при написании юнит- и интеграционных тестов.
Фокус является ключевым аспектом работы скринридеров. ally.js предоставляет функции:
tabbable(el) — возвращает массив всех элементов,
доступных для табуляции.focusable(el) — проверяет, может ли элемент получить
фокус.focus(el) — программно переводит фокус на элемент,
имитируя клавиатурную навигацию.Пример использования:
import ally from 'ally.js';
const tabbableElements = ally.query.tablist();
tabbableElements.forEach(el => {
if (ally.element.is.focusable(el)) {
ally.element.focus(el);
console.log(`Фокус установлен на: ${el.tagName}`);
}
});
Эти методы позволяют имитировать перемещение по форме или меню так, как это делает пользователь скринридера.
Скринридеры активно используют ARIA для озвучивания состояния элементов. ally.js предоставляет утилиты для проверки корректности этих атрибутов:
get.text(el) — извлекает текстовое содержимое, включая
aria-label и aria-labelledby.get.role(el) — возвращает роль элемента
(button, dialog, alert и
др.).get.state(el, stateName) — возвращает состояние aria
(aria-checked, aria-expanded и др.).Пример проверки роли и состояния:
const button = document.querySelector('#submit');
const role = ally.element.get.role(button);
const expanded = ally.element.get.state(button, 'expanded');
console.log(`Роль: ${role}, раскрыт: ${expanded}`);
Такой подход позволяет убедиться, что элементы правильно озвучиваются и реагируют на действия пользователя.
Скринридеры игнорируют элементы, скрытые с помощью CSS
(display: none, visibility: hidden) или
атрибутов (aria-hidden="true"). ally.js позволяет
тестировать это через:
is.visible(el) — проверяет видимость элемента.is.invisible(el) — обратная проверка.is.hiddenFromScreenReader(el) — проверяет, скрыт ли
элемент для вспомогательных технологий.Пример:
const menu = document.querySelector('#menu');
if (ally.element.is.hiddenFromScreenReader(menu)) {
console.log('Элемент недоступен для скринридеров');
}
Это помогает обнаружить элементы, которые случайно остаются доступными или наоборот скрыты неправильно.
Для полноценной эмуляции пользовательских сценариев важно генерировать события, на которые реагируют скринридеры:
keydown, keyup, focus,
blur — для навигации клавиатурой.click — для активации кнопок и ссылок.change — для обновления состояния элементов формы.Пример теста на активацию кнопки:
const button = document.querySelector('#confirm');
button.addEventListener('click', () => console.log('Нажата кнопка'));
ally.element.focus(button);
button.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
Так можно проверить, как изменяется DOM и aria-состояния при взаимодействии.
Ally.js легко интегрируется с Jest, Mocha, Cypress и другими инструментами для автоматизированного тестирования:
import ally from 'ally.js';
test('кнопка доступна и имеет правильную роль', () => {
const button = document.querySelector('#submit');
expect(ally.element.is.focusable(button)).toBe(true);
expect(ally.element.get.role(button)).toBe('button');
});
В комбинации с имитацией событий и проверкой aria-атрибутов это позволяет строить тестовые сценарии, максимально приближенные к поведению пользователей со скринридером.
Для веб-приложений с динамически обновляемым DOM ally.js предоставляет функции, позволяющие:
Пример:
const modal = document.createElement('div');
modal.setAttribute('role', 'dialog');
document.body.appendChild(modal);
expect(ally.element.is.focusable(modal)).toBe(false);
expect(ally.element.get.role(modal)).toBe('dialog');
Это критично для SPA, где элементы могут появляться или исчезать без перезагрузки страницы.
is.hiddenFromScreenReader для выявления
скрытых элементов.get.text и
get.state для имитации того, что озвучивает
скринридер.Ally.js обеспечивает детальную эмуляцию поведения скринридеров, позволяя выявлять ошибки доступности на ранних стадиях разработки и поддерживать интерфейсы, полностью совместимые с требованиями WCAG.