use crate::tui::render::mission_control::{McLayout, compute};
use ratatui::layout::Rect;
fn rect_inside(child: Rect, parent: Rect) -> bool {
child.x >= parent.x
&& child.y >= parent.y
&& child.x + child.width <= parent.x + parent.width
&& child.y + child.height <= parent.y + parent.height
}
fn rects_overlap(a: Rect, b: Rect) -> bool {
let a_right = a.x + a.width;
let b_right = b.x + b.width;
let a_bottom = a.y + a.height;
let b_bottom = b.y + b.height;
!(a_right <= b.x || b_right <= a.x || a_bottom <= b.y || b_bottom <= a.y)
}
#[test]
fn every_panel_stays_inside_outer_area() {
let outer = Rect::new(0, 0, 154, 50);
let layout: McLayout = compute(outer);
assert!(rect_inside(layout.inbox, outer), "inbox escaped outer");
assert!(
rect_inside(layout.analytics, outer),
"analytics escaped outer"
);
assert!(
rect_inside(layout.activity, outer),
"activity escaped outer"
);
assert!(
rect_inside(layout.schedule, outer),
"schedule escaped outer"
);
assert!(
rect_inside(layout.help_bar, outer),
"help_bar escaped outer"
);
}
#[test]
fn panels_do_not_overlap() {
let outer = Rect::new(0, 0, 154, 50);
let layout = compute(outer);
assert!(
!rects_overlap(layout.inbox, layout.activity),
"inbox/activity overlap"
);
assert!(
!rects_overlap(layout.inbox, layout.analytics),
"inbox/analytics overlap"
);
assert!(
!rects_overlap(layout.analytics, layout.activity),
"analytics/activity overlap"
);
assert!(
!rects_overlap(layout.analytics, layout.schedule),
"analytics/schedule overlap"
);
assert!(
!rects_overlap(layout.analytics, layout.help_bar),
"analytics overlaps help bar"
);
assert!(
!rects_overlap(layout.inbox, layout.schedule),
"inbox/schedule overlap"
);
assert!(
!rects_overlap(layout.activity, layout.schedule),
"activity/schedule overlap"
);
assert!(
!rects_overlap(layout.inbox, layout.help_bar),
"inbox overlaps help bar"
);
assert!(
!rects_overlap(layout.activity, layout.help_bar),
"activity overlaps help bar"
);
assert!(
!rects_overlap(layout.schedule, layout.help_bar),
"schedule overlaps help bar"
);
}
#[test]
fn help_bar_takes_exactly_one_row_when_area_is_tall_enough() {
let outer = Rect::new(0, 0, 100, 30);
let layout = compute(outer);
assert_eq!(layout.help_bar.height, 1);
assert_eq!(layout.help_bar.y, outer.y + outer.height - 1);
assert_eq!(layout.help_bar.x, outer.x);
assert_eq!(layout.help_bar.width, outer.width);
}
#[test]
fn help_bar_collapses_to_zero_when_area_is_too_short() {
let outer = Rect::new(0, 0, 100, 1);
let layout = compute(outer);
assert_eq!(layout.help_bar.height, 0);
}
#[test]
fn inbox_takes_left_40_percent() {
let outer = Rect::new(0, 0, 100, 30);
let layout = compute(outer);
assert_eq!(layout.inbox.x, 0);
assert!(
(layout.inbox.width as i32 - 40).abs() <= 1,
"inbox width was {}, expected ~40",
layout.inbox.width
);
}
#[test]
fn analytics_takes_full_right_column_left_stacks_three() {
let outer = Rect::new(0, 0, 100, 30);
let layout = compute(outer);
let panel_height = outer.height - layout.help_bar.height;
assert_eq!(
layout.analytics.height, panel_height,
"analytics should be full height"
);
let left_height = layout.inbox.height + layout.activity.height + layout.schedule.height;
assert_eq!(
left_height, panel_height,
"left column should fill the panel height"
);
assert!(
layout.analytics.x >= layout.inbox.x + layout.inbox.width,
"analytics should be right of the left column"
);
}
#[test]
fn handles_zero_area_without_panic() {
let outer = Rect::new(0, 0, 0, 0);
let _ = compute(outer);
}