Selkie--Test--Tree

NAME

Selkie::Test::Tree - Find and assert on widgets inside a built tree

SYNOPSIS

use Test;
use Selkie::Test::Tree;
use Selkie::Widget::Button;

# $root is some layout tree built by your app code
my $save-btn = find-widget $root, -> $w {
    $w ~~ Selkie::Widget::Button && $w.label eq 'Save';
};
ok $save-btn.defined, 'Save button exists';

my @all-buttons = find-widgets $root, -> $w { $w ~~ Selkie::Widget::Button };
is @all-buttons.elems, 3, 'three buttons total';

contains-widget-ok $root, $save-btn, 'save button reachable from root';

done-testing;

DESCRIPTION

When a widget tree is built by a subscription callback or a factory helper, you often don't hold direct references to every child. These helpers walk the tree (descending through Container children and Border/Modal content) so tests can locate widgets by predicate.

The walk function is the underlying iterator; the other helpers build on it. Write find-widget($root, &pred) for "first match" and find-widgets($root, &pred) for "all matches". The predicate is any Callable that takes a widget and returns a truthy value.

EXAMPLES

Find by widget type

my $first-input = find-widget $root,
    -> $w { $w ~~ Selkie::Widget::TextInput };

Find by attribute

my $title-bar = find-widget $root, -> $w {
    $w ~~ Selkie::Widget::Text && $w.text.starts-with('Settings');
};

Assert the tree's shape

is find-widgets($root, * ~~ Selkie::Widget::Button).elems, 2, 'two buttons';
is find-widgets($root, * ~~ Selkie::Widget::ListView).elems, 1, 'one list';

Verify a widget is still reachable

Useful to catch regressions where a widget gets destroyed but tests still held a reference:

contains-widget-ok $root, $my-input, 'input still in the tree';

SEE ALSO

sub walk

sub walk(
    Selkie::Widget $root
) returns Seq

Iterate every widget reachable from $root, depth-first. Yields $root itself first, then descends through Container.children and any .content (for Border/Modal). Lazy — safe to short-circuit with .first.

sub find-widget

sub find-widget(
    Selkie::Widget $root,
    &predicate
) returns Selkie::Widget

Return the first widget matching the predicate, or Nil. The predicate can be any Callable taking a widget; smartmatch also works thanks to Raku's * whatever star: find-widget root, -> w.focusable };

sub find-widgets

sub find-widgets(
    Selkie::Widget $root,
    &predicate
) returns List

Return every widget in the tree matching the predicate, in walk order.

sub contains-widget-ok

sub contains-widget-ok(
    Selkie::Widget $root,
    Selkie::Widget $target,
    Str:D $desc
) returns Mu

Test assertion: $target is reachable from $root. Uses identity comparison (===), so it's checking the same widget instance.

Selkie v0.10.0

High-level TUI framework built on Notcurses

Authors

  • Matt Doughty

License

Artistic-2.0

Dependencies

Notcurses::Native:ver<0.4.0+>:auth<zef:apogee>

Test Dependencies

Provides

  • Selkie
  • Selkie::App
  • Selkie::App::Internal::Dispatch
  • Selkie::App::Internal::ErrorLog
  • Selkie::App::Internal::FocusTree
  • Selkie::App::Internal::HitTest
  • Selkie::App::Internal::IdleBudget
  • Selkie::App::Internal::OverlayTree
  • Selkie::App::Internal::RenderLoop
  • Selkie::App::Internal::ScreenModalLifecycle
  • Selkie::App::Internal::Terminal
  • Selkie::App::Internal::TerminalSequences
  • Selkie::Container
  • Selkie::EffectiveBounds
  • Selkie::Event
  • Selkie::Layout::Allocate
  • Selkie::Layout::HBox
  • Selkie::Layout::Split
  • Selkie::Layout::VBox
  • Selkie::Plot::Palette
  • Selkie::Plot::Scaler
  • Selkie::Plot::Ticks
  • Selkie::ScreenManager
  • Selkie::Sizing
  • Selkie::Store
  • Selkie::Style
  • Selkie::Test::Focus
  • Selkie::Test::Keys
  • Selkie::Test::Snapshot
  • Selkie::Test::Snapshot::Harness
  • Selkie::Test::Store
  • Selkie::Test::Supply
  • Selkie::Test::Tree
  • Selkie::Theme
  • Selkie::Trace
  • Selkie::Tree
  • Selkie::Widget
  • Selkie::Widget::Axis
  • Selkie::Widget::BarChart
  • Selkie::Widget::Border
  • Selkie::Widget::Button
  • Selkie::Widget::CardList
  • Selkie::Widget::Checkbox
  • Selkie::Widget::CommandPalette
  • Selkie::Widget::ConfirmModal
  • Selkie::Widget::FileBrowser
  • Selkie::Widget::FocusableByDefault
  • Selkie::Widget::Heatmap
  • Selkie::Widget::HelpOverlay
  • Selkie::Widget::Histogram
  • Selkie::Widget::Image
  • Selkie::Widget::Legend
  • Selkie::Widget::LineChart
  • Selkie::Widget::ListView
  • Selkie::Widget::Modal
  • Selkie::Widget::MultiLineInput
  • Selkie::Widget::PasswordStrength
  • Selkie::Widget::Plot
  • Selkie::Widget::ProgressBar
  • Selkie::Widget::RadioGroup
  • Selkie::Widget::RichText
  • Selkie::Widget::RichText::Span
  • Selkie::Widget::ScatterPlot
  • Selkie::Widget::ScrollView
  • Selkie::Widget::Select
  • Selkie::Widget::Sparkline
  • Selkie::Widget::Spinner
  • Selkie::Widget::TabBar
  • Selkie::Widget::Table
  • Selkie::Widget::Text
  • Selkie::Widget::TextInput
  • Selkie::Widget::TextInput::HighlightSpan
  • Selkie::Widget::TextStream
  • Selkie::Widget::Toast
  • Selkie::Widget::ViewportedCardList

Documentation

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.