magi-code 0.77.1

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

#[test]
fn read_card_projects_single_running_success_failure_and_selectors() {
    let running = read_card_state(
        "read-running",
        ActivityStatus::Running,
        serde_json::json!({"path":"src/lib.rs:raw:2-3"}),
        serde_json::json!({}),
        "",
    );
    let running = &project_cards(&running)[0];
    assert_eq!(running.role, TranscriptCardRole::Read);
    assert_eq!(running.title, "Read");
    assert_eq!(running.body, "src/lib.rs:raw:2-3");

    let success = read_card_state(
        "read-success",
        ActivityStatus::Success,
        serde_json::json!({"path":"skill://rust-dev:3+"}),
        serde_json::json!({"hashline_seen_lines":[3,4],"truncated":true}),
        "secret file content",
    );
    let success = &project_cards(&success)[0];
    assert_eq!(success.title, "Read • truncated");
    assert_eq!(success.body, "skill://rust-dev:3+\n2 lines");
    assert!(!success.body.contains("secret file content"));

    let failed = read_card_state(
        "read-failed",
        ActivityStatus::Failed,
        serde_json::json!({"path":"docs/missing.md"}),
        serde_json::json!({}),
        "No such file or directory\nbacktrace omitted",
    );
    let failed = &project_cards(&failed)[0];
    assert_eq!(failed.title, "Read");
    assert_eq!(failed.body, "docs/missing.md\nNo such file or directory");
}

#[test]
fn read_card_projects_multi_all_partial_and_all_failed_in_request_order() {
    let all = read_card_state(
        "read-all",
        ActivityStatus::Success,
        serde_json::json!({"paths":["src/lib.rs", "https://example.com:raw", "issue://42"]}),
        serde_json::json!({
            "files":3,
            "succeeded":3,
            "failed":0,
            "results":[
                read_result("src/lib.rs", true, None),
                {
                    "requested_path":"https://example.com:raw",
                    "success":true,
                    "truncated":true
                },
                read_result("issue://42", true, None)
            ]
        }),
        "unshown content",
    );
    let all = &project_cards(&all)[0];
    assert_eq!(all.title, "Read • 3 resources");
    assert_eq!(
        all.body,
        "✓ src/lib.rs\n△ https://example.com:raw\n  result truncated\n✓ issue://42"
    );

    let partial = read_card_state(
        "read-partial",
        ActivityStatus::Success,
        serde_json::json!({"paths":["src/lib.rs", "docs/missing.md", "pr://7"]}),
        serde_json::json!({
            "files":3,
            "succeeded":2,
            "failed":1,
            "aggregate_truncated":true,
            "results":[
                read_result("src/lib.rs", true, None),
                read_result("docs/missing.md", false, Some("No such file or directory")),
                read_result("pr://7", true, None)
            ]
        }),
        "unshown content",
    );
    let partial = &project_cards(&partial)[0];
    assert_eq!(partial.title, "Read • 2/3 resources");
    assert_eq!(
        partial.body,
        "✓ src/lib.rs\n✗ docs/missing.md\n  No such file or directory\n✓ pr://7"
    );

    let omitted = read_card_state(
        "read-omitted",
        ActivityStatus::Success,
        serde_json::json!({"paths":["src/lib.rs", "docs/later.md"]}),
        serde_json::json!({
            "files":2,
            "succeeded":1,
            "failed":0,
            "omitted":1,
            "results":[
                read_result("src/lib.rs", true, None),
                read_result(
                    "docs/later.md",
                    false,
                    Some("aggregate read output limit exceeded")
                )
            ]
        }),
        "--- READ OMITTED ---\nERROR: aggregate read output limit",
    );
    let omitted = &project_cards(&omitted)[0];
    assert_eq!(omitted.title, "Read • 1/2 resources");
    assert!(omitted.body.contains("✗ docs/later.md"));

    let failed = read_card_state(
        "read-none",
        ActivityStatus::Failed,
        serde_json::json!({"paths":["missing-a", "missing-b"]}),
        serde_json::json!({
            "files":2,
            "succeeded":0,
            "failed":2,
            "results":[
                read_result("missing-a", false, Some("first failure")),
                read_result("missing-b", false, Some("second failure"))
            ]
        }),
        "",
    );
    let failed = &project_cards(&failed)[0];
    assert_eq!(failed.title, "Read • 2 resources");
    assert!(failed.body.contains("✗ missing-a\n  first failure"));
    assert!(failed.body.contains("✗ missing-b\n  second failure"));
}

#[test]
fn read_card_treats_one_element_paths_as_single_resource() {
    let state = read_card_state(
        "read-one-paths",
        ActivityStatus::Success,
        serde_json::json!({"paths":["session://abc:2"]}),
        serde_json::json!({
            "files":1,
            "succeeded":1,
            "failed":0,
            "results":[{
                "requested_path":"session://abc:2",
                "success":true,
                "hashline_seen_lines":[2]
            }]
        }),
        "selected session line",
    );

    let card = &project_cards(&state)[0];
    assert_eq!(card.title, "Read");
    assert_eq!(card.body, "session://abc:2\n1 lines");
}

#[test]
fn read_card_preserves_targets_errors_and_copy_text_except_display_controls() {
    let state = read_card_state(
        "read-safe",
        ActivityStatus::Failed,
        serde_json::json!({
            "path":"https://user:secret@example.com/file?token=literal\u{1b}[31m:raw:2-4\nforged\trow\u{1b}]0;hidden\u{7}"
        }),
        serde_json::json!({}),
        "authorization: Bearer useful-error\u{1b}[2J\nraw file contents",
    );
    let card = &project_cards(&state)[0];
    let target = "https://user:secret@example.com/file?token=literal:raw:2-4forgedrow";
    assert_eq!(
        card.body,
        format!("{target}\nauthorization: Bearer useful-error")
    );
    assert!(!card.body.contains('\u{1b}'));
    assert!(!card.body.contains('\u{7}'));
    assert!(!card.body.contains("hidden"));
    assert!(!card.body.contains("raw file contents"));

    for width in [1, 2, 12] {
        let copied = visual_text_for_width(&state, width);
        assert!(copied.contains("Read"), "width {width}: {copied:?}");
        assert!(copied.contains(target), "width {width}: {copied:?}");
        assert!(
            copied.contains("authorization: Bearer useful-error"),
            "width {width}: {copied:?}"
        );
        assert!(!copied.contains("raw file contents"));
        assert!(!copied.contains("STATUS:"));
        assert!(!copied.contains("OUTPUT:"));
        assert!(!copied.contains('\u{1b}'));
    }
}

#[test]
fn read_card_preserves_multi_resource_errors_except_display_controls() {
    let state = read_card_state(
        "read-multi-safe",
        ActivityStatus::Success,
        serde_json::json!({"paths":["ok?api_key=literal", "missing?token=literal\nforged\trow\u{1b}[31m"]}),
        serde_json::json!({
            "files":2,
            "succeeded":1,
            "failed":1,
            "results":[
                read_result("ok?api_key=literal", true, None),
                read_result(
                    "missing?token=literal\nforged\trow\u{1b}[31m",
                    false,
                    Some("authorization: Bearer useful-error\u{1b}]0;hidden\u{7}")
                )
            ]
        }),
        "unshown content",
    );

    let card = &project_cards(&state)[0];
    assert_eq!(card.title, "Read • 1/2 resources");
    assert_eq!(
        card.body,
        "✓ ok?api_key=literal\n✗ missing?token=literalforgedrow\n  authorization: Bearer useful-error"
    );
}