The sandbox module is helpful when developing components. It lets you
run the component using elm reactor outside the system and define several test cases.
If you want to run your sandbox on a CI you can add #markdown to the URL. This will output the test results as a markdown string inside a pre element:
<pre id="markdown-output"> Results here </pre>This way you can complile the sandbox, run it in a headless Chrome and dump the DOM. From the DOM you can extract the results.
Wrap a component in a sandbox application.
This will render each test case and log all messages.
Create a test file with a main function where you declare all
test cases.
A sandbox module example for YourComponent:
import YourComponent exposing (Model, MsgIn, MsgOut)
main : SandboxProgram Model MsgIn MsgOut
main =
Sandbox.ui
{ title = "Title of your component"
, component = YourComponent.component
, cases =
[ testCase1
, testCase2
]
, stringifyMsgIn = Debug.toString -- Or roll your own if you want prettier messages.
, stringifyMsgOut = Debug.toString
, wrapView = identity
}Sandbox a UI Component
Sandbox a Layout Component
Sandbox a Service Component
You need to provied a view function which renders the model of
your service component.
Test cases defines scenarios for the requirements of your component.
A Test Case is just a record with a title and description together with a list of Actions you want to perform on your sandboxed component. You can also map the component's out messages to actions to simulate the outside system.
A test case for the Component
testCase1 : Sandbox.TestCase MsgIn MsgOut
testCase1 =
{ title = "Test Case Title"
, desc = "Test Case Description"
, init =
[ Sandbox.sendMsg YourComponent.Hello
, Sandbox.spawnChild "Child Title" YourComponent.ReceiveChildPID
]
, onMsgOut = \msgOut ->
case msgOut of
YourComponent.ObserveSomething id ->
[ YourComponent.RecevieDataFor id "Some data"
|> Sandbox.sendMsg
|> Sandbox.delay 1000
]An action to perform on your sandboxed component.
Send a message to you sandboxed component
Sandbox.sendMsg YourComponent.SomeMessageSpawn a child component and send the PID to your component.
You can provide a String which will be displayed when the child
component is rendered (using renderPID in your layout component).
Sandbox.spawnChild "Hello child" YourComponent.ReceiveChildPerform a delayed action on your sandboxed component. Delay in milliseconds.
Sandbox.sendMsg YourComponent.SomeMessage
|> Sandbox.delay 1000Sometimes it is useful to test your expectations or requirements on a component.
You can express them using assertions. Assertions have three states: waiting, pass or fail. The state of a test case is visible in the sandbox UI.
In this example we expect that GoodMsg is sent by the component within 1s.
testGoodMsg : Sandbox.TestCase MsgIn MsgOut
testGoodMsg =
{ title = "Good messages are good"
, desc = "`GoodMsg` must be sent within 1 second. No other messages are allowed."
, init =
[ Sandbox.timeout 1000
, Sandbox.sendMsg YourComponent.SomeInput
]
, onMsgOut = \msgOut ->
case msgOut of
YourComponent.GoodMsg ->
[ Sandbox.pass
]
YourComponent.BadMsg ->
[ Sandbox.fail "I don't like bad messages"
]Flag test case as passed.
Sandbox.passFlag test case as failed. You can supply a message explaining what went wrong.
Sandbox.fail "Didn't receive some important out msg"Set a timeout in milliseconds. This will cause the test to automatically fail after the timeout if the test havn't been flagged as passed by then.
Sandbox.timeout 1000Create a mock PID for testing purposes.
mockPID "form-component"Check that a mock pid matches an expected label.
This will return True
mockPID "form-component"
|> checkPID "form-component"Assert that a PID matches a label.
This will result in action pass
mockPID "form-component"
|> assertPID "form-component"This will result in the action
fail "PID form-component does not match expectation other-component"
mockPID "form-component"
|> assertPID "other-component"Sadbox Msg
The Program type of your main function.