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
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);
});
});