use super::*;
#[test]
fn activity_preview_updates_invalidate_generic_tool_card_projection() {
let mut state = MissionControlState::default();
let id = ActivityId::new("call_dynamic");
state
.transcript
.push_back("tool: ⟳ dynamic_tool • running".to_string());
state.transcript.link_activity(
0,
TranscriptActivityLink {
activity_id: id.clone(),
tool_name: "dynamic_tool".to_string(),
},
);
state.apply_activity_event(ActivityEvent::Started {
id: id.clone(),
parent_id: None,
kind: ActivityKind::Tool,
status: ActivityStatus::Running,
metadata: ActivityMetadata::new("dynamic_tool"),
});
let before = state.transcript_visual_text();
assert!(!before.contains("fresh preview"));
state.apply_activity_event(ActivityEvent::Delta {
id,
preview: "fresh preview".to_string(),
});
assert!(state.transcript_visual_text().contains("fresh preview"));
}
#[test]
fn streaming_assistant_renders_markdown_as_plain_text() {
let mut state = MissionControlState::default();
state.apply_output_event(&OutputEvent::AssistantDelta {
text: format!("{}**bold** {}", "plain ".repeat(40), "tail ".repeat(40)),
});
let cards = project_cards(&state);
assert_eq!(cards[0].status, TranscriptCardStatus::Running);
let text = plain_projection(&cards[0].body_lines);
assert!(text.contains("**bold**"), "{text}");
}
#[test]
fn completed_assistant_projects_plain_first_then_rich_without_changing_body() {
let mut state = MissionControlState::default();
state.apply_output_event(&OutputEvent::AssistantComplete {
text: "**bold**".to_string(),
});
state.begin_final_assistant_plain_first_paint();
let first = project_cards(&state);
assert_eq!(first[0].status, TranscriptCardStatus::Success);
assert_eq!(first[0].body, "**bold**");
assert_eq!(plain_projection(&first[0].body_lines), "**bold**");
state.finish_final_assistant_plain_first_paint();
let second = project_cards(&state);
assert_eq!(second[0].body, "**bold**");
assert_eq!(plain_projection(&second[0].body_lines), "bold");
}
#[test]
fn completed_assistant_plain_first_waits_while_transcript_selection_active() {
let mut state = MissionControlState::default();
state.apply_output_event(&OutputEvent::AssistantComplete {
text: "**bold**".to_string(),
});
state.start_selection(
crate::tui::layout::TuiPane::Transcript,
crate::tui::selection::TextPosition::new(0, 0, 0),
);
assert!(!state.begin_final_assistant_plain_first_paint());
let selected_visible = crate::tui::transcript_projection::visible_transcript_lines(
&state,
CARD_LAYOUT_MIN_WIDTH,
10,
);
let selected_render = selected_visible
.lines
.iter()
.map(line_text)
.collect::<Vec<_>>()
.join("\n");
assert!(selected_render.contains("bold"), "{selected_render}");
assert!(!selected_render.contains("**bold**"), "{selected_render}");
assert!(state.clear_selection());
state.begin_final_assistant_plain_first_paint();
let first = project_cards(&state);
assert_eq!(first[0].body, "**bold**");
assert_eq!(plain_projection(&first[0].body_lines), "**bold**");
state.finish_final_assistant_plain_first_paint();
let second = project_cards(&state);
assert_eq!(second[0].body, "**bold**");
assert_eq!(plain_projection(&second[0].body_lines), "bold");
}
#[test]
fn completed_assistant_renders_markdown_projection() {
let mut state = MissionControlState::default();
state.apply_output_event(&OutputEvent::AssistantComplete {
text: "**bold**".to_string(),
});
let cards = project_cards(&state);
assert_eq!(cards[0].status, TranscriptCardStatus::Success);
let text = plain_projection(&cards[0].body_lines);
assert_eq!(text, "bold");
}
#[test]
fn tool_preview_card_body_is_line_bounded_without_visible_truncation_marker() {
let marker = "[… activity preview truncated …]";
let body = bounded_lines("one\ntwo\nthree\nfour\nfive", 4);
assert_eq!(body, "one\ntwo\nthree\nfour");
assert_eq!(body.lines().count(), 4);
assert!(!body.contains(marker));
}
#[test]
fn unknown_legacy_prefix_is_diagnostic_not_empty() {
let state = MissionControlState {
transcript: vec!["mystery: value".to_string()].into(),
..Default::default()
};
assert_eq!(roles(&state), vec![TranscriptCardRole::Diagnostic]);
}
#[test]
fn activity_viewer_matches_canonical_completed_assistant_markdown_card() {
let text = "**bold assistant output**";
let mut state = MissionControlState::default();
state.transcript.push_back(format!("assistant: {text}"));
let id = ActivityId::new("assistant-viewer-parity");
state.apply_activity_event(ActivityEvent::Started {
id: id.clone(),
parent_id: None,
kind: ActivityKind::Assistant,
status: ActivityStatus::Success,
metadata: ActivityMetadata::new("assistant"),
});
state.apply_activity_event(ActivityEvent::Delta {
id: id.clone(),
preview: text.to_string(),
});
let transcript = visual_lines(&state, 80);
let activity = activity_card_visual_lines(
&state,
state.nodes.get(&id).expect("assistant activity"),
80,
false,
);
assert_eq!(transcript.len(), activity.len() + 1);
assert_eq!(
transcript[..transcript.len() - 1]
.iter()
.map(|line| line_text(&line.line))
.collect::<Vec<_>>(),
activity
.iter()
.map(|line| line_text(&line.line))
.collect::<Vec<_>>()
);
}