Множественные окна и табы

Работа с множественными окнами и вкладками в веб-тестировании часто вызывает сложности из-за архитектуры браузеров и ограничений инструментов автоматизации. Cypress, как инструмент для end-to-end тестирования, изначально ориентирован на управление одним окном браузера, поэтому прямой работы с новыми окнами (window.open) и вкладками (target="_blank") нет. Для корректного тестирования необходимо использовать альтернативные подходы и обходные методы.


Особенности работы Cypress с окнами

  • Cypress работает в одном DOM-контексте. Все команды выполняются внутри одного окна браузера.
  • Любая попытка открыть новое окно через cy.window().then(win => win.open(...)) приведет к тому, что Cypress не сможет напрямую управлять содержимым этого окна.
  • Тесты Cypress выполняются асинхронно, но команда cy.visit() полностью заменяет текущий контент, что делает управление множественными окнами невозможным в классическом смысле.

Открытие ссылок в той же вкладке

Наиболее практичный подход при работе с внешними ссылками — принудительное открытие их в текущей вкладке. Это позволяет сохранить контроль Cypress над страницей.

Пример:

cy.get('a[target="_blank"]').invoke('removeAttr', 'target').click();
  • invoke('removeAttr', 'target') удаляет атрибут target="_blank".
  • После этого ссылка открывается в текущем окне, и Cypress может продолжить выполнение команд на новой странице.

Ключевой момент: Этот метод работает только для тестов, где нет необходимости проверять именно отдельное окно, а важен только контент страницы.


Работа с window.open

Если в приложении используется window.open, управление им можно реализовать через стабилизацию или перехват вызова окна:

cy.window().then((win) => {
  cy.stub(win, 'open').as('windowOpen');
});

// Действие, которое вызывает window.open
cy.get('#open-window-button').click();

// Проверка параметров нового окна
cy.get('@windowOpen').should('be.calledWith', 'https://example.com');
  • cy.stub позволяет перехватить вызов window.open.
  • Можно проверить URL, размеры, параметры окна, но не взаимодействовать с его содержимым.

Использование Cypress-плагинов

Существуют плагины, расширяющие возможности работы с несколькими окнами, например cypress-real-events или cypress-window-switch. Они позволяют имитировать пользовательские действия с вкладками и окнами.

Пример с имитацией перехода на новую вкладку:

cy.get('a[target="_blank"]')
  .then((link) => {
    const url = link.prop('href');
    cy.visit(url);
  });
  • Получение href ссылки позволяет напрямую посетить URL в текущей вкладке.
  • Этот метод полностью совместим с архитектурой Cypress и сохраняет возможность выполнения последующих команд теста.

Тестирование модальных окон vs новых вкладок

В большинстве современных приложений модальные окна заменяют открытие новых вкладок для сохранения UX. Cypress работает с модальными окнами без ограничений:

cy.get('#open-modal-button').click();
cy.get('.modal-content').should('be.visible');
cy.get('.modal-close').click();
cy.get('.modal-content').should('not.exist');
  • Модальные окна остаются в DOM текущей страницы.
  • Тестирование интерактивности, валидации форм и кнопок проходит естественным образом.

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

  1. Всегда использовать cy.visit для перехода на новый URL, вместо прямого открытия нового окна.
  2. Удалять target="_blank" у ссылок, если важно продолжить тест в текущем окне.
  3. Стабить window.open, если нужно проверить параметры открытия окна.
  4. Отдавать предпочтение модальным окнам и SPA-переходам, когда это возможно.
  5. Избегать параллельного управления несколькими окнами, так как Cypress не поддерживает переключение контекста между ними.

Итоговая стратегия

Работа с множественными окнами и вкладками в Cypress строится вокруг упрощения потоков переходов. Основные подходы включают: принудительное открытие ссылок в текущей вкладке, перехват вызовов window.open, использование модальных окон и прямой переход через cy.visit. Такой подход позволяет сохранить надёжность и стабильность тестов, избегая ошибок из-за недоступного контекста нового окна.