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 install
npm test
Paste 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
Storage
provided by jsdom. And usingspyOn
this 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-jsdom
is 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
jsdom
which can’t be spied on or mocked.There are lots of example with mocking localStorage before
jsdom
implementation but no solution after the lastest jsdom update.UPDATE:
jsdom
team 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.location
https://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.