use map2fig::cli::TickDirection;
use map2fig::layout::compute_gnomonic_layout_with_fonts;
#[test]
fn test_gnomonic_resolution_text_font_size_readability() {
let width_300: f64 = 300.0;
let font_size_300 = (12.0 * (width_300 / 800.0)).clamp(7.0, 24.0);
assert!(
font_size_300 >= 7.0,
"Font at width=300 is {} - below minimum 7px clamp",
font_size_300
);
let width_600: f64 = 600.0;
let font_size_600 = (12.0 * (width_600 / 800.0)).clamp(7.0, 24.0);
assert!(
font_size_600 >= 9.0,
"Font at width=600 is {} - may be hard to read",
font_size_600
);
let width_1200: f64 = 1200.0;
let font_size_1200 = (12.0 * (width_1200 / 800.0)).clamp(7.0, 24.0);
assert_eq!(font_size_1200, 18.0, "Font at width=1200 should be 18px");
assert!(
font_size_600 > font_size_300,
"Font should increase with image width"
);
assert!(
font_size_1200 > font_size_600,
"Font should increase with image width"
);
}
#[test]
fn test_gnomonic_resolution_text_y_position_at_map_bottom() {
let (layout, _cb_layout) = compute_gnomonic_layout_with_fonts(
300.0,
true,
TickDirection::Outward,
true,
true, None,
);
let expected_start_y = layout.map_y + layout.map_h;
assert!(
expected_start_y > layout.map_y,
"Resolution text Y position {} should be below map top {}",
expected_start_y,
layout.map_y
);
let center_y = layout.height / 2.0;
assert!(
expected_start_y > center_y,
"Resolution text Y position {} should be below center {}, not centered",
expected_start_y,
center_y
);
}
#[test]
fn test_gnomonic_resolution_text_x_position_in_left_margin() {
let width = 300.0;
let scale = width / 1200.0;
let outer_pad = 24.0 * scale;
let (layout, _cb_layout) = compute_gnomonic_layout_with_fonts(
width,
true,
TickDirection::Outward,
true,
true, None,
);
let text_x_min = outer_pad + 5.0;
let text_x_max = layout.map_x;
assert!(
text_x_max > text_x_min,
"Left margin area {} to {} is too small for 50px rotated text",
text_x_min,
text_x_max
);
assert!(
layout.map_x > outer_pad,
"Map position {} should be greater than outer padding {}",
layout.map_x,
outer_pad
);
}
#[test]
fn test_gnomonic_units_label_padding_consistency() {
let width = 300.0;
let scale = width / 1200.0;
let pdf_padding = 1.0 * scale;
assert!(
pdf_padding > 0.0,
"PDF padding {} should be positive (minimal spacing)",
pdf_padding
);
assert!(
pdf_padding < 5.0,
"PDF padding {} should match PNG tight crop approach (<5px)",
pdf_padding
);
}
#[test]
fn test_gnomonic_layout_dimensions_at_various_widths() {
let test_widths = vec![300.0, 600.0, 900.0, 1200.0];
for width in test_widths {
let (layout, cb_layout) = compute_gnomonic_layout_with_fonts(
width,
true,
TickDirection::Outward,
true,
true, None,
);
assert!(
layout.width >= width,
"Layout width {} should accommodate map width {}",
layout.width,
width
);
assert!(
layout.map_w == width,
"Map width {} should equal specified width {}",
layout.map_w,
width
);
assert!(
layout.map_h == width,
"Map height {} should be square ({}x{})",
layout.map_h,
width,
width
);
let left_margin = layout.map_x;
assert!(
left_margin > 15.0,
"Left margin {} should be >15px for text at width={}",
left_margin,
width
);
assert!(
cb_layout.y > layout.map_y + layout.map_h,
"Colorbar Y {} should be below map bottom {}",
cb_layout.y,
layout.map_y + layout.map_h
);
}
}
#[test]
fn test_resolution_text_rotation_bounds() {
let width = 300.0;
let (layout, _cb_layout) = compute_gnomonic_layout_with_fonts(
width,
true,
TickDirection::Outward,
true,
true, None,
);
let start_y = layout.map_y + layout.map_h;
let text_y_min = (start_y - 200.0).max(0.0); let text_y_max = start_y;
assert!(
text_y_max <= layout.height,
"Text top {} should not exceed image height {}",
text_y_max,
layout.height
);
assert!(
(text_y_max - text_y_min) <= 200.0,
"Text vertical span {} should be ≤200px",
(text_y_max - text_y_min)
);
}
#[test]
fn test_colorbar_alignment_with_map() {
let width = 300.0;
let (layout, cb_layout) = compute_gnomonic_layout_with_fonts(
width,
true,
TickDirection::Outward,
true,
true, None,
);
assert_eq!(
layout.cbar_x, cb_layout.x,
"Map X position {} should equal colorbar X position {}",
layout.cbar_x, cb_layout.x
);
assert_eq!(
layout.cbar_w, cb_layout.w,
"Map width {} should equal colorbar width {}",
layout.cbar_w, cb_layout.w
);
}
#[test]
fn test_text_shown_flag_affects_layout() {
let width = 300.0;
let (layout_with_text, _) = compute_gnomonic_layout_with_fonts(
width,
true,
TickDirection::Outward,
true,
true, None,
);
let (layout_no_text, _) = compute_gnomonic_layout_with_fonts(
width,
true,
TickDirection::Outward,
false,
true, None,
);
assert!(
layout_with_text.map_x > layout_no_text.map_x,
"Layout with text should have larger left margin: {} vs {}",
layout_with_text.map_x,
layout_no_text.map_x
);
assert!(
layout_with_text.width > layout_no_text.width,
"Layout with text should be wider: {} vs {}",
layout_with_text.width,
layout_no_text.width
);
}
#[test]
fn test_font_size_formula_scaling() {
let width_100: f64 = 100.0;
let font_100 = (12.0 * (width_100 / 800.0)).clamp(7.0, 24.0);
assert_eq!(font_100, 7.0, "Font at width=100 should clamp to 7.0");
let width_800: f64 = 800.0;
let font_800 = (12.0 * (width_800 / 800.0)).clamp(7.0, 24.0);
assert_eq!(font_800, 12.0, "Font at width=800 should be exactly 12.0");
let width_2400: f64 = 2400.0;
let font_2400 = (12.0 * (width_2400 / 800.0)).clamp(7.0, 24.0);
assert_eq!(font_2400, 24.0, "Font at width=2400 should clamp to 24.0");
}