Packages

An easy to use frontend framework written in Gleam.

Current section

Files

Jump to
novdom src novdom_testing testing.gleam
Raw

src/novdom_testing/testing.gleam

//// A module for initializing tests and rendering components. \
//// Use it in combination with `novdom_testing/component_should` to test novdom components.
import novdom/hotkey
import novdom/internals/component.{type Component} as internal_component
import novdom/internals/parameter.{type Event, type Parameter, Listener}
import novdom/parameter/motion
/// A type to check if a function was called.
pub opaque type Callee {
Callee(id: String)
}
/// A Type for a function that creates a parameter with a listener (e.g. `onclick`).
pub type ParameterFn =
fn(fn(Event) -> Nil) -> Parameter
/// Initialize the testing environment. This function should be called at the beginning of a test.
pub fn init(test_fn: fn() -> a) -> Nil {
init_js()
test_fn()
Nil
}
/// Render a component in the viewport. This function should be called in a test function. \
/// **Warning:** Never use `novdom.start()` in a test function, this can lead to unexpected behavior.
pub fn render(component: fn() -> Component) -> Nil {
// TODO: Move to init()??
motion.init()
hotkey.init()
component()
|> internal_component.add_to_viewport()
// wait(5)
}
/// Create a callee type that can be used to test if a function was called
pub fn create_callee() -> Callee {
create_callee_js()
|> Callee
}
/// Call a callee to later check if it was called (see `callee_count`).
/// Use this function to simulate a function call.
pub fn call_callee(callee: Callee) {
call_callee_js(callee.id)
}
/// Check how often a callee was called
pub fn callee_count(callee: Callee) -> Int {
callee_count_js(callee.id)
}
/// Trigger an event on a component.
///
/// Example for a click event:
/// ```gleam
/// trigger_event(my_component, onclick)
/// ```
///
pub fn trigger_event(component: Component, listener: ParameterFn) -> Component {
let assert Listener(name, _) = listener(fn(_) { Nil })
trigger_event_js(component, name)
component
}
/// Name a step in a test to make error messages more precise. This does only work with `novdom_testing/component_should` functions (not with `gleeunit/should`).
///
/// Example:
/// ```gleam
/// comp
/// |> step("Check if component is visible")
/// |> component_should.be_visible()
/// ```
///
pub fn step(subject: a, step: String) -> a {
set_step(step)
subject
}
/// Gets all children of a component.
pub fn children(component: Component) -> List(Component) {
internal_component.children(component)
}
/// Gets a specific child of a component.
pub fn child(component: Component, index: Int) -> Result(Component, Nil) {
internal_component.child(component, index)
}
/// Set a description for a component to be used in error messages
@external(javascript, "../testing_ffi.mjs", "set_description")
pub fn description(component: Component, desc: String) -> Component
/// Trigger the `onreplacement` modifier on a component.
@external(javascript, "../testing_ffi.mjs", "trigger_unrender")
pub fn trigger_replacement(component: Component) -> Component
@external(javascript, "../testing_ffi.mjs", "current_step")
fn set_step(step: String) -> Nil
@external(javascript, "../testing_ffi.mjs", "trigger_event")
fn trigger_event_js(component: Component, event: String) -> Nil
@external(javascript, "../testing_ffi.mjs", "create_callee")
fn create_callee_js() -> String
@external(javascript, "../testing_ffi.mjs", "call_callee")
fn call_callee_js(id: String) -> Nil
@external(javascript, "../testing_ffi.mjs", "callee_count")
fn callee_count_js(id: String) -> Int
@external(javascript, "../testing_ffi.mjs", "init")
fn init_js() -> Nil