avh4 / elm-program-test

Test Elm programs
https://elm-program-test.netlify.com/
MIT License
93 stars 28 forks source link

Port.send a Maybe Value #81

Open nikoskalogridis opened 4 years ago

nikoskalogridis commented 4 years ago

I am sending a Maybe Value on a port in order to clear the localstorage key when it receives a null value (through sending a Nothing on logout). Trying to do the same in the following code:

encode : Cred -> Decode.Value
encode (Cred user tokenInfo) =
    Encode.object
        [ ( "user", User.encode user )
        , ( "token", tokenInfoEncoder tokenInfo )
        ]

storeCredWith : Cred -> Cmd msg
storeCredWith cred =
    storeCache (Just (encode cred))

simulateStoreCredWith : Cred -> ProgramTest.SimulatedEffect msg
simulateStoreCredWith cred =
    SimulatedEffect.Ports.send "storeCache" (Just (encode cred))

logout : Cmd msg
logout =
    storeCache Nothing

port storeCache : Maybe Value -> Cmd msg

fails with:

TYPE MISMATCH - The 2nd argument to `send` is not what I expect:

SimulatedEffect.Ports.send "storeCache" (Just (encode cred))
                                        #^^^^^^^^^^^^^^^^^#
This `Just` call produces:
    #Maybe Value#
But `send` needs the 2nd argument to be:
    #Encode.Value#

is there a way to simulate this (ie Port.send a Maybe Value) ?

nikoskalogridis commented 4 years ago

I found a different way, sending explicitly a null value on logout:

storeCredWith : Cred -> Cmd msg
storeCredWith cred =
    storeCache (encode cred)

simulateStoreCredWith : Cred -> ProgramTest.SimulatedEffect msg
simulateStoreCredWith cred =
    SimulatedEffect.Ports.send "storeCache" (encode cred)

logout : Cmd msg
logout =
    storeCache Encode.null

port storeCache : Value -> Cmd msg

Its more explicit and I prefer it but I think it could be beneficial for users to have a note regarding this on the documentation of Port.send api.

avh4 commented 4 years ago

For your original port

port storeCache : Maybe Value -> Cmd msg

since the port type is Maybe Value, you'll need to encode the Maybe Value as a JSON Value when you use SimulatedEffect.Ports.send. When Json.Decode provides a maybe decoder, interestingly Json.Encode does not provide a maybe encoder, though I see that Json.Encode.Extra does have a maybe encoder.

So I think something like this should work:

import Json.Encode.Extra

simulateStoreCredWith : Maybe Cred -> ProgramTest.SimulatedEffect msg
simulateStoreCredWith maybeCred =
    SimulatedEffect.Ports.send "storeCache" (Json.Encode.Extra.maybe encode maybeCred)