a73x

tests/status_test.rs

Ref:   Size: 4.9 KiB

mod common;

use tempfile::TempDir;

use git_collab::event::ReviewVerdict;
use git_collab::status;

use common::{alice, bob, create_patch, init_repo, open_issue, close_issue, add_review};

// Additional helpers not in common/mod.rs

fn close_patch(repo: &git2::Repository, ref_name: &str, author: &git_collab::event::Author) {
    let sk = common::test_signing_key();
    let event = git_collab::event::Event {
        timestamp: common::now(),
        author: author.clone(),
        action: git_collab::event::Action::PatchClose { reason: None },
        clock: 0,
    };
    git_collab::dag::append_event(repo, ref_name, &event, &sk).unwrap();
}

fn merge_patch(repo: &git2::Repository, ref_name: &str, author: &git_collab::event::Author) {
    let sk = common::test_signing_key();
    let event = git_collab::event::Event {
        timestamp: common::now(),
        author: author.clone(),
        action: git_collab::event::Action::PatchMerge,
        clock: 0,
    };
    git_collab::dag::append_event(repo, ref_name, &event, &sk).unwrap();
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

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

    let status = status::compute(&repo).unwrap();
    assert_eq!(status.issues_open, 0);
    assert_eq!(status.issues_closed, 0);
    assert_eq!(status.patches_open, 0);
    assert_eq!(status.patches_closed, 0);
    assert_eq!(status.patches_merged, 0);
    assert_eq!(status.patches_approved, 0);
    assert_eq!(status.patches_changes_requested, 0);
    assert!(status.recent_items.is_empty());
}

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

    // 2 open, 1 closed
    open_issue(&repo, &alice(), "Open one");
    open_issue(&repo, &bob(), "Open two");
    let (ref_name, _) = open_issue(&repo, &alice(), "Will close");
    close_issue(&repo, &ref_name, &alice());

    let status = status::compute(&repo).unwrap();
    assert_eq!(status.issues_open, 2);
    assert_eq!(status.issues_closed, 1);
}

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

    // 1 open, 1 closed, 1 merged
    create_patch(&repo, &alice(), "Open patch");
    let (ref_name, _) = create_patch(&repo, &alice(), "Closed patch");
    close_patch(&repo, &ref_name, &alice());
    let (ref_name, _) = create_patch(&repo, &alice(), "Merged patch");
    merge_patch(&repo, &ref_name, &alice());

    let status = status::compute(&repo).unwrap();
    assert_eq!(status.patches_open, 1);
    assert_eq!(status.patches_closed, 1);
    assert_eq!(status.patches_merged, 1);
}

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

    // Patch with approval
    let (ref_name, _) = create_patch(&repo, &alice(), "Approved patch");
    add_review(&repo, &ref_name, &bob(), ReviewVerdict::Approve);

    // Patch with changes requested
    let (ref_name, _) = create_patch(&repo, &alice(), "Needs work");
    add_review(&repo, &ref_name, &bob(), ReviewVerdict::RequestChanges);

    // Patch with no reviews (just open)
    create_patch(&repo, &alice(), "No reviews yet");

    let status = status::compute(&repo).unwrap();
    assert_eq!(status.patches_open, 3);
    assert_eq!(status.patches_approved, 1);
    assert_eq!(status.patches_changes_requested, 1);
}

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

    open_issue(&repo, &alice(), "Recent issue");
    create_patch(&repo, &alice(), "Recent patch");

    let status = status::compute(&repo).unwrap();
    assert_eq!(status.recent_items.len(), 2);
    let titles: Vec<&str> = status.recent_items.iter().map(|i| i.title.as_str()).collect();
    assert!(titles.contains(&"Recent issue"));
    assert!(titles.contains(&"Recent patch"));
}

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

    for i in 0..15 {
        open_issue(&repo, &alice(), &format!("Issue {}", i));
    }

    let status = status::compute(&repo).unwrap();
    assert_eq!(status.recent_items.len(), 10);
}

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

    open_issue(&repo, &alice(), "Test issue");
    create_patch(&repo, &alice(), "Test patch");

    let status = status::compute(&repo).unwrap();
    let output = status.to_string();

    // Should contain section headers and counts
    assert!(output.contains("Issues"));
    assert!(output.contains("Patches"));
    assert!(output.contains("1 open"));
}