magi-code 0.64.0

Repository-aware CLI coding agent for terminal work
Documentation
use super::*;

#[test]
fn render_transcript_shows_streaming_assistant_label_until_complete() {
    let mut state = MissionControlState::default();
    state.apply_output_event(&OutputEvent::AssistantDelta {
        text: "working".to_string(),
    });
    let backend = TestBackend::new(80, 20);
    let mut terminal = ratatui::Terminal::new(backend).unwrap();
    terminal.draw(|frame| draw(frame, &state)).unwrap();
    let buffer = terminal.backend().buffer();
    assert!(find_text(buffer, "🤖").is_some());
    assert!(find_text(buffer, "Assistant …").is_some());

    state.apply_output_event(&OutputEvent::AssistantComplete {
        text: "working".to_string(),
    });
    terminal.draw(|frame| draw(frame, &state)).unwrap();
    let completed = terminal.backend().buffer();

    assert!(find_text(completed, "🤖").is_some());
    assert!(find_text(completed, "Assistant").is_some());
    assert!(find_text(completed, "Assistant …").is_none());
}

#[test]
fn render_transcript_shows_context_usage_on_right_border() {
    let mut state = MissionControlState::default();
    for line in 0..40 {
        state.apply_output_event(&OutputEvent::UserPrompt {
            text: format!("line-{line}"),
        });
    }
    state.apply_output_event(&OutputEvent::ContextUsage {
        current_tokens: 16274,
        max_tokens: 272000,
        reasoning_tokens: Some(0),
        source: crate::output::ContextUsageSource::ProviderExact,
        request_sequence: 0,
    });
    let backend = TestBackend::new(160, 20);
    let mut terminal = ratatui::Terminal::new(backend).unwrap();
    terminal.draw(|frame| draw(frame, &state)).unwrap();
    let buffer = terminal.backend().buffer();
    let layout = layout_for(Rect::new(0, 0, 160, 20), &state);
    let rendered_transcript = rendered_text_in_area(buffer, layout.transcript);
    let transcript = find_text(buffer, "Session:").unwrap();
    let usage = find_text(buffer, "Context   5%/272k • latest")
        .unwrap_or_else(|| panic!("usage label missing from transcript: {rendered_transcript}"));

    let latest = find_text(buffer, "latest").unwrap();

    assert_eq!(transcript.1, layout.transcript.y);
    assert_eq!(usage.1, layout.transcript.y);
    assert_eq!(latest.1, layout.transcript.y);
    assert!(latest.0 > layout.transcript.x + layout.transcript.width / 2);
    assert!(!rendered_transcript.contains("Thinking"));
}

#[test]
fn render_transcript_shows_scroll_position_on_top_right_title_strip() {
    let mut state = MissionControlState::default();
    for line in 0..12 {
        state.apply_output_event(&OutputEvent::UserPrompt {
            text: format!("line-{line}"),
        });
    }
    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 layout = layout_for(Rect::new(0, 0, 100, 20), &state);
    let title = find_text(buffer, "Session:").unwrap();
    let latest = find_text(buffer, "latest").unwrap();

    assert_eq!(title.1, layout.transcript.y);
    assert!(title.0 < layout.transcript.x + layout.transcript.width / 2);
    assert_eq!(latest.1, layout.transcript.y);
    assert!(latest.0 > layout.transcript.x + layout.transcript.width / 2);

    state.set_scroll_offset(&state.scroll_views.transcript, 3);
    terminal.draw(|frame| draw(frame, &state)).unwrap();
    let buffer = terminal.backend().buffer();
    let scrolled = find_text(buffer, "3 lines above latest").unwrap();

    assert_eq!(scrolled.1, layout.transcript.y);
    assert!(scrolled.0 > layout.transcript.x + layout.transcript.width / 2);
}

#[test]
fn render_places_activity_tree_above_detail_with_wider_transcript() {
    let mut state = MissionControlState::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 area = Rect::new(0, 0, 100, 30);
    let layout = layout_for(area, &state);
    assert_eq!(
        state.layout_mode,
        crate::tui::state::TuiLayoutMode::TranscriptFocused
    );
    assert!(layout.transcript.width > layout.activity_tree.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);

    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 transcript = find_text(buffer, "Session:").unwrap();
    let tree = find_text(buffer, "Activity Tree").unwrap();
    let detail = find_text(buffer, "Selected Activity Detail").unwrap();

    assert!(tree.0 <= detail.0 + 1);
    assert!(tree.1 < detail.1);
    assert!(transcript.0 < tree.0);
    assert!(tree.0 >= 60);
}

#[test]
fn render_transcript_tails_overflow_by_default() {
    let mut state = MissionControlState::default();
    for line in 0..8 {
        state.apply_output_event(&OutputEvent::UserPrompt {
            text: format!("line-{line}"),
        });
    }

    let backend = TestBackend::new(80, 12);
    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("line-7"));
    assert!(!rendered.contains("line-0"));
}

#[test]
fn render_transcript_tails_single_long_wrapped_message() {
    let mut state = MissionControlState::default();
    state.apply_output_event(&OutputEvent::AssistantComplete {
        text: format!("HEAD {}\nTAIL-WRAPPED", "x".repeat(180)),
    });

    let backend = TestBackend::new(50, 12);
    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("TAIL-WRAPPED"));
    assert!(!rendered.contains("HEAD"));
}

#[test]
fn render_transcript_tails_word_wrapped_overflow() {
    let state = MissionControlState {
        transcript: vec![
            "assistant: alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu nu xi omicron pi rho sigma tau upsilon phi chi psi omega SENTINEL".to_string(),
        ]
        .into(),
        ..Default::default()
    };

    let backend = TestBackend::new(33, 12);
    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("SENTINEL"), "{rendered}");
    assert!(!rendered.contains("alpha"), "{rendered}");
}

#[test]
fn render_transcript_markdown_code_and_boundaries() {
    let mut state = MissionControlState::default();
    state.apply_output_event(&OutputEvent::UserPrompt {
        text: "show code".to_string(),
    });
    state.apply_output_event(&OutputEvent::AssistantComplete {
        text: "# Plan\n\n- use `render`\n\n```rust\nfn main() {}\n```".to_string(),
    });
    state.apply_output_event(&OutputEvent::ToolResult {
        call: Box::new(crate::providers::ToolCall {
            id: "tool-1".to_string(),
            name: "bash".to_string(),
            arguments: serde_json::json!({}),
        }),
        result: Box::new(crate::tools::ToolResult {
            tool_name: "bash".to_string(),
            success: true,
            content: "ok".to_string(),
            metadata: serde_json::json!({}),
            display: crate::tools::ToolResultDisplay::default(),
        }),
        summary: Box::new(ToolDisplaySummary {
            tool_name: "bash".to_string(),
            status: ToolStatus::Success,
            unicode_mark: "✓",
            ascii_mark: "OK",
            label: "bash echo ok".to_string(),
            metadata: Vec::new(),
        }),
    });

    let backend = TestBackend::new(100, 30);
    let mut terminal = ratatui::Terminal::new(backend).unwrap();
    terminal.draw(|frame| draw(frame, &state)).unwrap();
    terminal.draw(|frame| draw(frame, &state)).unwrap();
    let buffer = terminal.backend().buffer();
    let rendered = buffer
        .content()
        .iter()
        .map(|cell| cell.symbol())
        .collect::<String>();

    assert!(find_text(buffer, "👤").is_some());
    assert!(find_text(buffer, "You").is_some());
    assert!(find_text(buffer, "🤖").is_some());
    assert!(find_text(buffer, "Assistant").is_some());
    assert!(rendered.contains("bash echo ok"));
    assert!(rendered.contains("# Plan"));
    assert!(rendered.contains("• use "));
    assert!(rendered.contains("language: rust"));
    assert!(rendered.contains("│ fn main"));
    let code = find_text(buffer, "fn main").unwrap();
    assert_eq!(buffer[code].bg, MATRIX_GREEN.panel);
    let heading = find_text(buffer, "# Plan").unwrap();
    assert_eq!(
        buffer[heading].style().fg,
        MATRIX_GREEN
            .display_role(crate::rendering::DisplayRole::Heading)
            .fg
    );
}

#[test]
fn render_transcript_assistant_diff_fence_uses_diff_styles() {
    let mut state = MissionControlState::default();
    state.apply_output_event(&OutputEvent::AssistantComplete {
        text: "```diff\n-old\n+new\n```".to_string(),
    });

    let backend = TestBackend::new(80, 20);
    let mut terminal = ratatui::Terminal::new(backend).unwrap();
    terminal.draw(|frame| draw(frame, &state)).unwrap();
    terminal.draw(|frame| draw(frame, &state)).unwrap();
    let buffer = terminal.backend().buffer();

    assert!(find_text(buffer, "language: diff").is_some());
    let removed = find_text(buffer, "-old").unwrap();
    assert_eq!(buffer[removed].fg, MATRIX_GREEN.lavender_cool);
    assert_eq!(buffer[removed].bg, MATRIX_GREEN.error_bg);
    let inserted = find_text(buffer, "+new").unwrap();
    assert_eq!(buffer[inserted].fg, MATRIX_GREEN.green_neon);
    assert_eq!(buffer[inserted].bg, MATRIX_GREEN.success_bg);
}

#[test]
fn render_transcript_multiline_markdown_preserves_alignment() {
    let mut state = MissionControlState::default();
    state.apply_output_event(&OutputEvent::AssistantComplete {
        text: "First paragraph\n\n- one\n- two\n\nAfter".to_string(),
    });

    let backend = TestBackend::new(80, 20);
    let mut terminal = ratatui::Terminal::new(backend).unwrap();
    terminal.draw(|frame| draw(frame, &state)).unwrap();
    terminal.draw(|frame| draw(frame, &state)).unwrap();
    let layout = layout_for(Rect::new(0, 0, 80, 20), &state);
    let rendered = rendered_text_in_area(terminal.backend().buffer(), layout.transcript);

    assert!(rendered.contains("  First paragraph"), "{rendered}");
    assert!(rendered.contains("  • one"), "{rendered}");
    assert!(rendered.contains("  • two"), "{rendered}");
    assert!(rendered.contains("  After"), "{rendered}");
}

#[test]
fn render_transcript_adds_muted_separator_before_later_user_turns() {
    let mut state = MissionControlState::default();
    state.apply_output_event(&OutputEvent::UserPrompt {
        text: "first prompt".to_string(),
    });
    state.apply_output_event(&OutputEvent::AssistantComplete {
        text: "answer".to_string(),
    });
    state.apply_output_event(&OutputEvent::UserPrompt {
        text: "second prompt".to_string(),
    });

    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 layout = layout_for(Rect::new(0, 0, 100, 30), &state);
    let rendered = rendered_text_in_area(buffer, layout.transcript);

    assert_eq!(rendered.matches("user turn").count(), 1, "{rendered}");
    let first_prompt = find_text(buffer, "first prompt").unwrap();
    let separator = find_text(buffer, "user turn").unwrap();
    let second_prompt = find_text(buffer, "second prompt").unwrap();
    assert!(first_prompt.1 < separator.1, "{rendered}");
    assert!(separator.1 < second_prompt.1, "{rendered}");
    assert_eq!(buffer[separator].fg, MATRIX_GREEN.green_dim);
    assert!(buffer[separator].modifier.contains(Modifier::DIM));
}

fn render_transcript_scrollbar_case(transcript: Vec<String>) -> (Buffer, Rect) {
    let state = MissionControlState {
        transcript: transcript.into(),
        ..Default::default()
    };
    let area = Rect::new(0, 0, 80, 20);
    let layout = layout_for(area, &state);
    let backend = TestBackend::new(area.width, area.height);
    let mut terminal = ratatui::Terminal::new(backend).unwrap();
    terminal.draw(|frame| draw(frame, &state)).unwrap();
    (
        terminal.backend().buffer().clone(),
        transcript_text_area_for_pane(layout.transcript),
    )
}

fn assert_transcript_scrollbar_gutter(
    buffer: &Buffer,
    text_area: Rect,
    adjacent_row_text: &str,
    expected_adjacent: &str,
) {
    let gutter_x = text_area.x + text_area.width - 1;
    let adjacent_row = find_text_in_area(buffer, text_area, adjacent_row_text)
        .unwrap_or_else(|| panic!("transcript fixture text missing: {adjacent_row_text}"))
        .1;
    let thumb = (gutter_x, adjacent_row);
    assert_eq!(buffer[thumb].symbol(), "┃");
    assert_eq!(buffer[thumb].fg, MATRIX_GREEN.green_bright);
    assert_eq!(buffer[thumb].bg, ratatui::style::Color::Reset);
    assert_eq!(
        buffer[(gutter_x - 1, adjacent_row)].symbol(),
        expected_adjacent,
    );
}

#[test]
fn production_transcript_scrollbar_is_visible_without_overflow() {
    let fixture = format!("fit-sentinel{}", "F".repeat(100));
    let (buffer, text_area) = render_transcript_scrollbar_case(vec![fixture]);

    assert_transcript_scrollbar_gutter(&buffer, text_area, "fit-sentinel", "F");
}

#[test]
fn production_transcript_scrollbar_is_visible_with_overflow() {
    let (buffer, text_area) = render_transcript_scrollbar_case(
        (0..40)
            .map(|line| format!("overflow-line-{line}{}", "O".repeat(60)))
            .collect(),
    );

    assert_transcript_scrollbar_gutter(&buffer, text_area, "overflow-line-39", "O");
    assert!(find_text_in_area(&buffer, text_area, "overflow-line-0").is_none());
}