authenticationtestingautomated-testscypress

Cypress test starts from the begining for every test case


I've created a Cypress script for testing inside of SAP Hybris for testing promotion items. It generally works without issues when considering a single test case. But when I add multiple test cases (1 per each promotion tested) then it successfully finishes Test Case 1, and receives a blocker as soon as Test Case 2 starts. The reason for that is that as soon as the Test Case 1 is done, Cypress shows a Blank Page so it cannot find the requested element for Test Case 2.

Cypress.on('uncaught:exception', (err, runnable) => {
    return false;
});

describe('Promotions test', () => {
    const loginPageUrl = 'https://backoffice.stg.iqos.com/backoffice/login.zul';
    const username = 'USERNAME HERE';
    const password = 'PASSWORD HERE';
    const promotionEditorRole = 'Promotion Editor';
    const proceedButtonText = 'PROCEED';
    const marketingMenuText = 'Marketing';
    const promotionRulesText = 'Promotion Rules';

    before(() => {
    // Login process that runs once before all test cases
    cy.visit(loginPageUrl, { failOnStatusCode: false }).wait(1000);
    cy.get('input[placeholder="Enter user name"]:visible')
        .type(username, { force: true }).wait(300);
    cy.get('input[placeholder="Enter password"]:visible')
        .type(password, { force: true });
    cy.get('.login_btn').click({ force: true }).wait(30000);

    // Select Promotion Editor Role
    cy.get('.z-listcell-content').contains(promotionEditorRole)
        .should('exist').click({ force: true }).wait(2000);
    cy.get('.yw-selector-btn').contains(proceedButtonText)
        .should('exist').click({ force: true }).wait(15000);
});

beforeEach(() => {
    // Navigation process before each test case
    cy.get('.yw-navigationNode-level1').contains(marketingMenuText)
        .should('exist').click({ force: true }).wait(3000);
    cy.get('span.z-label').contains(promotionRulesText)
        .should('exist').click({ force: true }).wait(5000);
});

    it('Check Promotion 1', () => {
        const promotionCode = 'CR_PMI_MGM_Godfather_Discount_01_More';
        const promotionName = 'MGM GODFATHER Reward';
        const websiteEnv = 'Costa Rica_Promotion_Group';
        const promotionVersion = '4';
    
        searchPromotion(promotionCode, promotionName, websiteEnv, promotionVersion);;
    
                    cy.get('.z-tab-content')
                      .contains('Rule Properties')
                      .scrollIntoView()
                      .click({ force: true });
                    cy.get('.ye-input-text.ye-com_hybris_cockpitng_editor_defaulttext.z-textbox.z-textbox-readonly')
                      .should('have.value', 'CR_PMI_MGM_Godfather_Discount_01_More');
                    cy.wait(10000);
                    });
    

    it('Check Promotion 2', () => {
                        const promotionCode = 'UK_15_Off_First_Order';
                        const promotionName = '15% off first ZYN Order';
                        const websiteEnv = 'PUBLISHED';
                        const promotionVersion = '0';
                
                        searchPromotion(promotionCode, promotionName, websiteEnv, promotionVersion);;
                
                                    cy.get('.z-tab-content')
                                      .contains('Rule Properties')
                                      .scrollIntoView()
                                      .click({ force: true });
                                    cy.get('.ye-input-text.ye-com_hybris_cockpitng_editor_defaulttext.z-textbox.z-textbox-readonly')
                                      .should('have.value', 'UK_15_Off_First_Order');
                                    });
                
it('Check Promotion 3', () => {
    const promotionCode = 'UK_ZYN_Free_Sample';
    const promotionName = 'ZYN Free Sample';
    const websiteEnv = 'PUBLISHED';
    const promotionVersion = '0';

    searchPromotion(promotionCode, promotionName, websiteEnv, promotionVersion);;

                cy.get('.z-tab-content')
                  .contains('Rule Properties')
                  .scrollIntoView()
                  .click({ force: true });
                cy.get('.ye-input-text.ye-com_hybris_cockpitng_editor_defaulttext.z-textbox.z-textbox-readonly')
                  .should('have.value', 'UK_ZYN_Free_Sample');
                });



});

function searchPromotion(promotionCode, promotionName, websiteEnv, promotionVersion) {
    cy.get('.z-bandbox-input')
        .eq(6)
        .should('exist')
        .clear()
        .type(promotionCode, { force: true })
        .wait(300);
    
    cy.get('.yw-textsearch-searchbutton.z-button')
        .eq(1)
        .click({ force: true })
        .wait(10000);
    
    cy.log("Promotion Code: " + promotionCode);
    cy.log("Promotion Name: " + promotionName);
    cy.log("Website Environment: " + websiteEnv);
    cy.log("Promotion Version: " + promotionVersion);
    
    const selector = "tr.yw-coll-browser-hyperlink:has(.yw-listview-cell-label.z-label:contains(\"" + promotionCode + "\")):has(.yw-listview-cell-label.z-label:contains(\"" + promotionName + "\")):has(.yw-listview-cell-label.z-label:contains(\"" + websiteEnv + "\")):has(.yw-listview-cell-label.z-label:contains(\"" + promotionVersion + "\"))";
    
    function checkPage() {
        cy.get('body').then($body => {
            if ($body.find(selector).length > 0) {
                cy.get(selector).within(() => {
                    cy.get(".yw-listview-cell-label.z-label:contains(\"" + promotionVersion + "\")")
                        .click({ force: true })
                        .wait(10000);
                });
            } else {
                cy.get('button.z-paging-button.z-paging-next[title="Next Page"]').eq(2).then($button => {
                    cy.log('Button found:', $button.length > 0 ? 'Yes' : 'No');
                    cy.log('Button visibility:', $button.is(':visible') ? 'Visible' : 'Not Visible');
                    cy.log('Button disabled attribute:', $button.attr('disabled') ? 'Disabled' : 'Enabled');
    
                    if ($button.is(':visible') && !$button.attr('disabled')) {
                        cy.log('Clicking the next page button');
                        cy.wrap($button).click({ force: true }).wait(5000);
                        checkPage();
                    } else {
                        cy.log('Promotion not found or next page button is not clickable');
                    }
                });
            }
        });
    }
    
    checkPage();
    }

enter image description here

The solutions I've found out that actually finishes all test cases is this:

beforeEach(() => {
        // Login process that runs once before all test cases
        cy.visit(loginPageUrl, { failOnStatusCode: false }).wait(1000);
        cy.get('input[placeholder="Enter user name"]:visible')
            .type(username, { force: true }).wait(300);
        cy.get('input[placeholder="Enter password"]:visible')
            .type(password, { force: true });
        cy.get('.login_btn').click({ force: true }).wait(30000);
    
        // Select Promotion Editor Role
        cy.get('.z-listcell-content').contains(promotionEditorRole)
            .should('exist').click({ force: true }).wait(2000);
        cy.get('.yw-selector-btn').contains(proceedButtonText)
            .should('exist').click({ force: true }).wait(15000);
    
    
    
        // Navigation process before each test case
        cy.get('.yw-navigationNode-level1').contains(marketingMenuText)
            .should('exist').click({ force: true }).wait(3000);
        cy.get('span.z-label').contains(promotionRulesText)
            .should('exist').click({ force: true }).wait(5000);
    });

Basically, I've added a beforeEach() command to the very beginning of the test. This way for every test case Cypress repeats all steps including the login, choosing role options and so on.
So from the functionality perspective this solution works, but I believe the test could be much more efficient if it wouldn't repeat all steps from the beginning for every test case (since it doesn't make sense to login again for every single test case).


Solution

  • The behavior you observed where the page starts blank is called test isolation, it's generally considered best practice as state from an earlier test can give an unintended false-positive result in a second test.

    Some docs to reference:

    Test Isolation as a Best Practice
    concepts - test isolation

    The beforeEach() is the simplest way to adhere to the test isolation principal, and it can possibly be improved by wrapping it's code in a cy.session() command.

    This command takes parameters cy.session(id, setup) where setup is a function which will contains the commands in your beforeEach().

    The setup function is only called on the first test, and at the end any values found in browser cookies, localstorage, and sessionstorage are saved.

    On the second call, the saved values are reinstated after the browser has been cleared. Theoretically, your web page sees these values and is "fooled" into thinking the page has already performed the login.

    This is the pattern for using it:

    beforeEach(() => {
      cy.session('login', () => {
        // code to perform to perform login
        // which will only be run during the first test
      })
    })