use super::*;
const FONT_BYTES: &[u8] = include_bytes!("../../../../demo/assets/CascadiaCode.ttf");
fn test_font() -> Arc<Font> {
Arc::new(Font::from_slice(FONT_BYTES).expect("font"))
}
#[test]
fn display_text_appends_suffix() {
let dv = DragValue::new(30.0, 0.0, 360.0, test_font())
.with_decimals(0)
.with_suffix("°");
assert_eq!(dv.display_text(), "30°");
assert_eq!(dv.format_value(), "30");
}
#[test]
fn suffix_with_space_reads_like_years() {
let dv = DragValue::new(2.0, 0.0, 99.0, test_font())
.with_decimals(0)
.with_suffix(" years");
assert_eq!(dv.display_text(), "2 years");
}
#[test]
fn edit_mode_buffer_excludes_suffix() {
let mut dv = DragValue::new(5.0, 0.0, 10.0, test_font())
.with_decimals(0)
.with_suffix(" m");
dv.enter_edit_mode();
assert_eq!(dv.edit_text, "5", "suffix must not enter the edit buffer");
}
#[test]
fn no_suffix_matches_plain_value() {
let dv = DragValue::new(1.5, 0.0, 10.0, test_font()).with_decimals(2);
assert_eq!(dv.display_text(), "1.50");
}
#[test]
fn intrinsic_min_width_fits_value_and_arrows() {
let font = test_font();
let dv = DragValue::new(1.0, 0.0, 10.0, Arc::clone(&font)).with_decimals(2);
assert_eq!(dv.display_text(), "1.00");
let text_w = measure_advance(&font, "1.00", dv.font_size);
let min_w = dv.min_size().width;
assert!(
min_w >= text_w + LABEL_SIDE_INSET * 2.0,
"min width {min_w} must cover text {text_w} plus both arrow zones"
);
let avail_w = min_w - LABEL_SIDE_INSET * 2.0;
assert!(
avail_w >= text_w,
"label clipped at min width: inner {avail_w} < text {text_w}"
);
}
#[test]
fn explicit_min_width_wins_when_larger() {
let dv = DragValue::new(1.0, 0.0, 10.0, test_font())
.with_decimals(2)
.with_min_size(Size::new(500.0, 0.0));
assert_eq!(dv.min_size().width, 500.0);
}
#[test]
fn layout_never_narrower_than_intrinsic() {
let mut dv = DragValue::new(1.0, 0.0, 10.0, test_font()).with_decimals(2);
let intrinsic = dv.intrinsic_min_width();
let sz = dv.layout(Size::new(4.0, 24.0));
assert!(
sz.width >= intrinsic,
"layout width {} must not fall below intrinsic {intrinsic}",
sz.width
);
}
#[test]
fn value_cell_tracks_external_writes_after_layout() {
use std::cell::Cell;
use std::rc::Rc;
let cell = Rc::new(Cell::new(42.0_f64));
let mut dv = DragValue::new(cell.get(), 0.0, 360.0, test_font())
.with_decimals(0)
.with_value_cell(Rc::clone(&cell));
assert_eq!(dv.value_label.text_str(), "42");
cell.set(140.0);
let _ = dv.layout(Size::new(120.0, 24.0));
assert_eq!(dv.value(), 140.0, "DragValue value must follow the cell");
assert_eq!(
dv.value_label.text_str(),
"140",
"DragValue label text must repaint to the cell's value"
);
}
#[test]
fn drag_writes_back_to_value_cell() {
use std::cell::Cell;
use std::rc::Rc;
let cell = Rc::new(Cell::new(10.0_f64));
let mut dv = DragValue::new(cell.get(), 0.0, 360.0, test_font())
.with_decimals(0)
.with_value_cell(Rc::clone(&cell));
dv.drag_start_x = 0.0;
dv.drag_start_value = 10.0;
dv.dragging = true;
dv.update_from_drag(5.0);
assert_eq!(dv.value(), 15.0);
assert_eq!(cell.get(), 15.0, "drag must write back to the shared cell");
}