testingautomated-testscypress

Navigating to the next page when element is not found


I've created a script for testing inside of SAP Hybris with Cypress. Generally everything works fine, although I wanted to include a function that will basically navigate to the next page if the searched element is not found on the current page. Please take a look at the code:

const checkProductOnPage = (CATALOG_LABEL, retries = 0) => {
        const maxRetries = 5; // Adjust this based on the maximum number of pages you expect
    
        // Try to find the product on the current page
        return cy.contains('span.yw-coll-browser-hyperlink', CATALOG_LABEL, { timeout: 10000 }) // Adjust timeout as needed
            .then(productElement => {
                if (productElement.length) {
                    // If the product element is found
                    return cy.wrap(productElement).scrollIntoView().should('be.visible').click({ force: true });
                } else if (retries < maxRetries) {
                    // If the product element is not found and we haven't exceeded max retries
                    return cy.get('body').then(body => {
                        if (body.find('.z-paging-icon.z-icon-angle-right').length > 0) {
                            // Click on the pagination button and wait for the page to update
                            return cy.get('.z-paging-icon.z-icon-angle-right').eq(0).click({ force: true })
                                .wait(5000) // Adjust wait time as needed
                                .then(() => checkProductOnPage(CATALOG_LABEL, retries + 1)); // Recurse with increased retry count
                        } else {
                            throw new Error('Reached the last page and product not found');
                        }
                    });
                } else {
                    throw new Error('Product not found after maximum retries');
                }
            });
    };

    const checkProductReplacements = (productCode, replacements, isFirstSearch) => {
        cy.get('.yw-fulltextsearch-search-button').eq(0).click();
    
        // Determine the correct input element to type into based on whether it's the first search
        const inputIndex = isFirstSearch ? 3 : 5;
        cy.get('.z-bandbox-input').eq(inputIndex).type(productCode, { force: true }).wait(300);
    
        cy.get('.yw-fulltextsearch-search-button').eq(0).click().wait(3000);
    
        return checkProductOnPage(CATALOG_LABEL).then(() => {
            cy.wait(5000);
            cy.get('.yw-editorarea-tabbox-tabs-tab').contains("Categories").click().wait(300);
    
            // Use cy.then to properly chain the commands
            cy.then(() => {
                replacements.forEach(replacement => {
                    const label = LABELS[replacement.level];
                    cy.get('.z-listitem')
                        .contains(replacement.code)
                        .should('contain', label)
                        .parent()
                        .should('contain', CATALOG_LABEL);
                });
    
                cy.get('.yw-navigationhistory-back').eq(0).should('be.visible').click({ force: true });
                cy.get('button[title="Clear"]').eq(0).click().wait(1000);
            });
        });
    };

    it('should test the replacement matrix', () => {
        checkProductReplacements("G0000605", [
          { code: "G0000605", level: 'L1' },
          { code: "G0000592", level: 'L2' },
          { code: "G0000604", level: 'L1' }
        ], true);
        checkProductReplacements("G0000606", [
          { code: "G0000606", level: 'L1' },
          { code: "G0000592", level: 'L3' },
          { code: "G0000604", level: 'L2' }
        ], false);
        checkProductReplacements("G0000607", [
          { code: "G0000607", level: 'L1' },
          { code: "G0000605", level: 'L2' },
          { code: "G0000593", level: 'L3' }
        ], false);
    });
});

It successfully tested the first product (G0000605) while when it tried to do the same with the second product (G0000606) I've received this error:

Timed out retrying after 10000ms: Expected to find content: 'Tunisia Product Catalog : Staged' within the selector: 'span.yw-coll-browser-hyperlink' but never did.

cypress/e2e/New.cy.js:40:19

  38 |     
  39 |         // Try to find the product on the current page
> 40 |         return cy.contains('span.yw-coll-browser-hyperlink', CATALOG_LABEL, { timeout: 10000 }) 
     |                   ^
  41 |             .then(productElement => {
  42 |                 if (productElement.length) {
  43 |                     // If the product element 

It didn't find the G0000606 product because it is located on the second page, so Cypress should have navigate to the second page, but instead it just dropped an error where it cannot find the requested product.

I believe that something should be modified in this part of the script:

const checkProductOnPage = (CATALOG_LABEL, retries = 0) => {
        const maxRetries = 5; // Adjust this based on the maximum number of pages you expect
    
        // Try to find the product on the current page
        return cy.contains('span.yw-coll-browser-hyperlink', CATALOG_LABEL, { timeout: 10000 }) // Adjust timeout as needed
            .then(productElement => {
                if (productElement.length) {
                    // If the product element is found
                    return cy.wrap(productElement).scrollIntoView().should('be.visible').click({ force: true });
                } else if (retries < maxRetries) {
                    // If the product element is not found and we haven't exceeded max retries
                    return cy.get('body').then(body => {
                        if (body.find('.z-paging-icon.z-icon-angle-right').length > 0) {
                            // Click on the pagination button and wait for the page to update
                            return cy.get('.z-paging-icon.z-icon-angle-right').eq(0).click({ force: true })
                                .wait(5000) // Adjust wait time as needed
                                .then(() => checkProductOnPage(CATALOG_LABEL, retries + 1)); // Recurse with increased retry count
                        } else {
                            throw new Error('Reached the last page and product not found');
                        }
                    });
                } else {
                    throw new Error('Product not found after maximum retries');
                }
            });
    };

Solution

  • The if/else block will never get to else

    This is the culprit;

    cy.contains('span.yw-coll-browser-hyperlink', CATALOG_LABEL, { timeout: 10000 }) 
      .then(productElement => {
        if (productElement.length) {
          ...
        } else if (retries < maxRetries) {
    
    1. cy.contains('span.yw-coll-browser-hyperlink', CATALOG_LABEL) test fails if it doesn't find CATALOG_LABEL.

    2. if (productElement.length) is saying "if I have found the element". But this always true because if it's not, point #1 above has already failed the test.

    Instead, this is the code you need. I'm assuming there might be several different span.yw-coll-browser-hyperlink containing different text.

    cy.get('span.yw-coll-browser-hyperlink', {timeout: 10_000})
      .then(links => {
    
        // check the contains CATALOG_LABEL here (non-failing if not found)
        const productElement = links.filter(`:contains(${CATALOG_LABEL})`)
    
        if (productElement.length) {
          ...
        } else if (retries < maxRetries) {