jest: jsdom update 5 days ago breaks back compatability
🐛 Bug Report
jest.spyOn(localStorage, “setItem”); doesn’t work;
jest-environment-jsdom has caret dependency on jsdom -> 11.5.1, jsdom latest version is 11.12.0 and it includes localStorage and sessionStorage. Previously we could mock localStorage easily but now we don’t have that option and we need to use the default localStorage implementation. So our option is to spy on it which doesn’t work because it throws TypeError: object[methodName].mockImplementation is not a function
What I have discovered is that in ./node_modules/jsdom/lib/jsdom/living/generated/Storage.js the issue is with the set method of the Proxy
Currently the code below is on line 278.
if (ownDesc === undefined) {
const parent = Reflect.getPrototypeOf(target);
if (parent !== null) {
return Reflect.set(parent, P, V, receiver);
}
ownDesc = { writable: true, enumerable: true, configurable: true, value: undefined };
}
if we remove receiver from return Reflect.set(parent, P, V, receiver); we will be able to spy on it. But I guess that’s coming from webidl converter
To Reproduce
Steps to reproduce the behavior:
- Install jest.
- Write a simple class that leverage
localStorage.setItem()orlocalStorage.getItem() - Try to spy on it -> jest.spyOn(localStorage, “setItem”); and it will throw an error
Expected behavior
The method should be available for spying.
Link to repl or repo (highly encouraged)
https://github.com/vlad0/jest-localstorage-issue
Run npx envinfo --preset jest
npm installnpm testPaste the results here:
> jest
FAIL ./service.spec.js
Service
✕ Service set value (7ms)
● Service › Service set value
TypeError: object[methodName].mockImplementation is not a function
8 |
9 | it('Service set value', () => {
> 10 | jest.spyOn(localStorage, "setItem");
11 | service.setValue("hello", "world")
12 |
13 | expect(localStorage.setItem).toHaveBeenCalled();
at ModuleMockerClass.spyOn (node_modules/jest-mock/build/index.js:597:26)
at Object.it (service.spec.js:10:14)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.785s, estimated 1s
Ran all test suites.
npm ERR! Test failed. See above for more details.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 22
- Comments: 23 (7 by maintainers)
Commits related to this issue
- fix(tests): new jsdom mocks localStorage, no need to provide a mock This also needs to be mocked a little different: https://github.com/facebook/jest/issues/6798#issuecomment-412871616 — committed to prymitive/karma by prymitive 6 years ago
- fix(tests): new jsdom mocks localStorage, no need to provide a mock This also needs to be mocked a little different: https://github.com/facebook/jest/issues/6798#issuecomment-412871616 — committed to prymitive/karma by prymitive 6 years ago
We found out that localStorage from Jest is an instance of a class called
Storageprovided by jsdom. And usingspyOnthis way works :jest.spyOn(window.localStorage.__proto__, 'setItem');should work without any additional imports.@SimenB , to be honest I was really confused where to raise this issue but since
jest-environment-jsdomis part of this repo and it has caret dependency to jsdom which causes the issue I decided to give it a try here.Let me give another perspective:
Imagine I am a new Jest user and want to spy on localStorage - What are our options to spy on localStorage with the latest version of Jest? - after all it downloads the latest version of
jsdomwhich can’t be spied on or mocked.There are lots of example with mocking localStorage before
jsdomimplementation but no solution after the lastest jsdom update.UPDATE:
jsdomteam suggests the fix should come from jest 😃 so we seem to be in the limbo 😃 https://github.com/jsdom/jsdom/issues/2318Thanks @mayank23, you made my day!
An example for those who would like to return a specific value according to the test case:
Here’s a utility function for mocking any window property with automatic cleanup:
https://gist.github.com/mayank23/7b994385eb030f1efb7075c4f1f6ac4c
Here’s a solution I adapted from a similar problem mocking
window.locationhttps://github.com/facebook/jest/issues/5124@mr-wildcard Thanks a lot for the workaround ! How would you distinguish between local and sessionStorage though ? I’d like to check that my data is saved in the right storage area in my tests.