From fefa91a39e95f35ce5d4eca494d4e44d5bdf74e1 Mon Sep 17 00:00:00 2001 From: iris Date: Thu, 21 May 2026 18:20:15 +0200 Subject: [PATCH] test: cover init_config approval deser + lenient row collection --- hive-c0re/src/approvals.rs | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/hive-c0re/src/approvals.rs b/hive-c0re/src/approvals.rs index 815ecf7..ba9f9f2 100644 --- a/hive-c0re/src/approvals.rs +++ b/hive-c0re/src/approvals.rs @@ -345,3 +345,68 @@ fn now_unix() -> i64 { .and_then(|d| i64::try_from(d.as_secs()).ok()) .unwrap_or(0) } + +#[cfg(test)] +mod tests { + use super::*; + use hive_sh4re::ApprovalKind; + + fn open_temp() -> (tempfile::TempDir, std::path::PathBuf, Approvals) { + let dir = tempfile::tempdir().expect("tempdir"); + let path = dir.path().join("approvals.sqlite"); + let db = Approvals::open(&path).expect("open approvals db"); + (dir, path, db) + } + + #[test] + fn init_config_approval_round_trips() { + // Regression for #160: an `init_config` row used to fail + // deserialization (row_to_approval matched only apply_commit + + // spawn), erroring out the whole `pending()` query — every + // approval then vanished from the dashboard. + let (_dir, _path, db) = open_temp(); + let id = db + .submit_kind("bitburner", ApprovalKind::InitConfig, "", Some("scaffold")) + .expect("submit init_config"); + let pending = db + .pending() + .expect("pending() must not error on an init_config row"); + assert_eq!(pending.len(), 1); + assert_eq!(pending[0].id, id); + assert!(matches!(pending[0].kind, ApprovalKind::InitConfig)); + } + + #[test] + fn mixed_kinds_all_listed() { + let (_dir, _path, db) = open_temp(); + db.submit_kind("a", ApprovalKind::ApplyCommit, "deadbeef", None) + .unwrap(); + db.submit_kind("b", ApprovalKind::Spawn, "", None).unwrap(); + db.submit_kind("c", ApprovalKind::InitConfig, "", None) + .unwrap(); + let pending = db.pending().expect("pending"); + assert_eq!(pending.len(), 3, "all three kinds must be visible"); + } + + #[test] + fn unknown_kind_row_is_skipped_not_fatal() { + // A single malformed / future-kind row must not blank the + // whole list — collect_lenient skips it instead of failing. + let (_dir, path, db) = open_temp(); + let good = db + .submit_kind("good", ApprovalKind::ApplyCommit, "cafe", None) + .unwrap(); + let raw = Connection::open(&path).unwrap(); + raw.execute( + "INSERT INTO approvals (agent, kind, commit_ref, requested_at, status) + VALUES ('weird', 'from_the_future', '', 0, 'pending')", + [], + ) + .unwrap(); + let pending = db + .pending() + .expect("pending() must survive an unparseable row"); + assert_eq!(pending.len(), 1); + assert_eq!(pending[0].id, good); + } +}