Cypress: Cookies set by http response are getting overwritten with a previous value

Created on 12 Feb 2019  路  10Comments  路  Source: cypress-io/cypress

Current behavior:

I am writing a test where I sign in with one user, logout and then sign in with another user. This endpoint drops a userId cookie. When I sign in as the second user the cookie seems to only be set on '/' and not '/events'.

When I try logging out debug cookies it looks like it gets set with the second user but then reset with the previous cookie.

Cookie debug logs for test below. (I've changed our ids for the example ones in the test - the domains are all the same.)

cypress-cookie-setting-issue

Desired behavior:

When I sign in with a second user the previous cookie does not get set on other paths.

Steps to reproduce: (app code and test code)

 it('should test cookies', () => {
    // sign in with user-1
    cy.visit('/')
    cy.login('[email protected]')
    cy.getCookie('userId')
      .its('value')
      .should('equal', 'userId1') // passes

    cy.visit('/events')
    cy.getCookie('userId')
      .its('value')
      .should('equal', 'userId1') // passes

    // logout
    cy.clearCookies()
    cy.visit('/')

    // sign in with user-2
    cy.login('[email protected]')
    cy.getCookie('userId')
      .its('value')
      .should('equal', 'userId2') // passes

    cy.visit('/events')
    SelectEventsPage.verifyIsLoaded()
    cy.getCookie('userId')
      .its('value')
      .should('equal', 'userId2') // fails gets userId1 instead
  })

Cypress.Commands.add('login', (email, password = 'password') => {
  Cypress.log({
    name: 'login',
    message: 'Logging in via POST /api/login'
  })

  return cy.request({
    method: 'POST',
    url: '/api/login',
    headers: { ['X-Csrf-Prevention']: 'true' },
    body: { email, password }
  })
})

Versions

Cypress: 3.1.5
Browser: Chrome 72
OS: macOS mojave

topic bug

Most helpful comment

Looked into this further and confirmed that clearing down buffers as part of cy.clearCookies() fixed the issue. I guess ideally we'd do something similar for cy.clearCookie().

I did this in a pretty horrible way though - added a couple of methods to options in server.coffee startWebSockets() and called straight into it from socket.coffee.

Any thoughts on better approach? I see a few TODOs lurking around buffers anyway.

All 10 comments

Hey, do you mind my asking, what does this method do here - SelectEventsPage.verifyIsLoaded()? Do you have the code for this?

yep it just checks for a data attribute on our events page
```
export const verifyIsLoaded = () => cy.get('.event-layout__wrapper[data-test-loading="false"]')
````

Might previous cookies may be hanging around on the buffers object on server.coffee? This doesn't seem to get cleared between tests, nor when cookies are cleared.

Would it make sense for this buffers object to be reset when cy.clearCookies() is called?

Looked into this further and confirmed that clearing down buffers as part of cy.clearCookies() fixed the issue. I guess ideally we'd do something similar for cy.clearCookie().

I did this in a pretty horrible way though - added a couple of methods to options in server.coffee startWebSockets() and called straight into it from socket.coffee.

Any thoughts on better approach? I see a few TODOs lurking around buffers anyway.

More info: we use a service worker with workbox, configured with workbox.routing.registerNavigationRoute. This intercepts navigation requests and serves them from index.html for our SPA, and this file is cached enabling the app to work offline.

In the absence of the service worker and with DEBUG=cypress:*, Cypress logs setting buffer for url:, (an entry being put into buffers) followed by found request buffer, at which point the entry would be removed from buffers by buffers.take(). The old cookies are not reapplied.

Our issue is due to the request URL being modified by the service worker - we can see that we go through buffers.take() with the URL modified to index.html and don't see the found request buffer logging. We then encounter the dreaded got previous request buffer for url, when that buffer entry would usually have been removed. This causes the old cookies to be reapplied incorrectly.

Hey @j-mew-s, feel free to open a work in progress [WIP] pull request to get some feedback on any fixes you've made to Cypress - that's probably better than trying to explain the changes.

Unfortunately my fix is very much a sticking plaster, it doesn't tackle the root cause at all, just the symptom. I need to get my head around the flow of data that results in different request URLs being used to set/take buffers by server/lib/controllers/proxy.coffee and server/lib/server.coffee to have a chance at a PR that's heading in the right direction.

If I can find time, I'll try to put together a small workbox-based project that demonstrates the issue though.

I have tried to recreate in this repo: https://github.com/majicmoo/cypress-cookie-bug
Its a little flakey but seems to fail for me 90% of the time when running in chrome.
Screenshot 2019-03-20 at 11 41 57

I believe I have run into this exact same issue. I started using the following command instead of cy.visit() directly as a workaround.

Cypress.Commands.add("goto", {prevSubject: false}, (url, options={}) => {
    if(options.log !== false) {
        Cypress.log({
            name: "goto",
            message: `Goto ${url}`
        });
    }

    const target = new URL("http://localhost" + url);
    const params = new URLSearchParams(target.search);
    params.append("cypressBuffferFix", Date.now());
    const adjusted = target.pathname + "?" + params.toString() + target.hash;
    cy.visit(adjusted, {
        log: false,
    });
});

This is very annoying, but it is getting me past the problem. I tried debugging Cypress as well, and the logs clearly show that buffers.set() and buffers.take() calls are not always matched correctly. This incorrect "caching" causes cookies to resurrect no matter what you try to do about it. It only seems to be a problem when calling cy.visit() and not when my application makes XHR requests. I'm not sure why that is.

This issue almost made my team give up on our Cypress experiment completely. It made it impossible to ever visit the same URL as two different users. Hoping for a proper fix!

This seems to be fixed for me on v4.0.* so going to close 馃憤

Was this page helpful?
0 / 5 - 0 ratings