Skip to main content

max / goingson

5.5 KB · 177 lines History Blame Raw
1 //! Integration tests for task commands.
2
3 use goingson_core::{NewTask, Priority};
4
5 use crate::test_utils::{create_test_project, setup_test_state};
6
7 #[tokio::test]
8 async fn test_create_task_success() {
9 let (state, user_id) = setup_test_state().await;
10 let project_id = create_test_project(&state, user_id).await;
11
12 let new_task = NewTask::builder("Test task description")
13 .project_id(project_id)
14 .priority(Priority::Medium)
15 .tag("test")
16 .build();
17
18 let result = state.tasks.create(user_id, new_task).await;
19 assert!(result.is_ok());
20
21 let task = result.unwrap();
22 assert_eq!(task.description, "Test task description");
23 assert_eq!(task.project_id, Some(project_id));
24 assert_eq!(task.priority, Priority::Medium);
25 assert_eq!(task.tags, vec!["test"]);
26 }
27
28 #[tokio::test]
29 async fn test_create_task_without_project() {
30 let (state, user_id) = setup_test_state().await;
31
32 let new_task = NewTask::builder("Standalone task")
33 .priority(Priority::High)
34 .build();
35
36 let result = state.tasks.create(user_id, new_task).await;
37 assert!(result.is_ok());
38
39 let task = result.unwrap();
40 assert_eq!(task.description, "Standalone task");
41 assert!(task.project_id.is_none());
42 }
43
44 #[tokio::test]
45 async fn test_complete_task() {
46 let (state, user_id) = setup_test_state().await;
47
48 let new_task = NewTask::builder("Task to complete")
49 .priority(Priority::Low)
50 .build();
51
52 let task = state.tasks.create(user_id, new_task).await.unwrap();
53
54 let completed = state.tasks.complete(task.id, user_id).await.unwrap();
55 assert!(completed.is_some()); // Returns the completed task
56
57 // Verify status changed
58 let fetched = state.tasks.get_by_id(task.id, user_id).await.unwrap().unwrap();
59 assert_eq!(fetched.status, goingson_core::TaskStatus::Completed);
60 }
61
62 #[tokio::test]
63 async fn test_list_tasks_filtered_by_status() {
64 let (state, user_id) = setup_test_state().await;
65
66 // Create pending task
67 let pending = NewTask::builder("Pending task")
68 .priority(Priority::Medium)
69 .build();
70 state.tasks.create(user_id, pending).await.unwrap();
71
72 // Create and complete a task
73 let to_complete = NewTask::builder("Completed task")
74 .priority(Priority::Low)
75 .build();
76 let task = state.tasks.create(user_id, to_complete).await.unwrap();
77 state.tasks.complete(task.id, user_id).await.unwrap();
78
79 // Filter for pending only
80 let query = goingson_core::TaskFilterQuery {
81 status: Some(goingson_core::TaskStatus::Pending),
82 ..Default::default()
83 };
84
85 let (tasks, total) = state.tasks.list_filtered(user_id, query).await.unwrap();
86 assert_eq!(total, 1);
87 assert_eq!(tasks.len(), 1);
88 assert_eq!(tasks[0].description, "Pending task");
89 }
90
91 #[tokio::test]
92 async fn test_list_tasks_filtered_by_priority() {
93 let (state, user_id) = setup_test_state().await;
94
95 // Create tasks with different priorities
96 let high = NewTask::builder("High priority")
97 .priority(Priority::High)
98 .build();
99 state.tasks.create(user_id, high).await.unwrap();
100
101 let low = NewTask::builder("Low priority")
102 .priority(Priority::Low)
103 .build();
104 state.tasks.create(user_id, low).await.unwrap();
105
106 // Filter for high priority only
107 let query = goingson_core::TaskFilterQuery {
108 priority: Some(Priority::High),
109 ..Default::default()
110 };
111
112 let (tasks, total) = state.tasks.list_filtered(user_id, query).await.unwrap();
113 assert_eq!(total, 1);
114 assert_eq!(tasks[0].description, "High priority");
115 }
116
117 #[tokio::test]
118 async fn test_list_tasks_pagination() {
119 let (state, user_id) = setup_test_state().await;
120
121 // Create 5 tasks
122 for i in 0..5 {
123 let task = NewTask::builder(format!("Task {}", i))
124 .priority(Priority::Medium)
125 .urgency(5.0 - i as f64) // Decreasing urgency for predictable order
126 .build();
127 state.tasks.create(user_id, task).await.unwrap();
128 }
129
130 // Get first page (2 items)
131 let query = goingson_core::TaskFilterQuery {
132 limit: Some(2),
133 offset: Some(0),
134 ..Default::default()
135 };
136 let (tasks, total) = state.tasks.list_filtered(user_id, query).await.unwrap();
137 assert_eq!(total, 5);
138 assert_eq!(tasks.len(), 2);
139
140 // Get second page
141 let query = goingson_core::TaskFilterQuery {
142 limit: Some(2),
143 offset: Some(2),
144 ..Default::default()
145 };
146 let (tasks, _) = state.tasks.list_filtered(user_id, query).await.unwrap();
147 assert_eq!(tasks.len(), 2);
148 }
149
150 #[tokio::test]
151 async fn test_task_with_subtasks() {
152 let (state, user_id) = setup_test_state().await;
153
154 let new_task = NewTask::builder("Task with subtasks")
155 .priority(Priority::Medium)
156 .build();
157 let task = state.tasks.create(user_id, new_task).await.unwrap();
158
159 // Add subtasks
160 state.tasks.add_subtask(task.id, user_id, "Subtask 1").await.unwrap();
161 state.tasks.add_subtask(task.id, user_id, "Subtask 2").await.unwrap();
162
163 // Get task with subtasks
164 let fetched = state.tasks.get_by_id(task.id, user_id).await.unwrap().unwrap();
165 assert_eq!(fetched.subtasks.len(), 2);
166 assert_eq!(fetched.subtask_count(), 2);
167 assert_eq!(fetched.subtasks_completed(), 0);
168
169 // Complete a subtask
170 let subtask_id = fetched.subtasks[0].id;
171 state.tasks.toggle_subtask(subtask_id, user_id).await.unwrap();
172
173 // Verify completion
174 let fetched = state.tasks.get_by_id(task.id, user_id).await.unwrap().unwrap();
175 assert_eq!(fetched.subtasks_completed(), 1);
176 }
177