cypress: cy.request doesn't set cookie with specific domain

Current behavior:

baseURLis set to: http://localhost:3000 cy.request() is not setting cookies that comes with a domain.

screenshot from 2019-01-25 11-13-18

Desired behavior:

cy.request() should set cookies with specific domain.

Steps to reproduce: (app code and test code)

describe('Cookie', () => {
  Cypress.Cookies.debug(true);

  it('SHOULD set the cookie if it have domain', () => {
    cy.request({
      method: 'POST',
      url: 'http://localhost:3000/cookie-with-domain'
    })
      .then(()=> {
        cy.getCookie('domain-cookie')
          .should('have.property', 'value', '1');
      });
  });

  it('Does set the cookie', () => {
    cy.request({
      method: 'POST',
      url: 'http://localhost:3000/cookie-without-domain'
    })
      .then(()=> {
        cy.getCookie('cookie')
          .should('have.property', 'value', '1');
      });
  });

  it('Works fine on both', () => {
    cy.visit('http://localhost:3000/cookie-with-domain');
    cy.visit('http://localhost:3000/cookie-without-domain');
    cy.getCookie('domain-cookie')
      .should('have.property', 'value', '1');
    cy.getCookie('cookie')
      .should('have.property', 'value', '1');
  });
});

Using expressjs on the server and this:

  app.all('/cookie-with-domain', (req, res)=>{
    res.cookie('domain-cookie',1, { maxAge: 900000, httpOnly: true, domain: 'localhost'});
    res.send('Hello!');
  });

  app.all('/cookie-without-domain', (req, res)=>{
    res.cookie('cookie',1, { maxAge: 900000, httpOnly: true});
    res.send('Hello!');
  });

Versions

Cypress: 3.1.1 OS: Ubuntu 18.04 Browser: Chrome 71

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 21 (7 by maintainers)

Most upvoted comments

Hello team,

Do you have any news about this regression? Unfortunately, the workarounds are not the final solution.

Thanks for information.

I just checked the reproducible example provided in the OP and it appears to be fixed starting with Cypress 3.5.0. Please upgrade your version of Cypress to the latest to get the fix for this issue.

My workaround, which is similar to @rewop 's one:

Cypress.Commands.add('loginNoUi', (email, password) => {
    // Regular form POST
    cy.request({
        method: 'POST',
        form: true,
        followRedirect: false,
        url: '/login',
        body: {
            username: email,
            password: password
        }
    }).then((response) => {
        //Extract cookie value from response's "set-cookie" header.
        const token = response.headers['set-cookie'][0].replace('SM_SESSION=', '').split(';')[0];

        //Set the cookie explicitly
        cy.setCookie('SM_SESSION', token);

        // Attach 'Cookie' header manually and go to main page of application. It's possible to navigate everywhere from there.
        cy.visit('/', {headers: {'Cookie': `SM_SESSION=${token}`}});
    });
});

After that, I use the regular page navigation with a click() function and navigation works correctly.

In my opinion, there are two problems here:

  1. cy.request() does not set cookies automatically (login endpoint responds with HTTP 302 and cookie with domain name set)
  2. cy.visit() does not attach cookies automatically

I hope I saved someone hours of experimenting.

It looks like I am facing the same problem. However to me it seems that the error only happen if Domain="localhost" is set. If the Domain= is present and set to something else cookies are set as expected.

Our work around is setting the cookie without domain

cy
    .request({
      url: `${backendHost}/api/v2/user`,
      method: 'POST',
      body: {
        email: `${uuid()}@test.ru`,
        ...details,
      },
      auth,
    })
    .then(response => {
      return cy.getCookie('session_id')
    })
    .then(({ headers, body }) => {
      const cookieHeader = headers['set-cookie'].map(cookie =>
        cookie.split('; ')[0].split('='),
      )[0];

      return cy.setCookie(cookieHeader[0], cookieHeader[1])
          .then(() => body);
    })

For information, this issue appears to be complete killing my ability to use Cypress against our application (and appreciate that this could be a limitation due to how our app works).

During the tests we need to interact with our API as an Administrator to create specific organizations to isolate tests. Once that’s done we shift to a specific tenant domain which responds correctly with a domain cookie in the response header. The tenant domain cookie isn’t set, and we end up with unauthenticated errors.

I’ve tried working around this by parsing the set-cookie header and then setting a cookie with the following code (without any luck so far):

cy.setCookie(name, value, {options}).then( () => {  
  cy.getCookies();      // The new cookie are shown in the Cypress log  
  cy.request(somePath); // This call doesn't have the new cookie
})

I figured the above would work…but no luck yet.