use crate::ansi_processor::{AnsiProcessor, DirtyRegion};
#[test]
fn test_baseline_capture() {
let mut processor = AnsiProcessor::with_screen_size(80, 24);
processor.set_screen_mode(true);
assert!(!processor.has_baseline());
processor.process_string("Initial content");
processor.capture_baseline();
assert!(processor.has_baseline());
}
#[test]
fn test_dirty_region_calculation_no_changes() {
let mut processor = AnsiProcessor::with_screen_size(80, 24);
processor.set_screen_mode(true);
processor.process_string("Static content");
processor.capture_baseline();
let message = processor.create_content_update_message(true);
if let crate::ansi_processor::TerminalMessage::ContentUpdate { dirty_regions, .. } = message {
assert_eq!(
dirty_regions.len(),
0,
"No changes should result in no dirty regions"
);
} else {
panic!("Expected ContentUpdate message");
}
}
#[test]
fn test_dirty_region_calculation_with_changes() {
let mut processor = AnsiProcessor::with_screen_size(80, 24);
processor.set_screen_mode(true);
processor.process_string("Line 1\nLine 2\nLine 3");
processor.capture_baseline();
processor.process_string("\x1b[2;1HChanged Line 2");
let message = processor.create_content_update_message(true);
if let crate::ansi_processor::TerminalMessage::ContentUpdate { dirty_regions, .. } = message {
assert!(
!dirty_regions.is_empty(),
"Changes should result in dirty regions"
);
assert!(
dirty_regions.len() >= 1,
"Should have at least one dirty region"
);
let region = &dirty_regions[0];
assert_eq!(
region.y, 1,
"Dirty region should be on line 2 (0-indexed as 1)"
);
assert!(region.width > 0, "Dirty region should have width");
assert!(region.height > 0, "Dirty region should have height");
} else {
panic!("Expected ContentUpdate message");
}
}
#[test]
fn test_dirty_region_multiple_changes() {
let mut processor = AnsiProcessor::with_screen_size(80, 24);
processor.set_screen_mode(true);
processor.process_string("Line 1\nLine 2\nLine 3\nLine 4\nLine 5");
processor.capture_baseline();
processor.process_string("\x1b[1;1HChanged Line 1");
processor.process_string("\x1b[4;1HChanged Line 4");
let message = processor.create_content_update_message(true);
if let crate::ansi_processor::TerminalMessage::ContentUpdate { dirty_regions, .. } = message {
assert!(
!dirty_regions.is_empty(),
"Changes should result in dirty regions"
);
assert!(
dirty_regions.len() >= 1,
"Should have dirty regions for changes"
);
} else {
panic!("Expected ContentUpdate message");
}
}
#[test]
fn test_dirty_region_adjacent_line_merging() {
let mut processor = AnsiProcessor::with_screen_size(80, 24);
processor.set_screen_mode(true);
processor.process_string("Line 1\nLine 2\nLine 3\nLine 4");
processor.capture_baseline();
processor.process_string("\x1b[2;1HChanged 2");
processor.process_string("\x1b[3;1HChanged 3");
let message = processor.create_content_update_message(true);
if let crate::ansi_processor::TerminalMessage::ContentUpdate { dirty_regions, .. } = message {
assert!(
!dirty_regions.is_empty(),
"Changes should result in dirty regions"
);
for region in &dirty_regions {
assert!(region.width > 0, "All dirty regions should have width");
assert!(region.height > 0, "All dirty regions should have height");
}
} else {
panic!("Expected ContentUpdate message");
}
}
#[test]
fn test_screen_state_update_cycle() {
let mut processor = AnsiProcessor::with_screen_size(80, 24);
processor.set_screen_mode(true);
processor.process_string("Initial state");
processor.capture_baseline();
processor.process_string("\x1b[1;1HFirst change");
let first_message = processor.create_content_update_message(true);
processor.update_screen_state();
processor.process_string("\x1b[1;1HSecond change");
let second_message = processor.create_content_update_message(true);
if let crate::ansi_processor::TerminalMessage::ContentUpdate {
dirty_regions: first_regions,
..
} = first_message
{
if let crate::ansi_processor::TerminalMessage::ContentUpdate {
dirty_regions: second_regions,
..
} = second_message
{
assert!(
!first_regions.is_empty(),
"First change should have dirty regions"
);
assert!(
!second_regions.is_empty(),
"Second change should have dirty regions"
);
} else {
panic!("Expected ContentUpdate message for second change");
}
} else {
panic!("Expected ContentUpdate message for first change");
}
}
#[test]
fn test_dirty_region_no_baseline_fallback() {
let processor = AnsiProcessor::with_screen_size(80, 24);
let message = processor.create_content_update_message(true);
if let crate::ansi_processor::TerminalMessage::ContentUpdate { dirty_regions, .. } = message {
assert_eq!(
dirty_regions.len(),
1,
"Should have one dirty region covering entire screen"
);
let region = &dirty_regions[0];
assert_eq!(region.x, 0, "Should start at x=0");
assert_eq!(region.y, 0, "Should start at y=0");
assert_eq!(region.width, 80, "Should cover full width");
assert_eq!(region.height, 24, "Should cover full height");
} else {
panic!("Expected ContentUpdate message");
}
}
#[test]
fn test_dirty_region_line_mode_fallback() {
let mut processor = AnsiProcessor::with_screen_size(80, 24);
processor.set_screen_mode(false);
processor.process_string("Line mode content");
processor.capture_baseline();
let message = processor.create_content_update_message(false);
if let crate::ansi_processor::TerminalMessage::ContentUpdate { dirty_regions, .. } = message {
assert_eq!(
dirty_regions.len(),
1,
"Line mode should have one full-screen dirty region"
);
assert_eq!(dirty_regions[0].width, 80, "Should cover full width");
assert_eq!(dirty_regions[0].height, 24, "Should cover full height");
} else {
panic!("Expected ContentUpdate message");
}
}
#[test]
fn test_dirty_region_bounds_validation() {
let mut processor = AnsiProcessor::with_screen_size(10, 5); processor.set_screen_mode(true);
processor.process_string("Small\nScreen\nTest");
processor.capture_baseline();
processor.process_string("\x1b[1;1HMod");
let message = processor.create_content_update_message(true);
if let crate::ansi_processor::TerminalMessage::ContentUpdate { dirty_regions, .. } = message {
for region in &dirty_regions {
assert!(
region.x < 10,
"Dirty region x should be within screen bounds"
);
assert!(
region.y < 5,
"Dirty region y should be within screen bounds"
);
assert!(
region.x + region.width <= 10,
"Dirty region should not exceed screen width"
);
assert!(
region.y + region.height <= 5,
"Dirty region should not exceed screen height"
);
}
} else {
panic!("Expected ContentUpdate message");
}
}
#[test]
fn test_pty_terminal_dimension_calculation() {
use crate::model::common::{Bounds, ExecutionMode};
use crate::model::muxbox::MuxBox;
let mut muxbox = MuxBox::default();
muxbox.id = "test_pty_box".to_string();
muxbox.title = Some("PTY Test Box".to_string());
muxbox.border_color = Some("white".to_string());
muxbox.execution_mode = ExecutionMode::Pty;
let test_cases = vec![
(100, 50, 99, 48, "Large box with improved dimensions"), (80, 24, 79, 22, "Standard terminal with improved sizing"), (50, 20, 49, 18, "Medium box with realistic adjustments"), (10, 5, 40, 10, "Tiny box falls back to minimum dimensions"), ];
for (width, height, expected_cols, expected_rows, description) in test_cases {
let bounds = Bounds::new(0, 0, width, height);
let (cols, rows) = muxbox.calculate_terminal_dimensions(&bounds);
assert_eq!(
cols, expected_cols,
"Terminal columns mismatch for {}: got {}, expected {}",
description, cols, expected_cols
);
assert_eq!(
rows, expected_rows,
"Terminal rows mismatch for {}: got {}, expected {}",
description, rows, expected_rows
);
}
}
#[test]
fn test_performance_optimization_integration() {
let mut processor = AnsiProcessor::with_screen_size(80, 24);
processor.set_screen_mode(true);
processor.process_string("Program starting...");
processor.capture_baseline();
processor.process_string("\x1b[1;1HCPU: 45%");
processor.update_screen_state();
processor.process_string("\x1b[2;1HMEM: 62%");
processor.update_screen_state();
processor.process_string("\x1b[1;1HCPU: 47%");
let message = processor.create_content_update_message(true);
if let crate::ansi_processor::TerminalMessage::ContentUpdate { dirty_regions, .. } = message {
assert!(
!dirty_regions.is_empty(),
"Updates should create dirty regions"
);
let total_dirty_cells: usize = dirty_regions.iter().map(|r| r.width * r.height).sum();
let total_screen_cells = 80 * 24;
assert!(
total_dirty_cells < total_screen_cells,
"Dirty regions should be smaller than full screen for efficiency"
);
} else {
panic!("Expected ContentUpdate message");
}
}