Packages

Native desktop GUI framework for Gleam, powered by Iced

Current section

Files

Jump to
plushie_gleam src plushie@testing@script@runner.erl
Raw

src/plushie@testing@script@runner.erl

-module(plushie@testing@script@runner).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/plushie/testing/script/runner.gleam").
-export([run/2]).
-export_type([failure/0]).
-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(
" Script executor for `.plushie` test scripts.\n"
"\n"
" Runs parsed scripts step by step, collecting per-instruction\n"
" results. Returns Ok(Nil) on success or Error(failures) with\n"
" a list of (instruction, reason) tuples.\n"
).
-type failure() :: {failure, plushie@testing@script:instruction(), binary()}.
-file("src/plushie/testing/script/runner.gleam", 292).
-spec default_window_id(plushie@node:node_()) -> binary().
default_window_id(Tree) ->
case erlang:element(3, Tree) of
<<"window"/utf8>> ->
erlang:element(2, Tree);
_ ->
case gleam@list:find(
erlang:element(5, Tree),
fun(Child) -> erlang:element(3, Child) =:= <<"window"/utf8>> end
) of
{ok, Window} ->
erlang:element(2, Window);
{error, _} ->
<<""/utf8>>
end
end.
-file("src/plushie/testing/script/runner.gleam", 303).
-spec last_segment(binary()) -> binary().
last_segment(Id) ->
case gleam@string:split(Id, <<"/"/utf8>>) of
[] ->
Id;
Segments ->
case gleam@list:last(Segments) of
{ok, Last} ->
Last;
{error, _} ->
Id
end
end.
-file("src/plushie/testing/script/runner.gleam", 315).
?DOC(" Recursively check if any node in the tree contains the given text.\n").
-spec tree_contains_text(plushie@node:node_(), binary()) -> boolean().
tree_contains_text(Tree, Text) ->
Props = erlang:element(4, Tree),
Values = [gleam_stdlib:map_get(Props, <<"content"/utf8>>),
gleam_stdlib:map_get(Props, <<"label"/utf8>>),
gleam_stdlib:map_get(Props, <<"value"/utf8>>),
gleam_stdlib:map_get(Props, <<"placeholder"/utf8>>)],
Found = gleam@list:any(Values, fun(Result) -> case Result of
{ok, {string_val, S}} ->
S =:= Text;
_ ->
false
end end),
case Found of
true ->
true;
false ->
gleam@list:any(
erlang:element(5, Tree),
fun(Child) -> tree_contains_text(Child, Text) end
)
end.
-file("src/plushie/testing/script/runner.gleam", 276).
-spec find_event_target_in_children(
list(plushie@node:node_()),
binary(),
binary()
) -> gleam@option:option(plushie@event:event_target()).
find_event_target_in_children(Children, Target, Current_window) ->
case Children of
[] ->
none;
[Child | Rest] ->
case find_event_target(Child, Target, Current_window) of
{some, Found} ->
{some, Found};
none ->
find_event_target_in_children(Rest, Target, Current_window)
end
end.
-file("src/plushie/testing/script/runner.gleam", 253).
-spec find_event_target(plushie@node:node_(), binary(), binary()) -> gleam@option:option(plushie@event:event_target()).
find_event_target(Tree, Target, Current_window) ->
Window_id = case erlang:element(3, Tree) of
<<"window"/utf8>> ->
erlang:element(2, Tree);
_ ->
Current_window
end,
Local_id = last_segment(erlang:element(2, Tree)),
Exact_match = erlang:element(2, Tree) =:= Target,
Local_match = not gleam_stdlib:contains_string(Target, <<"/"/utf8>>) andalso (Local_id
=:= Target),
case (erlang:element(3, Tree) /= <<"window"/utf8>>) andalso (Exact_match
orelse Local_match) of
true ->
Et = plushie@event:make_target(erlang:element(2, Tree), Window_id),
{some, Et};
false ->
find_event_target_in_children(
erlang:element(5, Tree),
Target,
Window_id
)
end.
-file("src/plushie/testing/script/runner.gleam", 240).
-spec resolve_event_target(plushie@node:node_(), binary()) -> plushie@event:event_target().
resolve_event_target(Tree, Selector) ->
case find_event_target(Tree, Selector, <<""/utf8>>) of
{some, Found} ->
Found;
none ->
{event_target, default_window_id(Tree), Selector, [], Selector}
end.
-file("src/plushie/testing/script/runner.gleam", 59).
-spec execute(
plushie@testing@session:test_session(XUN),
plushie@testing@script:instruction()
) -> {ok, plushie@testing@session:test_session(XUN)} | {error, binary()}.
execute(Session, Instruction) ->
case Instruction of
{click, Selector} ->
Target = resolve_event_target(
plushie@testing@session:current_tree(Session),
Selector
),
{ok,
plushie@testing@session:send_event(
Session,
{widget, {click, Target}}
)};
{type_text, Selector@1, Text} ->
Target@1 = resolve_event_target(
plushie@testing@session:current_tree(Session),
Selector@1
),
{ok,
plushie@testing@session:send_event(
Session,
{widget, {input, Target@1, Text}}
)};
{type_key, Key} ->
{ok,
plushie@testing@session:send_event(
Session,
{key,
{key_event,
key_pressed,
<<""/utf8>>,
Key,
Key,
plushie@event:modifiers_none(),
none,
standard,
{some, Key},
false,
false}}
)};
{press, Key@1} ->
{ok,
plushie@testing@session:send_event(
Session,
{key,
{key_event,
key_pressed,
<<""/utf8>>,
Key@1,
Key@1,
plushie@event:modifiers_none(),
none,
standard,
none,
false,
false}}
)};
{release, Key@2} ->
{ok,
plushie@testing@session:send_event(
Session,
{key,
{key_event,
key_released,
<<""/utf8>>,
Key@2,
Key@2,
plushie@event:modifiers_none(),
none,
standard,
none,
false,
false}}
)};
{toggle, Selector@2} ->
Target@2 = resolve_event_target(
plushie@testing@session:current_tree(Session),
Selector@2
),
{ok,
plushie@testing@session:send_event(
Session,
{widget, {toggle, Target@2, true}}
)};
{select, Selector@3, Value} ->
Target@3 = resolve_event_target(
plushie@testing@session:current_tree(Session),
Selector@3
),
{ok,
plushie@testing@session:send_event(
Session,
{widget, {select, Target@3, Value}}
)};
{slide, Selector@4, Value@1} ->
Target@4 = resolve_event_target(
plushie@testing@session:current_tree(Session),
Selector@4
),
{ok,
plushie@testing@session:send_event(
Session,
{widget, {slide, Target@4, Value@1}}
)};
{move, _} ->
{ok, Session};
{move_to, X, Y} ->
{ok,
plushie@testing@session:send_event(
Session,
{widget,
{move,
{event_target,
<<""/utf8>>,
<<""/utf8>>,
[],
<<""/utf8>>},
erlang:float(X),
erlang:float(Y),
mouse,
none,
plushie@event:modifiers_none(),
false}}
)};
{expect, Text@1} ->
Tree = plushie@testing@session:current_tree(Session),
case tree_contains_text(Tree, Text@1) of
true ->
{ok, Session};
false ->
{error,
<<<<"expected to find text \""/utf8, Text@1/binary>>/binary,
"\" in tree"/utf8>>}
end;
{assert_text, Selector@5, Expected} ->
Tree@1 = plushie@testing@session:current_tree(Session),
case plushie@testing@element:find(Tree@1, Selector@5) of
{some, El} ->
case plushie@testing@element:text(El) of
{some, Actual} ->
case Actual =:= Expected of
true ->
{ok, Session};
false ->
{error,
<<<<<<<<<<<<"expected text \""/utf8,
Expected/binary>>/binary,
"\" for \""/utf8>>/binary,
Selector@5/binary>>/binary,
"\", got \""/utf8>>/binary,
Actual/binary>>/binary,
"\""/utf8>>}
end;
none ->
{error,
<<<<"element \""/utf8, Selector@5/binary>>/binary,
"\" has no text content"/utf8>>}
end;
none ->
{error,
<<<<"element \""/utf8, Selector@5/binary>>/binary,
"\" not found"/utf8>>}
end;
{assert_model, Expression} ->
Model_str = gleam@string:inspect(
plushie@testing@session:model(Session)
),
case gleam_stdlib:contains_string(Model_str, Expression) of
true ->
{ok, Session};
false ->
{error,
<<<<<<"assert_model failed: \""/utf8,
Expression/binary>>/binary,
"\" not found in model: "/utf8>>/binary,
Model_str/binary>>}
end;
{assert_tree_hash, _} ->
{ok, Session};
{assert_screenshot, _} ->
{ok, Session};
{wait, _} ->
{ok, Session}
end.
-file("src/plushie/testing/script/runner.gleam", 29).
?DOC(
" Run a parsed script against a test session.\n"
" Returns Ok(Nil) on success or Error(failures).\n"
).
-spec run(
plushie@testing@script:script(),
plushie@testing@session:test_session(any())
) -> {ok, nil} | {error, list(failure())}.
run(Script_val, Session) ->
Result = gleam@list:index_fold(
erlang:element(3, Script_val),
{Session, []},
fun(Acc, Instruction, Idx) ->
{Sess, Failures} = Acc,
case execute(Sess, Instruction) of
{ok, New_sess} ->
{New_sess, Failures};
{error, Reason} ->
Failure = {failure,
Instruction,
<<<<<<"line "/utf8,
(erlang:integer_to_binary(Idx + 1))/binary>>/binary,
": "/utf8>>/binary,
Reason/binary>>},
{Sess, [Failure | Failures]}
end
end
),
case erlang:element(2, Result) of
[] ->
{ok, nil};
Failures@1 ->
{error, lists:reverse(Failures@1)}
end.