tests/archive_test.rs
Ref: Size: 7.5 KiB
mod common;
use tempfile::TempDir;
use git_collab::dag;
use git_collab::event::{Action, Event};
use git_collab::state::{self, IssueState, IssueStatus, PatchState, PatchStatus};
use common::{alice, close_issue, create_patch, init_repo, now, open_issue, test_signing_key};
// ---------------------------------------------------------------------------
// Archive on close: issues
// ---------------------------------------------------------------------------
#[test]
fn test_close_issue_moves_ref_to_archive() {
let tmp = TempDir::new().unwrap();
let repo = init_repo(tmp.path(), &alice());
let (ref_name, id) = open_issue(&repo, &alice(), "To be archived");
// Close + archive
close_issue(&repo, &ref_name, &alice());
state::archive_issue_ref(&repo, &id).unwrap();
// Old ref should be gone
assert!(repo.refname_to_id(&ref_name).is_err());
// New archive ref should exist
let archive_ref = format!("refs/collab/archive/issues/{}", id);
assert!(repo.refname_to_id(&archive_ref).is_ok());
// Should still be able to materialize state from archive ref
let issue = IssueState::from_ref(&repo, &archive_ref, &id).unwrap();
assert_eq!(issue.status, IssueStatus::Closed);
assert_eq!(issue.title, "To be archived");
}
#[test]
fn test_list_issues_excludes_archived() {
let tmp = TempDir::new().unwrap();
let repo = init_repo(tmp.path(), &alice());
let (_ref1, _id1) = open_issue(&repo, &alice(), "Active issue");
let (ref2, id2) = open_issue(&repo, &alice(), "Archived issue");
close_issue(&repo, &ref2, &alice());
state::archive_issue_ref(&repo, &id2).unwrap();
// Default list should only show active
let issues = state::list_issues(&repo).unwrap();
assert_eq!(issues.len(), 1);
assert_eq!(issues[0].title, "Active issue");
}
#[test]
fn test_list_issues_with_archived_shows_both() {
let tmp = TempDir::new().unwrap();
let repo = init_repo(tmp.path(), &alice());
let (_ref1, _id1) = open_issue(&repo, &alice(), "Active issue");
let (ref2, id2) = open_issue(&repo, &alice(), "Archived issue");
close_issue(&repo, &ref2, &alice());
state::archive_issue_ref(&repo, &id2).unwrap();
// With archived flag should show both
let issues = state::list_issues_with_archived(&repo).unwrap();
assert_eq!(issues.len(), 2);
}
#[test]
fn test_resolve_issue_ref_finds_archived() {
let tmp = TempDir::new().unwrap();
let repo = init_repo(tmp.path(), &alice());
let (ref_name, id) = open_issue(&repo, &alice(), "Will be archived");
close_issue(&repo, &ref_name, &alice());
state::archive_issue_ref(&repo, &id).unwrap();
// resolve_issue_ref should find it in archive
let (resolved_ref, resolved_id) = state::resolve_issue_ref(&repo, &id[..8]).unwrap();
assert_eq!(resolved_id, id);
assert!(resolved_ref.contains("archive"));
}
// ---------------------------------------------------------------------------
// Archive on close: patches
// ---------------------------------------------------------------------------
#[test]
fn test_close_patch_moves_ref_to_archive() {
let tmp = TempDir::new().unwrap();
let repo = init_repo(tmp.path(), &alice());
let (ref_name, id) = create_patch(&repo, &alice(), "To be archived");
// Close + archive
let sk = test_signing_key();
let event = Event {
timestamp: now(),
author: alice(),
action: Action::PatchClose { reason: None },
clock: 0,
};
dag::append_event(&repo, &ref_name, &event, &sk).unwrap();
state::archive_patch_ref(&repo, &id).unwrap();
// Old ref should be gone
assert!(repo.refname_to_id(&ref_name).is_err());
// New archive ref should exist
let archive_ref = format!("refs/collab/archive/patches/{}", id);
assert!(repo.refname_to_id(&archive_ref).is_ok());
// Should still be able to materialize state from archive ref
let patch = PatchState::from_ref(&repo, &archive_ref, &id).unwrap();
assert_eq!(patch.status, PatchStatus::Closed);
}
#[test]
fn test_list_patches_excludes_archived() {
let tmp = TempDir::new().unwrap();
let repo = init_repo(tmp.path(), &alice());
let (_ref1, _id1) = create_patch(&repo, &alice(), "Active patch");
let (ref2, id2) = create_patch(&repo, &alice(), "Archived patch");
let sk = test_signing_key();
let event = Event {
timestamp: now(),
author: alice(),
action: Action::PatchClose { reason: None },
clock: 0,
};
dag::append_event(&repo, &ref2, &event, &sk).unwrap();
state::archive_patch_ref(&repo, &id2).unwrap();
let patches = state::list_patches(&repo).unwrap();
assert_eq!(patches.len(), 1);
assert_eq!(patches[0].title, "Active patch");
}
#[test]
fn test_list_patches_with_archived_shows_both() {
let tmp = TempDir::new().unwrap();
let repo = init_repo(tmp.path(), &alice());
let (_ref1, _id1) = create_patch(&repo, &alice(), "Active patch");
let (ref2, id2) = create_patch(&repo, &alice(), "Archived patch");
let sk = test_signing_key();
let event = Event {
timestamp: now(),
author: alice(),
action: Action::PatchClose { reason: None },
clock: 0,
};
dag::append_event(&repo, &ref2, &event, &sk).unwrap();
state::archive_patch_ref(&repo, &id2).unwrap();
let patches = state::list_patches_with_archived(&repo).unwrap();
assert_eq!(patches.len(), 2);
}
#[test]
fn test_resolve_patch_ref_finds_archived() {
let tmp = TempDir::new().unwrap();
let repo = init_repo(tmp.path(), &alice());
let (ref_name, id) = create_patch(&repo, &alice(), "Will archive");
let sk = test_signing_key();
let event = Event {
timestamp: now(),
author: alice(),
action: Action::PatchClose { reason: None },
clock: 0,
};
dag::append_event(&repo, &ref_name, &event, &sk).unwrap();
state::archive_patch_ref(&repo, &id).unwrap();
let (resolved_ref, resolved_id) = state::resolve_patch_ref(&repo, &id[..8]).unwrap();
assert_eq!(resolved_id, id);
assert!(resolved_ref.contains("archive"));
}
// ---------------------------------------------------------------------------
// --relates-to on issue open
// ---------------------------------------------------------------------------
#[test]
fn test_issue_open_with_relates_to() {
let tmp = TempDir::new().unwrap();
let repo = init_repo(tmp.path(), &alice());
// First create an issue to relate to
let (_ref1, id1) = open_issue(&repo, &alice(), "Parent issue");
// Open an issue with relates_to
let sk = test_signing_key();
let event = Event {
timestamp: now(),
author: alice(),
action: Action::IssueOpen {
title: "Child issue".to_string(),
body: "".to_string(),
relates_to: Some(id1.clone()),
},
clock: 0,
};
let oid = dag::create_root_event(&repo, &event, &sk).unwrap();
let id = oid.to_string();
let ref_name = format!("refs/collab/issues/{}", id);
repo.reference(&ref_name, oid, false, "test open with relates_to")
.unwrap();
let issue = IssueState::from_ref(&repo, &ref_name, &id).unwrap();
assert_eq!(issue.title, "Child issue");
assert_eq!(issue.relates_to.as_deref(), Some(id1.as_str()));
}
#[test]
fn test_issue_open_without_relates_to() {
let tmp = TempDir::new().unwrap();
let repo = init_repo(tmp.path(), &alice());
let (ref_name, id) = open_issue(&repo, &alice(), "Solo issue");
let issue = IssueState::from_ref(&repo, &ref_name, &id).unwrap();
assert_eq!(issue.relates_to, None);
}