elm-explorations / test

Write unit and fuzz tests for Elm code.
https://package.elm-lang.org/packages/elm-explorations/test/latest
BSD 3-Clause "New" or "Revised" License
237 stars 39 forks source link

Anything with Browser.Navigation.Key cannot be tested #24

Open sporto opened 6 years ago

sporto commented 6 years ago

When using Browser.application I will put the Key in my model for later use.

When testing I want to create a model, but I don't have a way to get a Key. So I cannot test functions that take my Model.

Can test provide a way to get a navigation key?

Originally opened this here https://github.com/elm/browser/issues/30

mgold commented 6 years ago

If you are testing a function that calls pushUrl : Key -> String -> Cmd msg, you may want to pass it a String -> Cmd msg argument. This can be the real pushUrl model.key in production, and a stub for testing. I'm not sure how you're testing Cmds (elm-testable hasn't been upgraded for 0.19), but this is a fairly straightforward use of dependency injection.

gampleman commented 6 years ago

I don't think this is necessarily for effect testing, but for anything that takes a model. So for example, when testing a view, that typically has a signature view : Model -> Html Msg, but one cannot construct a Model value in a test without the key.

sporto commented 6 years ago

In our case, we have two scenarios where we need this:

mgold commented 6 years ago

Ah. Having dummyKey : Key that produces Cmd.none when used does sound helpful here.

You can also play around with record parameters, though I doubt this is news:

myView : { a | thing : Thing } -> Html Msg will accept a record with the thing field and anything else, so you can pass a Model or something simpler. This is actually a nice thing to do generally, if the fields aren't too numerous, to show that the view has limited dependencies.

type alias Model a = { a | thing : Thing } can be extended with { key : Key } to combine the records. It's a lot of boilerplate.

timojaask commented 6 years ago

I'm having a similar issue. I want to make sure that my init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg ) is returning a particular command depending on the Url passed by the Elm runtime. There seems to be currently no way to test this.

EDIT: Just realized I can’t generally compare Platform.Cmd’s, so that whole idea that I’d make sure that my main returns the right things seems to be doomed.

andys8 commented 6 years ago

One can compare Cmd.none and other Cmds and they're not equal. I had fuzz tests making sure there is "nothing" happening by comparing with Cmd.none. Not being able to create Key made them unusable.

The other option to the approach https://github.com/elm-explorations/test/issues/24#issuecomment-421514527 is to have a model with key: Maybe Key. This way the Model can be initialized in the tests, but Maybe has to be dealt with at runtime.

rtfeldman commented 5 years ago

Just a quick update: we're working on designs for a possible API to address this!

bryce13950 commented 5 years ago

Is there any news on this?

dkarter commented 5 years ago

I'm also hitting my head against the wall. Just added routes to my app using Navigation and all my tests broke with no way of fixing them other than throwing away all of my tests or all of the router integration. Neither seem like acceptable workarounds.

I'm considering opening a PR to update the README for this project and elm/browser so other devs are warned before investing their time in these libraries. Is that a good idea?

andys8 commented 5 years ago

Somebody pointed me to this interesting branch.

https://github.com/elm-explorations/test/compare/cmds

Abubabubi commented 5 years ago

Any updates?

chalmagean commented 5 years ago

This was recently released: https://package.elm-lang.org/packages/avh4/elm-program-test/3.1.0/

Abubabubi commented 5 years ago

That's already something, but still requires to change production code for tests.

ceddlyburge commented 5 years ago

I'm just upgrading to 0.19 at the moment and hitting this problem. I can't help feeling the situation is a bit crazy.

duganc commented 5 years ago

Agreed with others on this thread. One of the benefits of FP is that testing should be easy so not providing any way to get a dummy key for testing seems like a real problem. Any further work being done on the PR above?

danilol-zz commented 5 years ago

I'm also in the same situation.

ChickenProp commented 4 years ago

Elmer provides Elmer.Navigation.fakeKey for this, using kernel code. If you don't want Elmer, another option would be to replace the Key in your model with a () -> Key. In your application you initialise it with \() -> realKey, and in your tests you initialize it with let fakeKey () = fakeKey () in fakeKey. But you won't be able to test any code that tries to force the value.

(Edit: and it means putting a function in your model, which is bad practice and IIRC limits the functionality of the debugger.)

Bernardoow commented 4 years ago

Any updates?

twiking commented 4 years ago

Any updates?

jjant commented 4 years ago

Any updates?

avh4 commented 4 years ago

While not a solution to the fundamental issue imposed by the Browser API, I added an example of how to test programs that use navigation keys with elm-program-test:

src: https://github.com/avh4/elm-program-test/blob/main/examples/src/NavigationKeyExample.elm test: https://github.com/avh4/elm-program-test/blob/main/examples/tests/NavigationKeyExampleTest.elm background info if you haven't used elm-program-test for testing Cmds before: https://elm-program-test.netlify.app/cmds.html

jjant commented 3 years ago

Any updates? @rtfeldman

rtfeldman commented 3 years ago

No updates, sorry!