Home > Back-end >  Why can't I assign a value to document.cookie for each jest test?
Why can't I assign a value to document.cookie for each jest test?

Time:08-18

I'm trying to test how my application handles cookies or the lack of cookies. So far I have just two simple tests that I want to try.

How the tests should behave
Test 1: I set document.cookie to some value & my function returns the cookie as an object
Test 2: I set document.cookie back to empty string & my function returns undefined

How the tests actually behave
Test 1: document.cookie is set and my function returns the proper object
Test 2: `document.cookie1 is set back to empty string, but still returns the object from the previous test.

I could just run test # 2 first, but that just avoids the problem rather than fix the problem.
Plus, I would like to understand why the problem is happening.

Why can't I set or modify the document object after my initial change to document.cookie? I've also tried document.cookie = '' in the beforeEach and that didn't work either.

Jest Test

test('if the browser has a session cookie, then its data will be returned as an object', () => {
  document.cookie =
    'session={"userId":8,"expiration":1660938823,"accessToken":"fakeAccessToken","refreshToken":"fakeRefreshToken"}';
  const data = cookieData();
  expect(data).toEqual(EXPECTED_STRUCTURE);
});

test('if the browser does not have a session cookie, then undefined will be returned', () => {
  document.cookie = '';
  const data = cookieData();
  expect(data).toBe(undefined);
});

const EXPECTED_STRUCTURE = {
  userId: 8,
  expiration: 1660938823,
  accessToken: 'fakeAccessToken',
  refreshToken: 'fakeRefreshToken'
};

Code

export const cookieData = (): ICustomCookieStructure | undefined => {
  try {
    const cookies = document.cookie.split(COOKIES_SEPARATOR);
    const cookieIndex = cookies.findIndex((el) =>
      el.includes(TARGET_COOKIE_PREFIX)
    );
    if (cookieIndex === -1) return undefined;
    const cookieContent = cookies[cookieIndex].replace(
      TARGET_COOKIE_PREFIX,
      ''
    );
    const contentDecoded = decodeURIComponent(cookieContent);
    const contentParsed = JSON.parse(contentDecoded);
    if (Object.keys(contentParsed).length) {
      return {
        userId: contentParsed.userId,
        expiration: Number(contentParsed.expiration),
        accessToken: contentParsed.accessToken,
        refreshToken: contentParsed.refreshToken
      };
    }
  } catch (e: any) {
    throw new Error(
      `Failed to either get or parse cookie from browser: ${e.message}`
    );
  }

  return undefined;
};

CodePudding user response:

I figured out a solution to the problem, although I still don't understand why I couldn't set document.cookie more than once.

Here was the way around it:

const mockFunction = jest.fn();

beforeAll(() => {
  Object.defineProperty(document, 'cookie', {
    get: mockFunction
  });
});

beforeEach(() => {
  mockFunction.mockReturnValue('');
});

test('if browser has our cookie, then its data will be returned', () => {
  mockFunction.mockReturnValue(COOKIE_VALUE);
  const data = cookieData();
  expect(data).toEqual(EXPECTED_STRUCTURE);
});

test('if browser does not have our cookie, then undefined will be returned', () => {
  const data = cookieData();
  expect(data).toBe(undefined);
});

CodePudding user response:

I assume it's because once document.cookie is assigned it get's treated as readonly. I had something similar happening recently as well. What you can do though is something similar to this:

Object.defineProperty(document.documentElement, "lang", {
      value: null,
      configurable: true,
    });

So for your specific case you could try:

Object.defineProperty(document, "cookie", {
      value: '',
      configurable: true,
    });
  • Related