brian-watkins/elm-spec/3.3.0

NOTE: the latest version is 3.3.2

Spec.Port

Functions for working with ports during a spec.

Suppose your app sends a port command when a button is clicked, via a function called my-command-port that takes a string ("TRIGGER_REQUEST" in this case), and then displays a message received over a port subscription. You could write a scenario like so:

Spec.describe "command ports and subscription ports"
[ Spec.scenario "send and receive" (
    Spec.given (
      Spec.Setup.withInit (App.init testFlags)
        |> Spec.Setup.withUpdate App.update
        |> Spec.Setup.withView App.view
        |> Spec.Setup.withSubscriptions App.subscriptions
    )
    |> Spec.when "a message is sent out"
      [ Spec.Markup.target << by [ tag "button" ]
      , Spec.Markup.Event.click
      ]
    |> Spec.when "a response is received"
      [ Spec.Port.send "my-subscription-port" <|
          Json.Encode.object
            [ ("message", Encode.string "Have fun!")
            ]
      ]
    |> Spec.observeThat
      [ Spec.it "sent the right message over the port" (
          Spec.Port.observe "my-command-port" Json.Decode.string
            |> Spec.expect (Spec.Claim.isListWhere
              [ Spec.Claim.isEqual Debug.toString "TRIGGER_REQUEST"
              ]
            )
        )
      , Spec.it "shows the message received" (
          Spec.Markup.observeElement
            |> Spec.Markup.query << by [ id "message" ]
            |> Spec.expect (
              Spec.Claim.isSomethingWhere <|
              Spec.Markup.text <|
              Spec.Claim.isEqual Debug.toString "Have fun!"
            )
        )
      ]
  )
]

Observe Command Ports

observe : String -> Decoder a -> Observer model (List a)

Observe messages sent out via a command port.

Provide the name of the port (the function name) and a JSON decoder that can decode messages sent out over the port.

Simulate Subscription Ports

send : String -> Value -> Step model msg

A step that sends a message to a port subscription.

Provide the name of the port and an encoded JSON value that should be sent from the JavaScript side.

For example, if you have a port defined in Elm like so:

port listenForStuff : (String -> msg) -> Sub msg

Then you could send a message through this port during a scenario like so:

Spec.when "a message is sent to the subscription"
[ Json.Encode.string "Some words"
    |> Spec.Port.send "listenForStuff"
]

Simulate Request/Response Scenarios

respond : String -> Decoder a -> (a -> Step model msg) -> Step model msg

Use this step to respond to the last message received on the given port.

Provide the name of the port (the function name) and a JSON decoder that can decode messages sent out over the port. Then, provide a function that generates a Step based on the last message received. If no messages have been received from that port, the step will fail.

Use this function to simulate request/response style communication via ports, when the response depends on some aspect of the request that you may not know at the time of writing the scenario.

Spec.when "a response is sent to the request"
[ Spec.Port.respond "myPortCommand" Json.string <| \lastMessage ->
    Json.Encode.string ("You sent: " ++ lastMessage)
      |> Spec.Port.send "myPortSubscription"
]