|
2 | 2 | from unittest.mock import patch
|
3 | 3 | from datetime import datetime, timezone
|
4 | 4 |
|
| 5 | +from todo.exceptions.team_exceptions import ( |
| 6 | + CannotRemoveOwnerException, |
| 7 | + CannotRemoveTeamPOCException, |
| 8 | + NotTeamAdminException, |
| 9 | +) |
5 | 10 | from todo.services.team_service import TeamService
|
6 | 11 | from todo.dto.responses.get_user_teams_response import GetUserTeamsResponse
|
7 | 12 | from todo.models.team import TeamModel, UserTeamDetailsModel
|
8 | 13 | from todo.models.common.pyobjectid import PyObjectId
|
| 14 | +from todo.dto.user_dto import UserDTO |
| 15 | +from todo.dto.team_dto import TeamDTO |
9 | 16 |
|
10 | 17 |
|
11 | 18 | class TeamServiceTests(TestCase):
|
12 | 19 | def setUp(self):
|
13 | 20 | self.user_id = "507f1f77bcf86cd799439011"
|
14 | 21 | self.team_id = "507f1f77bcf86cd799439012"
|
15 |
| - |
| 22 | + self.poc_id = "507f1f77bcf86cd799439014" |
| 23 | + self.admin_id = "507f1f77bcf86cd799439015" |
| 24 | + self.member_id = "507f1f77bcf86cd799439016" |
16 | 25 | # Mock team model
|
17 | 26 | self.team_model = TeamModel(
|
18 | 27 | id=PyObjectId(self.team_id),
|
19 | 28 | name="Test Team",
|
20 | 29 | description="Test Description",
|
21 |
| - poc_id=PyObjectId(self.user_id), |
| 30 | + poc_id=PyObjectId(self.poc_id), |
22 | 31 | invite_code="TEST123",
|
23 | 32 | created_by=PyObjectId(self.user_id),
|
24 | 33 | updated_by=PyObjectId(self.user_id),
|
25 | 34 | created_at=datetime.now(timezone.utc),
|
26 | 35 | updated_at=datetime.now(timezone.utc),
|
27 | 36 | )
|
28 | 37 |
|
| 38 | + self.user_details = [ |
| 39 | + UserDTO(id=self.user_id, name="Test User 1", addedOn=datetime.now(timezone.utc), tasksAssignedCount=2), |
| 40 | + UserDTO(id=self.poc_id, name="Test User 2", addedOn=datetime.now(timezone.utc), tasksAssignedCount=1), |
| 41 | + UserDTO(id=self.admin_id, name="Test User 3", addedOn=datetime.now(timezone.utc), tasksAssignedCount=2), |
| 42 | + UserDTO(id=self.member_id, name="Test User 4", addedOn=datetime.now(timezone.utc), tasksAssignedCount=1), |
| 43 | + ] |
| 44 | + |
| 45 | + self.team_details = TeamDTO( |
| 46 | + id=self.team_id, |
| 47 | + name="Test Team", |
| 48 | + description="Test Description", |
| 49 | + poc_id=self.poc_id, |
| 50 | + invite_code="TEST123", |
| 51 | + created_by=self.user_id, |
| 52 | + updated_by=self.user_id, |
| 53 | + created_at=datetime.now(timezone.utc), |
| 54 | + updated_at=datetime.now(timezone.utc), |
| 55 | + ) |
| 56 | + |
29 | 57 | # Mock user team details model
|
30 | 58 | self.user_team_details = UserTeamDetailsModel(
|
31 | 59 | id=PyObjectId("507f1f77bcf86cd799439013"),
|
@@ -185,3 +213,90 @@ def test_join_team_by_invite_code_already_member(self, mock_get_by_user_id, mock
|
185 | 213 | with self.assertRaises(ValueError) as context:
|
186 | 214 | TeamService.join_team_by_invite_code("TEST123", self.user_id)
|
187 | 215 | self.assertIn("already a member", str(context.exception))
|
| 216 | + |
| 217 | + @patch("todo.services.user_service.UserService.get_users_by_team_id") |
| 218 | + @patch("todo.services.team_service.TeamService.get_team_by_id") |
| 219 | + def test_cannot_remove_owner(self, mock_get_by_team_id, mock_get_users_by_team_id): |
| 220 | + """Test cannot remove team owner""" |
| 221 | + mock_get_users_by_team_id.return_value = self.user_details |
| 222 | + mock_get_by_team_id.return_value = self.team_details |
| 223 | + with self.assertRaises(CannotRemoveOwnerException): |
| 224 | + TeamService._validate_remove_member_permissions(self.user_id, self.team_id, self.user_id) |
| 225 | + |
| 226 | + @patch("todo.services.user_service.UserService.get_users_by_team_id") |
| 227 | + @patch("todo.services.team_service.TeamService.get_team_by_id") |
| 228 | + def test_cannot_remove_poc(self, mock_get_by_team_id, mock_get_users_by_team_id): |
| 229 | + """Test cannot remove team POC""" |
| 230 | + mock_get_users_by_team_id.return_value = self.user_details |
| 231 | + mock_get_by_team_id.return_value = self.team_details |
| 232 | + |
| 233 | + with self.assertRaises(CannotRemoveTeamPOCException): |
| 234 | + TeamService._validate_remove_member_permissions(self.poc_id, self.team_id, self.user_id) |
| 235 | + |
| 236 | + @patch("todo.services.user_service.UserService.get_users_by_team_id") |
| 237 | + @patch("todo.services.team_service.TeamService.get_team_by_id") |
| 238 | + def test_normal_member_cannot_remove_member(self, mock_get_by_team_id, mock_get_users_by_team_id): |
| 239 | + mock_get_users_by_team_id.return_value = self.user_details |
| 240 | + mock_get_by_team_id.return_value = self.team_details |
| 241 | + |
| 242 | + with self.assertRaises(NotTeamAdminException): |
| 243 | + TeamService._validate_remove_member_permissions(self.admin_id, self.team_id, self.member_id) |
| 244 | + |
| 245 | + @patch("todo.services.user_service.UserService.get_users_by_team_id") |
| 246 | + @patch("todo.services.team_service.TeamService.get_team_by_id") |
| 247 | + def test_team_or_user_not_found(self, mock_get_by_team_id, mock_get_users_by_team_id): |
| 248 | + mock_get_users_by_team_id.return_value = self.user_details |
| 249 | + mock_get_by_team_id.return_value = self.team_details |
| 250 | + |
| 251 | + with self.assertRaises(TeamService.TeamOrUserNotFound): |
| 252 | + TeamService._validate_remove_member_permissions("not-existing-member", self.team_id, self.member_id) |
| 253 | + |
| 254 | + @patch("todo.services.task_assignment_service.TaskAssignmentService.reassign_tasks_from_user_to_team") |
| 255 | + @patch("todo.services.user_role_service.UserRoleService.remove_all_user_roles_for_team") |
| 256 | + @patch("todo.repositories.audit_log_repository.AuditLogRepository.create") |
| 257 | + @patch("todo.repositories.user_team_details_repository.UserTeamDetailsRepository.remove_member_from_team") |
| 258 | + @patch("todo.services.team_service.TeamService._validate_remove_member_permissions") |
| 259 | + def test_admin_can_remove_member_successfully( |
| 260 | + self, mock_validate, mock_remove_member, mock_audit_log_create, mock_remove_roles, mock_reassign_tasks |
| 261 | + ): |
| 262 | + mock_validate.return_value = None |
| 263 | + mock_remove_member.return_value = True |
| 264 | + mock_remove_roles.return_value = True |
| 265 | + mock_reassign_tasks.return_value = True |
| 266 | + |
| 267 | + result = TeamService.remove_member_from_team(self.member_id, self.team_id, self.admin_id) |
| 268 | + |
| 269 | + self.assertTrue(result) |
| 270 | + mock_remove_member.assert_called_once_with(user_id=self.member_id, team_id=self.team_id) |
| 271 | + mock_remove_roles.assert_called_once() |
| 272 | + mock_reassign_tasks.assert_called_once() |
| 273 | + mock_audit_log_create.assert_called_once() |
| 274 | + log_entry = mock_audit_log_create.call_args[0][0] |
| 275 | + self.assertEqual(log_entry.action, "member_removed_from_team") |
| 276 | + self.assertEqual(str(log_entry.team_id), self.team_id) |
| 277 | + self.assertEqual(str(log_entry.performed_by), self.admin_id) |
| 278 | + |
| 279 | + @patch("todo.services.task_assignment_service.TaskAssignmentService.reassign_tasks_from_user_to_team") |
| 280 | + @patch("todo.services.user_role_service.UserRoleService.remove_all_user_roles_for_team") |
| 281 | + @patch("todo.repositories.audit_log_repository.AuditLogRepository.create") |
| 282 | + @patch("todo.repositories.user_team_details_repository.UserTeamDetailsRepository.remove_member_from_team") |
| 283 | + @patch("todo.services.team_service.TeamService._validate_remove_member_permissions") |
| 284 | + def test_user_can_remove_themselves( |
| 285 | + self, mock_validate, mock_remove_member, mock_audit_log_create, mock_remove_roles, mock_reassign_tasks |
| 286 | + ): |
| 287 | + mock_validate.return_value = None |
| 288 | + mock_remove_member.return_value = True |
| 289 | + mock_remove_roles.return_value = True |
| 290 | + mock_reassign_tasks.return_value = True |
| 291 | + |
| 292 | + result = TeamService.remove_member_from_team(self.member_id, self.team_id, self.member_id) |
| 293 | + |
| 294 | + self.assertTrue(result) |
| 295 | + mock_remove_member.assert_called_once_with(user_id=self.member_id, team_id=self.team_id) |
| 296 | + mock_remove_roles.assert_called_once_with(self.member_id, self.team_id) |
| 297 | + mock_reassign_tasks.assert_called_once_with(self.member_id, self.team_id, self.member_id) |
| 298 | + mock_audit_log_create.assert_called_once() |
| 299 | + log_entry = mock_audit_log_create.call_args[0][0] |
| 300 | + self.assertEqual(log_entry.action, "member_left_team") |
| 301 | + self.assertEqual(str(log_entry.team_id), self.team_id) |
| 302 | + self.assertEqual(str(log_entry.performed_by), self.member_id) |
0 commit comments