Skip to content

Commit eb2f2db

Browse files
committed
feat(team-project-access): Added unit testcases for the team project access resource
1 parent c6fb4fc commit eb2f2db

2 files changed

Lines changed: 223 additions & 2 deletions

File tree

examples/team_project_access.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,14 @@ def main():
218218
run_tasks=args.workspace_run_tasks,
219219
)
220220

221-
has_granular_permissions = project_access is not None or workspace_access is not None
222-
if has_granular_permissions and args.access and args.access != TeamProjectAccessType.TEAM_PROJECT_ACCESS_CUSTOM.value:
221+
has_granular_permissions = (
222+
project_access is not None or workspace_access is not None
223+
)
224+
if (
225+
has_granular_permissions
226+
and args.access
227+
and args.access != TeamProjectAccessType.TEAM_PROJECT_ACCESS_CUSTOM.value
228+
):
223229
parser.error(
224230
"When custom project/workspace permissions are provided, --access must be 'custom'"
225231
)
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
# Copyright IBM Corp. 2025, 2026
2+
# SPDX-License-Identifier: MPL-2.0
3+
4+
"""Unit tests for the team_project_access module."""
5+
6+
from unittest.mock import Mock
7+
8+
import pytest
9+
10+
from pytfe._http import HTTPTransport
11+
from pytfe.errors import InvalidTeamProjectAccessIDError
12+
from pytfe.models.project import Project
13+
from pytfe.models.team import Team
14+
from pytfe.models.team_project_access import (
15+
ProjectSettingsPermissionType,
16+
ProjectTeamsPermissionType,
17+
ProjectVariableSetsPermissionType,
18+
TeamProjectAccess,
19+
TeamProjectAccessAddOptions,
20+
TeamProjectAccessListOptions,
21+
TeamProjectAccessProjectPermissionsOptions,
22+
TeamProjectAccessType,
23+
TeamProjectAccessUpdateOptions,
24+
TeamProjectAccessWorkspacePermissionsOptions,
25+
WorkspaceRunsPermissionType,
26+
WorkspaceSentinelMocksPermissionType,
27+
WorkspaceStateVersionsPermissionType,
28+
WorkspaceVariablesPermissionType,
29+
)
30+
from pytfe.resources.team_project_access import TeamProjectAccesses
31+
32+
33+
class TestTeamProjectAccesses:
34+
"""Test the TeamProjectAccesses service class."""
35+
36+
@pytest.fixture
37+
def mock_transport(self):
38+
"""Create a mock HTTPTransport."""
39+
return Mock(spec=HTTPTransport)
40+
41+
@pytest.fixture
42+
def team_project_accesses_service(self, mock_transport):
43+
"""Create a TeamProjectAccesses service with mocked transport."""
44+
return TeamProjectAccesses(mock_transport)
45+
46+
@pytest.fixture
47+
def team_project_access_response_data(self):
48+
"""Return sample API response data for team project access."""
49+
return {
50+
"id": "tprj-123",
51+
"attributes": {
52+
"access": "custom",
53+
"project-access": {
54+
"settings": "update",
55+
"teams": "manage",
56+
"variable-sets": "read",
57+
},
58+
"workspace-access": {
59+
"runs": "plan",
60+
"sentinel-mocks": "none",
61+
"state-versions": "read-outputs",
62+
"variables": "write",
63+
"run-tasks": True,
64+
"move": False,
65+
"locking": True,
66+
"delete": False,
67+
"create": True,
68+
},
69+
},
70+
"relationships": {
71+
"team": {"data": {"id": "team-123", "type": "teams"}},
72+
"project": {"data": {"id": "prj-123", "type": "projects"}},
73+
},
74+
}
75+
76+
def test_add_team_project_access_success(
77+
self,
78+
team_project_accesses_service,
79+
mock_transport,
80+
team_project_access_response_data,
81+
):
82+
"""Test successful add operation."""
83+
mock_response = Mock()
84+
mock_response.json.return_value = {"data": team_project_access_response_data}
85+
mock_transport.request.return_value = mock_response
86+
87+
options = TeamProjectAccessAddOptions(
88+
access=TeamProjectAccessType.TEAM_PROJECT_ACCESS_CUSTOM,
89+
team=Team(id="team-123"),
90+
project=Project(id="prj-123"),
91+
project_access=TeamProjectAccessProjectPermissionsOptions(
92+
settings=ProjectSettingsPermissionType.PROJECT_SETTINGS_PERMISSION_UPDATE,
93+
teams=ProjectTeamsPermissionType.PROJECT_TEAMS_PERMISSION_MANAGE,
94+
variable_sets=ProjectVariableSetsPermissionType.PROJECT_VARIABLE_SETS_PERMISSION_READ,
95+
),
96+
workspace_access=TeamProjectAccessWorkspacePermissionsOptions(
97+
runs=WorkspaceRunsPermissionType.WORKSPACE_RUNS_PERMISSION_PLAN,
98+
sentinel_mocks=WorkspaceSentinelMocksPermissionType.WORKSPACE_SENTINEL_MOCKS_PERMISSION_NONE,
99+
state_versions=WorkspaceStateVersionsPermissionType.WORKSPACE_STATE_VERSIONS_PERMISSION_READ_OUTPUTS,
100+
variables=WorkspaceVariablesPermissionType.WORKSPACE_VARIABLES_PERMISSION_WRITE,
101+
create=True,
102+
delete=False,
103+
locking=True,
104+
move=False,
105+
run_tasks=True,
106+
),
107+
)
108+
109+
result = team_project_accesses_service.add(options)
110+
111+
mock_transport.request.assert_called_once()
112+
assert isinstance(result, TeamProjectAccess)
113+
assert result.id == "tprj-123"
114+
assert result.access == TeamProjectAccessType.TEAM_PROJECT_ACCESS_CUSTOM
115+
assert result.team.id == "team-123"
116+
assert result.project.id == "prj-123"
117+
118+
def test_read_team_project_access_success(
119+
self,
120+
team_project_accesses_service,
121+
mock_transport,
122+
team_project_access_response_data,
123+
):
124+
"""Test successful read operation."""
125+
mock_response = Mock()
126+
mock_response.json.return_value = {"data": team_project_access_response_data}
127+
mock_transport.request.return_value = mock_response
128+
129+
result = team_project_accesses_service.read("tprj-123")
130+
131+
mock_transport.request.assert_called_once_with(
132+
"GET", path="/api/v2/team-projects/tprj-123"
133+
)
134+
assert isinstance(result, TeamProjectAccess)
135+
assert result.id == "tprj-123"
136+
assert result.workspace_access.run_tasks is True
137+
138+
def test_read_team_project_access_invalid_id(self, team_project_accesses_service):
139+
"""Test read operation with invalid team project access ID."""
140+
with pytest.raises(InvalidTeamProjectAccessIDError):
141+
team_project_accesses_service.read("")
142+
143+
def test_update_team_project_access_success(
144+
self,
145+
team_project_accesses_service,
146+
mock_transport,
147+
team_project_access_response_data,
148+
):
149+
"""Test successful update operation."""
150+
mock_response = Mock()
151+
mock_response.json.return_value = {"data": team_project_access_response_data}
152+
mock_transport.request.return_value = mock_response
153+
154+
options = TeamProjectAccessUpdateOptions(
155+
access=TeamProjectAccessType.TEAM_PROJECT_ACCESS_CUSTOM,
156+
workspace_access=TeamProjectAccessWorkspacePermissionsOptions(
157+
run_tasks=True
158+
),
159+
)
160+
161+
result = team_project_accesses_service.update("tprj-123", options)
162+
163+
mock_transport.request.assert_called_once()
164+
assert isinstance(result, TeamProjectAccess)
165+
assert result.id == "tprj-123"
166+
167+
def test_update_team_project_access_invalid_id(self, team_project_accesses_service):
168+
"""Test update operation with invalid team project access ID."""
169+
options = TeamProjectAccessUpdateOptions(
170+
access=TeamProjectAccessType.TEAM_PROJECT_ACCESS_READ
171+
)
172+
173+
with pytest.raises(InvalidTeamProjectAccessIDError):
174+
team_project_accesses_service.update("", options)
175+
176+
def test_list_team_project_accesses_success(
177+
self,
178+
team_project_accesses_service,
179+
team_project_access_response_data,
180+
):
181+
"""Test successful list operation."""
182+
team_project_accesses_service._list = Mock(
183+
return_value=[team_project_access_response_data]
184+
)
185+
186+
options = TeamProjectAccessListOptions(page_size=10, Project_id="prj-123")
187+
188+
result_iter = team_project_accesses_service.list(options)
189+
items = list(result_iter)
190+
191+
team_project_accesses_service._list.assert_called_once_with(
192+
"/api/v2/team-projects",
193+
params={"page[size]": 10, "filter[project][id]": "prj-123"},
194+
)
195+
assert len(items) == 1
196+
assert isinstance(items[0], TeamProjectAccess)
197+
assert items[0].id == "tprj-123"
198+
199+
def test_remove_team_project_access_success(
200+
self,
201+
team_project_accesses_service,
202+
mock_transport,
203+
):
204+
"""Test successful remove operation."""
205+
result = team_project_accesses_service.remove("tprj-123")
206+
207+
mock_transport.request.assert_called_once_with(
208+
"DELETE", path="/api/v2/team-projects/tprj-123"
209+
)
210+
assert result is None
211+
212+
def test_remove_team_project_access_invalid_id(self, team_project_accesses_service):
213+
"""Test remove operation with invalid team project access ID."""
214+
with pytest.raises(InvalidTeamProjectAccessIDError):
215+
team_project_accesses_service.remove("")

0 commit comments

Comments
 (0)