Skip to main content

max / goingson

6.2 KB · 204 lines History Blame Raw
1 //! Integration tests for project commands.
2
3 use goingson_core::{NewProject, ProjectStatus, ProjectType};
4
5 use crate::test_utils::setup_test_state;
6
7 #[tokio::test]
8 async fn test_create_project_success() {
9 let (state, user_id) = setup_test_state().await;
10
11 let new_project = NewProject {
12 name: "My Project".to_string(),
13 description: "A test project".to_string(),
14 project_type: ProjectType::SideProject,
15 status: ProjectStatus::Active,
16 };
17
18 let result = state.projects.create(user_id, new_project).await;
19 assert!(result.is_ok());
20
21 let project = result.unwrap();
22 assert_eq!(project.name, "My Project");
23 assert_eq!(project.description, "A test project");
24 assert_eq!(project.project_type, ProjectType::SideProject);
25 assert_eq!(project.status, ProjectStatus::Active);
26 }
27
28 #[tokio::test]
29 async fn test_list_projects() {
30 let (state, user_id) = setup_test_state().await;
31
32 // Create two projects
33 let project1 = NewProject {
34 name: "Project 1".to_string(),
35 description: "First".to_string(),
36 project_type: ProjectType::Job,
37 status: ProjectStatus::Active,
38 };
39 state.projects.create(user_id, project1).await.unwrap();
40
41 let project2 = NewProject {
42 name: "Project 2".to_string(),
43 description: "Second".to_string(),
44 project_type: ProjectType::Company,
45 status: ProjectStatus::OnHold,
46 };
47 state.projects.create(user_id, project2).await.unwrap();
48
49 // List all projects
50 let projects = state.projects.list_all(user_id).await.unwrap();
51 assert_eq!(projects.len(), 2);
52 }
53
54 #[tokio::test]
55 async fn test_get_project_by_id() {
56 let (state, user_id) = setup_test_state().await;
57
58 let new_project = NewProject {
59 name: "Findable Project".to_string(),
60 description: "Can be found".to_string(),
61 project_type: ProjectType::Essay,
62 status: ProjectStatus::Active,
63 };
64 let created = state.projects.create(user_id, new_project).await.unwrap();
65
66 let fetched = state.projects.get_by_id(created.id, user_id).await.unwrap();
67 assert!(fetched.is_some());
68 assert_eq!(fetched.unwrap().name, "Findable Project");
69 }
70
71 #[tokio::test]
72 async fn test_get_nonexistent_project() {
73 let (state, user_id) = setup_test_state().await;
74
75 let nonexistent_id = goingson_core::ProjectId::new();
76 let result = state.projects.get_by_id(nonexistent_id, user_id).await.unwrap();
77 assert!(result.is_none());
78 }
79
80 #[tokio::test]
81 async fn test_update_project() {
82 let (state, user_id) = setup_test_state().await;
83
84 let new_project = NewProject {
85 name: "Original Name".to_string(),
86 description: "Original".to_string(),
87 project_type: ProjectType::SideProject,
88 status: ProjectStatus::Active,
89 };
90 let created = state.projects.create(user_id, new_project).await.unwrap();
91
92 // Update the project
93 let update = goingson_core::UpdateProject {
94 name: "Updated Name".to_string(),
95 description: "Updated description".to_string(),
96 project_type: ProjectType::Job,
97 status: ProjectStatus::OnHold,
98 };
99 let updated = state
100 .projects
101 .update(created.id, user_id, update)
102 .await
103 .unwrap();
104
105 assert!(updated.is_some());
106 let project = updated.unwrap();
107 assert_eq!(project.name, "Updated Name");
108 assert_eq!(project.description, "Updated description");
109 assert_eq!(project.project_type, ProjectType::Job);
110 assert_eq!(project.status, ProjectStatus::OnHold);
111 }
112
113 #[tokio::test]
114 async fn test_delete_project() {
115 let (state, user_id) = setup_test_state().await;
116
117 let new_project = NewProject {
118 name: "To Delete".to_string(),
119 description: "Will be deleted".to_string(),
120 project_type: ProjectType::Other,
121 status: ProjectStatus::Active,
122 };
123 let created = state.projects.create(user_id, new_project).await.unwrap();
124
125 // Delete the project
126 let deleted = state.projects.delete(created.id, user_id).await.unwrap();
127 assert!(deleted);
128
129 // Verify it's gone
130 let fetched = state.projects.get_by_id(created.id, user_id).await.unwrap();
131 assert!(fetched.is_none());
132 }
133
134 #[tokio::test]
135 async fn test_find_project_by_name() {
136 let (state, user_id) = setup_test_state().await;
137
138 let new_project = NewProject {
139 name: "Unique Project Name".to_string(),
140 description: "Findable by name".to_string(),
141 project_type: ProjectType::Article,
142 status: ProjectStatus::Active,
143 };
144 state.projects.create(user_id, new_project).await.unwrap();
145
146 // Find by exact name
147 let found = state
148 .projects
149 .find_by_name(user_id, "Unique Project Name")
150 .await
151 .unwrap();
152 assert!(found.is_some());
153 assert_eq!(found.unwrap().name, "Unique Project Name");
154
155 // Find non-existent name
156 let not_found = state
157 .projects
158 .find_by_name(user_id, "Does Not Exist")
159 .await
160 .unwrap();
161 assert!(not_found.is_none());
162 }
163
164 #[tokio::test]
165 async fn test_project_isolation_between_users() {
166 let (state, user1_id) = setup_test_state().await;
167
168 // Create a second user
169 let user2_id = goingson_core::UserId::new();
170 let now = chrono::Utc::now().format("%Y-%m-%d %H:%M:%S").to_string();
171 sqlx::query(
172 "INSERT INTO users (id, email, password_hash, display_name, created_at) VALUES (?, ?, ?, ?, ?)"
173 )
174 .bind(user2_id.to_string())
175 .bind("user2@example.com")
176 .bind("password-hash")
177 .bind("User 2")
178 .bind(&now)
179 .execute(&state.pool)
180 .await
181 .unwrap();
182
183 // User 1 creates a project
184 let project = NewProject {
185 name: "User 1 Project".to_string(),
186 description: "Belongs to user 1".to_string(),
187 project_type: ProjectType::SideProject,
188 status: ProjectStatus::Active,
189 };
190 let created = state.projects.create(user1_id, project).await.unwrap();
191
192 // User 1 can see it
193 let user1_projects = state.projects.list_all(user1_id).await.unwrap();
194 assert_eq!(user1_projects.len(), 1);
195
196 // User 2 cannot see it
197 let user2_projects = state.projects.list_all(user2_id).await.unwrap();
198 assert_eq!(user2_projects.len(), 0);
199
200 // User 2 cannot access by ID
201 let fetched = state.projects.get_by_id(created.id, user2_id).await.unwrap();
202 assert!(fetched.is_none());
203 }
204