use kcode_credits::Credits;
use kcode_task_board::{CreateTask, Error, TaskBoard, UpdateTask};
#[rustfmt::skip]
fn task(title: &str, parents: Vec<String>, children: Vec<String>) -> CreateTask {
CreateTask { title: title.into(), description: String::new(), user_id: "user-a".into(), credits: 3, category_ids: vec![], parent_ids: parents, child_ids: children, related_ids: vec![] }
}
#[test]
fn combined_update_and_completion_archives_awards_and_pushes_only_final_parent_children() {
let directory = tempfile::tempdir().unwrap();
let credits = Credits::open(directory.path().join("credits.sqlite3")).unwrap();
let board = TaskBoard::open(directory.path().join("tasks.sqlite3"), credits.clone()).unwrap();
let child = board.create_task(task("child", vec![], vec![])).unwrap();
let mut parent = task("parent", vec![], vec![child.id.clone()]);
parent.credits = 0;
let parent = board.create_task(parent).unwrap();
let outcome = board
.update_task(UpdateTask {
task_id: parent.id.clone(),
credits: Some(150),
complete: true,
..Default::default()
})
.unwrap();
assert_eq!((outcome.completed, outcome.credits_awarded), (true, 150));
assert!(board.task(&parent.id).is_err());
assert_eq!(board.top_orphan().unwrap().unwrap().id, child.id);
assert_eq!(credits.balance("user-a").unwrap().amount, 150);
}
#[test]
fn updating_the_top_orphan_returns_it_to_the_world() {
let directory = tempfile::tempdir().unwrap();
let credits = Credits::open(directory.path().join("credits.sqlite3")).unwrap();
let board = TaskBoard::open(directory.path().join("tasks.sqlite3"), credits).unwrap();
let child = board.create_task(task("child", vec![], vec![])).unwrap();
let parent = board
.create_task(task("parent", vec![], vec![child.id.clone()]))
.unwrap();
board.remove_task(&parent.id).unwrap();
let updated = board
.update_task(UpdateTask {
task_id: child.id.clone(),
title: Some("independent".into()),
..Default::default()
})
.unwrap();
assert_eq!(updated.task.unwrap().title, "independent");
assert!(board.top_orphan().unwrap().is_none());
}
#[test]
fn multiple_parents_cycles_related_edges_and_lifo_orphans_work_together() {
let directory = tempfile::tempdir().unwrap();
let credits = Credits::open(directory.path().join("credits.sqlite3")).unwrap();
let board = TaskBoard::open(directory.path().join("tasks.sqlite3"), credits).unwrap();
let first = board.create_task(task("first", vec![], vec![])).unwrap();
let second = board.create_task(task("second", vec![], vec![])).unwrap();
let parent_a = board
.create_task(task("parent a", vec![], vec![first.id.clone()]))
.unwrap();
let parent_b = board
.create_task(task("parent b", vec![], vec![first.id.clone()]))
.unwrap();
board
.update_task(UpdateTask {
task_id: first.id.clone(),
child_ids: Some(vec![second.id.clone()]),
related_ids: Some(vec![second.id.clone()]),
..Default::default()
})
.unwrap();
board
.update_task(UpdateTask {
task_id: second.id.clone(),
child_ids: Some(vec![first.id.clone()]),
..Default::default()
})
.unwrap();
assert_eq!(board.task(&second.id).unwrap().related[0].id, first.id);
board
.update_task(UpdateTask {
task_id: second.id.clone(),
child_ids: Some(vec![]),
..Default::default()
})
.unwrap();
board
.update_task(UpdateTask {
task_id: first.id.clone(),
child_ids: Some(vec![]),
..Default::default()
})
.unwrap();
board.remove_task(&parent_a.id).unwrap();
assert!(board.top_orphan().unwrap().is_none());
board.remove_task(&parent_b.id).unwrap();
assert_eq!(board.top_orphan().unwrap().unwrap().id, first.id);
let later_parent = board
.create_task(task("later", vec![], vec![second.id.clone()]))
.unwrap();
board.remove_task(&later_parent.id).unwrap();
assert_eq!(board.top_orphan().unwrap().unwrap().id, second.id);
assert!(matches!(
board.remove_task(&first.id),
Err(Error::NotTopOrphan)
));
board
.update_task(UpdateTask {
task_id: second.id,
..Default::default()
})
.unwrap();
assert_eq!(board.top_orphan().unwrap().unwrap().id, first.id);
assert!(first.id.starts_with("task-id-") && first.id.len() == 20);
}