Popup окна

Popup окна (модальные диалоги, всплывающие окна, alert, confirm, prompt) являются важной частью современных веб-приложений. Их автоматизированное тестирование требует точного подхода, так как они могут блокировать поток выполнения скриптов или ожидать взаимодействия пользователя. Cypress предоставляет гибкие механизмы для работы с такими элементами.


Обработка стандартных JavaScript окон

Cypress перехватывает стандартные браузерные функции window.alert, window.confirm и window.prompt через команду cy.on. Это позволяет проверять их содержание и задавать поведение без необходимости взаимодействовать с настоящим UI.

Пример перехвата alert:

cy.on('window:alert', (text) => {
  expect(text).to.contains('Вы уверены, что хотите удалить элемент?');
});
cy.get('#delete-button').click();
  • cy.on('window:alert', callback) позволяет отлавливать текст алерта.
  • Проверка текста выполняется через expect.

Пример обработки confirm:

cy.on('window:confirm', (text) => {
  expect(text).to.equal('Вы хотите сохранить изменения?');
  return true; // true — подтверждение, false — отмена
});
cy.get('#save-button').click();
  • Возврат true имитирует нажатие “OK”.
  • Возврат false имитирует нажатие “Cancel”.

Обработка prompt:

cy.window().then((win) => {
  cy.stub(win, 'prompt').returns('Введённый текст');
});
cy.get('#prompt-button').click();
  • Используется cy.stub для замены поведения prompt.
  • Возвращаемое значение подставляется вместо пользовательского ввода.

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

Современные веб-приложения часто используют кастомные модальные окна, построенные на HTML и CSS. Они не используют стандартные alert/confirm, поэтому взаимодействие с ними происходит через DOM.

Поиск модального окна:

cy.get('.modal')
  .should('be.visible')
  .within(() => {
    cy.get('.modal-title').should('contain', 'Подтверждение действия');
    cy.get('.modal-body').should('contain', 'Вы действительно хотите продолжить?');
    cy.get('.confirm-button').click();
  });
  • Команда within ограничивает область поиска элементами внутри модального окна.
  • Позволяет проверять текст и выполнять действия, не затрагивая другие части страницы.

Ожидание появления модалки:

cy.get('.modal', { timeout: 10000 }).should('be.visible');
  • Использование увеличенного таймаута полезно для динамически загружаемых компонентов.
  • Проверка should('be.visible') гарантирует, что действия выполняются только после появления окна.

Работа с фоновыми overlay

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

cy.get('.modal').should('exist');
cy.get('body').then(($body) => {
  if ($body.find('.modal-backdrop').length) {
    cy.get('.modal-backdrop').click({ force: true });
  }
});
  • force: true позволяет взаимодействовать с элементами, которые перекрыты другими слоями.
  • Используется осторожно, чтобы не нарушить логику теста.

Проверка закрытия модальных окон

Закрытие модалки можно тестировать через клик по кнопке закрытия, по фону или через клавишу Escape:

cy.get('.modal .close-button').click();
cy.get('.modal').should('not.exist');

cy.get('body').type('{esc}');
cy.get('.modal').should('not.exist');
  • Проверка should('not.exist') гарантирует полное удаление модального окна из DOM.
  • Важна проверка видимости и существования, так как некоторые модалки скрываются через CSS, но остаются в DOM.

Асинхронные модальные окна

Модальные окна могут загружаться через AJAX или через delayed animation. Cypress позволяет синхронизировать тест с этими событиями:

cy.intercept('GET', '/modal-data').as('modalRequest');
cy.get('#open-modal').click();
cy.wait('@modalRequest');
cy.get('.modal').should('be.visible');
  • cy.intercept перехватывает сетевые запросы, что позволяет ждать загрузки данных перед взаимодействием с модалкой.
  • Используется для тестирования модалок с динамическим контентом.

Взаимодействие с формами внутри модальных окон

Модальные окна часто содержат формы, требующие ввода данных:

cy.get('.modal')
  .should('be.visible')
  .within(() => {
    cy.get('input[name="username"]').type('testuser');
    cy.get('input[name="password"]').type('secret');
    cy.get('button[type="submit"]').click();
  });
cy.get('.modal').should('not.exist');
  • Ввод текста осуществляется стандартными методами type.
  • Кнопка submit закрывает модалку, что проверяется через should('not.exist').

Рекомендации по надежности тестов

  • Всегда проверять видимость модалки перед взаимодействием.
  • Использовать within для локализации поиска.
  • Предпочтительно работать с асинхронными событиями через cy.intercept и cy.wait.
  • Для кастомных модалок избегать force: true, если есть возможность дождаться нормального клика.
  • Проверять как закрытие через UI, так и через клавиатурные события.

Этот подход позволяет автоматизировать тестирование всех типов popup окон — от стандартных alert до сложных кастомных модалок с динамическим контентом, обеспечивая надежность и читаемость тестов.