A Witness can be used to record information about the arguments passed to
a Cmd-generating function.
If you use dependency inversion to decouple part of your program from the
Cmd-generating functions it depends upon, you can use a Witness to prove that this
part of your program works with the Cmd-generating function in the right way.
Let's say I have a Cmd-generating function that takes a score (an Int) and saves
it to the server via some HTTP request. Let's further suppose I want to describe the behavior
of my user interface, without worrying about the details of how a score is saved. In this
case, I'll 'inject' the Cmd-generating function instead of calling it directly from my update
function. This allows me to substitute a fake function during my spec.
Here's the update function:
update : (Int -> Cmd Msg) -> Msg -> Model -> (Model, Cmd Msg)
update scoreSaver msg model =
case msg of
SaveScore score ->
( model, scoreSaver score )
...Now, I can write a spec that uses a witness to record the score passed to the injected
scoreSaver function like so:
Spec.describe "saving the score"
[ Spec.scenario "successful save" (
Spec.given (
Spec.Setup.withInit (App.init testFlags)
|> Spec.Setup.withView App.view
|> Witness.forUpdate (\witness ->
App.update <| \score ->
Witness.log "saved-score"
(Json.Encode.int score) witness
)
)
|> Spec.when "the score is saved"
[ Spec.Markup.target << by [ id "game-over-button" ]
, Spec.Markup.Event.click
]
|> it "saves the proper score" (
Witness.observe "saved-score" (Json.Decode.int)
|> Spec.expect (Spec.Claim.isList
[ Spec.Claim.isEqual Debug.toString 28
]
)
)
)
]Set up the scenario with the update function from the program whose behavior is being
described. You'll have access to a Witness to use in constructing this function.
See the example above.
Create a Cmd that logs some information.
Provide the name of this witness and a JSON value with any information to be logged.
Observe the logs recorded by a witness.
Provide the name of the witness and a JSON decoder that can decode whatever value you need to observe.
Use a
Witnessto record information from inside aCmd-generating function.