Home > Back-end >  How to implement Cypress v10 session() to persist cookies that are not initially available
How to implement Cypress v10 session() to persist cookies that are not initially available

Time:10-20

I am running cypress v10 on a react front-end and trying to get my cookies to persist through some of my tests.

I am testing the flow of logging in and out of my app. As of V10 cy.session() appears to be the way to go. However, most of the examples I have seen have just been adding a cookie in a named session object right at the start in a beforeEach().

I don't have the cookies initially available at the beginning of the test module, I create them a few tests down (as below), doing some more tests whilst logged in with the cookies and then logging out, removing the cookies.

So I'm a bit confused on how to implement session() into the mix of the following code. Could use some direction on the structure, thanks!

describe('Auth (e2e)', () => {
    
  it('should load and redirect to /login', () => {
    cy.visit('https://localhost:3000/');
    cy.wait(500);
    cy.url().should('include', 'login');
  });
    
  it('login button should be disabled initially', () => {
    cy.get('#btn-login').should('have.attr', 'disabled');
  });
    
  it('login button should be enabled upon enter valid details', () => {
    cy.get('#tbxUsername').click().type('hfisher');
    cy.get('#tbxPassword').click().type('#VS1DEV');
    cy.get('#btn-login').should('not.have.attr', 'disabled');
  });
    
  it('should navigate to the home/dashboard upon logging in', () => {
    cy.get('#btn-login').click();
    cy.wait(500);
    cy.url().should('not.include', 'login');
    cy.url().should('include', '/');
    /***** Here it finds the 4 cookies just fine ******/
    cy.getCookies().should('have.length', 4);
  });
    
  it('should have 4 cookies available', () => {
    /***** Cookies are gone at this point ******/
    cy.getCookies().should('have.length', 4);
  });
    
  it('should have a JwtToken cookie', () => {
    cy.getCookie('JwtToken').should('exist');
  });
  it('should have a SystemData cookie', () => {
    cy.getCookie('SystemData').should('exist');
  });
  it('should logout via the profile menu and navigate to the login', () => {
    cy.get('#profile-menu-icon').click();
    cy.get('#profile-menu-item-logout').click(); //Logout called here
    cy.wait(500);
    cy.url().should('include', 'login');
  });
  it('should not have any cookies after logout', () => {
    cy.getCookies().should('have.length', 0);
  });
  it('login button should be disabled after logout', () => {
    cy.get('#btn-login').should('have.attr', 'disabled');
  });
  it('should not display profile menu in the header after logout', () => {
    cy.get('#profile-menu-icon').should('not.exist');
  });
  //Login again via auto-authenticate
  it('should navigate to the dashboard from the auto-login upon clicking auto-authenticate button in the login screen', () => {
    cy.get('#autologin-link').click();
  });
});

CodePudding user response:

The cy.session() command seems to only work well where the tests are decoupled, that is one does not depend on the other.

But for your test suite it doesn't seem right to move the code from the first three tests into a beforeEach() in order to use cy.session() to persist the cookies.

Instead, you can take a simpler approach - in the test where the cookies are set, save them to the environment, then add a beforeEach() to restore them.

describe('Auth (e2e)', () => {
    
  beforeEach(() => {
    const cookies = Cypress.env('cookies')   
    cookies.forEach(c => cy.setCookie(c.name, c.value))
  })

  it('should load and redirect to /login', () => {...})        // no cookies here 
  it('login button should be disabled initially', () => {...}) // still no cookies
  it('login button should be enabled...', () => {...})         // still no cookies 
    
  it('should navigate to the home/dashboard upon logging in', () => {
    cy.get('#btn-login').click();
    ...
    // Save cookies to environment
    cy.getCookies().then(cookies => Cypress.env('cookies', cookies))
  });
    
  it('should have 4 cookies available', () => {...}) // cookies are persisted here
  it('should have a JwtToken cookie', () => {...})   // cookies are persisted here

  it('should logout via the profile menu and navigate to the login', () => {
    cy.get('#profile-menu-item-logout').click(); //Logout called here
    ...
    Cypress.env('cookies', null)   // Remove environment cookies
  });

  it('should not have any cookies after logout', () => {...})   // no cookies here
})

As an after-thought, you could divide the tests into three subsections

describe('Auth (e2e)', () => {
    
  describe('loggin in', () => {
    it('should load and redirect to /login', () => {...})  
    it('login button should be disabled initially', () => {...})
    it('login button should be enabled...', () => {...})     
    it('should navigate to the home/dashboard upon logging in', () => {
      cy.get('#btn-login').click();
      ...
      // Save cookies to environment
      cy.getCookies().then(cookies => Cypress.env('cookies', cookies))
    });
  }}

  describe('when logged in', () => {

    beforeEach(() => {
      const cookies = Cypress.env('cookies')   
      cookies.forEach(c => cy.setCookie(c.name, c.value))
    })
    
    it('should have 4 cookies available', () => {...}) 
    it('should have a JwtToken cookie', () => {...})   
  })

  describe('on logging out', () => {
    it('should logout...', () => {
      cy.get('#profile-menu-item-logout').click(); //Logout called here
      ...
    });
    it('should not have any cookies after logout', () => {...})   
  })
})
  • Related