use revue::widget::data::tree::Tree;
use revue::widget::data::tree::TreeNode;
#[test]
fn test_tree_render_internal_minimum_size() {
let mut buffer = revue::render::Buffer::new(3, 1);
let area = revue::layout::Rect::new(0, 0, 3, 1);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(TreeNode::new("T"));
tree.render_internal(&mut ctx);
}
#[test]
fn test_tree_render_internal_zero_width() {
let mut buffer = revue::render::Buffer::new(0, 10);
let area = revue::layout::Rect::new(0, 0, 0, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(TreeNode::new("Test"));
tree.render_internal(&mut ctx);
}
#[test]
fn test_tree_render_internal_zero_height() {
let mut buffer = revue::render::Buffer::new(40, 0);
let area = revue::layout::Rect::new(0, 0, 40, 0);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(TreeNode::new("Test"));
tree.render_internal(&mut ctx);
}
#[test]
fn test_tree_render_leaf_node_indicator() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(TreeNode::new("Leaf"));
tree.render_internal(&mut ctx);
assert_eq!(buffer.get(0, 0).unwrap().symbol, ' ');
}
#[test]
fn test_tree_render_collapsed_node_indicator() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(TreeNode::new("Parent").child(TreeNode::new("Child")));
tree.render_internal(&mut ctx);
assert_eq!(buffer.get(0, 0).unwrap().symbol, '▶');
}
#[test]
fn test_tree_render_expanded_node_indicator() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(
TreeNode::new("Parent")
.expanded(true)
.child(TreeNode::new("Child")),
);
tree.render_internal(&mut ctx);
assert_eq!(buffer.get(0, 0).unwrap().symbol, '▼');
}
#[test]
fn test_tree_render_node_label() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(TreeNode::new("TestLabel"));
tree.render_internal(&mut ctx);
assert_eq!(buffer.get(1, 0).unwrap().symbol, 'T');
assert_eq!(buffer.get(2, 0).unwrap().symbol, 'e');
assert_eq!(buffer.get(3, 0).unwrap().symbol, 's');
}
#[test]
fn test_tree_render_label_truncation() {
let mut buffer = revue::render::Buffer::new(10, 10);
let area = revue::layout::Rect::new(0, 0, 10, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(TreeNode::new("VeryLongLabelThatShouldBeTruncated"));
tree.render_internal(&mut ctx);
let truncated: String = "VeryLongLabelThatShouldBeTruncated"
.chars()
.take(9)
.collect();
assert_eq!(truncated.len(), 9);
}
#[test]
fn test_tree_render_single_child() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(
TreeNode::new("Parent")
.expanded(true)
.child(TreeNode::new("Child")),
);
tree.render_internal(&mut ctx);
assert_eq!(buffer.get(1, 0).unwrap().symbol, 'P');
let cell = buffer.get(0, 1).unwrap();
assert!(
cell.symbol == '└'
|| cell.symbol == '├'
|| cell.symbol == ' '
|| cell.symbol == '│'
|| cell.symbol == '─'
);
let mut found_child = false;
for x in 0..10 {
if buffer.get(x, 1).unwrap().symbol == 'C' {
found_child = true;
break;
}
}
assert!(found_child, "Could not find 'C' from 'Child' label");
}
#[test]
fn test_tree_render_multiple_children() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(
TreeNode::new("Parent")
.expanded(true)
.child(TreeNode::new("Child 1"))
.child(TreeNode::new("Child 2"))
.child(TreeNode::new("Child 3")),
);
tree.render_internal(&mut ctx);
assert_eq!(buffer.get(1, 0).unwrap().symbol, 'P');
for y in 1..=3 {
let mut found = false;
for x in 0..10 {
if buffer.get(x, y).unwrap().symbol == 'C' {
found = true;
break;
}
}
assert!(found, "Could not find 'C' on line {}", y);
}
}
#[test]
fn test_tree_render_nested_levels() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(
TreeNode::new("L0").expanded(true).child(
TreeNode::new("L1")
.expanded(true)
.child(TreeNode::new("L2")),
),
);
tree.render_internal(&mut ctx);
for y in 0..3 {
let mut found = false;
for x in 0..10 {
if buffer.get(x, y).unwrap().symbol == 'L' {
found = true;
break;
}
}
assert!(found, "Could not find 'L' on line {}", y);
}
}
#[test]
fn test_tree_render_multiple_roots() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new()
.node(TreeNode::new("Root 1"))
.node(TreeNode::new("Root 2"))
.node(TreeNode::new("Root 3"));
tree.render_internal(&mut ctx);
assert_eq!(buffer.get(1, 0).unwrap().symbol, 'R');
assert_eq!(buffer.get(1, 1).unwrap().symbol, 'R');
assert_eq!(buffer.get(1, 2).unwrap().symbol, 'R');
}
#[test]
fn test_tree_render_selected_node() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new()
.nodes(vec![TreeNode::new("First"), TreeNode::new("Second")])
.selected(1)
.selected_style(revue::style::Color::WHITE, revue::style::Color::BLUE);
tree.render_internal(&mut ctx);
let cell = buffer.get(0, 1).unwrap();
assert_eq!(cell.bg, Some(revue::style::Color::BLUE));
}
#[test]
fn test_tree_render_selected_first() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new()
.node(TreeNode::new("Test"))
.selected(0)
.selected_style(revue::style::Color::WHITE, revue::style::Color::BLUE);
tree.render_internal(&mut ctx);
let cell = buffer.get(0, 0).unwrap();
assert_eq!(cell.bg, Some(revue::style::Color::BLUE));
}
#[test]
fn test_tree_render_custom_fg() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new()
.node(TreeNode::new("Test"))
.fg(revue::style::Color::RED);
tree.render_internal(&mut ctx);
let cell = buffer.get(1, 0).unwrap();
assert!(cell.fg == Some(revue::style::Color::RED) || cell.fg.is_some());
}
#[test]
fn test_tree_render_custom_bg() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new()
.node(TreeNode::new("Test"))
.bg(revue::style::Color::BLACK);
tree.render_internal(&mut ctx);
let cell = buffer.get(0, 0).unwrap();
assert!(cell.bg == Some(revue::style::Color::BLACK) || cell.bg.is_some());
}
#[test]
fn test_tree_render_selected_colors() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new()
.node(TreeNode::new("Test"))
.selected(0)
.selected_style(revue::style::Color::YELLOW, revue::style::Color::GREEN);
tree.render_internal(&mut ctx);
let cell = buffer.get(1, 0).unwrap();
assert_eq!(cell.fg, Some(revue::style::Color::YELLOW));
assert_eq!(cell.bg, Some(revue::style::Color::GREEN));
}
#[test]
fn test_tree_render_default_indent() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(
TreeNode::new("Parent")
.expanded(true)
.child(TreeNode::new("Child")),
);
tree.render_internal(&mut ctx);
let cell = buffer.get(0, 1).unwrap();
assert_eq!(cell.symbol, ' ');
}
#[test]
fn test_tree_render_custom_indent() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().indent(4).node(
TreeNode::new("Parent")
.expanded(true)
.child(TreeNode::new("Child")),
);
tree.render_internal(&mut ctx);
let cell = buffer.get(0, 1).unwrap();
assert_eq!(cell.symbol, ' ');
}
#[test]
fn test_tree_render_lines_single_child() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(
TreeNode::new("Parent")
.expanded(true)
.child(TreeNode::new("Child")),
);
tree.render_internal(&mut ctx);
let mut found_connector = false;
for x in 0..10 {
let ch = buffer.get(x, 1).unwrap().symbol;
if ch == '└' || ch == '├' {
found_connector = true;
assert_eq!(ch, '└', "Single child should use └ connector");
break;
}
}
assert!(found_connector, "Could not find connector character");
}
#[test]
fn test_tree_render_lines_multiple_children() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(
TreeNode::new("Parent")
.expanded(true)
.child(TreeNode::new("Child 1"))
.child(TreeNode::new("Child 2")),
);
tree.render_internal(&mut ctx);
let mut found_first_connector = false;
for x in 0..10 {
let ch = buffer.get(x, 1).unwrap().symbol;
if ch == '├' || ch == '└' {
found_first_connector = true;
assert_eq!(ch, '├', "First child should use ├ connector");
break;
}
}
assert!(found_first_connector, "Could not find first connector");
let mut found_second_connector = false;
for x in 0..10 {
let ch = buffer.get(x, 2).unwrap().symbol;
if ch == '├' || ch == '└' {
found_second_connector = true;
assert_eq!(ch, '└', "Last child should use └ connector");
break;
}
}
assert!(found_second_connector, "Could not find second connector");
}
#[test]
fn test_tree_render_with_highlight() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let mut tree = Tree::new()
.nodes(vec![TreeNode::new("Hello World")])
.searchable(true)
.highlight_fg(revue::style::Color::YELLOW);
tree.set_query("hw");
tree.render_internal(&mut ctx);
let m = tree.get_match("Hello World").unwrap();
assert!(m.indices.contains(&0)); assert!(m.indices.contains(&6)); }
#[test]
fn test_tree_render_no_highlight_when_no_query() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new()
.nodes(vec![TreeNode::new("Test")])
.searchable(true)
.highlight_fg(revue::style::Color::YELLOW);
tree.render_internal(&mut ctx);
assert!(tree.get_match("Test").is_none());
}
#[test]
fn test_tree_render_clips_to_area_height() {
let mut buffer = revue::render::Buffer::new(40, 3);
let area = revue::layout::Rect::new(0, 0, 40, 3);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().nodes(vec![
TreeNode::new("Line 1"),
TreeNode::new("Line 2"),
TreeNode::new("Line 3"),
TreeNode::new("Line 4"),
TreeNode::new("Line 5"),
]);
tree.render_internal(&mut ctx);
}
#[test]
fn test_tree_render_clips_to_area_width() {
let mut buffer = revue::render::Buffer::new(10, 10);
let area = revue::layout::Rect::new(0, 0, 10, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(TreeNode::new("VeryVeryLongLabel"));
tree.render_internal(&mut ctx);
}
#[test]
fn test_tree_render_empty_label() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(TreeNode::new(""));
tree.render_internal(&mut ctx);
}
#[test]
fn test_tree_render_unicode_label() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(TreeNode::new("📁 文件夹"));
tree.render_internal(&mut ctx);
}
#[test]
fn test_tree_render_special_chars_label() {
let mut buffer = revue::render::Buffer::new(40, 10);
let area = revue::layout::Rect::new(0, 0, 40, 10);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(TreeNode::new("path/to/file.txt"));
tree.render_internal(&mut ctx);
assert_eq!(buffer.get(1, 0).unwrap().symbol, 'p');
}
#[test]
fn test_tree_render_very_deep_nesting() {
let mut buffer = revue::render::Buffer::new(40, 20);
let area = revue::layout::Rect::new(0, 0, 40, 20);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(
TreeNode::new("L0").expanded(true).child(
TreeNode::new("L1").expanded(true).child(
TreeNode::new("L2").expanded(true).child(
TreeNode::new("L3")
.expanded(true)
.child(TreeNode::new("L4")),
),
),
),
);
tree.render_internal(&mut ctx);
}
#[test]
fn test_tree_render_many_siblings() {
let mut buffer = revue::render::Buffer::new(40, 20);
let area = revue::layout::Rect::new(0, 0, 40, 20);
let mut ctx = revue::widget::traits::RenderContext::new(&mut buffer, area);
let tree = Tree::new().node(
TreeNode::new("Parent").expanded(true).children(
(0..15)
.map(|i| TreeNode::new(format!("Child {}", i)))
.collect(),
),
);
tree.render_internal(&mut ctx);
}