Unable to find the element to check if it exists in the before() hook in cypress.io

132 Views Asked by At

I have the following lines of code in my before() hook.

before(() ==> {
cy.get(this.testPopup).then(($el) => {
   if ($el.length) {
      cy.get(this.testPopupCloseButton).click();
      cy.get(this.testPopup).should("not.exist");
    } 
  });
});

There will be a popup which will display sometimes and sometimes it will not. I tried to write a logic to close that popup and check if it getting disappeared on closing only when the popup exists.

But I am getting the following error.

Timed out retrying after 30000ms: Expected to find element: #test-popup-element, but never found it.

Because this error occurred during a before all hook we are skipping the remaining tests in the current suite`

I am expecting a soft assert here basically, which will continue to run the rest of the tests even if this assertion fails.

Please advice.

2

There are 2 best solutions below

0
On

The issue is that using cy.get(this.testPopup) contains an implicit assertion that the this.testPopup element exists. So in the case where it doesn't, the test fails because Cypress can't find the element.

From the Cypress Conditional Testing documentation, they recommend using cy.get('body') and then querying for the element (using JQuery's .find().)

before(() ==> {
  cy.get('body').then(($body) => {
    if ($body.find(this.testPopup).length) {
      cy.get(this.testPopupCloseButton).click();
      cy.get(this.testPopup).should("not.exist");
    } 
  });
});
0
On

You can't resolve the issue using cy.get('body').then(($body) => because the code will finish before the popup appears. There is no retry in that code, it always decides imediately if the popup is present.

Instead, use element polling as shown by Fody here:
How to check for an element that may not exist using Cypress

const ifElementExists = (selector, attempt = 0) => {
  if (attempt === 100) return null           // no appearance, return null
  if (Cypress.$(selector).length === 0) {
    cy.wait(100, {log:false})                // wait in small chunks
    getDialog(selector, ++attempt)           // try again
  }
  return cy.get(selector, {log:false})       // done, exit with the element
}

// Wait for 10 seconds for the popup
ifElementExists(this.testPopup).then($el => {
  if ($el?.length) {
    cy.get(this.testPopupCloseButton).click()
    cy.get(this.testPopup).should('not.exist')
  }
})

This works because it will keep waiting for the popup up to 10 seconds.
Increase if (attempt === 100) if you need longer waiting time. You have to decide the longest time you need to wait and set attempt limit accordingly.

If it never appears in that time, if ($el?.length) will be false and the close button won't be clicked.

Otherwise, the popup has eventually appeared and the code can go ahead and click the close button.