🧪

JestでsessionStorageの値を使ったテストをする

2020/09/18に公開

TypeScriptでいい感じにかけるライブラリとかが見当たらなかったので、自前で書いた覚書。

参考記事

setupTests.ts

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,
});

力技的wrapper関数

都度spyOnしてそれをrestoreするコードを書くのめんどいなと思ったので、ラッパーいれます。

export type SessionStorageData = {
  [itemName: string]: string;
}
export function withMockSessionStorage<Mock extends SessionStorageData = SessionStorageData>(mockStorageData: Mock, describeFunction: jest.EmptyFunction) {
  let spy;
  beforeAll(() => {
    spy = jest.spyOn(window.sessionStorage, 'getItem')
      .mockImplementation((name: string) => {
        if (Object.keys(mockStorageData).includes(name)) {
          return mockStorageData[name];
        }
        return null;
      });
  });
  describeFunction();
  afterAll(() => {
    spy.mockRestore();
  });
}

使う

あとはこんな感じで使うだけです。
describeの第二引数と同じ型を指定してあるので、ラッパーの中はdescribeと同じようにかける(はず)です。


describe('with command id in the session storage', () => {
    const props = {
        siteId: 'xxx-xxx-xxx',
        describe: jest.fn()
    }
    withMockSessionStorage<{
        command_id: string
    }>({
      'command_id': 'session_command_id',
    }, () => {
      beforeEach(() => {
        renderHook(() => useMyCustomHook(props));
      });
      it('should call describeReuslt by default', () => {
        expect(props.describe).toHaveBeenCalledWith('session_command_id');
      });
      afterEach(() => {
          props.describe.mockClear()
      })
    });
  });

Discussion