javascripttestingcypresse2e-testingcypress-conditional-testing

Act when element exists, but don't fail when it doesn't (Cypress E2E tests)


I'm writing E2E tests in Cypress (version 12.3.0). I have a page with a table in a multi-step creation process that requires some data from back-end application. In some cases (rarely, but it occurs) the request gets stuck and the loader never disappears. The solution is simple: go back to the previous step and return to the "stuck" table. The request is sent anew and most likely receives a response - the process and the tests can proceed further. If the loader is not present, then going back and forth should be skipped (most of the times).

I managed to work around that with the code below, but I'm wondering if it could be done with some built-in Cypress functions and without explicit waiting. Unfortunately, I didn't find anything in the Cypress docs and on StackOverflow. I thought that maybe I could use the then function to work on a "conditionally present" element, but it fails on get, that's why I've used find on the jQuery ancestor element.

  waitForTableData() {
    return cy.get('.data-table')
             .should('exist')
             .then(table => {
               if (this.loaderNotPresent(table)) {
                 return;
               }
               cy.wait(200)
                 .then(() => {
                   if (this.loaderNotPresent(table)) {
                     return;
                   }
                   cy.get('button')
                     .contains('Back')
                     .click()
                     .get('button')
                     .contains('Next')
                     .click()
                     .then(() => this.waitForTableData());
                 });
             });
  }

  loaderNotPresent(table: JQuery) {
    return !table.find('.loader')?.length;
  }

Solution

  • Your code looks to me to be the best you could do at present.

    The cy.wait(200) is about the right size, maybe a bit smaller would be better - 50 - 100 ms. The recursive call is going to give you similar behaviour to Cypress retry (which also waits internally, in order not to hammer the test runner).

    Another approach would be to cy.intercept() and mock the backend, presuming it's the backend that gets stuck.

    Also worth trying a simple test retry, if the loading only fails on a small percentage of times.