#[cfg(test)]
#[test]
fn test_identical_accumulated_content_skips_rendering() {
use std::io::Cursor;
let test_printer = Rc::new(RefCell::new(TestPrinter::new()));
let printer: SharedPrinter = test_printer.clone();
let parser = ClaudeParser::with_printer(Colors { enabled: false }, Verbosity::Normal, printer)
.with_terminal_mode(TerminalMode::Full);
let input = r#"{"type":"stream_event","event":{"type":"message_start"}}
{"type":"stream_event","event":{"type":"content_block_start","index":0,"content_block":{"type":"text","text":"Hello"}}}
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" World"}}}
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":""}}}
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":""}}}
{"type":"stream_event","event":{"type":"message_stop"}}"#;
let reader = Cursor::new(input);
parser
.parse_stream(reader, &MemoryWorkspace::new_test())
.unwrap();
let printer_ref = test_printer.borrow();
let output = printer_ref.get_output();
let non_empty_lines: Vec<&str> = output.lines().filter(|l| !l.trim().is_empty()).collect();
assert!(
non_empty_lines.len() < 10,
"Empty deltas should not cause excessive output. Found {count} non-empty lines. Output: {output:?}",
count = non_empty_lines.len()
);
assert!(
output.contains("Hello World"),
"Should contain accumulated text. Output: {output:?}"
);
}
#[cfg(test)]
#[test]
fn test_streaming_session_is_content_rendered() {
use crate::json_parser::streaming_state::StreamingSession;
let mut session = StreamingSession::new();
session.on_message_start();
session.on_text_delta(0, "Hello");
assert!(
!session.is_content_rendered(super::types::ContentType::Text, "0"),
"First delta should not be detected as rendered"
);
session.mark_content_rendered(super::types::ContentType::Text, "0");
assert!(
session.is_content_rendered(super::types::ContentType::Text, "0"),
"Same content should be detected as already rendered"
);
session.on_text_delta(0, " World");
assert!(
!session.is_content_rendered(super::types::ContentType::Text, "0"),
"Changed content should not be detected as rendered"
);
assert!(
session.has_rendered_prefix(super::types::ContentType::Text, "0"),
"Changed content should have prefix match (starts with 'Hello')"
);
session.mark_content_rendered(super::types::ContentType::Text, "0");
assert!(
session.is_content_rendered(super::types::ContentType::Text, "0"),
"Marked content should be detected as rendered"
);
}
#[cfg(test)]
#[test]
fn test_streaming_session_mark_content_rendered() {
use crate::json_parser::streaming_state::StreamingSession;
let mut session = StreamingSession::new();
session.on_message_start();
session.on_text_delta(0, "Hello");
assert!(
!session.is_content_rendered(super::types::ContentType::Text, "0"),
"Should not skip before first render"
);
session.mark_content_rendered(super::types::ContentType::Text, "0");
assert!(
session.is_content_rendered(super::types::ContentType::Text, "0"),
"Should skip after marking same content as rendered"
);
session.on_text_delta(0, " World");
assert!(
!session.is_content_rendered(super::types::ContentType::Text, "0"),
"Should not skip after content changes"
);
assert!(
session.has_rendered_prefix(super::types::ContentType::Text, "0"),
"Should detect prefix match (Hello World starts with Hello)"
);
}
#[cfg(test)]
#[test]
fn test_message_start_clears_rendered_content() {
use crate::json_parser::streaming_state::StreamingSession;
let mut session = StreamingSession::new();
session.on_message_start();
session.on_text_delta(0, "Hello");
session.mark_content_rendered(super::types::ContentType::Text, "0");
assert!(
session.is_content_rendered(super::types::ContentType::Text, "0"),
"Should detect rendered content before message_start"
);
session.on_message_start();
session.on_text_delta(0, "Hello");
assert!(
!session.is_content_rendered(super::types::ContentType::Text, "0"),
"Should not skip after message_start clears trie"
);
}