Testing localStorage

9,236 views
Skip to first unread message

Martin Danielson

unread,
Oct 15, 2014, 3:55:51 AM10/15/14
to jes...@googlegroups.com
I would like to use Jest for all our unit tests in order to keep the number of test frameworks down. Jest is superior to any alternative we've used since the auto-mocking is incredible and outweighs the problem with speed.

However, is there a pattern used/recommended for handling globals? Specifically localStorage.

I've looked at a few ways recommended by Jasmine but they do not really work as far as I have tested. Right now we are conditioning the existence of localStorage in the code and then we populate anything related to getting information from the localStorage manually before every test. It works but it is not very flexible. I.e. language definitions that are stored in localStorage becomes a bit cumbersome to test (with different languages).

So, anyone have any good solutions to share, maybe anyone at the Jest team who have looked into this?

Kind regards,
Martin

vjeux

unread,
Oct 15, 2014, 10:58:29 AM10/15/14
to jes...@googlegroups.com
For localStorage tests we usually make a mock of localStorage in setup() and revert the global in teardown(). This way it's mocked like any other dependency.

Do you have ideas in how to make it easier to work with?

Martin Danielson

unread,
Oct 20, 2014, 3:51:34 AM10/20/14
to vjeux, jes...@googlegroups.com
Sorry for the late response, been taking care of my sick son and wife.

setup and teardown, how do you accomplish this? Is there an example you can show me? In Jasmine we have beforeEach and afterEach, but that would require us to include those mocks in every test. I would rather have these globals being mocked for all tests automatically so that we do not have to write so much boiler code. Right now, I am circumventing the problem by loading the data I need in env-setup.js and putting a condition on localStorage - not very nice at all and rather inflexible as I said before.

I tried mocking localStorage using spyOn but for whatever reason it never worked. Whatever I did with localStorage it complained about it not being specified. I think I tested having it both in beforeEach and also in env-setup.js. I think this is specific to Jest, since the code was written for Jasmine and should work there.

The best solution in my mind is having these things set up in env-setup.js (or simular) and then being able to be configured individually in tests (if needed).

I will give this another go soon, when I am back at work.

Thank you for replying and sharing,
Martin



Martin Danielson
Front Tech Lead

 

 

QUINYX AB
Vattugatan 17
111 52 STOCKHOLM



--
You received this message because you are subscribed to the Google Groups "Jest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jestjs+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jestjs/074463a3-2fe1-4323-bb16-b63d49d55082%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Martin Danielson

unread,
Oct 31, 2014, 12:39:51 PM10/31/14
to vjeux, jes...@googlegroups.com
A short update on this, for anyone who might run into this again.

I have been messing around with everything and nothing now. First of all. There are two files that are global that you can use, setupEnvScriptFile and setupTestFrameworkScriptFile. Both of these can be used to successfully mock localStorage. My current solution looks like this:

var mock = (function() {
  var store = {};
  return {
    getItem: function(key) {
      return store[key];
    },
    setItem: function(key, value) {
      store[key] = value.toString();
    },
    clear: function() {
      store = {};
    }
  };
})();
Object.defineProperty(window, 'localStorage', { value: mock });

It's working perfectly.
The problem I was having was actually not that local storage did not work, rather that a component (i18n) used local storage to store translations before updating over ajax. Since the ajax call referenced something that did not exist the local storage never got updated. Not sure if you can get this to work, I ended up changing so that our i18n module used require rather than ajax. Sorry about the confusion there.

Anyways, I will continue to dig through the setup and try to find other common/corner cases.

Thanks for leading me on the right path,
Martin

Martin Danielson
Front Tech Lead

 

 

QUINYX AB
Vattugatan 17
111 52 STOCKHOLM



arsto...@gmail.com

unread,
Apr 14, 2015, 1:33:27 PM4/14/15
to jes...@googlegroups.com, vje...@gmail.com
Although this is an old discussion, it was the only help I could find for dealing with local/sessionStorage in Jest tests. So thanks to Martin, and in case someone else runs into the same problem and finds this, I want to just add that to get this to work in a BeforeEach block, I had to make one modification:

Rather than just using `{ value: mock }`, I had to include `configurable: true` or `writable: true` (either one seems to work) to avoid a "TypeError: Cannot redefine property". It seems the default behavior of Object.defineProperty is to make the property unable to be redefined again. I found the solution here:

http://bjorn.tipling.com/advanced-objects-in-javascript


Regards,
Adam
> On 20 October 2014 09:51, Martin Danielson <martin.d...@quinyx.com> wrote:
>
> Sorry for the late response, been taking care of my sick son and wife.
>
>
> setup and teardown, how do you accomplish this? Is there an example you can show me? In Jasmine we have beforeEach and afterEach, but that would require us to include those mocks in every test. I would rather have these globals being mocked for all tests automatically so that we do not have to write so much boiler code. Right now, I am circumventing the problem by loading the data I need in env-setup.js and putting a condition on localStorage - not very nice at all and rather inflexible as I said before.
>
>
> I tried mocking localStorage using spyOn but for whatever reason it never worked. Whatever I did with localStorage it complained about it not being specified. I think I tested having it both in beforeEach and also in env-setup.js. I think this is specific to Jest, since the code was written for Jasmine and should work there.
>
>
> The best solution in my mind is having these things set up in env-setup.js (or simular) and then being able to be configured individually in tests (if needed).
>
>
> I will give this another go soon, when I am back at work.
>
>
> Thank you for replying and sharing,
> Martin
>
>
>
>
>
>
>
> Martin Danielson
> Front Tech Lead
>  
>
> Mobile: +46 (0)72 222 26 44
> martin.d...@quinyx.com 
>  
>
> QUINYX AB
> Vattugatan 17111 52 STOCKHOLM
>
>
>
>
>
>
>
>
>

dinot...@gmail.com

unread,
Aug 31, 2015, 4:10:23 PM8/31/15
to Jest, vje...@gmail.com
> On 20 October 2014 09:51, Martin Danielson <martin.d...@quinyx.com> wrote:
>
> Sorry for the late response, been taking care of my sick son and wife.
>
>
> setup and teardown, how do you accomplish this? Is there an example you can show me? In Jasmine we have beforeEach and afterEach, but that would require us to include those mocks in every test. I would rather have these globals being mocked for all tests automatically so that we do not have to write so much boiler code. Right now, I am circumventing the problem by loading the data I need in env-setup.js and putting a condition on localStorage - not very nice at all and rather inflexible as I said before.
>
>
> I tried mocking localStorage using spyOn but for whatever reason it never worked. Whatever I did with localStorage it complained about it not being specified. I think I tested having it both in beforeEach and also in env-setup.js. I think this is specific to Jest, since the code was written for Jasmine and should work there.
>
>
> The best solution in my mind is having these things set up in env-setup.js (or simular) and then being able to be configured individually in tests (if needed).
>
>
> I will give this another go soon, when I am back at work.
>
>
> Thank you for replying and sharing,
> Martin
>
>
>
>
>
>
>
> Martin Danielson
> Front Tech Lead
>  
>
> Mobile: +46 (0)72 222 26 44
> martin.d...@quinyx.com 
>  
>
> QUINYX AB
> Vattugatan 17111 52 STOCKHOLM
>
>
>
>
>
>
>
>
>
> On 15 October 2014 16:58, vjeux <vje...@gmail.com> wrote:
>
> For localStorage tests we usually make a mock of localStorage in setup() and revert the global in teardown(). This way it's mocked like any other dependency.
>
>
> Do you have ideas in how to make it easier to work with?
>
>
>
>
>
>
> On Wednesday, October 15, 2014 12:55:51 AM UTC-7, Martin Danielson wrote:
> I would like to use Jest for all our unit tests in order to keep the number of test frameworks down. Jest is superior to any alternative we've used since the auto-mocking is incredible and outweighs the problem with speed.
>
>
> However, is there a pattern used/recommended for handling globals? Specifically localStorage.
>
>
> I've looked at a few ways recommended by Jasmine but they do not really work as far as I have tested. Right now we are conditioning the existence of localStorage in the code and then we populate anything related to getting information from the localStorage manually before every test. It works but it is not very flexible. I.e. language definitions that are stored in localStorage becomes a bit cumbersome to test (with different languages).
>
>
> So, anyone have any good solutions to share, maybe anyone at the Jest team who have looked into this?
>
>
> Kind regards,
> Martin
>
>
>
>
>
>
> --
>
> You received this message because you are subscribed to the Google Groups "Jest" group.
>
> To unsubscribe from this group and stop receiving emails from it, send an email to jestjs+un...@googlegroups.com.
>
> To view this discussion on the web visit https://groups.google.com/d/msgid/jestjs/074463a3-2fe1-4323-bb16-b63d49d55082%40googlegroups.com.
>
>
>
> For more options, visit https://groups.google.com/d/optout.

Thanks for this it was very useful!

mumu...@rubiconproject.com

unread,
Dec 8, 2016, 7:14:04 PM12/8/16
to Jest, dinot...@gmail.com
Just a quick update to this so it works with current jest:

You need to use <pre>"setupFiles": [ "__tests__/window-env.js" ]</pre> in your Jest options instead of "setupEnvScriptFile".

Also if you have babel-transforms:

<pre>
const localStorageMock = (() => {
let store = {};

return {
getItem: key => store[key],
setItem: (key, value) => { store[key] = value.toString(); },
clear: () => { store = {}; }
};
})();

Object.defineProperty(window, 'localStorage', { value: localStorageMock });
</pre>

Willy Souza Catão

unread,
Oct 10, 2020, 11:50:06 PM10/10/20
to Jest
Hi guys, just starting with React Testint Library and Jest. 

Got myself with the same issue with local storage, do you guys have some sandbox where I can get to see how it works? 

It would be very helpful, maybe someone else like me. 

Thanks!

Reply all
Reply to author
Forward
0 new messages