Как слушать глобальные события с помощью Cypress?

У нас есть приложение, которое периодически опрашивает сервер, пока задача не будет выполнена. Мы запускаем глобальное событие, чтобы Cypress мог поймать и узнать, завершена ли задача, но у нас возникли проблемы с использованием document.addEventListener на Cypress. Вот что мы делаем:

document.addEventListener('queryEnd', () => {
    cy.get('.chart').should('be.visible')
    cy.get('.table').should('be.visible')
  })

Однако; когда мы используем его в спецификации, он не работает ожидаемо, и мы не можем его отловить. Кроме того, Cypress не ждет теста и запускается afterEach, не дожидаясь выполнения обратного вызова.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
7
0
5 955
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Причина, по которой ваш код не работает так, как вы ожидаете, заключается в том, что в Cypress ваши тесты выполняются в отдельном фрейме, чем тестируемое приложение (AUT). Событие, которого вы ждете, никогда не произойдет внутри document Cypress.

Чтобы получить document AUT, используйте cy.document() следующим образом:

cy.document()
.then($document => {
  // now $document is a reference to the AUT Document
  $document.addEventListener(...)
})

Чтобы Cypress дождался вашего события, прежде чем продолжить, вы можете просто заключить его в Cypress.Promise. В документации Cypress есть пример ожидание завершения обещания. Для вашего мероприятия queryEnd это будет выглядеть примерно так:

cy.document() // get a handle for the document
.then($document => {
  return new Cypress.Promise(resolve => { // Cypress will wait for this Promise to resolve
    const onQueryEnd = () => {
      $document.removeEventListener('queryEnd', onQueryEnd) // cleanup
      resolve() // resolve and allow Cypress to continue
    }
    $document.addEventListener('queryEnd', onQueryEnd)
  })
})
.then(() => {
  cy.get('.chart').should('be.visible')
  cy.get('.table').should('be.visible')
})

Должно ли это работать для события shiny:value, описанного здесь shining.rstudio.com/articles/js-events.html?

AdamB 09.03.2020 16:52

@AdamB да, так и должно быть

Zach Bloomquist 10.03.2020 18:07

Кажется сложным избежать условий гонки, потому что прослушиватель событий добавляется после cy.visit, может возникнуть риск того, что к тому времени событие уже будет запущено. Использование cy.window() кажется более надежным, потому что объект window доступен намного раньше, чем window.document.

Eric Burel 27.05.2021 15:12

@EricBurel Отличный момент. Было бы лучше добавить это как обратный вызов cy.visitonBeforeLoad, а не как cy.document().then или cy.window().then, по причине, которую вы описываете: docs.cypress.io/api/commands/…

Zach Bloomquist 28.05.2021 17:46

Еще лучше добавить прослушиватель для события, явно вызывая это событие (например, с cy.click()), а затем подтверждая, что оно произошло. Никаких условий гонки, если вы можете заказать такие действия своего приложения. Но это может быть сложно для вещей, которые происходят только при нагрузке.

Zach Bloomquist 28.05.2021 17:47

Вы должны опубликовать onBeforeLoad в качестве ответа, я думаю, что это может быть лучшим подходом. У вас есть доступ к материалам cy. в этом обратном вызове? Если нет, мы все равно можем использовать его, чтобы установить глобальную переменную, например, когда событие запускается, и проверить эту переменную позже. Проблема с запуском события вручную заключается в том, что это не всегда возможно (здесь я хочу сказать, когда на странице выполняется рендеринг WebGL, поэтому он запускается немедленно)

Eric Burel 31.05.2021 09:55

Сделал попытку onBeforeLoad: работает нормально, однако вы должны быть осторожны, потому что он не будет ждать вопреки обычным командам cy.*. Так что, если вы сделаете cy.visit("/foobar", onBeforeLoad: (win) => { win.addEventListener("foobar", () => { cy.expect(true).toBe(true)}) } }), cy.expect не будет ждать. Таким образом, вам все еще нужна дополнительная команда для ожидания события перед выходом.

Eric Burel 03.06.2021 09:46

Открыт запрос функции: github.com/cypress-io/cypress/issues/16793

Eric Burel 03.06.2021 09:58

Другие вопросы по теме