Selkie.git | t/ | 82-app-facade.rakutest
use Test;
use lib 'lib';
use Selkie::App;
use Selkie::App::Internal::HitTest;
use Selkie::Widget;
plan 4;
subtest 'stable App facade methods remain present' => {
my @methods = <
stdplane theme store screen-manager focused event-supply root
detect-sprixel-bug-prone-terminal force-refresh-sprixels
set-theme add-screen switch-screen set-title
build-title-osc build-terminal-cleanup-sequence
toast show-modal close-modal has-modal
on-key on-frame on-resize
focus widget-attached check-focus-invariant focus-next focus-prev
quit run widget-at-in shutdown set-error-log
hot-hz sprixel-refresh-idle-threshold sprixel-refresh-idle-interval error-log
>;
plan @methods.elems;
for @methods -> $name {
ok Selkie::App.^can($name).elems > 0, "$name is available on Selkie::App";
}
};
subtest 'public package helper still resolves through Selkie::App' => {
plan 3;
my constant HOT60 = 1e0 / 60e0;
my constant HZ30 = 1e0 / 30e0;
my constant HZ4 = 1e0 / 4e0;
is-approx Selkie::App::pick-frame-budget(HOT60, 0e0, 999e0), HOT60, 1e-9,
'active user traffic keeps hot budget';
is-approx Selkie::App::pick-frame-budget(HOT60, 999e0, 0e0), HZ30, 1e-9,
'store-only traffic remains capped at 30 Hz';
is-approx Selkie::App::pick-frame-budget(HOT60, 999e0, 999e0), HZ4, 1e-9,
'deep idle reaches 4 Hz tier';
};
subtest 'terminal sequence facade helpers keep exact behavior' => {
plan 5;
is Selkie::App.build-title-osc("a\eb\nc"), "\e]0;abc\a",
'title OSC sanitizes control characters';
like Selkie::App.build-title-osc('Hi', :tmux), /"\ePtmux;" .* "\e\e]0;Hi\a" .* "\e\\"/,
'tmux title passthrough still doubles inner ESC';
my $cleanup = Selkie::App.build-terminal-cleanup-sequence;
like $cleanup, /"\e[?1006l"/, 'cleanup disables SGR mouse mode';
is ($cleanup ~~ m:g/"\e[<u"/).elems, 3,
'cleanup emits three Kitty keyboard protocol pops';
like $cleanup, /"\e[?1049l"/, 'cleanup exits alternate screen';
};
subtest 'hit-test facade delegates to internal helper' => {
plan 4;
my class TestWidget does Selkie::Widget {
method render() { self.clear-dirty }
}
my $root = TestWidget.new;
$root.set-viewport(abs-y => 1, abs-x => 2, rows => 3, cols => 4);
is Selkie::App.widget-at-in($root, 1, 2), $root,
'App facade returns root for a root-contained point';
nok Selkie::App.widget-at-in($root, 99, 99).defined,
'App facade returns the Widget type object outside the root';
is app-widget-at-in($root, 1, 2), $root,
'internal helper matches facade for hit';
nok app-widget-at-in($root, 99, 99).defined,
'internal helper matches facade for miss';
};