Actually kind of tricky, because writing a store in the conventional Svelte way, by calling writable at the top-level, means that the store is instantiated as soon as you import the file.
That means you need a loadX function so that you can separate out the definition of the store from the loading from localStorage. This function would need to be called somewhere when your application loads, which I havenβt shown.
That means you need separate values for notLoaded and notLoggedIn, in this example.
Also, Svelte subscribe calls the callback immediately on definition, with whatever value the store currently has.
Also, I donβt call unsubcribe anywhere... which is probably fine... subscribe was likely never designed to be used outside of a component.
Another way to do this: I could have called setItem directly after calling user.set rather than using subscribe.
Btw, this doesnβt answer the question of how to set up local storage for a component that uses this store. I havenβt tried it but Iβd hope in that case you could call JSDOMβs non-stubbed getItem and then ensure that loadUser is called in your beforeEach.
I like them because they self hydrate from the localstorage. Also,, the value that is sent first is the correct one and not a placeholder; which means my components don't need to handle an empty value. I also don't need to call an initiate function anywhere in my app.
You are right that it seems there is no way around this in testing. I see what you have done with the user store and I like it as it works great for testing, but doesn't work for my situation as it seems localstorage doesn't get added to the window till later.
My app is a Chrome Extension, so I'm 100% sure the window will be there for my store when the app loads.
This may be one of those situations where I have to resort to manual testing!
Another thing you can try is instantiating JSDOM before you import any test files. For Jasmine, you can create a helper (which is simply an file thatβs loaded) and register it in spec/support/jasmine.json.
Jest does this implicitly because it has the notion of an βenvironmentβ in which your tests run, and the standard environment is a JSDOM environment.
I donβt really like this approach as not all test files require JSDOM, but it might solve this problem? Itβs worth trying.
Oh, of course. I should have thought of that. Youβll need to take that one function, create a new file with just that, and convert import -> require. I can try it myself tomorrow
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
I knocked this up just now:
github.com/dirv/svelte-testing-dem...
Actually kind of tricky, because writing a store in the conventional Svelte way, by calling
writable
at the top-level, means that the store is instantiated as soon as you import the file.That means you need a
loadX
function so that you can separate out the definition of the store from the loading fromlocalStorage
. This function would need to be called somewhere when your application loads, which I havenβt shown.That means you need separate values for
notLoaded
andnotLoggedIn
, in this example.Also, Svelte
subscribe
calls the callback immediately on definition, with whatever value the store currently has.Also, I donβt call
unsubcribe
anywhere... which is probably fine...subscribe
was likely never designed to be used outside of a component.Another way to do this: I could have called
setItem
directly after callinguser.set
rather than usingsubscribe
.Btw, this doesnβt answer the question of how to set up local storage for a component that uses this store. I havenβt tried it but Iβd hope in that case you could call JSDOMβs non-stubbed
getItem
and then ensure thatloadUser
is called in yourbeforeEach
.Let me know if this helps!
I appreciate you taking the time, I really hope this helps someone!
Here is a link to one of my custom stores:
github.com/Lamden/wallet/blob/mast...
I like them because they self hydrate from the localstorage. Also,, the value that is sent first is the correct one and not a placeholder; which means my components don't need to handle an empty value. I also don't need to call an initiate function anywhere in my app.
You are right that it seems there is no way around this in testing. I see what you have done with the user store and I like it as it works great for testing, but doesn't work for my situation as it seems localstorage doesn't get added to the window till later.
My app is a Chrome Extension, so I'm 100% sure the window will be there for my store when the app loads.
This may be one of those situations where I have to resort to manual testing!
Another thing you can try is instantiating JSDOM before you import any test files. For Jasmine, you can create a helper (which is simply an file thatβs loaded) and register it in
spec/support/jasmine.json
.Jest does this implicitly because it has the notion of an βenvironmentβ in which your tests run, and the standard environment is a JSDOM environment.
I donβt really like this approach as not all test files require JSDOM, but it might solve this problem? Itβs worth trying.
Would I then import the JSDOM into svelte.js? helpers don't seem to be ES6 compatible so this is causing me some syntax errors.
Oh, of course. I should have thought of that. Youβll need to take that one function, create a new file with just that, and convert import -> require. I can try it myself tomorrow