Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is the best way to mock window.sessionStorage in jest

Tags:

Below is a very simple jest unit test and when running it, you will get error like

Cannot spyOn on a primitive value; undefined given

TypeError: Cannot read property 'getItem' of undefined

but according to the last two comments of this post, localStorage and sessionStorage were already added to latest JSDOM and jest. If using jest-localstorage-mock and add it to my jest setupFiles then you will see weird error like

TypeError: object[methodName].mockImplementation is not a function

So my question is what's the best way to mock localStorage/sessionStorage in jest. Thanks

describe('window.sessionStorage', () => {
    let mockSessionStorage;
    beforeEach(() => {
        mockSessionStorage = {};
        jest.spyOn(window.sessionStorage, "getItem").mockImplementation(key => {
            return mockSessionStorage[key];
        });
    });

    describe('getItem-', () => {
        beforeEach(() => {
            mockSessionStorage = {
                foo: 'bar',
            }
        });

        it('gets string item', () => {
            const ret = window.sessionStorage.getItem('foo');
            expect(ret).toBe('bar');
        });
    });
});

Below is my jest config

module.exports = {
    verbose: true,
    //setupFiles: ["jest-localstorage-mock"],
    testURL: "http://localhost/"
};
like image 933
LHE Avatar asked Jul 27 '18 23:07

LHE


People also ask

How do I set session storage in Jest?

To mock local storage in Jest tests, we can create our own mock local storage methods. const localStorageMock = (() => { let store = {}; return { getItem(key) { return store[key]; }, setItem(key, value) { store[key] = value. toString(); }, clear() { store = {}; }, removeItem(key) { delete store[key]; } }; })(); Object.

Does Jest mock localStorage?

In short: localStorage is actually an instance of a Storage class. Sadly, mocking methods on a class instance (i.e. localStorage. getItem ) doesn't work with our jest.

How do I find my Windows sessionStorage?

# View sessionStorage keys and valuesClick the Application tab to open the Application panel. Expand the Session Storage menu. Click a domain to view its key-value pairs. Click a row of the table to view the value in the viewer below the table.

Is sessionStorage always available?

Session storage is the same as local storage but the only difference is that data stored in session storage will clear automatically once the page session will expire.


2 Answers

Here is the solution only use jestjs and typescript, nothing more.

index.ts:

export function getUserInfo() {
  const userInfo = window.sessionStorage.getItem('userInfo');
  if (userInfo) {
    return JSON.parse(userInfo);
  }
  return {};
}

index.spec.ts:

import { getUserInfo } from './';

const localStorageMock = (() => {
  let store = {};

  return {
    getItem(key) {
      return store[key] || null;
    },
    setItem(key, value) {
      store[key] = value.toString();
    },
    removeItem(key) {
      delete store[key];
    },
    clear() {
      store = {};
    }
  };
})();

Object.defineProperty(window, 'sessionStorage', {
  value: localStorageMock
});

describe('getUserInfo', () => {
  beforeEach(() => {
    window.sessionStorage.clear();
    jest.restoreAllMocks();
  });
  it('should get user info from session storage', () => {
    const getItemSpy = jest.spyOn(window.sessionStorage, 'getItem');
    window.sessionStorage.setItem('userInfo', JSON.stringify({ userId: 1, userEmail: '[email protected]' }));
    const actualValue = getUserInfo();
    expect(actualValue).toEqual({ userId: 1, userEmail: '[email protected]' });
    expect(getItemSpy).toBeCalledWith('userInfo');
  });

  it('should get empty object if no user info in session storage', () => {
    const getItemSpy = jest.spyOn(window.sessionStorage, 'getItem');
    const actualValue = getUserInfo();
    expect(actualValue).toEqual({});
    expect(window.sessionStorage.getItem).toBeCalledWith('userInfo');
    expect(getItemSpy).toBeCalledWith('userInfo');
  });
});

Unit test result with 100% coverage report:

 PASS  src/stackoverflow/51566816/index.spec.ts
  getUserInfo
    ✓ should get user info from session storage (6ms)
    ✓ should get empty object if no user info in session storage (1ms)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.ts |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        4.548s, estimated 6s

Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/51566816

like image 61
slideshowp2 Avatar answered Sep 24 '22 20:09

slideshowp2


You probably do not even need a mock. Just use window.sessionStorage as usual and write your condition based on window.sessionStorage.getItem(...) result instead of spying window.sessionStorage.setItem . Simply don't forget to call window.sessionStorage.clear() in beforeEach as demonstrated.

From Eric Burel's comment

like image 39
DLight Avatar answered Sep 23 '22 20:09

DLight