Coverage for app / backend / src / tests / test_blocking.py: 100%
178 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-03 06:18 +0000
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-03 06:18 +0000
1import grpc
2import pytest
3from google.protobuf import empty_pb2
4from sqlalchemy import select
6from couchers.db import session_scope
7from couchers.models import User, UserBlock
8from couchers.proto import blocking_pb2
9from couchers.servicers.blocking import is_not_visible
10from tests.fixtures.db import generate_user, make_user_block
11from tests.fixtures.sessions import blocking_session
14@pytest.fixture(autouse=True)
15def _(testconfig):
16 pass
19def test_BlockUser(db):
20 user1, token1 = generate_user()
21 user2, token2 = generate_user()
23 with session_scope() as session:
24 blocked_user_list = (
25 session.execute(select(UserBlock).where(UserBlock.blocking_user_id == user1.id)).scalars().all()
26 )
27 assert len(blocked_user_list) == 0
29 with blocking_session(token1) as user_blocks:
30 with pytest.raises(grpc.RpcError) as e:
31 user_blocks.BlockUser(blocking_pb2.BlockUserReq(username=user1.username))
32 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
33 assert e.value.details() == "You can't block yourself."
35 user_blocks.BlockUser(blocking_pb2.BlockUserReq(username=user2.username))
37 with pytest.raises(grpc.RpcError) as e:
38 user_blocks.BlockUser(blocking_pb2.BlockUserReq(username=user2.username))
39 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
40 assert e.value.details() == "Target user has already been blocked."
42 with session_scope() as session:
43 blocked_user_list = (
44 session.execute(select(UserBlock).where(UserBlock.blocking_user_id == user1.id)).scalars().all()
45 )
46 assert len(blocked_user_list) == 1
49def test_make_user_block(db):
50 user1, token1 = generate_user()
51 user2, token2 = generate_user()
53 make_user_block(user1, user2)
55 with session_scope() as session:
56 blocked_user_list = (
57 session.execute(select(UserBlock).where(UserBlock.blocking_user_id == user1.id)).scalars().all()
58 )
59 assert len(blocked_user_list) == 1
62def test_UnblockUser(db):
63 user1, token1 = generate_user()
64 user2, token2 = generate_user()
65 make_user_block(user1, user2)
67 with blocking_session(token1) as user_blocks:
68 user_blocks.UnblockUser(blocking_pb2.UnblockUserReq(username=user2.username))
70 with session_scope() as session:
71 blocked_users = session.execute(select(UserBlock).where(UserBlock.blocking_user_id == user1.id)).scalars().all()
72 assert len(blocked_users) == 0
74 with blocking_session(token1) as user_blocks:
75 with pytest.raises(grpc.RpcError) as e:
76 user_blocks.UnblockUser(blocking_pb2.UnblockUserReq(username=user2.username))
77 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
78 assert e.value.details() == "Target user is not blocked."
80 # Test re-blocking
81 user_blocks.BlockUser(blocking_pb2.BlockUserReq(username=user2.username))
83 with session_scope() as session:
84 blocked_users = session.execute(select(UserBlock).where(UserBlock.blocking_user_id == user1.id)).scalars().all()
85 assert len(blocked_users) == 1
88def test_GetBlockedUsers(db):
89 user1, token1 = generate_user()
90 user2, token2 = generate_user()
91 user3, token3 = generate_user()
93 with blocking_session(token1) as user_blocks:
94 # Check no blocked users to start
95 blocked_user_list = user_blocks.GetBlockedUsers(empty_pb2.Empty())
96 assert len(blocked_user_list.blocked_users) == 0
98 make_user_block(user1, user2)
99 make_user_block(user1, user3)
100 blocked_user_list = user_blocks.GetBlockedUsers(empty_pb2.Empty())
101 assert len(blocked_user_list.blocked_users) == 2
103 blocked_usernames = [user.username for user in blocked_user_list.blocked_users]
104 blocked_names = [user.name for user in blocked_user_list.blocked_users]
106 assert user2.username in blocked_usernames
107 assert user3.username in blocked_usernames
108 assert user2.name in blocked_names
109 assert user3.name in blocked_names
112def test_relationships_userblock_dot_user(db):
113 user1, token1 = generate_user()
114 user2, token2 = generate_user()
116 make_user_block(user1, user2)
118 with session_scope() as session:
119 block = session.execute(
120 select(UserBlock).where((UserBlock.blocking_user_id == user1.id) & (UserBlock.blocked_user_id == user2.id))
121 ).scalar_one()
123 blocking_user_username = block.blocking_user.username
124 blocking_user_name = block.blocking_user.name
126 blocked_user_username = block.blocked_user.username
127 blocked_user_name = block.blocked_user.name
129 assert blocking_user_username == user1.username
130 assert blocked_user_username == user2.username
131 assert blocking_user_name == user1.name
132 assert blocked_user_name == user2.name
135def test_is_not_visible(db):
136 """
137 Comprehensive tests for is_not_visible function covering:
138 1. Normal visible users (not blocked, not banned, not deleted) - should be visible to each other
139 2. User1 blocks User2 - not visible
140 3. User2 blocks User1 - not visible
141 4. Mutual blocking - not visible
142 5. User1 is deleted - not visible
143 6. User2 is deleted - not visible
144 7. Both users deleted - not visible
145 8. User1 is banned - not visible
146 9. User2 is banned - not visible
147 10. Both users banned - not visible
148 11. Mixed: User1 deleted and User2 banned - not visible
149 12. None user_id cases with visible users
150 13. None user_id cases with hidden users (banned/deleted)
151 14. Ensure we have extra users in DB to avoid edge cases with empty database
152 """
154 # Create extra users to ensure the database is not empty - these should remain visible
155 extra_user1, _ = generate_user()
156 extra_user2, _ = generate_user()
157 extra_user3, _ = generate_user()
159 # Create users for testing - all start as visible
160 normal_user1, _ = generate_user()
161 normal_user2, _ = generate_user()
163 # Users for blocking tests
164 blocker_user, _ = generate_user()
165 blockee_user, _ = generate_user()
167 # Users for reverse blocking tests
168 reverse_blocker, _ = generate_user()
169 reverse_blockee, _ = generate_user()
171 # Users for mutual blocking tests
172 mutual_blocker1, _ = generate_user()
173 mutual_blocker2, _ = generate_user()
175 # Users for deletion tests
176 deleted_user1, _ = generate_user()
177 visible_for_deleted, _ = generate_user()
178 deleted_user2, _ = generate_user()
179 both_deleted1, _ = generate_user()
180 both_deleted2, _ = generate_user()
182 # Users for ban tests
183 banned_user1, _ = generate_user()
184 visible_for_banned, _ = generate_user()
185 banned_user2, _ = generate_user()
186 both_banned1, _ = generate_user()
187 both_banned2, _ = generate_user()
189 # User for mixed test
190 mixed_deleted, _ = generate_user()
191 mixed_banned, _ = generate_user()
193 with session_scope() as session:
194 # Test 1: Two normal visible users - should be visible to each other
195 assert not is_not_visible(session, normal_user1.id, normal_user2.id)
196 assert not is_not_visible(session, normal_user2.id, normal_user1.id)
198 # Test 2: User1 blocks User2 - should not be visible
199 make_user_block(blocker_user, blockee_user)
200 assert is_not_visible(session, blocker_user.id, blockee_user.id)
201 assert is_not_visible(session, blockee_user.id, blocker_user.id) # symmetric
203 # Test 3: User2 blocks User1 (reverse block) - should not be visible
204 make_user_block(reverse_blockee, reverse_blocker)
205 assert is_not_visible(session, reverse_blocker.id, reverse_blockee.id)
206 assert is_not_visible(session, reverse_blockee.id, reverse_blocker.id) # symmetric
208 # Test 4: Mutual blocking - should not be visible
209 make_user_block(mutual_blocker1, mutual_blocker2)
210 make_user_block(mutual_blocker2, mutual_blocker1)
211 assert is_not_visible(session, mutual_blocker1.id, mutual_blocker2.id)
212 assert is_not_visible(session, mutual_blocker2.id, mutual_blocker1.id)
214 # Test 5: User1 is deleted - should not be visible
215 deleted_user1_db = session.get_one(User, deleted_user1.id)
216 deleted_user1_db.is_deleted = True
217 session.commit()
218 assert is_not_visible(session, deleted_user1.id, visible_for_deleted.id)
219 assert is_not_visible(session, visible_for_deleted.id, deleted_user1.id)
221 # Test 6: User2 is deleted - should not be visible
222 deleted_user2_db = session.get_one(User, deleted_user2.id)
223 deleted_user2_db.is_deleted = True
224 session.commit()
225 assert is_not_visible(session, normal_user1.id, deleted_user2.id)
226 assert is_not_visible(session, deleted_user2.id, normal_user1.id)
228 # Test 7: Both users deleted - should not be visible
229 both_deleted1_db = session.get_one(User, both_deleted1.id)
230 both_deleted2_db = session.get_one(User, both_deleted2.id)
231 both_deleted1_db.is_deleted = True
232 both_deleted2_db.is_deleted = True
233 session.commit()
234 assert is_not_visible(session, both_deleted1.id, both_deleted2.id)
235 assert is_not_visible(session, both_deleted2.id, both_deleted1.id)
237 # Test 8: User1 is banned - should not be visible
238 banned_user1_db = session.get_one(User, banned_user1.id)
239 banned_user1_db.is_banned = True
240 session.commit()
241 assert is_not_visible(session, banned_user1.id, visible_for_banned.id)
242 assert is_not_visible(session, visible_for_banned.id, banned_user1.id)
244 # Test 9: User2 is banned - should not be visible
245 banned_user2_db = session.get_one(User, banned_user2.id)
246 banned_user2_db.is_banned = True
247 session.commit()
248 assert is_not_visible(session, normal_user2.id, banned_user2.id)
249 assert is_not_visible(session, banned_user2.id, normal_user2.id)
251 # Test 10: Both users banned - should not be visible
252 both_banned1_db = session.get_one(User, both_banned1.id)
253 both_banned2_db = session.get_one(User, both_banned2.id)
254 both_banned1_db.is_banned = True
255 both_banned2_db.is_banned = True
256 session.commit()
257 assert is_not_visible(session, both_banned1.id, both_banned2.id)
258 assert is_not_visible(session, both_banned2.id, both_banned1.id)
260 # Test 11: Mixed - one deleted, one banned - should not be visible
261 mixed_deleted_db = session.get_one(User, mixed_deleted.id)
262 mixed_banned_db = session.get_one(User, mixed_banned.id)
263 mixed_deleted_db.is_deleted = True
264 mixed_banned_db.is_banned = True
265 session.commit()
266 assert is_not_visible(session, mixed_deleted.id, mixed_banned.id)
267 assert is_not_visible(session, mixed_banned.id, mixed_deleted.id)
269 # Test 12: None user_id cases with visible users - should be visible
270 assert not is_not_visible(session, None, normal_user1.id)
271 assert not is_not_visible(session, normal_user1.id, None)
272 assert not is_not_visible(session, None, None)
274 # Test 13: None user_id cases with hidden users (deleted/banned) - should not be visible
275 assert is_not_visible(session, None, deleted_user1.id)
276 assert is_not_visible(session, deleted_user1.id, None)
277 assert is_not_visible(session, None, banned_user1.id)
278 assert is_not_visible(session, banned_user1.id, None)
280 # Test 14: Verify extra users are still visible (database not empty)
281 assert not is_not_visible(session, extra_user1.id, extra_user2.id)
282 assert not is_not_visible(session, extra_user2.id, extra_user3.id)
283 assert not is_not_visible(session, extra_user1.id, extra_user3.id)
285 # Additional edge case: Check that normal users are still visible to each other after all the above
286 assert not is_not_visible(session, normal_user1.id, normal_user2.id)
287 assert not is_not_visible(session, normal_user1.id, extra_user1.id)