E2E тестирование фокуса

Библиотека Tabbable предназначена для определения элементов DOM, на которые можно попасть с помощью клавиши Tab. В отличие от стандартных методов, таких как document.querySelectorAll, Tabbable учитывает не только атрибуты tabindex, но и видимость элементов, состояние disabled и контекстные особенности, что делает её особенно полезной для E2E тестирования фокуса.

Главный экспорт библиотеки — функция tabbable(container, options), которая возвращает массив элементов, доступных для фокусировки в заданном контейнере.

import { tabbable } from 'tabbable';

const elements = tabbable(document.body);
console.log(elements); // массив доступных для фокуса элементов

container — это DOM-узел, в пределах которого производится поиск. Если передан document, проверка проводится по всему документу.

options — объект с возможными параметрами:

  • includeContainer (boolean) — включает сам контейнер в список, если он фокусируемый.

  • displayCheck (string или function) — определяет способ проверки видимости элемента. Возможные значения:

    • 'full' — элемент полностью видим.
    • 'none' — игнорируется проверка видимости.
    • Пользовательская функция — получает элемент и возвращает true или false.

Ключевые правила фокусируемости

  1. Атрибут tabindex

    • Значение 0 делает элемент доступным через Tab в обычном порядке.
    • Положительное значение задаёт приоритет фокуса перед другими элементами.
    • Отрицательное значение исключает элемент из порядка Tab, но элемент остаётся программно фокусируемым через element.focus().
  2. Элементы по умолчанию

    • <a> с href, <button>, <input>, <select>, <textarea> и <iframe> автоматически включаются в список.
  3. Состояние и видимость

    • Элементы с display: none, visibility: hidden, opacity: 0 или с родительским элементом, скрывающим содержимое, исключаются.
    • Элементы с disabled также игнорируются.
  4. Роль ARIA

    • Атрибуты ARIA (aria-hidden) используются для исключения элементов, невидимых для пользователей.

Использование в E2E тестах

В автоматизированных тестах фокуса важно контролировать порядок обхода элементов клавишей Tab. Tabbable позволяет:

  • Проверять, что интерактивные элементы доступны в правильном порядке.
  • Обеспечивать совместимость с доступностью и ARIA-стандартами.
  • Исключать скрытые или заблокированные элементы из проверок.

Пример интеграции с Cypress:

cy.get('body').then(($body) => {
  const focusableElements = tabbable($body[0]);
  expect(focusableElements[0]).to.have.attr('id', 'first-input');
  expect(focusableElements[focusableElements.length - 1]).to.have.attr('id', 'submit-button');
});

Пример с имитацией обхода клавишей Tab:

import { tabbable } from 'tabbable';

const elements = tabbable(document.querySelector('#form-container'));
let currentIndex = 0;

function pressTab() {
  currentIndex = (currentIndex + 1) % elements.length;
  elements[currentIndex].focus();
}

Продвинутые возможности

  1. Фильтрация по типу Можно отфильтровать элементы по тегам или классам:
const buttons = tabbable(document.body).filter(el => el.tagName === 'BUTTON');
  1. Вложенные контейнеры В сложных интерфейсах, где есть модальные окна или табы, важно учитывать только видимые элементы текущей вкладки:
const activeTab = document.querySelector('.tab-pane.active');
const focusable = tabbable(activeTab);
  1. Настройка проверки видимости Иногда необходимо включить элементы с opacity: 0 или скрытые через CSS-анимации:
const allFocusable = tabbable(document.body, { displayCheck: 'none' });

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

  • Всегда использовать Tabbable для проверки порядка Tab в E2E тестах, чтобы избежать зависимостей от специфических селекторов.
  • Для модальных окон и динамических интерфейсов проверять только активные и видимые контейнеры.
  • Сочетать Tabbable с библиотеками для имитации клавиш (@testing-library/user-event, Cypress type('{tab}')) для полной симуляции пользовательских действий.
  • Отслеживать элементы с tabindex > 0, чтобы убедиться, что приоритет фокуса соответствует требованиям UX.

Tabbable обеспечивает точную и предсказуемую проверку доступности элементов интерфейса, упрощая E2E тестирование фокуса и соблюдение стандартов доступности. Контроль порядка фокуса с помощью этой библиотеки повышает надёжность тестов и позволяет выявлять ошибки взаимодействия до релиза.