a73x

2107d307

Add JSON serialization tests for issue and patch state

a73x   2026-03-21 16:03

Tests cover: IssueState/PatchState serialize to JSON with correct
field names (lowercase enums, hex OID strings, verdict strings),
list_json/show_json filter and format correctly, and closed status
serializes properly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

diff --git a/tests/collab_test.rs b/tests/collab_test.rs
index af75d8c..4f97d83 100644
--- a/tests/collab_test.rs
+++ b/tests/collab_test.rs
@@ -1262,3 +1262,140 @@ fn test_patch_list_offset_beyond_end() {
    );
}

// ---------------------------------------------------------------------------
// JSON serialization tests
// ---------------------------------------------------------------------------

#[test]
fn test_issue_state_serializes_to_json() {
    let tmp = TempDir::new().unwrap();
    let repo = init_repo(tmp.path(), &alice());

    let (ref_name, id) = open_issue(&repo, &alice(), "JSON test issue");
    add_comment(&repo, &ref_name, &bob(), "A comment for JSON");

    let state = IssueState::from_ref(&repo, &ref_name, &id).unwrap();
    let json = serde_json::to_value(&state).unwrap();

    assert_eq!(json["title"], "JSON test issue");
    assert_eq!(json["status"], "open");
    assert_eq!(json["author"]["name"], "Alice");
    assert_eq!(json["comments"].as_array().unwrap().len(), 1);
    assert_eq!(json["comments"][0]["author"]["name"], "Bob");
    assert_eq!(json["comments"][0]["body"], "A comment for JSON");
    // commit_id should be serialized as a hex string
    assert!(json["comments"][0]["commit_id"].is_string());
}

#[test]
fn test_issue_state_closed_serializes() {
    let tmp = TempDir::new().unwrap();
    let repo = init_repo(tmp.path(), &alice());

    let (ref_name, id) = open_issue(&repo, &alice(), "Closed JSON");
    close_issue(&repo, &ref_name, &alice());

    let state = IssueState::from_ref(&repo, &ref_name, &id).unwrap();
    let json = serde_json::to_value(&state).unwrap();
    assert_eq!(json["status"], "closed");
}

#[test]
fn test_patch_state_serializes_to_json() {
    let tmp = TempDir::new().unwrap();
    let repo = init_repo(tmp.path(), &alice());

    let (ref_name, id) = create_patch(&repo, &alice(), "JSON patch test");
    add_review(&repo, &ref_name, &bob(), ReviewVerdict::Approve);

    let state = PatchState::from_ref(&repo, &ref_name, &id).unwrap();
    let json = serde_json::to_value(&state).unwrap();

    assert_eq!(json["title"], "JSON patch test");
    assert_eq!(json["status"], "open");
    assert_eq!(json["base_ref"], "main");
    assert_eq!(json["branch"], "test-branch");
    assert_eq!(json["reviews"].as_array().unwrap().len(), 1);
    assert_eq!(json["reviews"][0]["verdict"], "approve");
}

#[test]
fn test_issue_list_json_output() {
    let tmp = TempDir::new().unwrap();
    let repo = init_repo(tmp.path(), &alice());

    open_issue(&repo, &alice(), "Issue one");
    open_issue(&repo, &bob(), "Issue two");

    let json_str = git_collab::issue::list_json(&repo, false).unwrap();
    let value: serde_json::Value = serde_json::from_str(&json_str).unwrap();
    let arr = value.as_array().unwrap();
    assert_eq!(arr.len(), 2);

    let titles: Vec<&str> = arr.iter().map(|v| v["title"].as_str().unwrap()).collect();
    assert!(titles.contains(&"Issue one"));
    assert!(titles.contains(&"Issue two"));
}

#[test]
fn test_issue_list_json_filters_closed() {
    let tmp = TempDir::new().unwrap();
    let repo = init_repo(tmp.path(), &alice());

    open_issue(&repo, &alice(), "Open issue");
    let (ref2, _) = open_issue(&repo, &alice(), "Closed issue");
    close_issue(&repo, &ref2, &alice());

    // Without --all, only open issues
    let json_str = git_collab::issue::list_json(&repo, false).unwrap();
    let value: serde_json::Value = serde_json::from_str(&json_str).unwrap();
    assert_eq!(value.as_array().unwrap().len(), 1);

    // With --all, both
    let json_str = git_collab::issue::list_json(&repo, true).unwrap();
    let value: serde_json::Value = serde_json::from_str(&json_str).unwrap();
    assert_eq!(value.as_array().unwrap().len(), 2);
}

#[test]
fn test_issue_show_json_output() {
    let tmp = TempDir::new().unwrap();
    let repo = init_repo(tmp.path(), &alice());

    let (ref_name, id) = open_issue(&repo, &alice(), "Show JSON test");
    add_comment(&repo, &ref_name, &bob(), "test comment");

    let json_str = git_collab::issue::show_json(&repo, &id[..8]).unwrap();
    let value: serde_json::Value = serde_json::from_str(&json_str).unwrap();
    assert_eq!(value["title"], "Show JSON test");
    assert_eq!(value["comments"].as_array().unwrap().len(), 1);
}

#[test]
fn test_patch_list_json_output() {
    let tmp = TempDir::new().unwrap();
    let repo = init_repo(tmp.path(), &alice());

    create_patch(&repo, &alice(), "Patch one");
    create_patch(&repo, &bob(), "Patch two");

    let json_str = git_collab::patch::list_json(&repo, false).unwrap();
    let value: serde_json::Value = serde_json::from_str(&json_str).unwrap();
    let arr = value.as_array().unwrap();
    assert_eq!(arr.len(), 2);
}

#[test]
fn test_patch_show_json_output() {
    let tmp = TempDir::new().unwrap();
    let repo = init_repo(tmp.path(), &alice());

    let (ref_name, id) = create_patch(&repo, &alice(), "Show patch JSON");
    add_review(&repo, &ref_name, &bob(), ReviewVerdict::Approve);

    let json_str = git_collab::patch::show_json(&repo, &id[..8]).unwrap();
    let value: serde_json::Value = serde_json::from_str(&json_str).unwrap();
    assert_eq!(value["title"], "Show patch JSON");
    assert_eq!(value["reviews"].as_array().unwrap().len(), 1);
}