Test harness for Harlock apps.
Boots an app under a :test backend — no /dev/tty required — then
exposes synchronous helpers for driving events and inspecting state.
test "tab moves focus to next field" do
h = Harlock.Test.start_app(MyApp, %{...})
Harlock.Test.send_key(h, :tab)
assert Harlock.Test.focused(h) == :email_field
Harlock.Test.stop(h)
endAnything that requires a real terminal lives behind the backend abstraction; everything tested here is the same code path that runs in production except for the bytes-in/bytes-out boundary.
Summary
Functions
Returns the current cell buffer struct.
Returns the current Frame.cursor — {row, col} or nil if hidden.
Returns the id of the currently focused element, or nil.
Returns the current model from the runtime.
Returns true if the app has signaled :quit from its update callback.
The runtime exits but the supervisor stays alive until you call stop/1.
Returns the raw bytes the writer has received so far.
Returns the rendered cell buffer as a single string (rows joined by \n).
Inject a resize event. Stand-in for SIGWINCH in headless tests — the
runtime updates its dimensions, discards prev_frame, and re-renders.
The test writer's cell buffer is resized first so the new frame has
somewhere to land.
Inject a synthetic event into the runtime. The event uses the same shape
the input parser emits (e.g. {:key, :tab, []}).
Convenience for {:key, key, mods} events.
Start an app under the test backend and return a handle for the helpers in this module.
Stop the app cleanly. Safe to call after the app has already quit on its
own (e.g. via update returning :quit). Drains any pending
:harlock_done message from the calling process's mailbox.
Types
Functions
@spec cells(handle()) :: Harlock.Render.Buffer.t()
Returns the current cell buffer struct.
@spec cursor(handle()) :: {non_neg_integer(), non_neg_integer()} | nil
Returns the current Frame.cursor — {row, col} or nil if hidden.
Returns the id of the currently focused element, or nil.
Returns the current model from the runtime.
Returns true if the app has signaled :quit from its update callback.
The runtime exits but the supervisor stays alive until you call stop/1.
Returns the raw bytes the writer has received so far.
Returns the rendered cell buffer as a single string (rows joined by \n).
@spec resize(handle(), pos_integer(), pos_integer()) :: :ok
Inject a resize event. Stand-in for SIGWINCH in headless tests — the
runtime updates its dimensions, discards prev_frame, and re-renders.
The test writer's cell buffer is resized first so the new frame has
somewhere to land.
Inject a synthetic event into the runtime. The event uses the same shape
the input parser emits (e.g. {:key, :tab, []}).
Convenience for {:key, key, mods} events.
Harlock.Test.send_key(h, :tab)
Harlock.Test.send_key(h, {:char, ?q})
Harlock.Test.send_key(h, :enter, [:ctrl])
Start an app under the test backend and return a handle for the helpers in this module.
@spec stop(handle()) :: :ok
Stop the app cleanly. Safe to call after the app has already quit on its
own (e.g. via update returning :quit). Drains any pending
:harlock_done message from the calling process's mailbox.