Keyboard navigation

В современных веб-приложениях обеспечение доступности через клавиатуру является критически важным аспектом тестирования. Cypress предоставляет гибкие возможности для имитации взаимодействия пользователя с клавишами, что позволяет проверять поведение элементов при клавиатурной навигации.


Симуляция нажатий клавиш

Метод cy.type() позволяет отправлять симуляции ввода с клавиатуры в выбранный элемент. Основные моменты:

  • Можно вводить как текст, так и специальные клавиши.
  • Специальные клавиши указываются в фигурных скобках, например: {enter}, {esc}, {tab}.
  • Метод поддерживает комбинированные нажатия с модификаторами: {ctrl}, {shift}, {alt}.

Пример:

cy.get('input[name="search"]')
  .type('Cypress testing{enter}');

Для нажатий без фокусировки на конкретном элементе используется cy.get('body').type(...). Это полезно для проверки глобальных сочетаний клавиш.

cy.get('body').type('{tab}');

Проверка фокусировки элементов

Фокусировка играет ключевую роль в навигации по клавиатуре. Cypress предоставляет метод .focus() для установки фокуса и команду .should('have.focus') для проверки:

cy.get('button.submit')
  .focus()
  .should('have.focus');

Чтобы убедиться, что последовательность фокусировки правильная, можно комбинировать .tab() с проверкой активного элемента. Плагин cypress-plugin-tab расширяет возможности Cypress и позволяет эмулировать нажатия Tab в более удобном формате:

cy.get('input:first').focus()
  .tab()
  .should('have.focus')
  .tab()
  .should('have.focus')

Работа с модификаторами клавиш

Для проверки функционала сочетаний клавиш используются модификаторы:

  • {ctrl}, {cmd} — управление и команды
  • {shift} — заглавные буквы или расширенные действия
  • {alt} — альтернативные действия
  • {meta} — клавиша Command на macOS

Пример проверки горячих клавиш для сохранения:

cy.get('body')
  .type('{ctrl}s');
cy.get('.notification')
  .should('contain', 'Файл сохранен');

Навигация между элементами формы

Клавиатурная навигация особенно важна для форм. Последовательность Tab должна следовать логике доступности. Cypress позволяет проверять это:

cy.get('input[name="firstName"]').focus()
  .tab()
  .should('have.focus')
  .tab()
  .should('have.focus');

Для элементов, скрытых через display: none или visibility: hidden, Cypress корректно обрабатывает их недоступность для фокусировки.


Проверка доступности модальных окон

При открытии модальных окон важно убедиться, что фокус автоматически перемещается внутрь модального окна, а клавиша Esc закрывает его:

cy.get('button.open-modal').click();
cy.get('.modal')
  .should('be.visible')
  .within(() => {
    cy.get('input:first').should('have.focus');
    cy.get('body').type('{esc}');
  });
cy.get('.modal').should('not.exist');

Управление последовательностью клавиш

Для сложных сценариев можно комбинировать несколько клавиш одновременно:

cy.get('body').type('{shift}{tab}');
cy.get('body').type('{ctrl}{alt}k');

Cypress гарантирует, что последовательность событий соответствует реальному поведению браузера.


Отслеживание событий клавиатуры

Иногда необходимо проверить, что нажатия клавиш вызывают определённые события. Для этого используется .trigger():

cy.get('input[name="search"]')
  .trigger('keydown', { key: 'Enter', code: 'Enter', keyCode: 13 })
  .trigger('keyup', { key: 'Enter', code: 'Enter', keyCode: 13 });

Это позволяет эмулировать низкоуровневые события, которые не всегда срабатывают через .type().


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

  • Фокус всегда проверять перед действием. Любое нажатие клавиши должно происходить на активном элементе.
  • Использовать плагины для Tab-навигации. Это облегчает проверку доступности и ускоряет написание тестов.
  • Проверять сочетания клавиш. Они должны корректно работать на всех элементах интерфейса.
  • Обрабатывать модальные окна и диалоги. Убедиться, что фокус возвращается после закрытия.
  • Локаторы должны быть устойчивыми. Для клавиатурной навигации лучше использовать атрибуты tabindex, role и уникальные селекторы.

Эффективное тестирование клавиатурной навигации в Cypress позволяет выявить ошибки доступности, гарантировать корректное поведение интерфейса при использовании только клавиатуры и обеспечить соответствие современным стандартам доступности.