from test/more import *;
requires_capability( "gui" );
from std/gui import *;
let ui := Window(
title: "Phase 3",
VBox(
id: "root",
Separator( id: "sep" ),
Slider(
id: "slider",
value: 25,
min: 0,
max: 100,
step: 5,
),
Progress(
id: "progress",
value: 30,
max: 200,
show_text: true,
),
DatePicker(
id: "date",
value: "2026-04-26",
min: "2020-01-01",
max: "2030-12-31",
first_day_of_week: 1,
),
Tabs(
id: "tabs",
selected: "details",
Tab( id: "summary", title: "Summary", value: "summary" ),
Tab(
id: "details",
title: "Details",
value: "details",
icon: "details.png",
closable: true,
),
),
ListView(
id: "list",
items: [
{ label: "Alpha", value: "a" },
{ label: "Beta", value: "b" },
],
selected_index: 0,
),
TreeView(
id: "tree",
multiple: true,
items: [
{
label: "Root",
value: "root",
children: [
{ label: "Child", value: "child" },
],
},
],
selected_path: [ 0, 0 ],
),
),
);
ok( ui.find_by_id("sep") instanceof Widget, "Separator is a Widget" );
is(
ui.find_by_id("sep").orientation(),
"horizontal",
"Separator orientation",
);
let slider := ui.find_by_id("slider");
is( slider.value(), 25, "Slider value getter" );
is( slider.value(40), slider, "Slider value setter returns self" );
is( slider.value(), 40, "Slider value setter updates value" );
is( slider.min(), 0, "Slider min getter" );
is( slider.max(), 100, "Slider max getter" );
is( slider.step(), 5, "Slider step getter" );
let progress := ui.find_by_id("progress");
is( progress.value(), 30, "Progress value getter" );
is( progress.max(), 200, "Progress max getter" );
is( progress.show_text(), true, "Progress show_text getter" );
is(
progress.indeterminate(true),
progress,
"Progress indeterminate setter returns self",
);
is( progress.indeterminate(), true, "Progress indeterminate getter" );
let date := ui.find_by_id("date");
ok( date instanceof Widget, "DatePicker is a Widget" );
is( date.value(), "2026-04-26", "DatePicker value getter" );
is( date.min(), "2020-01-01", "DatePicker min getter" );
is( date.max(), "2030-12-31", "DatePicker max getter" );
is(
date.first_day_of_week(),
1,
"DatePicker first_day_of_week getter",
);
is( date.value("2026-05-01"), date, "DatePicker value setter returns self" );
is( date.value(), "2026-05-01", "DatePicker value setter updates value" );
is(
date.set_value("2026-06-01"),
date,
"DatePicker set_value returns self",
);
is( date.value(), "2026-06-01", "DatePicker set_value updates value" );
is( date.min("2021-01-01"), date, "DatePicker min setter returns self" );
is( date.min(), "2021-01-01", "DatePicker min setter updates value" );
is( date.max("2029-12-31"), date, "DatePicker max setter returns self" );
is( date.max(), "2029-12-31", "DatePicker max setter updates value" );
is(
date.first_day_of_week(0),
date,
"DatePicker first_day_of_week setter returns self",
);
is(
date.first_day_of_week(),
0,
"DatePicker first_day_of_week setter updates value",
);
let date_changed := [];
date.change( function ( e ) {
date_changed.push( e.name() );
} );
date.change();
is( date_changed[0], "change", "DatePicker change event dispatches" );
let tabs := ui.find_by_id("tabs");
let summary := ui.find_by_id("summary");
let details := ui.find_by_id("details");
is( tabs.tabs().length(), 2, "Tabs returns Tab children" );
is( tabs.selected(), "details", "Tabs initial selection" );
is( details.selected(), true, "Tabs initial selection checks matching tab" );
is( summary.selected(), false, "Tabs initial selection unchecks other tab" );
is( tabs.selected_tab(), details, "Tabs selected_tab returns selected tab" );
is( details.closable(), true, "Tab closable getter" );
is( details.icon(), "details.png", "Tab icon getter" );
is( tabs.selected("summary"), tabs, "Tabs selected setter returns self" );
is( summary.selected(), true, "Tabs selected setter checks matching tab" );
details.selected(true);
is( tabs.selected(), "details", "Tab selected setter updates parent" );
let list := ui.find_by_id("list");
is( list.items().length(), 2, "ListView items getter" );
is( list.selected_index(), 0, "ListView selected_index getter" );
is( list.selected_item(){label}, "Alpha", "ListView selected item" );
is(
list.selected_index(1),
list,
"ListView selected_index setter returns self",
);
is( list.selected_item(){value}, "b", "ListView selected index updates item" );
is(
list.add_item( { label: "Gamma", value: "g" } ),
list,
"ListView add_item returns self",
);
is( list.items().length(), 3, "ListView add_item mutates items" );
let selected_events := [];
list.on( "select", function ( e ) {
selected_events.push( e.name() );
} );
list.emit("select");
is( selected_events[0], "select", "ListView select event dispatches" );
let activated_events := [];
list.activate( function ( e ) {
activated_events.push( e.name() );
} );
is( list.activate_index(2), list, "ListView activate_index returns self" );
is( activated_events[0], "activate", "ListView activate event dispatches" );
is( list.clear_items(), list, "ListView clear_items returns self" );
is( list.items().length(), 0, "ListView clear_items removes items" );
is( list.selected_index(), null, "ListView clear_items clears selection" );
let tree := ui.find_by_id("tree");
is( tree.items().length(), 1, "TreeView items getter" );
is( tree.multiple(), true, "TreeView multiple getter" );
is( tree.selected_path()[0], 0, "TreeView selected_path first index" );
is( tree.selected_path()[1], 0, "TreeView selected_path second index" );
is( tree.selected_item(){value}, "child", "TreeView selected item" );
is(
tree.selected_path([ 0 ]),
tree,
"TreeView selected_path setter returns self",
);
is(
tree.selected_item(){value},
"root",
"TreeView selected_path updates item",
);
let tree_activated := [];
let tree_expanded := [];
let tree_collapsed := [];
tree.activate( function ( e ) {
tree_activated.push( e.name() );
} );
tree.expand( function ( e ) {
tree_expanded.push( e.name() );
} );
tree.collapse( function ( e ) {
tree_collapsed.push( e.name() );
} );
is(
tree.activate_path([ 0, 0 ]),
tree,
"TreeView activate_path returns self",
);
is( tree_activated[0], "activate", "TreeView activate event dispatches" );
is( tree.collapse_path([ 0 ]), tree, "TreeView collapse_path returns self" );
is( tree.is_expanded([ 0 ]), false, "TreeView collapse_path mutates state" );
is( tree_collapsed[0], "collapse", "TreeView collapse event dispatches" );
is( tree.expand_path([ 0 ]), tree, "TreeView expand_path returns self" );
is( tree.is_expanded([ 0 ]), true, "TreeView expand_path mutates state" );
is( tree_expanded[0], "expand", "TreeView expand event dispatches" );
is(
tree.add_item( { label: "Other", value: "other" } ),
tree,
"TreeView add_item returns self",
);
is( tree.items().length(), 2, "TreeView add_item mutates items" );
is( tree.clear_items(), tree, "TreeView clear_items returns self" );
is( tree.items().length(), 0, "TreeView clear_items removes items" );
let bad_orientation := exception( function () {
Slider( orientation: "diagonal" );
} );
ok( bad_orientation instanceof Exception, "invalid enum prop throws" );
ok(
bad_orientation{message} ~ /GUI_PROP_TYPE/,
"invalid enum error includes code",
);
let bad_items := exception( function () {
ListView( items: "nope" );
} );
ok( bad_items instanceof Exception, "invalid items type throws" );
ok( bad_items{message} ~ /GUI_PROP_TYPE/, "invalid items type includes code" );
done_testing();