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';
};