Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot clear cookies between Jest tests #1586

Closed
4 tasks done
antoinetissier opened this issue Apr 6, 2023 · 6 comments
Closed
4 tasks done

Cannot clear cookies between Jest tests #1586

antoinetissier opened this issue Apr 6, 2023 · 6 comments
Labels
bug Something isn't working needs:triage Issues that have not been investigated yet. scope:node Related to MSW running in Node

Comments

@antoinetissier
Copy link

antoinetissier commented Apr 6, 2023

Hello,

I am trying to clear cookies between Jest tests but I haven't been able to, even though #708 suggests it should be feasible.

I have a minimal reproduction setup as described below.
Please let me know if I missed something !

Prerequisites

Environment check

  • I'm using the latest msw version
  • I'm using Node.js version 14 or higher

Node.js version

18.12.1

Reproduction repository

https://github.com/antoinetissier/msw-jest-cookies

Reproduction steps

Run yarn test: the second test fails (the authentication is unexpectedly successful as the cookie should have been cleared).
If the second test is run in isolation through it.only(), the test passes.

Current behavior

It doesn't seem possible to clear cookies between different tests.

Expected behavior

I expect to be able to clear cookies between tests.
#708 suggests that it's possible but I haven't been able to do it.

Note: I am using jsdom as testing environment for Jest.

@antoinetissier antoinetissier added bug Something isn't working needs:triage Issues that have not been investigated yet. scope:node Related to MSW running in Node labels Apr 6, 2023
@kettanaito
Copy link
Member

Hi! Thanks for reporting this.

Although MSW sets the document cookie, it does that per your intention. This means that it's also your responsibility to clear that cookie between tests not to introduce a shared state that results in unreliable test runs.

I can see you're already doing that right here but note that working with document.cookie is a bit tricky. That's why what we do internally when testing cookies, we use a special utility that clears all the cookies:

export function clearCookies(): void {
document.cookie.split(';').forEach((cookie) => {
document.cookie = cookie
.replace(/^ +/, '')
.replace(/=.*/, `=;expires=${new Date(0).toUTCString()};path=/`)
})
}

I recommend you give this utility a try. Alternatively, you can research how to correctly clear document.cookie string in Jest (since Jest/JSDOM implements it, its behavior may even differ compared to how it behaves in the browser, so beware that).

@antoinetissier
Copy link
Author

Hi @kettanaito,

Thank you for your answer.

I had tried this clearCookies function from msw's code, but unfortunately it led to the same behavior.
That's why I ended going for something simpler in the minimal reproduction setup.

@kettanaito
Copy link
Member

kettanaito commented Apr 6, 2023

Sorry to hear it didn't help. I recommend raising this in the Jest community (or Reactiflux discord) because it doesn't look like an MSW issue. I think you can even rule out MSW from this reproduction by assigning document.cookie manually in the first test, I think the behavior will be the same.

@antoinetissier
Copy link
Author

antoinetissier commented Apr 7, 2023

@kettanaito I did some more investigation and this does look like an MSW issue (or lack of documentation) to me.

Here are my findings:

So what happens in the reproduction setup is that:

  • After the first test, a cookie is set both in MSW's store and document.cookie.
  • At the beginning of the second test, the cookie is successfully cleared from document.cookie, but not from MSW's store.
  • So the cookie "leaked" from the first test is sent in the second test's request, which makes the second test fail when not run in isolation.

The solution is to clear both document.cookie and MSW's cookie store:

import { store as cookieStore } from "@mswjs/cookies";

function clearCookies() {
  document.cookie.split(";").forEach((cookie) => {
    document.cookie = cookie
      .replace(/^ +/, "")
      .replace(/=.*/, `=;expires=${new Date(0).toUTCString()}`);
  });
  cookieStore.clear();
  window.localStorage.clear();
}

beforeEach(() => {
  clearCookies();
});

In my opinion it would be nice to make that clear in the documentation, as currently MSW's internal cookie store is not mentioned anywhere.
I'm happy to do a PR if you agree with this analysis.

Side note: in the test setup, it seems that to prevent the cookie from being accessible through document.cookie, both HttpOnly and Secure must be set.
This looks like a jsdom bug to me: in a real browser setting HttpOnly is enough.

@michaelnwani
Copy link

@antoinetissier adding an update for anyone that finds their way here from google like myself:

You may have to clear your cookie without adding the expires= segment. It's the only form that worked for me (using jsdom + vitest + msw). So it would look like so:

function clearCookies() {
  document.cookie.split(';').forEach((cookie) => {
    document.cookie = cookie.replace(/^ +/, '').replace(/=.*/, `=;`);
  });

  cookieStore.clear();
  window.localStorage.clear();
}

@antoinetissier
Copy link
Author

Hey @michaelnwani, thanks for your answer. The snippet that I posted above worked for me. Maybe this has something to do with jest vs vitest ?

@kettanaito sorry to insist, but would you consider documenting this somewhere ? I'm happy to do a PR if you agree with the idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs:triage Issues that have not been investigated yet. scope:node Related to MSW running in Node
Projects
None yet
Development

No branches or pull requests

3 participants