magi-code 0.77.1

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

#[test]
fn list_files_card_projects_running_modes_and_empty_success() {
    let files = list_files_card_state(
        "list-running-files",
        ActivityStatus::Running,
        serde_json::json!({"path":"src"}),
        serde_json::json!({}),
        "",
    );
    let card = &project_cards(&files)[0];
    assert_eq!(card.title, "List Files");
    assert_eq!(card.body, "src");
    assert!(card.metadata.is_empty());

    let mixed = list_files_card_state(
        "list-running-mixed",
        ActivityStatus::Running,
        serde_json::json!({"path":"src","include_directories":true}),
        serde_json::json!({}),
        "",
    );
    assert_eq!(project_cards(&mixed)[0].body, "src\ninclude directories");

    let empty = list_files_card_state(
        "list-empty",
        ActivityStatus::Success,
        serde_json::json!({"path":"."}),
        serde_json::json!({"files":0,"directories":0}),
        "",
    );
    let card = &project_cards(&empty)[0];
    assert_eq!(card.title, "List Files • 0 files");
    assert_eq!(card.body, ".\n0 entries");

    let unknown_empty = list_files_card_state(
        "list-unknown-empty",
        ActivityStatus::Success,
        serde_json::json!({"path":"unknown"}),
        serde_json::json!({}),
        "",
    );
    let card = &project_cards(&unknown_empty)[0];
    assert_eq!(card.title, "List Files");
    assert_eq!(card.body, "unknown");

    let unknown_nonempty = list_files_card_state(
        "list-unknown-nonempty",
        ActivityStatus::Success,
        serde_json::json!({"path":"unknown"}),
        serde_json::json!({}),
        "visible.txt",
    );
    let card = &project_cards(&unknown_nonempty)[0];
    assert_eq!(card.title, "List Files");
    assert_eq!(card.body, "unknown\nvisible.txt");
}

#[test]
fn list_files_card_uses_paths_and_metadata_contract() {
    let success = list_files_card_state(
        "list-success",
        ActivityStatus::Success,
        serde_json::json!({"path":"request","include_directories":false}),
        serde_json::json!({"path":"resolved","files":2,"directories":1}),
        "a.txt\nb.txt\ndir",
    );
    let card = &project_cards(&success)[0];
    assert_eq!(card.title, "List Files • 3 entries");
    assert_eq!(card.body, "resolved\na.txt\nb.txt\ndir");
    assert!(card.metadata.is_empty());

    let metadata_mixed = list_files_card_state(
        "list-metadata-mixed",
        ActivityStatus::Success,
        serde_json::json!({"path":"request"}),
        serde_json::json!({"path":"resolved","files":2,"directories":3}),
        "file\ndir",
    );
    assert_eq!(
        project_cards(&metadata_mixed)[0].title,
        "List Files • 5 entries"
    );

    let fallback = list_files_card_state(
        "list-fallback",
        ActivityStatus::Success,
        serde_json::json!({"path":"request"}),
        serde_json::json!({"files":1,"directories":0}),
        "file",
    );
    let card = &project_cards(&fallback)[0];
    assert_eq!(card.title, "List Files • 1 file");
    assert_eq!(card.body, "request\nfile");

    let default_path = list_files_card_state(
        "list-default-path",
        ActivityStatus::Success,
        serde_json::json!({}),
        serde_json::json!({"files":1,"directories":0}),
        "file",
    );
    assert_eq!(project_cards(&default_path)[0].body, ".\nfile");
}

#[test]
fn list_files_card_bounds_preview_truncation_and_untrusted_text() {
    let output_secret = "list-files-output-secret";
    let path_secret = "list-files-path-secret";
    let long_path = format!(
        "界/token={path_secret}/{}\u{1b}[31m",
        "very-long-path/".repeat(30)
    );
    let state = list_files_card_state(
        "list-bounded",
        ActivityStatus::Success,
        serde_json::json!({"path":long_path,"include_directories":true}),
        serde_json::json!({"files":998,"directories":2,"truncated":true}),
        &format!("one\nauthorization: Bearer {output_secret}\u{1b}[31m\nthree\nfour\nfive"),
    );
    let card = &project_cards(&state)[0];
    assert_eq!(card.title, "List Files • 1000 entries returned");
    assert!(card.body.contains("… preview limited to 4 lines"));
    assert!(card.body.contains("… output capped at 1000 entries"));
    assert!(card.body.contains("<redacted>"));
    assert!(!card.body.contains("five"));
    assert!(!card.body.contains(output_secret));
    assert!(!card.body.contains(path_secret));
    assert!(!card.body.contains('\u{1b}'));
    assert!(
        card.body
            .lines()
            .all(|line| { UnicodeWidthStr::width(line) <= PREVIEW_LINE_MAX_DISPLAY_WIDTH })
    );

    let unknown_count = list_files_card_state(
        "list-truncated-unknown-count",
        ActivityStatus::Success,
        serde_json::json!({"path":"."}),
        serde_json::json!({"truncated":true}),
        "visible.txt",
    );
    let card = &project_cards(&unknown_count)[0];
    assert_eq!(card.title, "List Files • entries returned");
    assert!(card.body.ends_with("… output capped at 1000 entries"));
}

#[test]
fn list_files_card_failed_and_canceled_paths_are_safe_and_recover() {
    let failed = list_files_card_state(
        "list-failed",
        ActivityStatus::Failed,
        serde_json::json!({"path":"params-path"}),
        serde_json::json!({"path":"metadata-path"}),
        "authorization: Bearer list-files-secret\u{1b}[2J\nsecond line",
    );
    let card = &project_cards(&failed)[0];
    assert_eq!(card.title, "List Files");
    assert_eq!(
        card.body, "params-path\nauthorization: <redacted> <redacted>",
        "body={:?}",
        card.body
    );

    for (status, output) in [
        (ActivityStatus::Canceled, "partial output"),
        (ActivityStatus::Failed, "prompt canceled"),
    ] {
        let state = list_files_card_state(
            &format!("list-canceled-{status:?}"),
            status,
            serde_json::json!({"path":"cancel-path"}),
            serde_json::json!({"outcome":"canceled"}),
            output,
        );
        let card = &project_cards(&state)[0];
        assert_eq!(card.status, TranscriptCardStatus::Canceled);
        assert_eq!(card.title, "List Files • canceled");
        assert_eq!(card.body, "cancel-path\nCanceled before completion");
    }
}

#[test]
fn list_files_card_visual_copy_is_bounded_at_tiny_widths() {
    let state = list_files_card_state(
        "list-visual",
        ActivityStatus::Success,
        serde_json::json!({"path":"visual"}),
        serde_json::json!({"files":1}),
        "entry",
    );
    for width in [1, 2, 3, 12, CARD_LAYOUT_MIN_WIDTH, 80] {
        let lines = visual_lines(&state, width);
        assert!(
            lines.iter().all(|line| {
                UnicodeWidthStr::width(line_text(&line.line).as_str()) == usize::from(width)
            }),
            "width {width}"
        );
        let copied = visual_text_for_width(&state, width);
        assert!(copied.contains("List Files"), "width {width}: {copied:?}");
        assert!(copied.contains("visual"), "width {width}: {copied:?}");
        assert!(copied.contains("entry"), "width {width}: {copied:?}");
    }
    let unicode = list_files_card_state(
        "list-visual-unicode",
        ActivityStatus::Success,
        serde_json::json!({"path":"visual/界"}),
        serde_json::json!({"files":1}),
        "entry-界",
    );
    let copied = visual_text_for_width(&unicode, 12);
    assert!(copied.contains("visual/界"));
    assert!(copied.contains("entry-界"));
}