use super::*;
use chrono::Utc;
use ito_domain::tasks::TasksParseResult;
struct FakeReader {
changes: Vec<ChangeSummary>,
full: Vec<Change>,
}
impl FakeReader {
fn new(changes: Vec<ChangeSummary>, full: Vec<Change>) -> Self {
Self { changes, full }
}
}
impl BackendChangeReader for FakeReader {
fn list_changes(
&self,
_filter: ito_domain::changes::ChangeLifecycleFilter,
) -> DomainResult<Vec<ChangeSummary>> {
Ok(self.changes.clone())
}
fn get_change(
&self,
change_id: &str,
_filter: ito_domain::changes::ChangeLifecycleFilter,
) -> DomainResult<Change> {
for c in &self.full {
if c.id == change_id {
return Ok(c.clone());
}
}
Err(ito_domain::errors::DomainError::not_found(
"change", change_id,
))
}
}
fn make_summary(id: &str, completed: u32, total: u32) -> ChangeSummary {
ChangeSummary {
id: id.to_string(),
module_id: None,
sub_module_id: None,
completed_tasks: completed,
shelved_tasks: 0,
in_progress_tasks: 0,
pending_tasks: total - completed,
total_tasks: total,
last_modified: Utc::now(),
has_proposal: true,
has_design: false,
has_specs: true,
has_tasks: true,
orchestrate: ito_domain::changes::ChangeOrchestrateMetadata::default(),
}
}
fn make_change(id: &str) -> Change {
Change {
id: id.to_string(),
module_id: None,
sub_module_id: None,
path: std::path::PathBuf::from("/fake"),
proposal: Some("# Proposal".to_string()),
design: None,
specs: vec![],
tasks: TasksParseResult::empty(),
orchestrate: ito_domain::changes::ChangeOrchestrateMetadata::default(),
last_modified: Utc::now(),
}
}
#[test]
fn list_returns_all_changes() {
let summaries = vec![
make_summary("001-01_a", 0, 2),
make_summary("001-02_b", 1, 2),
];
let reader = FakeReader::new(summaries.clone(), vec![]);
let repo = BackendChangeRepository::new(reader);
let result = repo.list().unwrap();
assert_eq!(result.len(), 2);
}
#[test]
fn resolve_target_exact_match() {
let summaries = vec![make_summary("001-01_a", 0, 2)];
let reader = FakeReader::new(summaries, vec![]);
let repo = BackendChangeRepository::new(reader);
let resolution = DomainChangeRepository::resolve_target(&repo, "001-01_a");
assert!(matches!(resolution, ChangeTargetResolution::Unique(id) if id == "001-01_a"));
}
#[test]
fn resolve_target_prefix_match() {
let summaries = vec![make_summary("001-01_something", 0, 2)];
let reader = FakeReader::new(summaries, vec![]);
let repo = BackendChangeRepository::new(reader);
let resolution = DomainChangeRepository::resolve_target(&repo, "001-01");
assert!(matches!(resolution, ChangeTargetResolution::Unique(id) if id == "001-01_something"));
}
#[test]
fn resolve_target_ambiguous() {
let summaries = vec![
make_summary("001-01_a", 0, 2),
make_summary("001-01_b", 0, 2),
];
let reader = FakeReader::new(summaries, vec![]);
let repo = BackendChangeRepository::new(reader);
let resolution = DomainChangeRepository::resolve_target(&repo, "001-01");
assert!(matches!(resolution, ChangeTargetResolution::Ambiguous(_)));
}
#[test]
fn resolve_target_not_found() {
let summaries = vec![make_summary("001-01_a", 0, 2)];
let reader = FakeReader::new(summaries, vec![]);
let repo = BackendChangeRepository::new(reader);
let resolution = DomainChangeRepository::resolve_target(&repo, "999");
assert!(matches!(resolution, ChangeTargetResolution::NotFound));
}
#[test]
fn get_delegates_to_reader() {
let change = make_change("001-01_a");
let reader = FakeReader::new(vec![], vec![change]);
let repo = BackendChangeRepository::new(reader);
let result = DomainChangeRepository::get(&repo, "001-01_a").unwrap();
assert_eq!(result.id, "001-01_a");
}
#[test]
fn list_incomplete_filters_correctly() {
let summaries = vec![
make_summary("001-01_a", 2, 2),
make_summary("001-02_b", 1, 2),
];
let reader = FakeReader::new(summaries, vec![]);
let repo = BackendChangeRepository::new(reader);
let incomplete = DomainChangeRepository::list_incomplete(&repo).unwrap();
assert_eq!(incomplete.len(), 1);
assert_eq!(incomplete[0].id, "001-02_b");
}
#[test]
fn list_complete_filters_correctly() {
let summaries = vec![
make_summary("001-01_a", 2, 2),
make_summary("001-02_b", 1, 2),
];
let reader = FakeReader::new(summaries, vec![]);
let repo = BackendChangeRepository::new(reader);
let complete = DomainChangeRepository::list_complete(&repo).unwrap();
assert_eq!(complete.len(), 1);
assert_eq!(complete[0].id, "001-01_a");
}