Since the latest release of JSDom, I'm not able to mock localStorage
anymore.
I've tried the following methods:
Object.defineProperty(window, 'localStorage', {value: LocalStorageMock})
window.localStorage = LocalStorageMock;
jest.spyOn(window.localStorage, 'setItem')
Any of those methods not worked for me, I get always the original localStorage
.
Since the latest release of JSDom, I'm not able to mock localStorage
anymore.
I've tried the following methods:
Object.defineProperty(window, 'localStorage', {value: LocalStorageMock})
window.localStorage = LocalStorageMock;
jest.spyOn(window.localStorage, 'setItem')
Any of those methods not worked for me, I get always the original localStorage
.
4 Answers
Reset to default 8setItemSpy = jest.spyOn(Storage.prototype, 'setItem');
works for me.
Saw this fix here: https://github.com/facebook/jest/issues/6858#issuecomment-413677180
I actually ran into this same issue when updating Jest, not sure if that's what happened to you but I found this fix here: https://github.com/facebook/jest/issues/6766
From OlivierB-OB:
As a temporary workaround you can install jsdom "11.11.0" (exact) as a dev-dependency in your package. jest-environment-jsdom should then use this version instead of the lastest "11.12.0" causing the behavior. Cheers!
After that I mocked localstorage in test setup and spying was back to normal.
And an implementation of localstorage mock: https://github.com/facebook/jest/issues/2098 lacks removeItem though, so you might need to add it.
You can use the dom-storage package available via npm:
const Storage = require('dom-storage');
global.localStorage = new Storage(null, { strict: true });
global.sessionStorage = new Storage(null, { strict: true });
We use the latest release of jsdom
for our unit tests and the above method has worked great.
I've create a function that mocks localStorage
. It implements only two methods getItem
and setItem
. You can easily add other methods if needed.
export const localStorageImpl = {
register: () => {
let storage = (window as any).customLocalStorage;
if(storage) {
return {
storage,
methods: (window as any).customLocalStorageMethods
}
}
storage = (window as any).customLocalStorage = {} as any;
const setItem = jest.spyOn(Storage.prototype, 'setItem');
setItem.mockImplementation((key, value) => {
storage[key] = value;
});
const getItem = jest.spyOn(Storage.prototype, 'getItem');
getItem.mockImplementation((key) => {
return storage[key];
});
const methods = (window as any).customLocalStorageMethods = {
setItem,
getItem
};
return {
storage,
methods
}
},
unregister: () => {
const methods = (window as any).customLocalStorageMethods;
if(methods){
const { setItem, getItem } = methods as { setItem: jest.SpyInstance<void, [key: string, value: string]>, getItem: jest.SpyInstance<string, [key: string]> };
setItem.mockReset();
getItem.mockReset();
}
delete (window as any).customLocalStorageMethods;
delete (window as any).customLocalStorage;
}
}
Usage:
it('should mock localStorage', () => {
const { methods } = localStorageImpl.register(); // mock localStorage
const { getByTestId } = render(<Root />);
fireEvent.click(getByTestId('column-size'));
expect(methods.setItem).toBeCalledTimes(1);
localStorageImpl.unregister();
});