// SPDX-License-Identifier: LGPL-2.1-only // Copyright (C) 2026 Liberux Labs, S. L. use super::*; use crate::render::Canvas; use crate::types::Rect; fn make_canvas() -> Canvas { Canvas::new( 400, 400 ) } #[ test ] fn value_clamped_on_creation() { let s: VSlider<()> = vslider( 1.5 ); assert_eq!( s.value, 1.0 ); let s: VSlider<()> = vslider( -0.5 ); assert_eq!( s.value, 0.0 ); } #[ test ] fn value_from_y_top_is_one() { let rect = Rect { x: 0.0, y: 0.0, width: 56.0, height: 160.0 }; assert_eq!( value_from_y_in_rect( rect, 0.0 ), 1.0 ); } #[ test ] fn value_from_y_bottom_is_zero() { let rect = Rect { x: 0.0, y: 0.0, width: 56.0, height: 160.0 }; assert_eq!( value_from_y_in_rect( rect, 160.0 ), 0.0 ); } #[ test ] fn value_from_y_center_is_half() { let rect = Rect { x: 0.0, y: 0.0, width: 56.0, height: 160.0 }; let v = value_from_y_in_rect( rect, 80.0 ); assert!( ( v - 0.5 ).abs() < 1e-6 ); } #[ test ] fn value_from_y_above_rect_clamps_to_one() { let rect = Rect { x: 0.0, y: 10.0, width: 56.0, height: 160.0 }; assert_eq!( value_from_y_in_rect( rect, -50.0 ), 1.0 ); } #[ test ] fn value_from_y_below_rect_clamps_to_zero() { let rect = Rect { x: 0.0, y: 10.0, width: 56.0, height: 160.0 }; assert_eq!( value_from_y_in_rect( rect, 500.0 ), 0.0 ); } #[ test ] fn value_from_y_respects_rect_offset() { // A rect starting at y=100 with height=100: y=100 → 1.0, y=200 → 0.0. let rect = Rect { x: 0.0, y: 100.0, width: 56.0, height: 100.0 }; assert_eq!( value_from_y_in_rect( rect, 100.0 ), 1.0 ); assert_eq!( value_from_y_in_rect( rect, 200.0 ), 0.0 ); let v = value_from_y_in_rect( rect, 150.0 ); assert!( ( v - 0.5 ).abs() < 1e-6 ); } #[ test ] fn size_overrides_defaults() { let canvas = make_canvas(); let s: VSlider<()> = vslider( 0.5 ).size( 40.0, 200.0 ); let ( w, h ) = s.preferred_size( 500.0, &canvas ); assert_eq!( w, 40.0 ); assert_eq!( h, 200.0 ); } #[ test ] fn size_clamps_to_minimum() { let canvas = make_canvas(); let s: VSlider<()> = vslider( 0.5 ).size( 0.0, 0.0 ); let ( w, h ) = s.preferred_size( 500.0, &canvas ); assert_eq!( w, 2.0 ); assert_eq!( h, 2.0 ); } #[ test ] fn preferred_size_ignores_max_width() { // A VSlider is intrinsically sized — the parent's max_width doesn't // change what we return. let canvas = make_canvas(); let s: VSlider<()> = vslider( 0.5 ); let ( w_small, _ ) = s.preferred_size( 10.0, &canvas ); let ( w_big, _ ) = s.preferred_size( 9_999.0, &canvas ); assert_eq!( w_small, theme::WIDTH ); assert_eq!( w_big, theme::WIDTH ); } #[ test ] fn default_dimensions_are_the_theme_constants() { let s: VSlider<()> = vslider( 0.0 ); assert_eq!( s.width, theme::WIDTH ); assert_eq!( s.height, theme::HEIGHT ); } #[ test ] fn draw_at_value_zero_does_not_panic() { let mut canvas = make_canvas(); let rect = Rect { x: 10.0, y: 10.0, width: 56.0, height: 160.0 }; let s: VSlider<()> = vslider( 0.0 ); s.draw( &mut canvas, rect, false ); } #[ test ] fn draw_at_value_one_does_not_panic() { let mut canvas = make_canvas(); let rect = Rect { x: 10.0, y: 10.0, width: 56.0, height: 160.0 }; let s: VSlider<()> = vslider( 1.0 ); s.draw( &mut canvas, rect, true ); } #[ test ] fn on_change_is_stored() { let s: VSlider = vslider( 0.5 ).on_change( |v| ( v * 100.0 ) as u32 ); let cb = s.on_change.expect( "on_change was set" ); assert_eq!( cb( 0.25 ), 25 ); } #[ test ] fn element_from_vslider() { let s: VSlider<()> = vslider( 0.5 ); let el: Element<()> = s.into(); assert!( matches!( el, Element::VSlider( _ ) ) ); } #[ test ] fn paint_bounds_equals_layout_rect() { let rect = Rect { x: 4.0, y: 8.0, width: 56.0, height: 160.0 }; let s: VSlider<()> = vslider( 0.5 ); let pb = s.paint_bounds( rect ); assert_eq!( pb.x, rect.x ); assert_eq!( pb.y, rect.y ); assert_eq!( pb.width, rect.width ); assert_eq!( pb.height, rect.height ); }