Библиотека 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.Атрибут tabindex
0 делает элемент доступным через Tab в обычном
порядке.element.focus().Элементы по умолчанию
<a> с href,
<button>, <input>,
<select>, <textarea> и
<iframe> автоматически включаются в список.Состояние и видимость
display: none,
visibility: hidden, opacity: 0 или с
родительским элементом, скрывающим содержимое, исключаются.disabled также игнорируются.Роль ARIA
aria-hidden) используются для исключения
элементов, невидимых для пользователей.В автоматизированных тестах фокуса важно контролировать порядок обхода элементов клавишей Tab. Tabbable позволяет:
Пример интеграции с 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();
}
const buttons = tabbable(document.body).filter(el => el.tagName === 'BUTTON');
const activeTab = document.querySelector('.tab-pane.active');
const focusable = tabbable(activeTab);
opacity: 0 или скрытые через
CSS-анимации:const allFocusable = tabbable(document.body, { displayCheck: 'none' });
@testing-library/user-event, Cypress
type('{tab}')) для полной симуляции пользовательских
действий.tabindex > 0, чтобы
убедиться, что приоритет фокуса соответствует требованиям UX.Tabbable обеспечивает точную и предсказуемую проверку доступности элементов интерфейса, упрощая E2E тестирование фокуса и соблюдение стандартов доступности. Контроль порядка фокуса с помощью этой библиотеки повышает надёжность тестов и позволяет выявлять ошибки взаимодействия до релиза.