Skip to content

Commit be8b666

Browse files
committed
Add unit tests and integration tests for new add/delete methods
1 parent 711c402 commit be8b666

File tree

5 files changed

+179
-31
lines changed

5 files changed

+179
-31
lines changed

integration/tests/posit/connect/test_users.py

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,46 @@ def test_get(self):
4848
assert self.client.users.get(self.cole["guid"]) == self.cole
4949

5050
# Also tests Groups.members
51-
def test_groups(self):
51+
def test_user_group_interactions(self):
5252
try:
53-
unit_friends = self.client.groups.create(name="UnitFriends")
54-
self.client.post(
55-
f"/v1/groups/{unit_friends['guid']}/members",
56-
json={"user_guid": self.bill["guid"]},
57-
)
53+
test_group = self.client.groups.create(name="UnitFriends")
54+
55+
# `Group.members.count()`
56+
assert test_group.members.count() == 0
57+
58+
# `Group.members.add()`
59+
test_group.members.add(self.bill)
60+
# `User.groups.add()`
61+
assert test_group.members.count() == 1
62+
self.cole.groups.add(test_group)
63+
assert test_group.members.count() == 2
64+
65+
# `Group.members.find()`
66+
group_users = test_group.members.find()
67+
assert len(group_users) == 2
68+
assert group_users[0]["guid"] == self.bill["guid"]
69+
assert group_users[1]["guid"] == self.cole["guid"]
70+
71+
# `User.group.find()`
5872
bill_groups = self.bill.groups.find()
5973
assert len(bill_groups) == 1
60-
assert bill_groups[0]["guid"] == unit_friends["guid"]
74+
assert bill_groups[0]["guid"] == test_group["guid"]
75+
76+
# `Group.members.delete()`
77+
test_group.members.delete(self.bill)
78+
assert test_group.members.count() == 1
79+
80+
# `User.groups.delete()`
81+
self.cole.groups.delete(test_group)
82+
assert test_group.members.count() == 0
83+
6184
finally:
6285
groups = self.client.groups.find(prefix="UnitFriends")
6386
if len(groups) > 0:
64-
unit_friends = groups[0]
65-
unit_friends.delete()
87+
test_group = groups[0]
88+
test_group.delete()
89+
90+
assert len(self.client.groups.find(prefix="UnitFriends")) == 0
6691

6792

6893
class TestUserContent:

src/posit/connect/groups.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,17 @@ def add(self, *args: User, user_guid: Optional[str] = None) -> None:
116116
raise ValueError("Only one of `*args` or `user_guid=` should be provided.")
117117
for i, user in enumerate(args):
118118
if not isinstance(user, User):
119-
raise ValueError(f"args[{i}] is not a User object.")
119+
raise TypeError(f"args[{i}] is not a `User` object. Received {user}")
120120

121121
for user in args:
122122
self.add(user_guid=user["guid"])
123123

124124
return
125125

126126
if not isinstance(user_guid, str):
127-
raise TypeError("`user_guid=` should be a string.")
127+
raise TypeError(f"`user_guid=` should be a string. Received {user_guid}")
128128
if not user_guid:
129-
raise ValueError("`user_guid=` should not be empty")
129+
raise ValueError("`user_guid=` should not be empty.")
130130

131131
path = f"v1/groups/{self._group_guid}/members"
132132
url = self._ctx.url + path
@@ -176,17 +176,17 @@ def delete(self, *args: User, user_guid: Optional[str] = None) -> None:
176176
raise ValueError("Only one of `*args` or `user_guid=` should be provided.")
177177
for i, user in enumerate(args):
178178
if not isinstance(user, User):
179-
raise TypeError(f"`args[{i}]` is not a `User` object.")
179+
raise TypeError(f"`args[{i}]` is not a `User` object. Received {user}")
180180

181181
for user in args:
182182
self.delete(user_guid=user["guid"])
183183

184184
return
185185

186186
if not isinstance(user_guid, str):
187-
raise TypeError("`user_guid=` should be a string.")
187+
raise TypeError(f"`user_guid=` should be a string. Received {user_guid}")
188188
if not user_guid:
189-
raise ValueError("`user_guid=` should not be empty")
189+
raise ValueError("`user_guid=` should not be empty.")
190190

191191
path = f"v1/groups/{self._group_guid}/members/{user_guid}"
192192
url = self._ctx.url + path

src/posit/connect/users.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919

2020
class User(Resource):
21-
def __init__(self, ctx: Context, /, **attributes: dict) -> None:
21+
def __init__(self, ctx: Context, /, **attributes) -> None:
2222
super().__init__(ctx.client.resource_params, **attributes)
2323
self._ctx: Context = ctx
2424

@@ -214,7 +214,7 @@ def add(
214214
for i, group in enumerate(args):
215215
if not isinstance(group, Group):
216216
raise TypeError(
217-
f"`args[{i}]` is not an instance of Group",
217+
f"`args[{i}]` is not an instance of Group. Received {group}",
218218
)
219219
for group in args:
220220
group.members.add(user_guid=self._user_guid)
@@ -282,14 +282,14 @@ def delete(
282282
for i, group in enumerate(args):
283283
if not isinstance(group, Group):
284284
raise TypeError(
285-
f"`args[{i}]` is not an instance of Group",
285+
f"`args[{i}]` is not an instance of Group. Received {group}",
286286
)
287287
for group in args:
288288
group.members.delete(user_guid=self._user_guid)
289289
return
290290

291291
if not isinstance(group_guid, str):
292-
raise TypeError("`group_guid=` must be a string.")
292+
raise TypeError("`group_guid=` must be a string. Received {user}")
293293
if not group_guid:
294294
raise ValueError("`group_guid=` must not be empty.")
295295

tests/posit/connect/test_groups.py

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from unittest import mock
22
from unittest.mock import Mock
33

4+
import pytest
45
import responses
56

67
from posit.connect.client import Client
@@ -43,7 +44,7 @@ def setup_class(cls):
4344
@responses.activate
4445
def test_members_count(self):
4546
responses.get(
46-
"https://connect.example/__api__/v1/groups/6f300623-1e0c-48e6-a473-ddf630c0c0c3/members",
47+
f"https://connect.example/__api__/v1/groups/{self.group['guid']}/members",
4748
json=load_mock_dict(f"v1/groups/{self.group['guid']}/members.json"),
4849
)
4950
group_members = self.group.members
@@ -53,11 +54,65 @@ def test_members_count(self):
5354
@responses.activate
5455
def test_members_find(self):
5556
responses.get(
56-
"https://connect.example/__api__/v1/groups/6f300623-1e0c-48e6-a473-ddf630c0c0c3/members",
57+
f"https://connect.example/__api__/v1/groups/{self.group['guid']}/members",
5758
json=load_mock_dict(f"v1/groups/{self.group['guid']}/members.json"),
5859
)
5960

6061
group_users = self.group.members.find()
6162
assert len(group_users) == 2
6263
for user in group_users:
6364
assert isinstance(user, User)
65+
66+
@responses.activate
67+
def test_members_add(self):
68+
user_guid = "user-guid"
69+
responses.post(
70+
f"https://connect.example/__api__/v1/groups/{self.group['guid']}/members",
71+
json=[], # No need to return anything
72+
)
73+
74+
user = User(self.client._ctx, guid=user_guid)
75+
self.group.members.add(user)
76+
self.group.members.add(user, user)
77+
self.group.members.add(user_guid=user["guid"])
78+
79+
with pytest.raises(TypeError):
80+
self.group.members.add(
81+
"not-a-user", # pyright: ignore[reportArgumentType]
82+
)
83+
with pytest.raises(TypeError):
84+
self.group.members.add(group_guid=42) # pyright: ignore[reportCallIssue]
85+
with pytest.raises(ValueError):
86+
self.group.members.add(user, user_guid=user["guid"]) # pyright: ignore[reportCallIssue]
87+
with pytest.raises(ValueError):
88+
self.group.members.add(user_guid="")
89+
90+
@responses.activate
91+
def test_members_delete(self):
92+
user_guid = "user-guid"
93+
responses.get(
94+
f"https://connect.example/__api__/v1/groups/{self.group['guid']}",
95+
json=dict(self.group),
96+
)
97+
responses.delete(
98+
f"https://connect.example/__api__/v1/groups/{self.group['guid']}/members/{user_guid}",
99+
json=[], # No need to return anything
100+
)
101+
102+
user = User(self.client._ctx, guid=user_guid)
103+
104+
self.group.members.delete(user)
105+
self.group.members.delete(user, user)
106+
self.group.members.delete(user_guid=user["guid"])
107+
108+
with pytest.raises(TypeError):
109+
self.group.members.delete(
110+
"not-a-user", # pyright: ignore[reportArgumentType]
111+
)
112+
with pytest.raises(TypeError):
113+
self.group.members.delete(group_guid=42) # pyright: ignore[reportCallIssue]
114+
with pytest.raises(ValueError):
115+
self.group.members.delete(user, user_guid=user["guid"]) # pyright: ignore[reportCallIssue]
116+
117+
with pytest.raises(ValueError):
118+
self.group.members.delete(user_guid="")

tests/posit/connect/test_users.py

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from responses import matchers
77

88
from posit.connect.client import Client
9+
from posit.connect.groups import Group
10+
from posit.connect.users import User
911

1012
from .api import load_mock, load_mock_dict
1113

@@ -139,13 +141,18 @@ class TestUserGroups:
139141
def test_groups(self):
140142
# Get user
141143
carlos_guid = "20a79ce3-6e87-4522-9faf-be24228800a4"
144+
carlos_empty_group_guid = "empty-group-guid"
142145
responses.get(
143146
f"https://connect.example/__api__/v1/users/{carlos_guid}",
144147
json=load_mock_dict(f"v1/users/{carlos_guid}.json"),
145148
)
149+
responses.get(
150+
f"https://connect.example/__api__/v1/groups/{carlos_empty_group_guid}/members?page_number=1&page_size=500",
151+
json=load_mock_dict(f"v1/groups/{carlos_empty_group_guid}/members.json"),
152+
)
146153
responses.get(
147154
"https://connect.example/__api__/v1/users",
148-
json=load_mock("v1/users?page_number=1&page_size=500.jsonc"),
155+
json=load_mock_dict("v1/users?page_number=1&page_size=500.jsonc"),
149156
)
150157
# Get groups
151158
responses.get(
@@ -154,29 +161,90 @@ def test_groups(self):
154161
)
155162
# Get group members
156163
group_guid = "6f300623-1e0c-48e6-a473-ddf630c0c0c3"
157-
empty_group_guid = "empty-group-guid"
158-
for guid in (group_guid, empty_group_guid):
159-
responses.get(
160-
f"https://connect.example/__api__/v1/groups/{guid}/members",
161-
json=load_mock_dict(f"v1/groups/{guid}/members.json"),
162-
)
164+
responses.get(
165+
f"https://connect.example/__api__/v1/groups/{group_guid}/members",
166+
json=load_mock_dict(f"v1/groups/{group_guid}/members.json"),
167+
)
163168

164169
client = Client("https://connect.example/", "12345")
165-
users = client.users.find()
166-
assert len(users) == 2 + 2
167170

168171
carlos = client.users.get(carlos_guid)
169172
no_groups = carlos.groups.find()
170173
assert len(no_groups) == 0
171174

172-
user = users[1]
175+
user = client.users.find()[1]
173176
assert user["guid"] == "87c12c08-11cd-4de1-8da3-12a7579c4998"
174177

175178
groups = user.groups.find()
179+
assert isinstance(groups, list)
176180
assert len(groups) == 1
177181
group = groups[0]
182+
assert isinstance(group, Group)
178183
assert group["name"] == "Friends"
179184

185+
@responses.activate
186+
def test_groups_add(self):
187+
group_guid = "new-group-guid"
188+
user_guid = "user-guid"
189+
responses.get(
190+
f"https://connect.example/__api__/v1/groups/{group_guid}",
191+
json={"guid": group_guid},
192+
)
193+
responses.post(
194+
f"https://connect.example/__api__/v1/groups/{group_guid}/members",
195+
json=[],
196+
)
197+
198+
client = Client("https://connect.example/", "12345")
199+
200+
user = User(client._ctx, guid=user_guid)
201+
new_group = Group(client._ctx, guid=group_guid)
202+
# Add via Group
203+
user.groups.add(new_group)
204+
# Add via guid
205+
user.groups.add(group_guid=new_group["guid"])
206+
207+
with pytest.raises(TypeError):
208+
user.groups.add(
209+
"not a group", # pyright: ignore[reportArgumentType]
210+
)
211+
with pytest.raises(ValueError):
212+
user.groups.add(group_guid="")
213+
with pytest.raises(ValueError):
214+
user.groups.add(new_group, group_guid=new_group["guid"]) # pyright: ignore[reportCallIssue]
215+
216+
@responses.activate
217+
def test_groups_delete(self):
218+
group_guid = "new-group-guid"
219+
user_guid = "user-guid"
220+
responses.get(
221+
f"https://connect.example/__api__/v1/groups/{group_guid}",
222+
json={"guid": group_guid},
223+
)
224+
responses.delete(
225+
f"https://connect.example/__api__/v1/groups/{group_guid}/members/{user_guid}",
226+
json=[],
227+
)
228+
229+
client = Client("https://connect.example/", "12345")
230+
231+
user = User(client._ctx, guid=user_guid)
232+
group = Group(client._ctx, guid=group_guid)
233+
234+
# Delete via Group
235+
user.groups.delete(group)
236+
# Delete via guid
237+
user.groups.delete(group_guid=group["guid"])
238+
239+
with pytest.raises(TypeError):
240+
user.groups.delete(
241+
"not a group", # pyright: ignore[reportArgumentType]
242+
)
243+
with pytest.raises(ValueError):
244+
user.groups.delete(group_guid="")
245+
with pytest.raises(ValueError):
246+
user.groups.delete(group, group_guid=group["guid"]) # pyright: ignore[reportCallIssue]
247+
180248

181249
class TestUsers:
182250
@responses.activate

0 commit comments

Comments
 (0)