use super::*;
#[test]
fn modal_helpers_preserve_existing_centered_geometry() {
let area = Rect::new(0, 0, 100, 30);
assert_eq!(
modal_rect(area, SYSTEM_PROMPT_MODAL),
Some(Rect::new(5, 3, 90, 24))
);
assert_eq!(system_prompt_text_area(area), Some(Rect::new(7, 6, 86, 19)));
assert_eq!(
sessions_modal_list_area(area),
Some(Rect::new(8, 7, 28, 17))
);
assert_eq!(
sessions_modal_preview_area(area),
Some(Rect::new(39, 7, 53, 17))
);
assert_eq!(
model_picker_list_area(area, true),
Some(Rect::new(12, 10, 76, 12))
);
assert_eq!(modal_rect(Rect::new(0, 0, 10, 4), PICKER_MODAL), None);
}
#[test]
fn render_has_header_transcript_tree_detail_prompt_and_help() {
let mut state = MissionControlState {
status: "ready".to_string(),
..Default::default()
};
state.apply_output_event(&OutputEvent::AssistantDelta {
text: "hello".to_string(),
});
state.apply_activity_event(ActivityEvent::Started {
id: ActivityId::new("a1"),
parent_id: None,
kind: ActivityKind::Tool,
status: ActivityStatus::Running,
metadata: ActivityMetadata::new("bash echo"),
});
let backend = TestBackend::new(100, 30);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let rendered = terminal
.backend()
.buffer()
.content()
.iter()
.map(|cell| cell.symbol())
.collect::<String>();
assert!(rendered.contains(&format!("🤘 MAGI-CODE v{}🤘", env!("CARGO_PKG_VERSION"))));
assert!(!rendered.contains("bash preview"));
assert!(!rendered.contains("Header"));
assert!(!rendered.contains("Mission Control"));
assert!(rendered.contains("Session:"));
assert!(rendered.contains("Activity Tree"));
assert!(rendered.contains("Selected Activity Detail"));
assert!(rendered.contains("Prompt"));
state.show_help = true;
terminal.draw(|frame| draw(frame, &state)).unwrap();
let rendered_with_help = terminal
.backend()
.buffer()
.content()
.iter()
.map(|cell| cell.symbol())
.collect::<String>();
assert!(rendered_with_help.contains("Help"));
}
#[test]
fn render_body_starts_with_transcript_title_strip() {
let state = MissionControlState {
footer_session: "session-a".to_string(),
focus_pane: crate::tui::state::TuiFocusPane::Prompt,
..Default::default()
};
let backend = TestBackend::new(100, 20);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let session = find_text(buffer, "Session: session-a").unwrap();
let layout = layout_for(Rect::new(0, 0, 100, 20), &state);
assert_eq!(layout.transcript.y, 0);
assert_eq!(session.1, layout.transcript.y);
assert!(find_text(buffer, "Transcript [Alt-1]").is_none());
assert!(find_text(buffer, "MAGI-CODE").is_some());
assert_ne!(
buffer[(layout.transcript.x, layout.transcript.y)].symbol(),
"┌"
);
assert_ne!(
buffer[(layout.transcript.x, layout.transcript.y)].symbol(),
"â””"
);
}
#[test]
fn activity_focused_layout_makes_activity_column_wider() {
let mut state = MissionControlState::default();
state.focus_activity_layout();
let layout = layout_for(Rect::new(0, 0, 100, 30), &state);
assert_eq!(
state.layout_mode,
crate::tui::state::TuiLayoutMode::ActivityFocused
);
assert!(layout.activity_tree.width > layout.transcript.width);
assert_eq!(layout.activity_tree.width, layout.detail.width);
assert_eq!(layout.activity_tree.x, layout.detail.x);
assert!(layout.activity_tree.y < layout.detail.y);
}
#[test]
fn render_transcript_tints_non_assistant_body_text_by_role() {
let state = MissionControlState {
transcript: vec![
"you: user body".to_string(),
"assistant: assistant body".to_string(),
"tool: tool body".to_string(),
"error: error body".to_string(),
"session: session body".to_string(),
]
.into(),
..Default::default()
};
let backend = TestBackend::new(100, 30);
let mut terminal = ratatui::Terminal::new(backend).unwrap();
terminal.draw(|frame| draw(frame, &state)).unwrap();
let buffer = terminal.backend().buffer();
let user_body = find_text(buffer, "user body").unwrap();
assert_eq!(buffer[user_body].fg, MATRIX_GREEN.mint);
assert_eq!(buffer[user_body].bg, MATRIX_GREEN.background);
assert!(!buffer[user_body].modifier.contains(Modifier::DIM));
let assistant_body = find_text(buffer, "assistant body").unwrap();
assert_eq!(buffer[assistant_body].fg, MATRIX_GREEN.text);
assert_eq!(buffer[assistant_body].bg, MATRIX_GREEN.background);
let tool_body = find_text(buffer, "tool body").unwrap();
assert_eq!(buffer[tool_body].fg, MATRIX_GREEN.cyan_mint);
assert_eq!(buffer[tool_body].bg, MATRIX_GREEN.background);
assert!(buffer[tool_body].modifier.contains(Modifier::DIM));
let error_label = find_text(buffer, "Error").unwrap();
assert_eq!(buffer[error_label].fg, MATRIX_GREEN.lavender_cool);
assert_eq!(buffer[error_label].bg, MATRIX_GREEN.error_bg);
assert!(buffer[error_label].modifier.contains(Modifier::BOLD));
let error_body = find_text(buffer, "error body").unwrap();
assert_eq!(buffer[error_body].fg, MATRIX_GREEN.lavender_cool);
assert_eq!(buffer[error_body].bg, MATRIX_GREEN.error_bg);
assert!(buffer[error_body].modifier.contains(Modifier::DIM));
let session_body = find_text(buffer, "session body").unwrap();
assert_eq!(buffer[session_body].fg, MATRIX_GREEN.green_muted);
assert_eq!(buffer[session_body].bg, MATRIX_GREEN.background);
assert!(buffer[session_body].modifier.contains(Modifier::DIM));
}
#[test]
fn layout_grows_prompt_to_five_wrapped_rows() {
let mut state = MissionControlState {
input: "x".repeat(28),
focus_pane: crate::tui::state::TuiFocusPane::Prompt,
prompt_cursor_visible: true,
..Default::default()
};
let layout = layout_for(Rect::new(0, 0, 20, 30), &state);
assert_eq!(layout.prompt.height, 4);
state.input = "x".repeat(100);
let capped_layout = layout_for(Rect::new(0, 0, 20, 30), &state);
assert_eq!(capped_layout.prompt.height, 7);
}
#[test]
fn layout_routes_mouse_coordinates_to_hovered_pane() {
let mut state = MissionControlState::default();
let layout = layout_for(Rect::new(0, 0, 100, 30), &state);
assert_eq!(layout.pane_at(1, 4), Some(TuiPane::Transcript));
assert_eq!(layout.pane_at(61, 4), Some(TuiPane::ActivityTree));
assert_eq!(layout.pane_at(61, 18), Some(TuiPane::Detail));
assert_eq!(layout.pane_at(1, 27), Some(TuiPane::Prompt));
state.show_help = true;
let layout = layout_for(Rect::new(0, 0, 100, 30), &state);
assert_eq!(layout.pane_at(50, 15), Some(TuiPane::Help));
}