Add Storex.Test for driving a store from a test - #15
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Exercising a store today means going through
Storex.Supervisor.add_store/4andmutate_store/4, both@moduledoc false— a test written against them iswritten against internals that are free to move. The alternative is the browser
suite, which needs real Chrome through Wallaby with chromedriver on PATH.
Storex.Testis the supported way:result.diffis the reason this exists. The diff is the contract with thefrontend — it is what actually goes over the wire — and it is the part a store
author cannot otherwise get at without driving a browser.
The API
commit/3returns a plain map rather than a struct, so a test can match the partit cares about and ignore the rest.
{:error, reason}is whatever the clientwould have received as an error frame: a mutation returning
{:error, reason}, aname no clause matches, or an unsupported return value.
start_store/2returns{:error, reason}when the store'sinit/2does, so refusing to start istestable; the bang variants raise instead, for the cases a test does not mean to
assert on.
Storex.Testlives inlib/so it ships to users, the wayPlug.Testdoes.mix.exsalready packageslib.broadcast/4 closes a real gap
Storex.mutate/3fans out over:pgand sends the mutation to each session'ssocket process, which is what normally turns it into a call on the store. There
is no socket in a unit test — this repo writes a 30-line
FakeWebsocketServerinstorex_test.exsto work around exactly that.broadcast/4waits for themessage and applies it, so the
:pgpath, the registry match and the:keyfilter are covered by one call.
{:error, :timeout}is the assertion for a storethe fan-out should not have reached.
stop/1 waits
Storex.Supervisor.remove_store/2is a cast, so asserting on whatterminate/3did on the next line is a race.
stop/1monitors the store and waits for it to godown.
Cleanup is not a convenience
start_store/2registers anExUniton_exitthat stops the store.Storex.Registrymonitors the store process, not the session, so without thisevery test that starts a store leaks one for the rest of the run. ExUnit is
reached through
apply/3behindCode.ensure_loaded?/1, so the module carries nocompile-time reference to a test-only dependency and
mix compile --warnings-as-errorsstays clean in dev and prod.The calling process is registered as the session, which is what lets
broadcast/4observe the fan-out.
Deliberately not done
supervisor_test.exsandstore_test.exstestStorex.SupervisorandStorex.Storeon purpose, whichis the layer below this. Rewriting them through the helper would lose that.
Storex.HTTP.init_store/2is already a plain functionreturning a plain map, and
http_test.exscalls it directly without ceremony.assert_diff,assert_state).commit/3hands backplain data and
asserton it reads fine; a macro layer would be more to learn,not less.
Tests
test/storex/test_test.exs, 28 tests covering every function, both bang variants,the error paths, the
:keyfilter,terminate/3throughstop/1, and theautomatic cleanup. 143 non-browser tests pass on three seeds;
mix compile --warnings-as-errorsandmix format --check-formattedare clean.The 21 browser tests still need chromedriver and did not run here.