-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
jsdom update 5 days ago breaks back compatability #6798
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Not much for jest to do here, I'm afraid... You can always rollback jsdom and use a lockfile |
@SimenB , to be honest I was really confused where to raise this issue but since 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 There are lots of example with mocking localStorage before UPDATE: |
@vlad0 did you manage to mock/spy anything from jsdom's localStorage implementation ? Since jsdom released its 11.12.0, if I recall, there is no workaround for this :/ kind of a blocker when you want to unit test... |
Like they said in the jsdom issue, how would this be mocked in the browser? If it's impossible to mock in the browser we might be at an impasse. There is nothing we can do inside Jest that you cannot do in userland, but if you're able to mock it using plain JSDOM then we can look into porting the solution into Jest |
I understand the pov of @domenic on the jsdom side, and I agree this should not be fixed by them. Maybe I'm missing something, but how comes that I can I'm getting the same error than @vlad0 :
Edit : with Jasmine's global |
I added a comment over there. Jsdom has different behaviour from chrome - the function is not possible to replace by simple assignment, which is what Jest does (or tries to do) see https://github.com/facebook/jest/blob/bed7e17ff0900320ef8409f5453836a94bb8456d/packages/jest-mock/src/index.js#L762-L768. Line 766 is the one that throws since the assignment on line 762 silently fails |
Ok, that's apparently a bug in Chrome. If anyone is able to somehow replace a function on I'll send a PR throwing an error when trying to spy on something that's not replacable |
We found out that localStorage from Jest is an instance of a class called
|
Spying on the prototype is an interesting solution. @thymikee @rickhanlonii thoughts on falling back to trying to spy on the prototype? My local diff is this: diff --git i/packages/jest-mock/src/index.js w/packages/jest-mock/src/index.js
index 9b679c73e..cedbe376a 100644
--- i/packages/jest-mock/src/index.js
+++ w/packages/jest-mock/src/index.js
@@ -763,6 +763,10 @@ class ModuleMockerClass {
object[methodName] = original;
});
+ if (object[methodName] === original) {
+ throw new Error(`Unable to mock method \`${methodName}\``);
+ }
+
object[methodName].mockImplementation(function() {
return original.apply(this, arguments);
}); and a test, but in theory we could try some more fancy stuff by looking up constructors etc |
What if your obj/fn overrides the prototype? You'll end up mocking different functions, no? |
@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. |
Something to bear in mind is now that jsdom provides a working localStorage implementation, you may no longer need to mock it. I just update my tests to assert on the value retrieved via |
@moimael good question, I didn't think about sessionStorage. I can't give it a try right now but if both sessionStorage and localStorage are instantiated from a generic @tamlyn yes, but in this case you're not unit testing your code anymore because localStorage is not mocked and by doing that way you now need to take care of clearing mutated state with |
This also needs to be mocked a little different: jestjs/jest#6798 (comment)
This also needs to be mocked a little different: jestjs/jest#6798 (comment)
Here's a solution I adapted from a similar problem mocking
|
|
`read` method doesn't exist on LocalStorage prototype. You're probably
looking for `getItem` instead.
|
@mr-wildcard I am so embarrassed that I had to delete my comment. It actually looks like a big plus that we can't overwrite this, otherwise someone might accidentally create a mock with read instead of getItem :). |
How about this, what do you guys think about below code pluses and deltas:
similarly we can set the item .... I haven't tried setItem yet but will try ... |
If people can come up with some way we can handle this generically in |
technically, |
Here's a utility function for mocking any window property with automatic cleanup: https://gist.github.com/mayank23/7b994385eb030f1efb7075c4f1f6ac4c |
Thanks @mayank23, you made my day! An example for those who would like to return a specific value according to the test case: // file.js
const funcToTest = () => {
const { localStorage } = window;
return JSON.parse(localStorage.getItem('toto'));
};
export { funcToTest }; // file.test.js
import mockWindowProperty from './mock-window-property';
import { funcToTest } from './file';
describe('funcToTest', () => {
let mockGetItem;
mockWindowProperty('localStorage', {
getItem: params => mockGetItem(params),
});
beforeEach(() => {
mockGetItem = jest.fn().mockReturnValue(null);
});
it('Should do something with id', (done) => {
mockGetItem = jest.fn().mockReturnValue('{"id": "1"}');
const res = funcToTest();
expect(mockGetItem.mock.calls.length).toBe(1);
expect(mockGetItem.mock.calls[0][0]).toBe('toto');
expect(res).toStrictEqual({ id: 1 });
// ...
});
}); |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
🐛 Bug Report
jest.spyOn(localStorage, "setItem"); doesn't work;
jest-environment-jsdom
has caret dependency on jsdom ->11.5.1
,jsdom
latest version is11.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 defaultlocalStorage
implementation. So our option is to spy on it which doesn't work because it throwsTypeError: 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 theset
method of theProxy
Currently the code below is on line 278.
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 fromwebidl
converterTo Reproduce
Steps to reproduce the behavior:
localStorage.setItem()
orlocalStorage.getItem()
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:
The text was updated successfully, but these errors were encountered: