//! Toggling a task line: the status, the completion date and the deletion. use notescraft_tasks::{StatusType, ToggleCfg, next_status, status_type, toggle}; use notescraft_templates::Date; /// The day the tests toggle on. fn today() -> Date { Date::new(2026, 10, 22).expect("a valid date") } /// The default configuration of a toggle. fn cfg() -> ToggleCfg { ToggleCfg::default() } #[test] fn a_todo_task_becomes_done_with_the_completion_date() { let out = toggle("- [ ] Buy milk 📅 2026-10-20", today(), &cfg()).expect("a task"); assert_eq!(out.lines, ["- [x] Buy milk 📅 2026-10-20 ✅ 2026-10-22"]); assert_eq!(out.next_index, None); } #[test] fn a_done_task_becomes_todo_and_loses_the_completion_date() { let out = toggle("- [x] Buy milk 📅 2026-10-20 ✅ 2026-10-20", today(), &cfg()).expect("a task"); assert_eq!(out.lines, ["- [ ] Buy milk 📅 2026-10-20"]); } #[test] fn the_completion_date_goes_when_it_is_not_at_the_end() { let out = toggle("- [x] Buy milk ✅ 2026-10-20 📅 2026-10-01", today(), &cfg()).expect("a task"); assert_eq!(out.lines, ["- [ ] Buy milk 📅 2026-10-01"]); } #[test] fn a_task_in_progress_becomes_done() { let out = toggle("- [/] Buy milk", today(), &cfg()).expect("a task"); assert_eq!(out.lines, ["- [x] Buy milk ✅ 2026-10-22"]); } #[test] fn a_cancelled_task_becomes_todo_and_keeps_its_cancellation_date() { let out = toggle("- [-] Buy milk ❌ 2026-10-20", today(), &cfg()).expect("a task"); assert_eq!(out.lines, ["- [ ] Buy milk ❌ 2026-10-20"]); } #[test] fn the_completion_date_is_not_written_when_it_is_turned_off() { let cfg = ToggleCfg { set_done_date: false, ..ToggleCfg::default() }; let out = toggle("- [ ] Buy milk", today(), &cfg).expect("a task"); assert_eq!(out.lines, ["- [x] Buy milk"]); } #[test] fn an_old_completion_date_is_replaced_by_today() { let out = toggle("- [ ] Buy milk ✅ 2026-01-01", today(), &cfg()).expect("a task"); assert_eq!(out.lines, ["- [x] Buy milk ✅ 2026-10-22"]); } #[test] fn a_task_that_is_dropped_on_completion_is_deleted() { let out = toggle("- [ ] Buy milk 🏁 delete", today(), &cfg()).expect("a task"); assert_eq!(out.lines, Vec::::new()); assert_eq!(out.next_index, None); } #[test] fn a_dropped_task_that_goes_back_to_todo_stays() { let out = toggle("- [x] Buy milk 🏁 delete", today(), &cfg()).expect("a task"); assert_eq!(out.lines, ["- [ ] Buy milk 🏁 delete"]); } #[test] fn the_text_outside_the_signifiers_is_byte_preserved() { let original = " * [ ] Buy milk #home 📅 2026-10-20"; let out = toggle(original, today(), &cfg()).expect("a task"); let result = out.lines.first().expect("one line"); let open = original.find('[').expect("a box"); let close = original.find(']').expect("a box"); assert_eq!(&result[..open], &original[..open]); assert_eq!(&result[open..open + 2], "[x"); assert!(result[open + 2..].starts_with(&original[close..])); assert_eq!(result, " * [x] Buy milk #home 📅 2026-10-20 ✅ 2026-10-22"); } #[test] fn the_indent_and_the_marker_are_kept() { let out = toggle(" 1. [ ] Buy milk", today(), &cfg()).expect("a task"); assert_eq!(out.lines, [" 1. [x] Buy milk ✅ 2026-10-22"]); } #[test] fn a_recurring_task_gets_its_next_occurrence() { let out = toggle("- [ ] Water 🔁 every week 📅 2026-10-20", today(), &cfg()).expect("a task"); assert_eq!(out.lines, ["- [ ] Water 🔁 every week 📅 2026-10-27", "- [x] Water 🔁 every week 📅 2026-10-20 ✅ 2026-10-22"]); assert_eq!(out.next_index, Some(0)); } #[test] fn a_line_that_is_not_a_task_has_no_toggle() { assert!(toggle("Buy milk", today(), &cfg()).is_none()); } #[test] fn the_status_kinds_are_known() { assert_eq!(status_type(' '), StatusType::Todo); assert_eq!(status_type('/'), StatusType::InProgress); assert_eq!(status_type('x'), StatusType::Done); assert_eq!(status_type('X'), StatusType::Done); assert_eq!(status_type('-'), StatusType::Cancelled); assert_eq!(status_type('?'), StatusType::Todo); } #[test] fn the_next_status_follows_the_plugin() { assert_eq!(next_status(' '), 'x'); assert_eq!(next_status('/'), 'x'); assert_eq!(next_status('x'), ' '); assert_eq!(next_status('X'), ' '); assert_eq!(next_status('-'), ' '); assert_eq!(next_status('?'), 'x'); } #[test] fn the_default_configuration_writes_the_completion_date() { let cfg = ToggleCfg::default(); assert!(cfg.set_done_date); assert!(!cfg.remove_scheduled_on_recurrence); assert!(!cfg.next_below); }