use buoyant::{
app::{App, Harness as _},
focus::Role,
primitives::Size,
render::ContentShape,
view::prelude::*,
};
struct State {
tapped: bool,
}
fn view_with_invisible_button(_: &State) -> impl View<(), State> + use<> {
VStack::new((
Button::new(|s: &mut State| s.tapped = true, |_| Circle).opacity(0),
Button::new(|s: &mut State| s.tapped = true, |_| Rectangle),
))
}
fn view_with_visible_buttons(_: &State) -> impl View<(), State> + use<> {
VStack::new((
Button::new(|s: &mut State| s.tapped = true, |_| Circle),
Button::new(|s: &mut State| s.tapped = true, |_| Rectangle),
))
}
#[test]
fn opacity_zero_skips_focus() {
let state = State { tapped: false };
let mut harness =
App::new(state, Size::new(100, 100), view_with_invisible_button).with_roles(Role::Button);
let result = harness.focus_forward();
assert!(result.requested_focus());
assert!(
matches!(result.shape(), Some(ContentShape::Rectangle(_))),
"Should skip invisible Circle button"
);
}
#[test]
fn opacity_one_allows_focus() {
let state = State { tapped: false };
let mut harness =
App::new(state, Size::new(100, 100), view_with_visible_buttons).with_roles(Role::Button);
let result = harness.focus_forward();
assert!(result.requested_focus());
assert!(
matches!(result.shape(), Some(ContentShape::Circle(_))),
"Should focus first button (Circle)"
);
}
#[test]
fn partial_opacity_allows_focus() {
fn view(_: &State) -> impl View<(), State> + use<> {
VStack::new((
Button::new(|s: &mut State| s.tapped = true, |_| Circle).opacity(128),
Button::new(|s: &mut State| s.tapped = true, |_| Rectangle),
))
}
let state = State { tapped: false };
let mut harness = App::new(state, Size::new(100, 100), view).with_roles(Role::Button);
let result = harness.focus_forward();
assert!(result.requested_focus());
assert!(
matches!(result.shape(), Some(ContentShape::Circle(_))),
"Should focus first button with partial opacity"
);
}