use crate::tui::plan::TaskStatus;
use crate::utils::plan_files::latest_archived_plan_from_path;
fn finished_plan_json(title: &str) -> String {
format!(
r#"{{"title":"{title}","description":"","status":"Active",
"tasks":[{{"title":"Ship it","description":"The only step",
"task_type":"Edit","status":"Completed"}}]}}"#
)
}
fn archive_as(json_path: &std::path::Path, stamp: &str, title: &str) {
let dir = json_path.parent().unwrap().join("archive");
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(
dir.join(format!("plan-{stamp}.json")),
finished_plan_json(title),
)
.unwrap();
}
#[test]
fn the_last_archived_plan_is_recovered() {
let tmp = tempfile::tempdir().unwrap();
let live = tmp.path().join("plan.json");
archive_as(&live, "20260726-101500", "Ship the fix");
let found = latest_archived_plan_from_path(&live).expect("archived plan must be readable");
assert_eq!(found.title, "Ship the fix");
assert_eq!(found.tasks[0].status, TaskStatus::Completed);
}
#[test]
fn the_newest_archive_wins() {
let tmp = tempfile::tempdir().unwrap();
let live = tmp.path().join("plan.json");
archive_as(&live, "20260725-090000", "Older plan");
archive_as(&live, "20260726-101500", "Newer plan");
let found = latest_archived_plan_from_path(&live).unwrap();
assert_eq!(found.title, "Newer plan");
}
#[test]
fn a_date_rollover_still_picks_the_newer_one() {
let tmp = tempfile::tempdir().unwrap();
let live = tmp.path().join("plan.json");
archive_as(&live, "20260731-235900", "July");
archive_as(&live, "20260801-000100", "August");
assert_eq!(
latest_archived_plan_from_path(&live).unwrap().title,
"August"
);
}
#[test]
fn no_archive_yields_nothing() {
let tmp = tempfile::tempdir().unwrap();
assert!(latest_archived_plan_from_path(&tmp.path().join("plan.json")).is_none());
}
#[test]
fn reading_an_archive_never_mutates_it() {
let tmp = tempfile::tempdir().unwrap();
let live = tmp.path().join("plan.json");
let dir = tmp.path().join("archive");
std::fs::create_dir_all(&dir).unwrap();
let archived = dir.join("plan-20260726-101500.json");
std::fs::write(
&archived,
r#"{"title":"Terminal status","description":"","status":"Completed",
"tasks":[{"title":"Ship it","description":"d","task_type":"Edit",
"status":"Completed"}]}"#,
)
.unwrap();
let found = latest_archived_plan_from_path(&live);
assert!(
found.is_some(),
"an archived plan must stay readable whatever status it carries"
);
assert!(
archived.exists(),
"reading an archived plan must not move or delete it"
);
}
#[test]
fn a_non_json_file_in_the_archive_is_ignored() {
let tmp = tempfile::tempdir().unwrap();
let live = tmp.path().join("plan.json");
archive_as(&live, "20260726-101500", "Ship the fix");
let dir = tmp.path().join("archive");
std::fs::write(dir.join("plan-20260726-999999.md"), "# design prose").unwrap();
let found = latest_archived_plan_from_path(&live).expect("the .md must not shadow the .json");
assert_eq!(found.title, "Ship the fix");
}