Home > Blockchain >  waiting for cookie in Cypress spec
waiting for cookie in Cypress spec

Time:06-22

I have problem with reading cookie in my Cypress test

/// <reference types="cypress" />

describe('cookie', () => {
    beforeEach(() => {
        cy.setCookie('abc', 'def');
    });

    it('read', () => {
        let cookieValue: string;
        cy.getCookie('abc').should('exist').then(c => cookieValue = c.value);
        cy.wrap(cookieValue).should('not.equal', undefined);
    });
});

I have error from last should: expected undefined to not equal undefined

Cypress console

Edit 1

My aim is to have cookie value synchronically. I managed to have working code:

  let cookieValue: string;
  it('read', async () => {
    cy.wrap(cookieValue).should('equal', undefined);
    cookieValue = await new Promise(resolve => cy.getCookie('abc').should('exist').then(c => resolve(c.value)));
    cy.wrap(cookieValue).should('not.equal', undefined);
  });

but it doesn't look cypress-way. Any other solution?

CodePudding user response:

The Cypress commands are async, you need to wrap and test inside the .then()

cy.getCookie('abc').should('exist').then(c => 
  cookieValue = c.value
  cy.wrap(cookieValue).should('not.equal', undefined);
);

More precisely, Cypress commands run in a queue, but cy.wrap(cookieValue) will take the value of cookieValue before the queue runs, i.e it has the original empty value when enqueued.


You can synchronously get all the cookies related to test document using plain javascript.

Since the return value is a string you may need to parse more complex values such as objects.

const document = cy.state('document')
const cookieValue = document.cookie
  .split('; ')
  .find(row => row.startsWith('abc='))
  ?.split('=')[1];

You can also await cy.now()

it('takes the cookie', async () => {
  const cookieObject = await cy.now('getCookie', 'abc')
  /* Properties
    domain: "localhost"
    expiry: 2287046766
    httpOnly: false
    name: "abc"
    path: "/"
    secure: false
    value: "my-cookie-value"
  */
  const cookieValue = cookieObject.value

CodePudding user response:

You can use an alias as to save the cookie value and then access it outside then like this. One thing to remember is the aliases will work within the same test, because cypress clears aliases between tests. If you want to access the value throughout the tests, I would suggest you to use Cypress.env(), explained below.

/// <reference types="cypress" />

describe('cookie', () => {
  beforeEach(() => {
    cy.setCookie('abc', 'def')
  })

  it('read', () => {
    let cookieValue: string
    cy.getCookie('abc')
      .should('exist')
      .then((c) => {
        cy.wrap(c.value).as('cookieValue')
      })
    cy.get('@cookieValue').then((cookieValue) => {
      expect(cookieValue).to.not.be.undefined
    })
  })
})

You can also use Cypress.env to globally save the cookie value and use it anywhere throughout the project.

/// <reference types="cypress" />

describe('cookie', () => {
  beforeEach(() => {
    cy.setCookie('abc', 'def')
  })

  it('read', () => {
    let cookieValue: string
    cy.getCookie('abc')
      .should('exist')
      .then((c) => {
        Cypress.env('cookieValue', c.value)
      })
    cy.wrap(Cypress.env('cookieValue')).should('not.equal', undefined)
  })
})

CodePudding user response:

You can store the cookie in a variable at the same time as setting it

describe('cookie', () => {
   let cookieValue: string;

    beforeEach(() => {
        cy.setCookie('abc', 'def');
        cookieValue = 'def'
    });

    it('read', () => {
        cy.wrap(cookieValue).should('not.equal', undefined);
    });
});

If the cookie is already set going in to the test, extracting in beforeEach block gives you a synchronous value.

describe('cookie', () => {
   let cookieValue: string;

    beforeEach(() => {
        cy.getCookie('abc').should('exist')
          .then(c => cookieValue = c.value);
    });

    it('read', () => {
        cy.wrap(cookieValue).should('not.equal', undefined);
    });
});
  • Related