use super::*;
use crate::task::Blocker;
use crate::taskfile::write_task;
use tempfile::TempDir;
fn ball(parent: Option<&str>, gates: &[&str]) -> Task {
Task {
title: "T".into(),
parent: parent.map(str::to_string),
blockers: gates.iter().map(|id| Blocker { id: (*id).to_string(), on: Verb::Close }).collect(),
..Task::default()
}
}
fn store(balls: &[(&str, Task)]) -> TempDir {
let tmp = TempDir::new().unwrap();
for (id, task) in balls {
write_task(tmp.path(), id, task).unwrap();
}
tmp
}
#[test]
fn close_gating_the_parent_is_what_declares_nesting() {
assert!(close_gated("bl-kid", &ball(None, &["bl-kid"])));
assert!(!close_gated("bl-kid", &ball(None, &["bl-other"]))); assert!(!close_gated("bl-kid", &ball(None, &[]))); let claim_gated = Task { blockers: vec![Blocker { id: "bl-kid".into(), on: Verb::Claim }], ..Task::default() };
assert!(!close_gated("bl-kid", &claim_gated));
}
#[test]
fn a_ball_close_gating_its_live_parent_targets_that_parent() {
let tmp = store(&[("bl-epic", ball(None, &["bl-kid"]))]);
let kid = ball(Some("bl-epic"), &[]);
assert_eq!(derive(tmp.path(), "bl-kid", Some(&kid)), Some("bl-epic".into()));
}
#[test]
fn nesting_needs_both_coordinates_so_either_alone_delivers_flat() {
let ungated = store(&[("bl-epic", ball(None, &[]))]);
let kid = ball(Some("bl-epic"), &[]);
assert_eq!(derive(ungated.path(), "bl-kid", Some(&kid)), None);
let gated = store(&[("bl-other", ball(None, &["bl-kid"]))]);
let orphan = ball(None, &[]);
assert_eq!(derive(gated.path(), "bl-kid", Some(&orphan)), None);
}
#[test]
fn a_closed_parent_gates_nothing_and_create_has_no_ball_at_all() {
let empty = store(&[]);
let kid = ball(Some("bl-gone"), &[]);
assert_eq!(derive(empty.path(), "bl-kid", Some(&kid)), None);
assert_eq!(derive(empty.path(), "bl-kid", None), None);
}