Search code examples
javascriptcookiesjestjsfetch-apie2e-testing

Cookies with Fetch polyfill in Jest


I'm setting up e2e tests in jest, and I'd like to have fetch send my cookies when I call it like:

const userinfo = await fetch('/api/auth/me')

I've set up my jest config with

testEnvironmentOptions: {
  url: 'http://localhost:5544/'
},

and added import 'whatwg-fetch' to my jest.setup.js file, which is great it gets me to the point where my fetch requests are working on relative paths. However, I cannot for the life of me get fetch to send along my auth cookie.

I've added my cookie to the document like so

  Object.defineProperty(window.document, 'cookie', {
    writable: true,
    value: 'auth=...',
  });

I've tried setting my fetch credentials property to include and same-origin with no luck. I read through the CORS guide, but that's all about how to get the browser to set the cookie - in my case I've already set the cookie myself. On my server the request always comes through with no cookie attached. I'm stumped, has anyone else solved this issue before?

UPDATE: I have tried more things without success:

  1. adding domain and path to the cookie
  Object.defineProperty(window.document, 'cookie', {
    writable: true,
    value: 'auth=...;domain=localhost:5544;path=/',
  });
  1. adding 'same-origin' mode to verify that the request is the same origin (it is, the request goes through without error)
const userinfo = await fetch('/api/auth/me', {credentials: "same-origin", mode: 'same-origin'});
  1. checking the headers on the incoming request on the server side:
{
  referer: 'http://localhost:5544/',
  'user-agent': 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/20.0.3',
  'accept-language': 'en',
  accept: '*/*',
  'accept-encoding': 'gzip, deflate',
  host: 'localhost:5544',
  connection: 'keep-alive'
}

None of these things has helped, the request still goes through without attaching the cookie


Solution

  • GOT IT!! Took me a while of hunting down what was happening, but basically jsdom has its own cookie implementation, and so calling Object.defineProperty was overriding the implementation in jsdom. AWESOME. All you have to do is set

    document.cookie = 'auth=...'
    

    and you're good to go. I also discovered that fetch defaults to {credentials: 'same-origin'} so my calls can just be:

    await fetch(`/api/auth/me`)
    

    and everything is gold.