ito_core/
backend_task_repository.rs1use ito_domain::backend::BackendTaskReader;
8use ito_domain::errors::DomainResult;
9use ito_domain::tasks::{TaskRepository as DomainTaskRepository, TasksParseResult};
10
11pub struct BackendTaskRepository<R: BackendTaskReader> {
16 reader: R,
17}
18
19impl<R: BackendTaskReader> BackendTaskRepository<R> {
20 pub fn new(reader: R) -> Self {
22 Self { reader }
23 }
24}
25
26impl<R: BackendTaskReader> DomainTaskRepository for BackendTaskRepository<R> {
27 fn load_tasks(&self, change_id: &str) -> DomainResult<TasksParseResult> {
28 let content = self.reader.load_tasks_content(change_id)?;
29 let Some(content) = content else {
30 return Ok(TasksParseResult::empty());
31 };
32
33 Ok(ito_domain::tasks::parse_tasks_tracking_file(&content))
34 }
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40 use ito_domain::errors::DomainResult;
41
42 struct FakeTaskReader {
44 content: Option<String>,
45 }
46
47 impl FakeTaskReader {
48 fn with_content(content: &str) -> Self {
49 Self {
50 content: Some(content.to_string()),
51 }
52 }
53
54 fn empty() -> Self {
55 Self { content: None }
56 }
57 }
58
59 impl BackendTaskReader for FakeTaskReader {
60 fn load_tasks_content(&self, _change_id: &str) -> DomainResult<Option<String>> {
61 Ok(self.content.clone())
62 }
63 }
64
65 #[test]
66 fn missing_tasks_returns_empty() {
67 let reader = FakeTaskReader::empty();
68 let repo = BackendTaskRepository::new(reader);
69
70 let result = repo.load_tasks("test-change").unwrap();
71 assert_eq!(result.progress.total, 0);
72 assert_eq!(result.progress.complete, 0);
73 }
74
75 #[test]
76 fn checkbox_tasks_parsed_correctly() {
77 let reader = FakeTaskReader::with_content("# Tasks\n- [x] Done\n- [ ] Pending\n");
78 let repo = BackendTaskRepository::new(reader);
79
80 let result = repo.load_tasks("test-change").unwrap();
81 assert_eq!(result.progress.total, 2);
82 assert_eq!(result.progress.complete, 1);
83 }
84
85 #[test]
86 fn get_task_counts_from_backend() {
87 let reader = FakeTaskReader::with_content("# Tasks\n- [x] A\n- [x] B\n- [ ] C\n");
88 let repo = BackendTaskRepository::new(reader);
89
90 let (completed, total) = repo.get_task_counts("test-change").unwrap();
91 assert_eq!(completed, 2);
92 assert_eq!(total, 3);
93 }
94
95 #[test]
96 fn has_tasks_detects_content() {
97 let reader = FakeTaskReader::with_content("# Tasks\n- [ ] A\n");
98 let repo = BackendTaskRepository::new(reader);
99
100 assert!(repo.has_tasks("test-change").unwrap());
101 }
102
103 #[test]
104 fn has_tasks_empty_content() {
105 let reader = FakeTaskReader::empty();
106 let repo = BackendTaskRepository::new(reader);
107
108 assert!(!repo.has_tasks("test-change").unwrap());
109 }
110}