#![ cfg( feature = "test-support" ) ] use ltk::test_support:: { value_from_y_in_rect, value_from_pos_in_rect, thumb_design_px, SliderAxis, }; use ltk::{ Point, Rect }; fn rect( x: f32, y: f32, w: f32, h: f32 ) -> Rect { Rect { x, y, width: w, height: h } } #[ test ] fn top_is_one() { let r = rect( 0.0, 0.0, 56.0, 160.0 ); assert_eq!( value_from_y_in_rect( r, 0.0 ), 1.0 ); assert_eq!( value_from_y_in_rect( r, -50.0 ), 1.0 ); } #[ test ] fn bottom_is_zero() { let r = rect( 0.0, 0.0, 56.0, 160.0 ); assert_eq!( value_from_y_in_rect( r, 160.0 ), 0.0 ); assert_eq!( value_from_y_in_rect( r, 999.0 ), 0.0 ); } #[ test ] fn center_returns_half() { let r = rect( 0.0, 0.0, 56.0, 160.0 ); let v = value_from_y_in_rect( r, 80.0 ); assert!( ( v - 0.5 ).abs() < 1e-6, "expected 0.5 got {}", v ); } #[ test ] fn rect_offset_translates_correctly() { let r = rect( 0.0, 500.0, 56.0, 160.0 ); assert_eq!( value_from_y_in_rect( r, 500.0 ), 1.0 ); assert_eq!( value_from_y_in_rect( r, 660.0 ), 0.0 ); let v = value_from_y_in_rect( r, 580.0 ); assert!( ( v - 0.5 ).abs() < 1e-6, "expected 0.5 got {}", v ); } #[ test ] fn output_is_always_in_unit_range() { let r = rect( 10.0, 10.0, 56.0, 200.0 ); for y in -100i32 ..= 400 { let v = value_from_y_in_rect( r, y as f32 ); assert!( ( 0.0..= 1.0 ).contains( &v ), "v={} out of range at y={}", v, y ); } } #[ test ] fn very_short_rect_does_not_divide_by_zero() { // Height < 1.0 — track_h is clamped to 1.0 internally so the formula // stays defined. let r = rect( 0.0, 0.0, 56.0, 0.1 ); let v = value_from_y_in_rect( r, 0.05 ); assert!( v.is_finite() ); assert!( ( 0.0..= 1.0 ).contains( &v ) ); } #[ test ] fn value_is_monotonically_decreasing_along_y() { // Moving downward inside the pill must never *increase* the value — // the invariant behind the "drag up = larger" UX contract. let r = rect( 0.0, 0.0, 56.0, 160.0 ); let mut prev = value_from_y_in_rect( r, 0.0 ); for y in 0 ..= 160 { let v = value_from_y_in_rect( r, y as f32 ); assert!( v <= prev + 1e-6, "not monotonic: y={} v={} prev={}", y, v, prev ); prev = v; } } #[ test ] fn value_from_pos_dispatches_horizontal() { let r = rect( 0.0, 0.0, 200.0, 36.0 ); let v = value_from_pos_in_rect( r, Point { x: 200.0, y: 0.0 }, SliderAxis::Horizontal, thumb_design_px(), ); assert_eq!( v, 1.0 ); } #[ test ] fn value_from_pos_dispatches_vertical() { let r = rect( 0.0, 0.0, 56.0, 160.0 ); let v = value_from_pos_in_rect( r, Point { x: 9_999.0, y: 0.0 }, SliderAxis::Vertical, thumb_design_px(), ); assert_eq!( v, 1.0 ); } #[ test ] fn value_from_pos_axes_are_independent() { let r = rect( 0.0, 0.0, 200.0, 200.0 ); let h = value_from_pos_in_rect( r, Point { x: 100.0, y: 0.0 }, SliderAxis::Horizontal, thumb_design_px() ); let v = value_from_pos_in_rect( r, Point { x: 0.0, y: 100.0 }, SliderAxis::Vertical, thumb_design_px() ); assert!( ( h - 0.5 ).abs() < 0.1 ); assert!( ( v - 0.5 ).abs() < 1e-6 ); }