Are global signals ever reset between test runs?
@lexlohr Sorry - another issue 😅
As I've described in another issue I have structured my application in a way, that my global state mainly consists of global stores.
Now to create tests I usually need to first populate my stores with some test data. This does seem to work fine in general, howerver I noticed, that apparently these stores will keep their state between tests. Is this a mistake on my end, am I using stores wrong, or is this a bug?
13 Replies
My guess is that the file in which the signal is defined would need to be imported again in order to reset the state, and I doubt that any test would do that (it would probably slow it down a lot)
Which would be interesting, because testing is not a downside we usually mention when discussing global signals
hm, is there a better way to handle state in solid, then? Or would I have to write reset functions which are always called after each test (this seems to be a pretty heavy and boilerplaty solution)
The usual alternative is to use a context provider
And put the provider at the root of your app
Unfortunately, for component tests, you'd need to make sure that you render the component wrapped in the provider
Which results in some boilerplate
Hm, yeah this is still a lot of manual wiring 😦 I really like that I can just place a store whereever I want and consume it. I consider contexts only in cases, where I want to make sure the state is scoped to a specific part of the component tree
Right, that make sense
Hm, as it stands I will probably have to manually reset my stores then 😬
I'm not sure there's really a better option for global state 🤷
That's a real good point. Mmh, this shall require some thought, but I might be able to create something that allows us to store and restore states between tests in our testing library.
I'm not sure how I'll do it, though, so don't expect a fast solution.
One odd thing I noticed (but this might be a misunderstanding of stores on my end):
When I try to fully reset a store, this still won't update the store correctly.
For example:
This seems to work in our running app, but in tests stores won't be emptied and still keep their state.
Any idea what I could be doing wrong here?
just calling the setter on a property updates the store accoringly, e.g.
setMyStore('SOME_ID", { id: 'UPDATE_ID' })
apparently reconcile
seems to help, but do I actually need this here?Yes, you basically have to set every root property to undefined yourself.
and reconcile does this? (I am still a bit confused about reconcile and what it actually does)
Reconcile transforms the store to match the shape and values of the value passed to the reconcile function. The advantage of that (vs just setting to an empty object) is
1. it only updates properties that need to be updated
2. it also deletes properties that don't exist in the target object, while the regular setter merges (but shallowly!) the current store and the object passed to setStore
Ah I see. Thanks! So if I understand that correctly, reconcile could change the underlying store completely (speaking in static types, it could change to a different type). However, if the target object contains properties which are identical in the current store, no updates will be triggered. And properties which are no longer present in the reconciled store will be removed instead of being kept. Therefore handing an empty object to reconcile will remove all properties. Correct? 🙂
I think it would be nice to have some more of these "how to properly update a store"-real world examples in the docs. The description of functions like
reconcile
is currently very technical and hard to grasp.
(Same thing for fns like runWithOwner
etc., to get a better understanding when and how these are actually being used)
I would love to contribute, but I don't quite get most of these myself, yet 😅