I get
Error: expect(jest.fn())[.not].toHaveBeenCalledTimes()
jest.fn() value must be a mock function or spy.
Received:
function: [Function getItem]
import localStorageWrapper from "./localStorage";
const mockStorage = {
string: "some string value",
object: `{"foo": "bar"}`
};
beforeEach(() => {
window.localStorage = {
getItem: jest.fn(key => mockStorage[key]),
setItem: jest.fn()
};
});
describe("get", () => {
it("should get string item", () => {
const key = "string";
const result = localStorageWrapper.get(key);
expect(window.localStorage.getItem).toHaveBeenCalledTimes(1);
expect(window.localStorage.getItem.mock.calls[0][0]).toEqual(key);
expect(result).toEqual(mockStorage.string);
});
it("should get object item", () => {
const key = "object";
const result = localStorageWrapper.get(key);
expect(window.localStorage.getItem).toHaveBeenCalledTimes(1);
expect(window.localStorage.getItem.mock.calls[0][0]).toEqual(key);
expect(result).toEqual(JSON.parse(mockStorage.object));
});
});
describe("set", () => {
it("should set string item", () => {
localStorageWrapper.set("foo", "bar");
expect(window.localStorage.setItem).toHaveBeenCalledTimes(1);
expect(window.localStorage.setItem.mock.calls[0]).toMatchSnapshot();
});
it("should set object item", () => {
localStorageWrapper.set("some_object", { foo: "bar" });
expect(window.localStorage.setItem).toHaveBeenCalledTimes(1);
expect(window.localStorage.setItem.mock.calls[0]).toMatchSnapshot();
});
});
Steps to reproduce the behavior:
A clear and concise description of what you expected to happen.
Please provide either a repl.it demo or a minimal repository on GitHub.
Issues without a reproduction link are likely to stall.
npx envinfo --preset jestPaste the results here:
These tests are not running with latest jest version but were working earlier.
Jest uses jsdom under the hood for simulating dom. In browsers and in jsdom, you cannot just set window.localStorage to new object, because setter function for it is undefined.
Instead do this in order to override original window.localStorage
beforeEach(() => {
const localStorageMock = {
getItem: jest.fn(key => mockStorage[key]),
setItem: jest.fn((args) => console.log(args)),
};
Object.defineProperty(window, 'localStorage', {
value: localStorageMock,
writable: true
})
});
Your code was working in the older version of Jest, because jsdom did not have it's own implementation for localStorage. window.localStorage was undefined and you could assign whatever you wanted to it.
Nice answer @grosto, thanks!
Most helpful comment
Jest uses jsdom under the hood for simulating dom. In browsers and in jsdom, you cannot just set
window.localStorageto new object, because setter function for it isundefined.Instead do this in order to override original
window.localStorageYour code was working in the older version of Jest, because jsdom did not have it's own implementation for
localStorage.window.localStoragewas undefined and you could assign whatever you wanted to it.