Current section
Files
Jump to
Current section
Files
src/plushie@testing.erl
-module(plushie@testing).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/plushie/testing.gleam").
-export([element_text/1, element_prop/2, element_children/1, start/1, stop/1, model/1, tree/1, send_event/2, click/2, type_text/3, toggle/2, submit/2, slide/3, select/3, find/2]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Test facade for plushie applications.\n"
"\n"
" Provides a unified test API that works across all backends:\n"
" mock (pure Gleam), pooled_mock (shared renderer), headless\n"
" (software rendering), and windowed (GPU + display).\n"
"\n"
" ## Backend selection\n"
"\n"
" Set `PLUSHIE_TEST_BACKEND` to choose the backend:\n"
"\n"
" PLUSHIE_TEST_BACKEND=pooled_mock gleam test\n"
" PLUSHIE_TEST_BACKEND=headless gleam test\n"
"\n"
" Default: `mock` (pure Gleam, no renderer binary needed).\n"
"\n"
" ## Usage\n"
"\n"
" let session = testing.start(my_app())\n"
" let session = testing.click(session, \"increment\")\n"
" let assert option.Some(el) = testing.find(session, \"count\")\n"
" should.equal(element.text(el), option.Some(\"Count: 1\"))\n"
" testing.stop(session)\n"
).
-file("src/plushie/testing.gleam", 171).
?DOC(" Extract text content from an element.\n").
-spec element_text(plushie@testing@element:element()) -> gleam@option:option(binary()).
element_text(El) ->
plushie@testing@element:text(El).
-file("src/plushie/testing.gleam", 176).
?DOC(" Get a prop value from an element.\n").
-spec element_prop(plushie@testing@element:element(), binary()) -> gleam@option:option(plushie@node:prop_value()).
element_prop(El, Key) ->
plushie@testing@element:prop(El, Key).
-file("src/plushie/testing.gleam", 181).
?DOC(" Get an element's children.\n").
-spec element_children(plushie@testing@element:element()) -> list(plushie@testing@element:element()).
element_children(El) ->
plushie@testing@element:children(El).
-file("src/plushie/testing.gleam", 199).
?DOC(
" Get or start a pooled backend. The pool is started once per\n"
" test run and cached in the process dictionary.\n"
).
-spec get_or_start_pooled(plushie@testing@session_pool:pool_mode()) -> plushie@testing@backend:test_backend(any()).
get_or_start_pooled(Mode) ->
case plushie_test_pool_ffi:get_pool() of
{ok, Pool_subject} ->
plushie@testing@backend@pooled:backend(Pool_subject);
{error, _} ->
Config = begin
_record = plushie@testing@session_pool:default_config(),
{pool_config,
Mode,
erlang:element(3, _record),
erlang:element(4, _record),
erlang:element(5, _record)}
end,
Pool_subject@2 = case plushie@testing@session_pool:start(Config) of
{ok, Pool_subject@1} -> Pool_subject@1;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"plushie/testing"/utf8>>,
function => <<"get_or_start_pooled"/utf8>>,
line => 205,
value => _assert_fail,
start => 6219,
'end' => 6275,
pattern_start => 6230,
pattern_end => 6246})
end,
plushie_test_pool_ffi:put_pool(Pool_subject@2),
plushie@testing@backend@pooled:backend(Pool_subject@2)
end.
-file("src/plushie/testing.gleam", 189).
?DOC(
" Resolve the backend from PLUSHIE_TEST_BACKEND env var.\n"
" Returns None for mock (use helpers directly), Some for pooled backends.\n"
).
-spec resolve_backend() -> gleam@option:option(plushie@testing@backend:test_backend(any())).
resolve_backend() ->
case plushie_ffi:get_env(<<"PLUSHIE_TEST_BACKEND"/utf8>>) of
{ok, <<"pooled_mock"/utf8>>} ->
{some, get_or_start_pooled(mock)};
{ok, <<"headless"/utf8>>} ->
{some, get_or_start_pooled(headless)};
_ ->
none
end.
-file("src/plushie/testing.gleam", 44).
?DOC(
" Start a test session for a simple app (msg = Event).\n"
"\n"
" The backend is selected via `PLUSHIE_TEST_BACKEND`:\n"
" - (unset/`mock`): pure Gleam, no renderer binary\n"
" - `pooled_mock`: shared `plushie --mock` process\n"
" - `headless`: `plushie --headless` with software rendering\n"
).
-spec start(plushie@app:app(SIS, plushie@event:event())) -> plushie@testing@session:test_session(SIS, plushie@event:event()).
start(App) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(2, Be))(App);
none ->
plushie@testing@session:start(App)
end.
-file("src/plushie/testing.gleam", 55).
?DOC(
" Stop the test session and release resources.\n"
"\n"
" No-op for mock backend. Releases the renderer session for\n"
" pooled and headless backends.\n"
).
-spec stop(plushie@testing@session:test_session(any(), plushie@event:event())) -> nil.
stop(Session) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(3, Be))(Session);
none ->
nil
end.
-file("src/plushie/testing.gleam", 63).
?DOC(" Return the current model from the session.\n").
-spec model(plushie@testing@session:test_session(SJA, plushie@event:event())) -> SJA.
model(Session) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(11, Be))(Session);
none ->
plushie@testing@session:model(Session)
end.
-file("src/plushie/testing.gleam", 71).
?DOC(" Return the current normalized tree from the session.\n").
-spec tree(plushie@testing@session:test_session(any(), plushie@event:event())) -> plushie@node:node_().
tree(Session) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(12, Be))(Session);
none ->
plushie@testing@session:current_tree(Session)
end.
-file("src/plushie/testing.gleam", 79).
?DOC(" Dispatch a raw event through the update cycle.\n").
-spec send_event(
plushie@testing@session:test_session(SJG, plushie@event:event()),
plushie@event:event()
) -> plushie@testing@session:test_session(SJG, plushie@event:event()).
send_event(Session, Event) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(14, Be))(Session, Event);
none ->
plushie@testing@session:send_event(Session, Event)
end.
-file("src/plushie/testing.gleam", 92).
?DOC(" Simulate a click on a widget by ID.\n").
-spec click(
plushie@testing@session:test_session(SJL, plushie@event:event()),
binary()
) -> plushie@testing@session:test_session(SJL, plushie@event:event()).
click(Session, Id) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(5, Be))(Session, Id);
none ->
plushie@testing@helpers:click(Session, Id)
end.
-file("src/plushie/testing.gleam", 103).
?DOC(" Simulate text input on a widget by ID.\n").
-spec type_text(
plushie@testing@session:test_session(SJQ, plushie@event:event()),
binary(),
binary()
) -> plushie@testing@session:test_session(SJQ, plushie@event:event()).
type_text(Session, Id, Text) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(6, Be))(Session, Id, Text);
none ->
plushie@testing@helpers:type_text(Session, Id, Text)
end.
-file("src/plushie/testing.gleam", 115).
?DOC(" Simulate a checkbox/toggler toggle by ID.\n").
-spec toggle(
plushie@testing@session:test_session(SJV, plushie@event:event()),
binary()
) -> plushie@testing@session:test_session(SJV, plushie@event:event()).
toggle(Session, Id) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(8, Be))(Session, Id);
none ->
plushie@testing@helpers:toggle(Session, Id)
end.
-file("src/plushie/testing.gleam", 126).
?DOC(" Simulate form submission on a widget by ID.\n").
-spec submit(
plushie@testing@session:test_session(SKA, plushie@event:event()),
binary()
) -> plushie@testing@session:test_session(SKA, plushie@event:event()).
submit(Session, Id) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(7, Be))(Session, Id);
none ->
plushie@testing@helpers:submit(Session, Id)
end.
-file("src/plushie/testing.gleam", 137).
?DOC(" Simulate a slider change by ID.\n").
-spec slide(
plushie@testing@session:test_session(SKF, plushie@event:event()),
binary(),
float()
) -> plushie@testing@session:test_session(SKF, plushie@event:event()).
slide(Session, Id, Value) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(10, Be))(Session, Id, Value);
none ->
plushie@testing@helpers:slide(Session, Id, Value)
end.
-file("src/plushie/testing.gleam", 149).
?DOC(" Simulate selection on a widget by ID.\n").
-spec select(
plushie@testing@session:test_session(SKK, plushie@event:event()),
binary(),
binary()
) -> plushie@testing@session:test_session(SKK, plushie@event:event()).
select(Session, Id, Value) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(9, Be))(Session, Id, Value);
none ->
plushie@testing@helpers:select(Session, Id, Value)
end.
-file("src/plushie/testing.gleam", 163).
?DOC(" Find an element by ID in the session's current tree.\n").
-spec find(
plushie@testing@session:test_session(any(), plushie@event:event()),
binary()
) -> gleam@option:option(plushie@testing@element:element()).
find(Session, Id) ->
case resolve_backend() of
{some, Be} ->
(erlang:element(4, Be))(Session, Id);
none ->
plushie@testing@element:find(
plushie@testing@session:current_tree(Session),
Id
)
end.