How to listen global events with Cypress?

2019-08-02 20:28发布

问题:

We have an application that polls the server periodically until a task is completed. We fire a global event so that Cypress can catch and find out if the task is finished but we had trouble using document.addEventListener on Cypress. Here's what we're doing:

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

However; when we use it in a spec, it doesn't work expected and we're not able to catch it. Also, Cypress doesn't wait for the test and runs afterEach without waiting for the callback to run.

回答1:

The reason why your code isn't working like you expect is because in Cypress, your tests run in a separate frame than your application under test (AUT). The event you're waiting for will never fire inside of Cypress's document.

To get the document of the AUT, use cy.document() like this:

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

To make Cypress wait for your event before continuing, you can just wrap it in a Cypress.Promise. The Cypress docs have an example about waiting for a Promise to complete. For your queryEnd event, it would look something like this:

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')
})


标签: cypress