Cypress: is there an event listener for notifications in the app

Viewed 35

In principle, the app under test could throw at any time Error notifications (usually when something is not working as it should: server side). My problem is that my cypress test does not fail over such error messages.

Is it possible to configure a listener in cypress for such events? It would basically always listen if something like a message box pops up.

Eg. listening for:

cy.contains('[data-e2e-notification-message-text]', 'ERROR: ')
1 Answers

You're talking about the difference between active and passive element checking.

Generally speaking, active waiting for the notification is better

cy.contains('[data-e2e-notification-message-text]', 'ERROR: ', {timeout: 7000})
  .should('not.exist')

than passive waiting

cy.on('notification', (message) => {   // NOT REAL CODE - for illustration
  if (message.includes('ERROR: ')) {
    throw 'Notification occurred'      // fail the test
  }
})

because the chain of events involves asynchronous call from the backend, which can vary in timing. If the test ends before the notification arrives, you get a false positive test.


You can set up an intercept if the action is request/response style, e.g

cy.intercept(...).as('notification')         // listen
cy.get(button).click()                       // action
cy.wait('@notification')                     // assert

Add a stub if the live server is slow

cy.intercept(url, { notification: 'Error: ' })          // immediately fake response
cy.get(button).click()                                          // action
cy.contains('[data-e2e-notification-message-text]', 'ERROR: ')  // assert

Or don't explicitly wait

cy.intercept(url, (req) => {
  req.on('response', (res) => {
    if (res.body.includes('Error:')) {
      throw 'Notification of error'            // fail the test
    }
  })
cy.get(button).click()                                          // action

But also a chance of false positive result depending on timing.


If you did have a use case for periodic checking for an element, you could tap into the command:end event.

You can only do static (jQuery) DOM querying in an event handler (no cy.() commands).

// after every command look for notification
Cypress.on('command:end', () => {
  const notification = Cypress.$('[data-e2e-notification-message-text]:contains(ERROR:)')
  if (notification.length) {
    throw 'Notification of error happened'    // fail the test
  }
})

Same caveat applies - this could be flaky if the test is faster than the notification.

Related