lustre/dev/simulate
Types
A simulated lustre.App ready
to be started. This module exposes constructor functions that mirrors those
provided by the main lustre module:
Note: running a simulated app is not the same as running a real app! Any effects that would normally be run after update will be discarded. If you want to simulate messages coming from the outside world, you can use the
messageoreventfunctions.
pub opaque type App(args, model, msg)
The simulation keeps a log of events that occur. This includes both simulated
DOM events and messages dispatched using the event and
message functions but also entries for failures like an event
target not existing in the current view or an event that was fired but not
handled.
The event log is primarily useful for debugging simulations that don’t produce
the results you expect. You can use the history function to
introspect a simulation for this event log.
pub type Event(msg) {
Dispatch(message: msg)
Event(target: query.Query, name: String, data: json.Json)
Problem(name: String, message: String)
}
Constructors
-
Dispatch(message: msg) -
Event(target: query.Query, name: String, data: json.Json) -
Problem(name: String, message: String)
A running simulation of a Lustre application, produced by calling
start.This is similar to the Runtime
type and both DOM events and messages dispatched by effects can be simulated
using the event and message functions respectively.
Each simulated event returns an updated simulation, making it convenient to pipe multiple events in sequence.
pub opaque type Simulation(model, msg)
Values
pub fn application(
init init: fn(args) -> #(model, effect.Effect(msg)),
update update: fn(model, msg) -> #(model, effect.Effect(msg)),
view view: fn(model) -> @internal Element(msg),
) -> App(args, model, msg)
Construct a simulated Lustre application. The simulation can be started
with the start function by providing the initial arguments for
your app’s init function.
DOM events and messages dispatched by effects can be simulated using the
event and messgae functions.
Note: simulated apps do not run any effects! You can simulate the result of an effect by using the
messagefunction, but to test side effects you should test your application in a real environment.
pub fn click(
simulation: Simulation(model, msg),
on query: query.Query,
) -> Simulation(model, msg)
A convenience function that simulates a click event on the first element
matching the given query. This event will have no payload and is only
appropriate for event handlers that use Lustre’s on_click handler or custom
handlers that do not decode the event payload.
pub fn event(
simulation: Simulation(model, msg),
on query: query.Query,
name event: String,
data payload: List(#(String, json.Json)),
) -> Simulation(model, msg)
Simulate a DOM event on the first element that matches the given query. The payload represents a simulated event object, and should be used to pass data you expect your event handlers to decode.
If no element matches the query, an EventTargetNotFound event is
logged in the simulation history. If an element is found, but the application
has no handler for the event, the EventHandlerNotFound event is
logged instead.
Note: this is not a perfect simulation of a real DOM event. There is no capture phase of a simulated event and simulated events will not bubble up to parent elements.
pub fn history(
simulation: Simulation(model, msg),
) -> List(Event(msg))
Receive the current Event log of a running simulation. You can
use this to produce more detailed snapshots by also rendering the sequence of
events that produced the given view.
In addition to simulated DOM events and message dispatch, the event log will also include entries for when the queried event target could not be found in the view and cases where an event was fired but not handled by your application.
pub fn input(
simulation: Simulation(model, msg),
on query: query.Query,
value value: String,
) -> Simulation(model, msg)
Simulate an input event on the first element matching the given query. This helper has an event payload that looks like this:
{
"target": {
"value": value
}
}
and is appropriate for event handlers that use Lustre’s on_input handler
or custom handlers that only decode the event target value.
pub fn message(
simulation: Simulation(model, msg),
msg: msg,
) -> Simulation(model, msg)
Simulate a message sent directly to the runtime. This is often used to mimic the result of some effect you would have run in a real environment. For example, you might simulate a click event on a login button and then simulate the successful response from the server by calling this function with the message you would dispatch from the effect:
import birdie
import lustre/dev/simulate
import lustre/dev/query
import lustre/element
pub fn login_test() {
let app = simulate.application(init:, update:, view:)
let login_button = query.element(matching: query.id("login"))
let user = User(name: "Lucy")
simulate.start(app, Nil)
|> simulate.event(on: login_button, name: "click", data: [])
// Simulate a successful response from the server
|> simulate.message(ApiReturnedUser(Ok(user)))
|> simulate.view
|> element.to_readable_string
|> birdie.snap("Successful login")
}
Note: your app’s
viewfunction will probably be rendering quite a lot of HTML! To make your snapshots more meaningful, you might want to couple this with thequerymodule to only snapshot parts of the page that are relevant to the test.
pub fn model(simulation: Simulation(model, msg)) -> model
Introspect the current model of a running simulation. This can be useful
to debug why a simulation is not producing the view you expect.
pub fn problem(
simulation: Simulation(model, msg),
name name: String,
message message: String,
) -> Simulation(model, msg)
Log a problem that occured during the simulation. This function is useful for
external packages that want to provide functions to simulate certain effects
that may fail in the real world. For example, a routing package may log a
problem if a link has an invalid href attribute that would cause no message
to be dispatched.
Note: logging a problem will not stop the simulation from running, just like a real application!
pub fn simple(
init init: fn(args) -> model,
update update: fn(model, msg) -> model,
view view: fn(model) -> @internal Element(msg),
) -> App(args, model, msg)
pub fn start(
app: App(args, model, msg),
args: args,
) -> Simulation(model, msg)
pub fn submit(
simulation: Simulation(model, msg),
on query: query.Query,
fields form_data: List(#(String, String)),
) -> Simulation(model, msg)
Simulate a submit event on the first element matching the given query. The simulated event payload looks like this:
{
"detail": {
"formData": [
...
]
}
}
and is appropriate for event handlers that use Lustre’s on_submit handler
or custom handlers that only decode the non-standard detail.formData
property.
pub fn view(
simulation: Simulation(model, msg),
) -> @internal Element(msg)