use crate::render_tree::{RenderNode, RenderNodeType};
use crate::style::{Border, BorderStyle, Color, Dimension, Direction, Spacing, Style};
use crate::utils::display_width;
use std::cell::RefCell;
use std::rc::Rc;
#[test]
fn test_content_based_sizing_text() {
let mut parent = RenderNode::element();
parent.x = 0;
parent.y = 0;
let text_child = RenderNode::text("Hello, World!");
let parent_rc = Rc::new(RefCell::new(parent));
let child_rc = Rc::new(RefCell::new(text_child));
RenderNode::add_child_with_parent(&parent_rc, child_rc.clone());
parent_rc.borrow_mut().layout_with_parent(100, 50);
let parent_ref = parent_rc.borrow();
let child_ref = child_rc.borrow();
assert_eq!(
parent_ref.width, 13,
"Parent width should match text width (13 chars)"
);
assert_eq!(
parent_ref.height, 1,
"Parent height should be 1 for single line text"
);
assert_eq!(child_ref.width, 13, "Child text width should be 13");
}
#[test]
fn test_content_based_sizing_vertical_stack() {
let mut parent = RenderNode::element();
parent.x = 0;
parent.y = 0;
parent.style = Some(Style {
direction: Some(Direction::Vertical),
..Default::default()
});
let text1 = RenderNode::text("Short");
let text2 = RenderNode::text("Medium text");
let text3 = RenderNode::text("This is a longer text");
let parent_rc = Rc::new(RefCell::new(parent));
let child1_rc = Rc::new(RefCell::new(text1));
let child2_rc = Rc::new(RefCell::new(text2));
let child3_rc = Rc::new(RefCell::new(text3));
RenderNode::add_child_with_parent(&parent_rc, child1_rc.clone());
RenderNode::add_child_with_parent(&parent_rc, child2_rc.clone());
RenderNode::add_child_with_parent(&parent_rc, child3_rc.clone());
parent_rc.borrow_mut().layout_with_parent(100, 50);
let parent_ref = parent_rc.borrow();
assert_eq!(
parent_ref.width, 21,
"Parent width should match widest child (21 chars)"
);
assert_eq!(
parent_ref.height, 3,
"Parent height should be sum of children (3 lines)"
);
}
#[test]
fn test_content_based_sizing_horizontal_stack() {
let mut parent = RenderNode::element();
parent.x = 0;
parent.y = 0;
parent.style = Some(Style {
direction: Some(Direction::Horizontal),
..Default::default()
});
let text1 = RenderNode::text("One");
let text2 = RenderNode::text("Two");
let text3 = RenderNode::text("Three");
let parent_rc = Rc::new(RefCell::new(parent));
let child1_rc = Rc::new(RefCell::new(text1));
let child2_rc = Rc::new(RefCell::new(text2));
let child3_rc = Rc::new(RefCell::new(text3));
RenderNode::add_child_with_parent(&parent_rc, child1_rc.clone());
RenderNode::add_child_with_parent(&parent_rc, child2_rc.clone());
RenderNode::add_child_with_parent(&parent_rc, child3_rc.clone());
parent_rc.borrow_mut().layout_with_parent(100, 50);
let parent_ref = parent_rc.borrow();
assert_eq!(
parent_ref.width, 11,
"Parent width should be sum of children (3+3+5 = 11)"
);
assert_eq!(
parent_ref.height, 1,
"Parent height should match tallest child (1 line)"
);
}
#[test]
fn test_content_sizing_with_border() {
let mut parent = RenderNode::element();
parent.x = 0;
parent.y = 0;
parent.style = Some(Style {
width: Some(Dimension::Content),
height: Some(Dimension::Content),
border: Some(Border {
enabled: true,
style: BorderStyle::Single,
color: Color::White,
edges: crate::style::BorderEdges::ALL,
}),
..Default::default()
});
let text = RenderNode::text("Content");
let parent_rc = Rc::new(RefCell::new(parent));
let child_rc = Rc::new(RefCell::new(text));
RenderNode::add_child_with_parent(&parent_rc, child_rc.clone());
parent_rc.borrow_mut().layout_with_parent(100, 50);
let parent_ref = parent_rc.borrow();
assert_eq!(
parent_ref.width, 9,
"Parent width should be content (7) + border (2)"
);
assert_eq!(
parent_ref.height, 3,
"Parent height should be content (1) + border (2)"
);
}
#[test]
fn test_explicit_content_dimension() {
let mut parent = RenderNode::element();
parent.x = 0;
parent.y = 0;
parent.style = Some(Style {
width: Some(Dimension::Content),
height: Some(Dimension::Content),
padding: Some(Spacing::all(2)),
..Default::default()
});
let text = RenderNode::text("Test text");
let parent_rc = Rc::new(RefCell::new(parent));
let child_rc = Rc::new(RefCell::new(text));
RenderNode::add_child_with_parent(&parent_rc, child_rc.clone());
parent_rc.borrow_mut().layout_with_parent(10, 5);
let parent_ref = parent_rc.borrow();
assert_eq!(
parent_ref.width, 10,
"Parent width should be capped at viewport (10)"
);
assert_eq!(
parent_ref.height, 5,
"Parent height should be content+padding (5)"
);
}
#[test]
fn test_nested_content_sizing() {
let mut outer = RenderNode::element();
outer.x = 0;
outer.y = 0;
outer.style = Some(Style {
width: Some(Dimension::Content),
height: Some(Dimension::Content),
padding: Some(Spacing::all(1)),
..Default::default()
});
let mut inner = RenderNode::element();
inner.style = Some(Style {
width: Some(Dimension::Content),
height: Some(Dimension::Content),
padding: Some(Spacing::all(1)),
..Default::default()
});
let text = RenderNode::text("Nested");
let outer_rc = Rc::new(RefCell::new(outer));
let inner_rc = Rc::new(RefCell::new(inner));
let text_rc = Rc::new(RefCell::new(text));
RenderNode::add_child_with_parent(&inner_rc, text_rc.clone());
RenderNode::add_child_with_parent(&outer_rc, inner_rc.clone());
outer_rc.borrow_mut().layout_with_parent(100, 50);
let outer_ref = outer_rc.borrow();
let inner_ref = inner_rc.borrow();
let text_ref = text_rc.borrow();
assert_eq!(text_ref.width, 6, "Text width should be 6");
assert_eq!(inner_ref.width, 8, "Inner width should be 6 + 2 padding");
assert_eq!(outer_ref.width, 10, "Outer width should be 8 + 2 padding");
}
#[test]
fn test_complex_nested_convergence() {
let mut root = RenderNode::element();
root.x = 0;
root.y = 0;
root.style = Some(Style {
width: Some(Dimension::Content),
height: Some(Dimension::Fixed(20)),
..Default::default()
});
let mut container = RenderNode::element();
container.style = Some(Style {
width: Some(Dimension::Content),
height: Some(Dimension::Percentage(0.5)),
..Default::default()
});
let mut child = RenderNode::element();
child.style = Some(Style {
width: Some(Dimension::Percentage(0.8)),
height: Some(Dimension::Percentage(1.0)),
..Default::default()
});
let text = RenderNode::text("Content text");
let root_rc = Rc::new(RefCell::new(root));
let container_rc = Rc::new(RefCell::new(container));
let child_rc = Rc::new(RefCell::new(child));
let text_rc = Rc::new(RefCell::new(text));
RenderNode::add_child_with_parent(&child_rc, text_rc.clone());
RenderNode::add_child_with_parent(&container_rc, child_rc.clone());
RenderNode::add_child_with_parent(&root_rc, container_rc.clone());
root_rc.borrow_mut().layout_with_parent(100, 50);
let root_ref = root_rc.borrow();
let container_ref = container_rc.borrow();
let text_ref = text_rc.borrow();
assert_eq!(root_ref.height, 20, "Root height should be fixed at 20");
assert_eq!(
container_ref.height, 10,
"Container height should be 50% of root"
);
let _text_width = match &text_ref.node_type {
RenderNodeType::Text(t) => display_width(t) as u16,
RenderNodeType::TextWrapped(lines) => {
lines.iter().map(|l| display_width(l)).max().unwrap_or(0) as u16
}
_ => 0,
};
let _child_ref = child_rc.borrow();
}