Coverage for src/tests/test_blocking.py: 100%
176 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-12-06 08:02 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-12-06 08:02 +0000
1import grpc
2import pytest
3from google.protobuf import empty_pb2
5from couchers.models import User, UserBlock
6from couchers.proto import blocking_pb2
7from couchers.servicers.blocking import is_not_visible
8from couchers.sql import couchers_select as select
9from tests.test_fixtures import blocking_session, db, generate_user, make_user_block, session_scope, testconfig # noqa
12@pytest.fixture(autouse=True)
13def _(testconfig):
14 pass
17def test_BlockUser(db):
18 user1, token1 = generate_user()
19 user2, token2 = generate_user()
21 with session_scope() as session:
22 blocked_user_list = (
23 session.execute(select(UserBlock).where(UserBlock.blocking_user_id == user1.id)).scalars().all()
24 )
25 assert len(blocked_user_list) == 0
27 with blocking_session(token1) as user_blocks:
28 with pytest.raises(grpc.RpcError) as e:
29 user_blocks.BlockUser(blocking_pb2.BlockUserReq(username=user1.username))
30 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
31 assert e.value.details() == "You can't block yourself."
33 user_blocks.BlockUser(blocking_pb2.BlockUserReq(username=user2.username))
35 with pytest.raises(grpc.RpcError) as e:
36 user_blocks.BlockUser(blocking_pb2.BlockUserReq(username=user2.username))
37 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
38 assert e.value.details() == "Target user has already been blocked."
40 with session_scope() as session:
41 blocked_user_list = (
42 session.execute(select(UserBlock).where(UserBlock.blocking_user_id == user1.id)).scalars().all()
43 )
44 assert len(blocked_user_list) == 1
47def test_make_user_block(db):
48 user1, token1 = generate_user()
49 user2, token2 = generate_user()
51 make_user_block(user1, user2)
53 with session_scope() as session:
54 blocked_user_list = (
55 session.execute(select(UserBlock).where(UserBlock.blocking_user_id == user1.id)).scalars().all()
56 )
57 assert len(blocked_user_list) == 1
60def test_UnblockUser(db):
61 user1, token1 = generate_user()
62 user2, token2 = generate_user()
63 make_user_block(user1, user2)
65 with blocking_session(token1) as user_blocks:
66 user_blocks.UnblockUser(blocking_pb2.UnblockUserReq(username=user2.username))
68 with session_scope() as session:
69 blocked_users = session.execute(select(UserBlock).where(UserBlock.blocking_user_id == user1.id)).scalars().all()
70 assert len(blocked_users) == 0
72 with blocking_session(token1) as user_blocks:
73 with pytest.raises(grpc.RpcError) as e:
74 user_blocks.UnblockUser(blocking_pb2.UnblockUserReq(username=user2.username))
75 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
76 assert e.value.details() == "Target user is not blocked."
78 # Test re-blocking
79 user_blocks.BlockUser(blocking_pb2.BlockUserReq(username=user2.username))
81 with session_scope() as session:
82 blocked_users = session.execute(select(UserBlock).where(UserBlock.blocking_user_id == user1.id)).scalars().all()
83 assert len(blocked_users) == 1
86def test_GetBlockedUsers(db):
87 user1, token1 = generate_user()
88 user2, token2 = generate_user()
89 user3, token3 = generate_user()
91 with blocking_session(token1) as user_blocks:
92 # Check no blocked users to start
93 blocked_user_list = user_blocks.GetBlockedUsers(empty_pb2.Empty())
94 assert len(blocked_user_list.blocked_users) == 0
96 make_user_block(user1, user2)
97 make_user_block(user1, user3)
98 blocked_user_list = user_blocks.GetBlockedUsers(empty_pb2.Empty())
99 assert len(blocked_user_list.blocked_users) == 2
101 blocked_usernames = [user.username for user in blocked_user_list.blocked_users]
102 blocked_names = [user.name for user in blocked_user_list.blocked_users]
104 assert user2.username in blocked_usernames
105 assert user3.username in blocked_usernames
106 assert user2.name in blocked_names
107 assert user3.name in blocked_names
110def test_relationships_userblock_dot_user(db):
111 user1, token1 = generate_user()
112 user2, token2 = generate_user()
114 make_user_block(user1, user2)
116 with session_scope() as session:
117 block = session.execute(
118 select(UserBlock).where((UserBlock.blocking_user_id == user1.id) & (UserBlock.blocked_user_id == user2.id))
119 ).scalar_one_or_none()
121 blocking_user_username = block.blocking_user.username
122 blocking_user_name = block.blocking_user.name
124 blocked_user_username = block.blocked_user.username
125 blocked_user_name = block.blocked_user.name
127 assert blocking_user_username == user1.username
128 assert blocked_user_username == user2.username
129 assert blocking_user_name == user1.name
130 assert blocked_user_name == user2.name
133def test_is_not_visible(db):
134 """
135 Comprehensive tests for is_not_visible function covering:
136 1. Normal visible users (not blocked, not banned, not deleted) - should be visible to each other
137 2. User1 blocks User2 - not visible
138 3. User2 blocks User1 - not visible
139 4. Mutual blocking - not visible
140 5. User1 is deleted - not visible
141 6. User2 is deleted - not visible
142 7. Both users deleted - not visible
143 8. User1 is banned - not visible
144 9. User2 is banned - not visible
145 10. Both users banned - not visible
146 11. Mixed: User1 deleted and User2 banned - not visible
147 12. None user_id cases with visible users
148 13. None user_id cases with hidden users (banned/deleted)
149 14. Ensure we have extra users in DB to avoid edge cases with empty database
150 """
152 # Create extra users to ensure the database is not empty - these should remain visible
153 extra_user1, _ = generate_user()
154 extra_user2, _ = generate_user()
155 extra_user3, _ = generate_user()
157 # Create users for testing - all start as visible
158 normal_user1, _ = generate_user()
159 normal_user2, _ = generate_user()
161 # Users for blocking tests
162 blocker_user, _ = generate_user()
163 blockee_user, _ = generate_user()
165 # Users for reverse blocking tests
166 reverse_blocker, _ = generate_user()
167 reverse_blockee, _ = generate_user()
169 # Users for mutual blocking tests
170 mutual_blocker1, _ = generate_user()
171 mutual_blocker2, _ = generate_user()
173 # Users for deletion tests
174 deleted_user1, _ = generate_user()
175 visible_for_deleted, _ = generate_user()
176 deleted_user2, _ = generate_user()
177 both_deleted1, _ = generate_user()
178 both_deleted2, _ = generate_user()
180 # Users for ban tests
181 banned_user1, _ = generate_user()
182 visible_for_banned, _ = generate_user()
183 banned_user2, _ = generate_user()
184 both_banned1, _ = generate_user()
185 both_banned2, _ = generate_user()
187 # User for mixed test
188 mixed_deleted, _ = generate_user()
189 mixed_banned, _ = generate_user()
191 with session_scope() as session:
192 # Test 1: Two normal visible users - should be visible to each other
193 assert not is_not_visible(session, normal_user1.id, normal_user2.id)
194 assert not is_not_visible(session, normal_user2.id, normal_user1.id)
196 # Test 2: User1 blocks User2 - should not be visible
197 make_user_block(blocker_user, blockee_user)
198 assert is_not_visible(session, blocker_user.id, blockee_user.id)
199 assert is_not_visible(session, blockee_user.id, blocker_user.id) # symmetric
201 # Test 3: User2 blocks User1 (reverse block) - should not be visible
202 make_user_block(reverse_blockee, reverse_blocker)
203 assert is_not_visible(session, reverse_blocker.id, reverse_blockee.id)
204 assert is_not_visible(session, reverse_blockee.id, reverse_blocker.id) # symmetric
206 # Test 4: Mutual blocking - should not be visible
207 make_user_block(mutual_blocker1, mutual_blocker2)
208 make_user_block(mutual_blocker2, mutual_blocker1)
209 assert is_not_visible(session, mutual_blocker1.id, mutual_blocker2.id)
210 assert is_not_visible(session, mutual_blocker2.id, mutual_blocker1.id)
212 # Test 5: User1 is deleted - should not be visible
213 deleted_user1_db = session.get(User, deleted_user1.id)
214 deleted_user1_db.is_deleted = True
215 session.commit()
216 assert is_not_visible(session, deleted_user1.id, visible_for_deleted.id)
217 assert is_not_visible(session, visible_for_deleted.id, deleted_user1.id)
219 # Test 6: User2 is deleted - should not be visible
220 deleted_user2_db = session.get(User, deleted_user2.id)
221 deleted_user2_db.is_deleted = True
222 session.commit()
223 assert is_not_visible(session, normal_user1.id, deleted_user2.id)
224 assert is_not_visible(session, deleted_user2.id, normal_user1.id)
226 # Test 7: Both users deleted - should not be visible
227 both_deleted1_db = session.get(User, both_deleted1.id)
228 both_deleted2_db = session.get(User, both_deleted2.id)
229 both_deleted1_db.is_deleted = True
230 both_deleted2_db.is_deleted = True
231 session.commit()
232 assert is_not_visible(session, both_deleted1.id, both_deleted2.id)
233 assert is_not_visible(session, both_deleted2.id, both_deleted1.id)
235 # Test 8: User1 is banned - should not be visible
236 banned_user1_db = session.get(User, banned_user1.id)
237 banned_user1_db.is_banned = True
238 session.commit()
239 assert is_not_visible(session, banned_user1.id, visible_for_banned.id)
240 assert is_not_visible(session, visible_for_banned.id, banned_user1.id)
242 # Test 9: User2 is banned - should not be visible
243 banned_user2_db = session.get(User, banned_user2.id)
244 banned_user2_db.is_banned = True
245 session.commit()
246 assert is_not_visible(session, normal_user2.id, banned_user2.id)
247 assert is_not_visible(session, banned_user2.id, normal_user2.id)
249 # Test 10: Both users banned - should not be visible
250 both_banned1_db = session.get(User, both_banned1.id)
251 both_banned2_db = session.get(User, both_banned2.id)
252 both_banned1_db.is_banned = True
253 both_banned2_db.is_banned = True
254 session.commit()
255 assert is_not_visible(session, both_banned1.id, both_banned2.id)
256 assert is_not_visible(session, both_banned2.id, both_banned1.id)
258 # Test 11: Mixed - one deleted, one banned - should not be visible
259 mixed_deleted_db = session.get(User, mixed_deleted.id)
260 mixed_banned_db = session.get(User, mixed_banned.id)
261 mixed_deleted_db.is_deleted = True
262 mixed_banned_db.is_banned = True
263 session.commit()
264 assert is_not_visible(session, mixed_deleted.id, mixed_banned.id)
265 assert is_not_visible(session, mixed_banned.id, mixed_deleted.id)
267 # Test 12: None user_id cases with visible users - should be visible
268 assert not is_not_visible(session, None, normal_user1.id)
269 assert not is_not_visible(session, normal_user1.id, None)
270 assert not is_not_visible(session, None, None)
272 # Test 13: None user_id cases with hidden users (deleted/banned) - should not be visible
273 assert is_not_visible(session, None, deleted_user1.id)
274 assert is_not_visible(session, deleted_user1.id, None)
275 assert is_not_visible(session, None, banned_user1.id)
276 assert is_not_visible(session, banned_user1.id, None)
278 # Test 14: Verify extra users are still visible (database not empty)
279 assert not is_not_visible(session, extra_user1.id, extra_user2.id)
280 assert not is_not_visible(session, extra_user2.id, extra_user3.id)
281 assert not is_not_visible(session, extra_user1.id, extra_user3.id)
283 # Additional edge case: Check that normal users are still visible to each other after all the above
284 assert not is_not_visible(session, normal_user1.id, normal_user2.id)
285 assert not is_not_visible(session, normal_user1.id, extra_user1.id)