Skip to content

Commit d950790

Browse files
committed
Project-Teams API tests:
- Add projects-teams API endpoint tests - Fix project teams exceptions and retrieval of user id
1 parent d7de770 commit d950790

File tree

3 files changed

+258
-12
lines changed

3 files changed

+258
-12
lines changed

backend/api/projects/teams.py

+14-10
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def get(self, project_id):
3131
responses:
3232
200:
3333
description: Teams listed successfully
34-
403:
34+
401:
3535
description: Forbidden, if user is not authenticated
3636
404:
3737
description: Not found
@@ -41,6 +41,8 @@ def get(self, project_id):
4141
try:
4242
teams_dto = TeamService.get_project_teams_as_dto(project_id)
4343
return teams_dto.to_primitive(), 200
44+
except NotFound:
45+
return {"Error": "Project Not Found", "SubCode": "NotFound"}, 404
4446
except Exception as e:
4547
error_msg = f"Team GET - unhandled error: {str(e)}"
4648
current_app.logger.critical(error_msg)
@@ -85,9 +87,9 @@ def post(self, team_id, project_id):
8587
201:
8688
description: Team project assignment created
8789
401:
88-
description: Forbidden, if user is not a manager of the project
89-
403:
9090
description: Forbidden, if user is not authenticated
91+
403:
92+
description: Forbidden, if user is not a manager of the project or team
9193
404:
9294
description: Not found
9395
500:
@@ -97,7 +99,7 @@ def post(self, team_id, project_id):
9799
return {
98100
"Error": "User is not an admin or a manager for the team",
99101
"SubCode": "UserPermissionError",
100-
}, 401
102+
}, 403
101103

102104
try:
103105
role = request.get_json(force=True)["role"]
@@ -107,7 +109,7 @@ def post(self, team_id, project_id):
107109

108110
try:
109111
if not ProjectAdminService.is_user_action_permitted_on_project(
110-
token_auth.current_user, project_id
112+
token_auth.current_user(), project_id
111113
):
112114
raise ValueError()
113115
TeamService.add_team_project(team_id, project_id, role)
@@ -119,6 +121,8 @@ def post(self, team_id, project_id):
119121
},
120122
201,
121123
)
124+
except NotFound:
125+
return {"Error": "No Project Found", "SubCode": "NotFound"}, 404
122126
except ValueError:
123127
return {
124128
"Error": "User is not a manager of the project",
@@ -184,11 +188,11 @@ def patch(self, team_id, project_id):
184188

185189
try:
186190
if not ProjectAdminService.is_user_action_permitted_on_project(
187-
token_auth.current_user, project_id
191+
token_auth.current_user(), project_id
188192
):
189193
raise ValueError()
190194
TeamService.change_team_role(team_id, project_id, role)
191-
return {"Status": "Team role updated successfully."}, 200
195+
return {"Status": "Team role updated successfully"}, 200
192196
except NotFound as e:
193197
return {"Error": str(e), "SubCode": "NotFound"}, 404
194198
except ValueError:
@@ -229,17 +233,17 @@ def delete(self, team_id, project_id):
229233
200:
230234
description: Team unassigned of the project
231235
401:
232-
description: Forbidden, if user is not a manager of the project
233-
403:
234236
description: Forbidden, if user is not authenticated
237+
403:
238+
description: Forbidden, if user is not a manager of the project
235239
404:
236240
description: Not found
237241
500:
238242
description: Internal Server Error
239243
"""
240244
try:
241245
if not ProjectAdminService.is_user_action_permitted_on_project(
242-
token_auth.current_user, project_id
246+
token_auth.current_user(), project_id
243247
):
244248
raise ValueError()
245249
TeamService.delete_team_project(team_id, project_id)

backend/services/team_service.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from backend.models.dtos.stats_dto import Pagination
1717
from backend.models.postgis.message import Message, MessageType
1818
from backend.models.postgis.team import Team, TeamMembers
19-
from backend.models.postgis.project import ProjectTeams
19+
from backend.models.postgis.project import Project, ProjectTeams
2020
from backend.models.postgis.project_info import ProjectInfo
2121
from backend.models.postgis.utils import NotFound
2222
from backend.models.postgis.statuses import (
@@ -388,8 +388,12 @@ def get_projects_by_team_id(team_id: int):
388388
@staticmethod
389389
def get_project_teams_as_dto(project_id: int) -> TeamsListDTO:
390390
"""Gets all the teams for a specified project"""
391+
project = Project.get(project_id)
392+
if project is None:
393+
raise NotFound()
394+
391395
project_teams = ProjectTeams.query.filter(
392-
ProjectTeams.project_id == project_id
396+
ProjectTeams.project_id == project.id
393397
).all()
394398
teams_list_dto = TeamsListDTO()
395399

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
from tests.backend.base import BaseTestCase
2+
from tests.backend.helpers.test_helpers import (
3+
assign_team_to_project,
4+
create_canned_project,
5+
create_canned_team,
6+
return_canned_user,
7+
generate_encoded_token,
8+
TEST_TEAM_NAME,
9+
)
10+
from backend.models.postgis.statuses import UserRole, TeamRoles
11+
12+
13+
class TestProjectsTeamsAPI(BaseTestCase):
14+
def setUp(self):
15+
super().setUp()
16+
self.test_project, self.test_author = create_canned_project()
17+
self.test_author.role = UserRole.ADMIN.value
18+
self.test_team = create_canned_team()
19+
self.test_user = return_canned_user("test_user", 11111111)
20+
self.test_user.create()
21+
self.test_author_session_token = generate_encoded_token(self.test_author.id)
22+
self.test_user_session_token = generate_encoded_token(self.test_user.id)
23+
self.all_project_teams_url = f"/api/v2/projects/{self.test_project.id}/teams/"
24+
self.single_project_team_url = (
25+
f"/api/v2/projects/{self.test_project.id}/teams/{self.test_team.id}/"
26+
)
27+
self.non_existent_project_team_url = "/api/v2/projects/99/teams/99/"
28+
29+
# get
30+
def test_get_project_teams_by_unauthenticated_user_fails(self):
31+
"""
32+
Test that endpoint returns 401 when an unauthenticated user retrieves teams
33+
"""
34+
response = self.client.get(self.all_project_teams_url)
35+
response_body = response.get_json()
36+
self.assertEqual(response.status_code, 401)
37+
self.assertEqual(response_body["SubCode"], "InvalidToken")
38+
39+
def test_get_project_teams_for_non_existent_project_fails(self):
40+
"""
41+
Test that endpoint returns 404 when retrieving teams for non-existent projects
42+
"""
43+
response = self.client.get(
44+
"/api/v2/projects/99/teams/",
45+
headers={"Authorization": self.test_user_session_token},
46+
)
47+
response_body = response.get_json()
48+
self.assertEqual(response.status_code, 404)
49+
self.assertEqual(response_body["Error"], "Project Not Found")
50+
self.assertEqual(response_body["SubCode"], "NotFound")
51+
52+
def test_get_project_teams_passes(self):
53+
"""
54+
Test that endpoint returns 200 when an authenticated user retrieves teams
55+
"""
56+
response = self.client.get(
57+
self.all_project_teams_url,
58+
headers={"Authorization": self.test_user_session_token},
59+
)
60+
response_body = response.get_json()
61+
self.assertEqual(response.status_code, 200)
62+
self.assertEqual(len(response_body["teams"]), 0)
63+
self.assertEqual(response_body["teams"], [])
64+
# setup: add team to project
65+
assign_team_to_project(project=self.test_project, team=self.test_team, role=0)
66+
response = self.client.get(
67+
self.all_project_teams_url,
68+
headers={"Authorization": self.test_user_session_token},
69+
)
70+
response_body = response.get_json()
71+
self.assertEqual(response.status_code, 200)
72+
self.assertEqual(len(response_body["teams"]), 1)
73+
self.assertEqual(response_body["teams"][0]["name"], TEST_TEAM_NAME)
74+
self.assertEqual(response_body["teams"][0]["role"], 0)
75+
76+
# post
77+
def test_assign_team_to_project_by_unauthenticated_user_fails(self):
78+
"""
79+
Test that endpoint returns 401 when unauthenticated user assigns team to project
80+
"""
81+
response = self.client.post(
82+
self.single_project_team_url, json={"role": TeamRoles.MAPPER.name}
83+
)
84+
response_body = response.get_json()
85+
self.assertEqual(response.status_code, 401)
86+
self.assertEqual(response_body["SubCode"], "InvalidToken")
87+
88+
def test_assign_team_to_project_by_non_admin_fails(self):
89+
"""
90+
Test that endpoint returns 403 when non admin assigns team to a project
91+
"""
92+
response = self.client.post(
93+
self.single_project_team_url,
94+
json={"role": TeamRoles.MAPPER.name},
95+
headers={"Authorization": self.test_user_session_token},
96+
)
97+
response_body = response.get_json()
98+
self.assertEqual(response.status_code, 403)
99+
self.assertEqual(
100+
response_body["Error"], "User is not an admin or a manager for the team"
101+
)
102+
self.assertEqual(response_body["SubCode"], "UserPermissionError")
103+
104+
def test_assign_team_to_non_existent_project_fails(self):
105+
"""
106+
Test that endpoint returns 404 when admin assigns a team to a non-existent project
107+
"""
108+
response = self.client.post(
109+
f"/api/v2/projects/99/teams/{self.test_team.id}/",
110+
json={"role": TeamRoles.MAPPER.name},
111+
headers={"Authorization": self.test_author_session_token},
112+
)
113+
response_body = response.get_json()
114+
self.assertEqual(response.status_code, 404)
115+
self.assertEqual(response_body["Error"], "No Project Found")
116+
self.assertEqual(response_body["SubCode"], "NotFound")
117+
118+
def test_assign_team_to_project_by_admin_passes(self):
119+
"""
120+
Test that endpoint returns 201 when admin successfully assigns a team to a project
121+
"""
122+
response = self.client.post(
123+
self.single_project_team_url,
124+
json={"role": TeamRoles.MAPPER.name},
125+
headers={"Authorization": self.test_author_session_token},
126+
)
127+
response_body = response.get_json()
128+
self.assertEqual(response.status_code, 201)
129+
self.assertEqual(
130+
response_body["Success"],
131+
f"Team {self.test_team.id} assigned to project {self.test_project.id} with role MAPPER",
132+
)
133+
134+
# patch
135+
def test_update_team_role_by_unauthenticated_user_fails(self):
136+
"""
137+
Test that endpoint returns 401 when unauthenticated user updates project team role
138+
"""
139+
response = self.client.patch(
140+
self.single_project_team_url, json={"role": TeamRoles.MAPPER.name}
141+
)
142+
response_body = response.get_json()
143+
self.assertEqual(response.status_code, 401)
144+
self.assertEqual(response_body["SubCode"], "InvalidToken")
145+
146+
def test_update_team_role_by_non_admin_fails(self):
147+
"""
148+
Test that endpoint returns 403 when non admin updates project team role
149+
"""
150+
response = self.client.patch(
151+
self.single_project_team_url,
152+
json={"role": TeamRoles.MAPPER.name},
153+
headers={"Authorization": self.test_user_session_token},
154+
)
155+
response_body = response.get_json()
156+
self.assertEqual(response.status_code, 403)
157+
self.assertEqual(response_body["Error"], "User is not a manager of the project")
158+
self.assertEqual(response_body["SubCode"], "UserPermissionError")
159+
160+
def test_update_team_role_of_non_existent_project_fails(self):
161+
"""
162+
Test that endpoint returns 404 when admin updates non-existent project team role
163+
"""
164+
response = self.client.patch(
165+
self.non_existent_project_team_url,
166+
json={"role": TeamRoles.MAPPER.name},
167+
headers={"Authorization": self.test_author_session_token},
168+
)
169+
response_body = response.get_json()
170+
self.assertEqual(response.status_code, 404)
171+
self.assertEqual(response_body["SubCode"], "NotFound")
172+
173+
def test_update_team_role_by_admin_passes(self):
174+
"""
175+
Test that endpoint returns 200 when admin successfully updates project team role
176+
"""
177+
assign_team_to_project(
178+
self.test_project, self.test_team, TeamRoles.MAPPER.value
179+
)
180+
response = self.client.patch(
181+
self.single_project_team_url,
182+
json={"role": TeamRoles.VALIDATOR.name},
183+
headers={"Authorization": self.test_author_session_token},
184+
)
185+
response_body = response.get_json()
186+
self.assertEqual(response.status_code, 200)
187+
self.assertEqual(response_body["Status"], "Team role updated successfully")
188+
189+
# delete
190+
def test_delete_project_team_by_unauthenticated_user_fails(self):
191+
"""
192+
Test that endpoint returns 401 when unauthenticated user deletes project team
193+
"""
194+
response = self.client.delete(self.single_project_team_url)
195+
response_body = response.get_json()
196+
self.assertEqual(response.status_code, 401)
197+
self.assertEqual(response_body["SubCode"], "InvalidToken")
198+
199+
def test_delete_project_team_by_non_admin_fails(self):
200+
"""
201+
Test that endpoint returns 403 when non admin deletes project team
202+
"""
203+
response = self.client.delete(
204+
self.single_project_team_url,
205+
headers={"Authorization": self.test_user_session_token},
206+
)
207+
response_body = response.get_json()
208+
self.assertEqual(response.status_code, 403)
209+
self.assertEqual(response_body["Error"], "User is not a manager of the project")
210+
self.assertEqual(response_body["SubCode"], "UserPermissionError")
211+
212+
def test_delete_non_existent_project_team_fails(self):
213+
"""
214+
Test that endpoint returns 404 when admin deletes non-existent project team
215+
"""
216+
response = self.client.delete(
217+
self.non_existent_project_team_url,
218+
headers={"Authorization": self.test_author_session_token},
219+
)
220+
response_body = response.get_json()
221+
self.assertEqual(response.status_code, 404)
222+
self.assertEqual(response_body["Error"], "No team found")
223+
self.assertEqual(response_body["SubCode"], "NotFound")
224+
225+
def test_delete_project_team_by_admin_passes(self):
226+
"""
227+
Test that endpoint returns 200 when admin successfully deletes project team
228+
"""
229+
assign_team_to_project(
230+
self.test_project, self.test_team, TeamRoles.MAPPER.value
231+
)
232+
response = self.client.delete(
233+
self.single_project_team_url,
234+
headers={"Authorization": self.test_author_session_token},
235+
)
236+
response_body = response.get_json()
237+
self.assertEqual(response.status_code, 200)
238+
self.assertEqual(response_body["Success"], True)

0 commit comments

Comments
 (0)