Coverage for app/backend/src/tests/test_conversations.py: 100%
1299 statements
« prev ^ index » next coverage.py v7.14.2, created at 2026-06-21 09:29 +0000
« prev ^ index » next coverage.py v7.14.2, created at 2026-06-21 09:29 +0000
1from datetime import timedelta
3import grpc
4import pytest
5from google.protobuf import wrappers_pb2
6from sqlalchemy import func, select
8from couchers.db import session_scope
9from couchers.jobs.worker import process_job
10from couchers.models import (
11 GroupChatRole,
12 GroupChatSubscription,
13 Notification,
14 NotificationDelivery,
15 NotificationDeliveryType,
16 NotificationTopicAction,
17 RateLimitAction,
18)
19from couchers.proto import api_pb2, conversations_pb2, notification_data_pb2, notifications_pb2
20from couchers.rate_limits.definitions import RATE_LIMIT_DEFINITIONS, RATE_LIMIT_HOURS
21from couchers.utils import Duration_from_timedelta, now, to_aware_datetime
22from tests.fixtures.db import generate_user, make_friends, make_user_block, make_user_invisible
23from tests.fixtures.misc import EmailCollector, Moderator, PushCollector, process_jobs
24from tests.fixtures.sessions import api_session, conversations_session, notifications_session
27@pytest.fixture(autouse=True)
28def _(testconfig):
29 pass
32def test_list_group_chats(db, moderator):
33 user1, token1 = generate_user()
34 user2, token2 = generate_user()
35 user3, token3 = generate_user()
37 make_friends(user2, user1)
38 make_friends(user1, user3)
40 with conversations_session(token1) as c:
41 # no threads initially
42 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
43 assert len(res.group_chats) == 0
45 # create some group chats with messages
46 res = c.CreateGroupChat(
47 conversations_pb2.CreateGroupChatReq(
48 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title")
49 )
50 )
51 group_chat1_id = res.group_chat_id
52 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1"))
53 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 2"))
54 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
55 group_chat2_id = res.group_chat_id
56 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 1"))
57 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 2"))
59 moderator.approve_group_chat(group_chat1_id)
60 moderator.approve_group_chat(group_chat2_id)
62 with conversations_session(token1) as c:
63 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
64 assert len(res.group_chats) == 2
65 assert res.no_more
67 with conversations_session(token2) as c:
68 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
69 assert len(res.group_chats) == 2
70 assert res.no_more
72 with conversations_session(token3) as c:
73 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
74 assert len(res.group_chats) == 1
75 assert res.no_more
77 # Test archive filtering: archive group_chat1 for user1
78 with conversations_session(token1) as c:
79 res = c.SetGroupChatArchiveStatus(
80 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=group_chat1_id, is_archived=True)
81 )
82 assert res.group_chat_id == group_chat1_id
83 assert res.is_archived
85 with conversations_session(token1) as c:
86 # Without filter, returns all chats
87 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
88 assert len(res.group_chats) == 2
90 # only_archived=False returns non-archived chats only
91 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False))
92 assert len(res.group_chats) == 1
94 # only_archived=True returns archived chats only
95 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True))
96 assert len(res.group_chats) == 1
98 # user2 should still see both as non-archived (archive is per-user)
99 with conversations_session(token2) as c:
100 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False))
101 assert len(res.group_chats) == 2
103 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True))
104 assert len(res.group_chats) == 0
107def test_list_empty_group_chats(db, moderator):
108 user1, token1 = generate_user()
109 user2, token2 = generate_user()
110 user3, token3 = generate_user()
112 make_friends(user1, user3)
113 make_friends(user2, user1)
114 make_friends(user2, user3)
116 with conversations_session(token1) as c:
117 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
118 assert len(res.group_chats) == 0
120 res1 = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
121 res2 = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
123 moderator.approve_group_chat(res1.group_chat_id)
124 moderator.approve_group_chat(res2.group_chat_id)
126 with conversations_session(token1) as c:
127 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
128 assert len(res.group_chats) == 2
129 assert res.no_more
131 with conversations_session(token2) as c:
132 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
133 assert len(res.group_chats) == 2
134 assert res.no_more
136 res3 = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
137 moderator.approve_group_chat(res3.group_chat_id)
139 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
140 assert len(res.group_chats) == 3
141 assert res.no_more
143 with conversations_session(token3) as c:
144 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
145 assert len(res.group_chats) == 2
146 assert res.no_more
149def test_list_group_chats_ordering(db, moderator):
150 # user is member of 5 group chats, order them correctly
151 user, token = generate_user()
152 user2, token2 = generate_user()
153 user3, token3 = generate_user()
154 user4, token4 = generate_user()
156 make_friends(user2, user)
157 make_friends(user2, user3)
158 make_friends(user2, user4)
159 make_friends(user3, user)
160 make_friends(user3, user4)
161 make_friends(user, user4)
163 chat_ids = []
165 with conversations_session(token2) as c:
166 res = c.CreateGroupChat(
167 conversations_pb2.CreateGroupChatReq(
168 recipient_user_ids=[user.id], title=wrappers_pb2.StringValue(value="Chat 0")
169 )
170 )
171 chat_ids.append(res.group_chat_id)
172 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
173 res = c.CreateGroupChat(
174 conversations_pb2.CreateGroupChatReq(
175 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 1")
176 )
177 )
178 chat_ids.append(res.group_chat_id)
179 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
180 res = c.CreateGroupChat(
181 conversations_pb2.CreateGroupChatReq(
182 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 2")
183 )
184 )
185 chat_ids.append(res.group_chat_id)
186 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
188 with conversations_session(token3) as c:
189 res = c.CreateGroupChat(
190 conversations_pb2.CreateGroupChatReq(
191 recipient_user_ids=[user.id, user2.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 3")
192 )
193 )
194 chat_ids.append(res.group_chat_id)
195 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
197 for chat_id in chat_ids:
198 moderator.approve_group_chat(chat_id)
200 with conversations_session(token) as c:
201 res = c.CreateGroupChat(
202 conversations_pb2.CreateGroupChatReq(
203 recipient_user_ids=[user2.id, user3.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 4")
204 )
205 )
206 moderator.approve_group_chat(res.group_chat_id)
207 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
208 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
209 assert len(res.group_chats) == 5
210 assert res.group_chats[0].title == "Chat 4"
211 assert res.group_chats[1].title == "Chat 3"
212 assert res.group_chats[2].title == "Chat 2"
213 assert res.group_chats[3].title == "Chat 1"
214 assert res.group_chats[4].title == "Chat 0"
216 c.SendMessage(
217 conversations_pb2.SendMessageReq(group_chat_id=res.group_chats[3].group_chat_id, text="Test message 2a")
218 )
219 c.SendMessage(
220 conversations_pb2.SendMessageReq(group_chat_id=res.group_chats[2].group_chat_id, text="Test message 2b")
221 )
223 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
224 assert len(res.group_chats) == 5
225 assert res.group_chats[0].title == "Chat 2"
226 assert res.group_chats[0].latest_message.text.text == "Test message 2b"
227 assert res.group_chats[1].title == "Chat 1"
228 assert res.group_chats[1].latest_message.text.text == "Test message 2a"
229 assert res.group_chats[2].title == "Chat 4"
230 assert res.group_chats[3].title == "Chat 3"
231 assert res.group_chats[4].title == "Chat 0"
234def test_list_group_chats_ordering_after_left(db, moderator):
235 # user is member to 4 group chats, and has left one.
236 # The one user left has the most recent message, but user left before then,
237 # this should display as e.g. 3rd most recent depending on last message when they were in the chat
238 user, token = generate_user()
239 user2, token2 = generate_user()
240 user3, token3 = generate_user()
241 user4, token4 = generate_user()
243 make_friends(user2, user)
244 make_friends(user2, user3)
245 make_friends(user2, user4)
246 make_friends(user3, user)
247 make_friends(user3, user4)
248 make_friends(user, user4)
250 chat_ids = []
252 with conversations_session(token2) as c:
253 res = c.CreateGroupChat(
254 conversations_pb2.CreateGroupChatReq(
255 recipient_user_ids=[user.id], title=wrappers_pb2.StringValue(value="Chat 0")
256 )
257 )
258 chat_ids.append(res.group_chat_id)
259 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
260 res = c.CreateGroupChat(
261 conversations_pb2.CreateGroupChatReq(
262 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Left Chat 1")
263 )
264 )
265 left_chat_id = res.group_chat_id
266 chat_ids.append(left_chat_id)
267 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Test message"))
268 res = c.CreateGroupChat(
269 conversations_pb2.CreateGroupChatReq(
270 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 2")
271 )
272 )
273 chat2_id = res.group_chat_id
274 chat_ids.append(chat2_id)
275 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=chat2_id, text="Test message"))
277 with conversations_session(token3) as c:
278 res = c.CreateGroupChat(
279 conversations_pb2.CreateGroupChatReq(
280 recipient_user_ids=[user.id, user2.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 3")
281 )
282 )
283 chat_ids.append(res.group_chat_id)
284 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
286 for chat_id in chat_ids:
287 moderator.approve_group_chat(chat_id)
289 with conversations_session(token) as c:
290 res = c.CreateGroupChat(
291 conversations_pb2.CreateGroupChatReq(
292 recipient_user_ids=[user2.id, user3.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 4")
293 )
294 )
295 moderator.approve_group_chat(res.group_chat_id)
296 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
298 # leave chat
299 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=left_chat_id))
301 with conversations_session(token3) as c:
302 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=chat2_id, text="Test message"))
303 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Test message"))
305 with conversations_session(token2) as c:
306 # other user sends a message to that chat
307 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Another test message"))
308 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
309 assert len(res.group_chats) == 5
310 assert res.group_chats[0].title == "Left Chat 1"
311 assert res.group_chats[1].title == "Chat 2"
312 assert res.group_chats[2].title == "Chat 4"
313 assert res.group_chats[3].title == "Chat 3"
314 assert res.group_chats[4].title == "Chat 0"
316 with conversations_session(token) as c:
317 # we can't see the new message since we left before it was sent
318 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
319 assert len(res.group_chats) == 5
320 assert res.group_chats[0].title == "Chat 2"
321 assert res.group_chats[1].title == "Left Chat 1"
322 assert res.group_chats[2].title == "Chat 4"
323 assert res.group_chats[3].title == "Chat 3"
324 assert res.group_chats[4].title == "Chat 0"
327def test_get_group_chat_messages(db):
328 user1, token1 = generate_user()
329 user2, token2 = generate_user()
330 user3, token3 = generate_user()
332 make_friends(user1, user2)
334 with conversations_session(token1) as c:
335 # create some threads with messages
336 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
337 group_chat_id = res.group_chat_id
338 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1"))
339 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 2"))
341 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
342 # created + 2 normal
343 assert len(res.messages) == 3
344 assert res.no_more
346 assert res.messages[0].text.text == "Test message 2"
347 assert res.messages[1].text.text == "Test message 1"
348 assert res.messages[2].WhichOneof("content") == "chat_created"
350 # test that another user can't access the thread
351 with conversations_session(token3) as c:
352 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
353 assert len(res.messages) == 0
356def test_get_group_chat_messages_pagination(db, moderator):
357 user1, token1 = generate_user()
358 user2, token2 = generate_user()
359 make_friends(user1, user2)
361 with conversations_session(token1) as c:
362 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
363 group_chat_id = res.group_chat_id
364 for i in range(30):
365 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=str(i)))
367 moderator.approve_group_chat(group_chat_id)
369 with conversations_session(token2) as c:
370 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
371 # pagination
372 assert len(res.messages) == 20
373 assert res.messages[0].text.text == "29"
374 assert res.messages[19].text.text == "10"
375 assert not res.no_more
376 res = c.GetGroupChatMessages(
377 conversations_pb2.GetGroupChatMessagesReq(
378 group_chat_id=group_chat_id, last_message_id=res.messages[19].message_id
379 )
380 )
381 assert len(res.messages) == 11
382 assert res.messages[0].text.text == "9"
383 assert res.messages[9].text.text == "0"
384 assert res.no_more
387def test_get_group_chat_messages_joined_left(db, moderator):
388 user1, token1 = generate_user()
389 user2, token2 = generate_user()
390 user3, token3 = generate_user()
391 user4, token4 = generate_user()
392 make_friends(user1, user2)
393 make_friends(user1, user3)
394 make_friends(user1, user4)
396 with conversations_session(token1) as c:
397 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id]))
398 group_chat_id = res.group_chat_id
399 moderator.approve_group_chat(group_chat_id)
401 for i in range(10):
402 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=str(i)))
404 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
406 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="10"))
408 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
410 # created + 10 normal + invited + normal
411 assert len(res.messages) == 13
413 with conversations_session(token3) as c:
414 # can only see last message after invited
415 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
416 # joined + normal
417 assert len(res.messages) == 2
418 assert res.messages[0].text.text == "10"
420 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
422 with conversations_session(token1) as c:
423 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="11"))
424 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="12"))
426 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
428 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="13"))
429 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="14"))
431 with conversations_session(token3) as c:
432 # can only see last message after invited
433 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
434 # joined + normal + left + invite + 2 normal
435 assert len(res.messages) == 6
436 assert res.messages[0].text.text == "14"
437 assert res.messages[1].text.text == "13"
438 assert res.messages[2].WhichOneof("content") == "user_invited"
439 assert res.messages[3].WhichOneof("content") == "user_left"
440 assert res.messages[4].text.text == "10"
441 assert res.messages[5].WhichOneof("content") == "user_invited"
444def test_get_group_chat_info(db):
445 user1, token1 = generate_user()
446 user2, token2 = generate_user()
447 user3, token3 = generate_user()
449 make_friends(user1, user2)
450 make_friends(user3, user1)
452 with conversations_session(token1) as c:
453 # create some threads with messages
454 res = c.CreateGroupChat(
455 conversations_pb2.CreateGroupChatReq(
456 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title")
457 )
458 )
459 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1"))
460 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 2"))
461 group_chat1_id = res.group_chat_id
462 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
463 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 1"))
464 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 2"))
465 group_chat2_id = res.group_chat_id
467 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat1_id))
468 assert res.title == "Test title"
469 assert user2.id in res.member_user_ids
470 assert user1.id in res.admin_user_ids
471 assert to_aware_datetime(res.created) <= now()
472 assert res.only_admins_invite
473 assert res.is_dm
474 assert not res.is_archived
476 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat2_id))
477 assert not res.title
478 assert user2.id in res.member_user_ids
479 assert user3.id in res.member_user_ids
480 assert user1.id in res.admin_user_ids
481 assert to_aware_datetime(res.created) <= now()
482 assert res.only_admins_invite
483 assert not res.is_dm
484 assert not res.is_archived
487def test_get_group_chat_info_denied(db):
488 user1, token1 = generate_user()
489 user2, token2 = generate_user()
490 user3, token3 = generate_user()
491 user4, token4 = generate_user()
493 make_friends(user1, user2)
494 make_friends(user3, user1)
496 with conversations_session(token1) as c:
497 # create a group chat with messages
498 res = c.CreateGroupChat(
499 conversations_pb2.CreateGroupChatReq(
500 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title")
501 )
502 )
503 group_chat_id = res.group_chat_id
504 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
506 with conversations_session(token4) as c:
507 with pytest.raises(grpc.RpcError) as e:
508 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
509 assert e.value.code() == grpc.StatusCode.NOT_FOUND
512def test_get_group_chat_info_left(db, moderator):
513 user1, token1 = generate_user()
514 user2, token2 = generate_user()
515 user3, token3 = generate_user()
516 user4, token4 = generate_user()
518 make_friends(user1, user2)
519 make_friends(user3, user1)
520 make_friends(user1, user4)
522 with conversations_session(token1) as c:
523 # create a group chat with messages
524 res = c.CreateGroupChat(
525 conversations_pb2.CreateGroupChatReq(
526 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title")
527 )
528 )
529 group_chat_id = res.group_chat_id
530 moderator.approve_group_chat(group_chat_id)
531 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
533 with conversations_session(token3) as c:
534 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
536 with conversations_session(token1) as c:
537 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user4.id))
539 with conversations_session(token3) as c:
540 # this user left when user4 wasn't a member,
541 # so the returned members should be user1, user2, and user3 only
542 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
543 assert len(res.member_user_ids) == 3
544 assert user1.id in res.member_user_ids
545 assert user2.id in res.member_user_ids
546 assert user3.id in res.member_user_ids
549def test_remove_group_chat_user(db):
550 # create 3 uses and connect them
551 user1, token1 = generate_user()
552 user2, token2 = generate_user()
553 user3, token3 = generate_user()
554 make_friends(user1, user2)
555 make_friends(user1, user3)
557 # using user token, create a Conversations API for testing
558 with conversations_session(token1) as c:
559 # create a group chat
560 res = c.CreateGroupChat(
561 conversations_pb2.CreateGroupChatReq(
562 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title")
563 )
564 )
565 group_chat_id = res.group_chat_id
567 # remove a user from group
568 c.RemoveGroupChatUser(conversations_pb2.RemoveGroupChatUserReq(group_chat_id=group_chat_id, user_id=user2.id))
569 assert user3.id in res.member_user_ids # other users are still in the group
571 # can't remove the same user twice
572 with pytest.raises(grpc.RpcError) as e:
573 c.RemoveGroupChatUser(
574 conversations_pb2.RemoveGroupChatUserReq(group_chat_id=group_chat_id, user_id=user2.id)
575 )
576 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
579def test_edit_group_chat(db, moderator):
580 user1, token1 = generate_user()
581 user2, token2 = generate_user()
582 user3, token3 = generate_user()
583 make_friends(user1, user2)
585 with conversations_session(token1) as c:
586 # create some threads with messages
587 res = c.CreateGroupChat(
588 conversations_pb2.CreateGroupChatReq(
589 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title")
590 )
591 )
592 group_chat_id = res.group_chat_id
593 moderator.approve_group_chat(group_chat_id)
595 c.EditGroupChat(
596 conversations_pb2.EditGroupChatReq(
597 group_chat_id=group_chat_id,
598 title=wrappers_pb2.StringValue(value="Modified title"),
599 only_admins_invite=wrappers_pb2.BoolValue(value=False),
600 )
601 )
602 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
603 assert res.title == "Modified title"
604 assert not res.only_admins_invite
606 # make sure non-admin is not allowed to modify
607 with conversations_session(token2) as c:
608 with pytest.raises(grpc.RpcError) as e:
609 c.EditGroupChat(
610 conversations_pb2.EditGroupChatReq(
611 group_chat_id=group_chat_id,
612 title=wrappers_pb2.StringValue(value="Other title"),
613 only_admins_invite=wrappers_pb2.BoolValue(value=True),
614 )
615 )
616 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
618 # make sure non-recipient is not allowed to modify
619 with conversations_session(token3) as c:
620 with pytest.raises(grpc.RpcError) as e:
621 c.EditGroupChat(
622 conversations_pb2.EditGroupChatReq(
623 group_chat_id=group_chat_id,
624 title=wrappers_pb2.StringValue(value="Other title"),
625 only_admins_invite=wrappers_pb2.BoolValue(value=True),
626 )
627 )
628 assert e.value.code() == grpc.StatusCode.NOT_FOUND
631def test_make_remove_group_chat_admin(db, moderator):
632 user1, token1 = generate_user()
633 user2, token2 = generate_user()
634 user3, token3 = generate_user()
636 make_friends(user1, user2)
637 make_friends(user1, user3)
638 make_friends(user2, user3)
640 with conversations_session(token1) as c:
641 # create some threads with messages
642 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
643 group_chat_id = res.group_chat_id
644 moderator.approve_group_chat(group_chat_id)
646 # shouldn't be able to remove only admin
647 with pytest.raises(grpc.RpcError) as e:
648 c.RemoveGroupChatAdmin(
649 conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user1.id)
650 )
651 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
652 assert e.value.details() == "You can't remove the last admin."
654 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user2.id))
656 # shouldn't be able to make admin again
657 with pytest.raises(grpc.RpcError) as e:
658 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user2.id))
659 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
660 assert e.value.details() == "That user is already an admin."
662 with conversations_session(token2) as c:
663 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
664 assert user1.id in res.admin_user_ids
665 assert user2.id in res.admin_user_ids
667 with conversations_session(token1) as c:
668 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user2.id))
670 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
671 assert user1.id in res.admin_user_ids
672 assert user2.id not in res.admin_user_ids
674 with conversations_session(token2) as c:
675 # shouldn't be able to make admin if not admin
676 with pytest.raises(grpc.RpcError) as e:
677 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user3.id))
678 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
681def test_send_message(db, moderator: Moderator, push_collector: PushCollector, email_collector: EmailCollector):
682 user1, token1 = generate_user()
683 user2, token2 = generate_user()
684 user3, token3 = generate_user()
685 make_friends(user1, user2)
686 make_friends(user1, user3)
688 # Let user2 receive email notifications for every chat message
689 with notifications_session(token2) as n:
690 n.SetNotificationSettings(
691 notifications_pb2.SetNotificationSettingsReq(
692 preferences=[
693 notifications_pb2.SingleNotificationPreference(
694 topic=NotificationTopicAction.chat__message.topic,
695 action=NotificationTopicAction.chat__message.action,
696 delivery_method="email",
697 enabled=True,
698 )
699 ]
700 )
701 )
703 group_chat_title = "My group chat"
704 message1 = "Test message 1"
706 # Let user1 create a group chat with user2 and send a message
707 with conversations_session(token1) as c:
708 res = c.CreateGroupChat(
709 conversations_pb2.CreateGroupChatReq(
710 title=wrappers_pb2.StringValue(value=group_chat_title), recipient_user_ids=[user2.id]
711 )
712 )
713 group_chat_id = res.group_chat_id
714 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=message1))
716 # Sender can already see group chat
717 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
718 assert res.messages[0].text.text == message1
719 assert to_aware_datetime(res.messages[0].time) <= now()
720 assert res.messages[0].author_user_id == user1.id
722 # user2 sees nothing until the group chat is approved
723 assert push_collector.count_for_user(user2.id) == 0
724 assert email_collector.count_for_recipient(user2.email) == 0
726 moderator.approve_group_chat(group_chat_id)
728 # user2 gets email and push notifications
729 push = push_collector.pop_for_user(user2.id, last=True)
730 assert push.topic_action == NotificationTopicAction.chat__message.display
731 assert message1 in push.content.body
733 email = email_collector.pop_for_recipient(user2.email, last=True)
734 assert group_chat_title in email.subject
735 assert message1 in email.plain
736 assert message1 in email.html
738 # can't send message if not in chat
739 with conversations_session(token3) as c:
740 with pytest.raises(grpc.RpcError) as e:
741 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 2"))
742 assert e.value.code() == grpc.StatusCode.NOT_FOUND
744 make_user_block(user2, user1)
745 with conversations_session(token1) as c:
746 with pytest.raises(grpc.RpcError) as e:
747 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Message after block"))
748 assert e.value.details() == "You can't send a message in this chat."
751def test_send_direct_message(db, moderator: Moderator, push_collector: PushCollector, email_collector: EmailCollector):
752 user1, token1 = generate_user(complete_profile=True)
753 user2, token2 = generate_user(complete_profile=True)
755 make_friends(user1, user2)
757 # Let user2 receive email notifications for every chat message
758 with notifications_session(token2) as n:
759 n.SetNotificationSettings(
760 notifications_pb2.SetNotificationSettingsReq(
761 preferences=[
762 notifications_pb2.SingleNotificationPreference(
763 topic=NotificationTopicAction.chat__message.topic,
764 action=NotificationTopicAction.chat__message.action,
765 delivery_method="email",
766 enabled=True,
767 )
768 ]
769 )
770 )
772 # Let user1 send two DM's to user2
773 message1 = "Hello, user2!"
774 message2 = "One more message."
776 with conversations_session(token1) as c1:
777 # Send a DM from user1 to user2
778 res = c1.SendDirectMessage(conversations_pb2.SendDirectMessageReq(recipient_user_id=user2.id, text=message1))
779 moderator.approve_group_chat(res.group_chat_id)
781 c1.SendDirectMessage(conversations_pb2.SendDirectMessageReq(recipient_user_id=user2.id, text=message2))
783 # user2 should have received push and email notifications for both messages
784 push = push_collector.pop_for_user(user2.id, last=False)
785 assert push.topic_action == NotificationTopicAction.chat__message.display
786 assert push.content.title == user1.name
787 assert push.content.body == message1
789 email = email_collector.pop_for_recipient(user2.email, last=False)
790 assert user1.name in email.subject
791 assert message1 in email.plain
792 assert message1 in email.html
794 push = push_collector.pop_for_user(user2.id, last=True)
795 assert push.topic_action == NotificationTopicAction.chat__message.display
796 assert push.content.title == user1.name
797 assert push.content.body == message2
799 email = email_collector.pop_for_recipient(user2.email, last=True)
800 assert user1.name in email.subject
801 assert message2 in email.plain
802 assert message2 in email.html
804 with conversations_session(token2) as c2:
805 # Fetch the chat by ID returned from SendDirectMessage
806 chat = c2.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=res.group_chat_id))
808 assert chat.is_dm
809 group_chat_id = chat.group_chat_id
811 # Verify that the messages was received
812 messages = c2.GetGroupChatMessages(
813 conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id)
814 ).messages
816 assert len(messages) == 2
817 assert messages[0].text.text == message2
818 assert messages[1].text.text == message1
819 assert messages[0].author_user_id == user1.id
822def test_excessive_chat_initiations_are_reported(db, email_collector: EmailCollector):
823 """Test that excessive chat initiations are first reported in a warning email and finally lead blocking of further contacting other users."""
824 user, token = generate_user()
825 rate_limit_definition = RATE_LIMIT_DEFINITIONS[RateLimitAction.chat_initiation]
826 with conversations_session(token) as c:
827 # Test warning email
828 for _ in range(rate_limit_definition.warning_limit):
829 recipient_user, _ = generate_user()
830 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id]))
832 assert email_collector.count_for_reports() == 0
834 recipient_user, _ = generate_user()
835 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id]))
837 email = email_collector.pop_for_reports(last=True)
838 assert email.plain.startswith(
839 f"User {user.username} has sent {rate_limit_definition.warning_limit} chat initiations in the past {RATE_LIMIT_HOURS} hours."
840 )
842 # Test new chat initiations fail after exceeding CHAT_INITIATION_HARD_LIMIT
843 for _ in range(rate_limit_definition.hard_limit - rate_limit_definition.warning_limit - 1):
844 recipient_user, _ = generate_user()
845 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id]))
847 assert email_collector.count_for_reports() == 0
849 recipient_user, _ = generate_user()
850 with pytest.raises(grpc.RpcError) as exc_info:
851 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id]))
852 assert exc_info.value.code() == grpc.StatusCode.RESOURCE_EXHAUSTED
853 assert (
854 exc_info.value.details()
855 == "You have messaged a lot of users in the past 24 hours. To avoid spam, you can't contact any more users for now."
856 )
858 email = email_collector.pop_for_reports(last=True)
859 assert email.plain.startswith(
860 f"User {user.username} has sent {rate_limit_definition.hard_limit} chat initiations in the past {RATE_LIMIT_HOURS} hours."
861 )
862 assert "The user has been blocked from sending further chat initiations for now." in email.plain
865def test_send_direct_message_rate_limit(db, moderator, email_collector: EmailCollector):
866 """SendDirectMessage should enforce the chat_initiation rate limit when creating a new DM, but not when sending into an existing one."""
867 user, token = generate_user(complete_profile=True)
868 rate_limit_definition = RATE_LIMIT_DEFINITIONS[RateLimitAction.chat_initiation]
870 with conversations_session(token) as c:
871 for _ in range(rate_limit_definition.warning_limit):
872 recipient, _ = generate_user()
873 c.SendDirectMessage(conversations_pb2.SendDirectMessageReq(recipient_user_id=recipient.id, text="hi"))
875 assert email_collector.count_for_reports() == 0
877 recipient, _ = generate_user()
878 existing_dm_recipient_id = recipient.id
879 c.SendDirectMessage(
880 conversations_pb2.SendDirectMessageReq(recipient_user_id=existing_dm_recipient_id, text="hi")
881 )
883 email = email_collector.pop_for_reports(last=True)
884 assert email.plain.startswith(
885 f"User {user.username} has sent {rate_limit_definition.warning_limit} chat initiations in the past {RATE_LIMIT_HOURS} hours."
886 )
888 for _ in range(rate_limit_definition.hard_limit - rate_limit_definition.warning_limit - 1):
889 recipient, _ = generate_user()
890 c.SendDirectMessage(conversations_pb2.SendDirectMessageReq(recipient_user_id=recipient.id, text="hi"))
892 assert email_collector.count_for_reports() == 0
894 # follow-up into an existing DM must not count as a new initiation
895 c.SendDirectMessage(
896 conversations_pb2.SendDirectMessageReq(recipient_user_id=existing_dm_recipient_id, text="follow-up")
897 )
898 assert email_collector.count_for_reports() == 0
900 recipient, _ = generate_user()
901 with pytest.raises(grpc.RpcError) as exc_info:
902 c.SendDirectMessage(conversations_pb2.SendDirectMessageReq(recipient_user_id=recipient.id, text="hi"))
903 assert exc_info.value.code() == grpc.StatusCode.RESOURCE_EXHAUSTED
904 assert (
905 exc_info.value.details()
906 == "You have messaged a lot of users in the past 24 hours. To avoid spam, you can't contact any more users for now."
907 )
909 email = email_collector.pop_for_reports(last=True)
910 assert email.plain.startswith(
911 f"User {user.username} has sent {rate_limit_definition.hard_limit} chat initiations in the past {RATE_LIMIT_HOURS} hours."
912 )
913 assert "The user has been blocked from sending further chat initiations for now." in email.plain
916def test_leave_invite_to_group_chat(db, moderator):
917 user1, token1 = generate_user()
918 user2, token2 = generate_user()
919 user3, token3 = generate_user()
920 user4, token4 = generate_user()
921 user5, token5 = generate_user()
922 user6, token6 = generate_user(delete_user=True)
923 user7, token7 = generate_user()
924 user8, token8 = generate_user()
926 make_friends(user1, user2)
927 make_friends(user1, user3)
928 make_friends(user1, user5)
929 make_friends(user1, user7)
930 make_friends(user1, user8)
931 make_friends(user2, user3)
932 make_friends(user4, user3)
933 make_user_block(user1, user7)
934 make_user_block(user8, user1)
936 with conversations_session(token1) as c:
937 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user5.id]))
938 group_chat_id = res.group_chat_id
939 moderator.approve_group_chat(group_chat_id)
940 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
942 # other user not in chat
943 with conversations_session(token3) as c:
944 with pytest.raises(grpc.RpcError) as e:
945 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
946 assert e.value.code() == grpc.StatusCode.NOT_FOUND
947 with pytest.raises(grpc.RpcError) as e:
948 res = c.InviteToGroupChat(
949 conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user4.id)
950 )
951 assert e.value.code() == grpc.StatusCode.NOT_FOUND
952 with pytest.raises(grpc.RpcError) as e:
953 res = c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
954 assert e.value.code() == grpc.StatusCode.NOT_FOUND
956 with conversations_session(token2) as c:
957 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
958 assert user3.id not in res.member_user_ids
960 # only_admins_invite defaults to true so shouldn't be able to invite
961 with pytest.raises(grpc.RpcError) as e:
962 res = c.InviteToGroupChat(
963 conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)
964 )
965 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
966 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
968 with conversations_session(token1) as c:
969 # invite invisible user fails
970 with pytest.raises(grpc.RpcError) as e:
971 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user6.id))
972 assert e.value.code() == grpc.StatusCode.NOT_FOUND
973 assert e.value.details() == "Couldn't find that user."
974 # invite fake user fails
975 with pytest.raises(grpc.RpcError) as e:
976 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=999))
977 assert e.value.code() == grpc.StatusCode.NOT_FOUND
978 assert e.value.details() == "Couldn't find that user."
979 # invite blocked user fails
980 with pytest.raises(grpc.RpcError) as e:
981 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user7.id))
982 assert e.value.code() == grpc.StatusCode.NOT_FOUND
983 assert e.value.details() == "Couldn't find that user."
984 # invite blocking user fails
985 with pytest.raises(grpc.RpcError) as e:
986 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user8.id))
987 assert e.value.code() == grpc.StatusCode.NOT_FOUND
988 assert e.value.details() == "Couldn't find that user."
990 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
991 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
992 assert user1.id in res.member_user_ids
993 assert user5.id in res.member_user_ids
994 assert user3.id in res.member_user_ids
996 # test non-admin inviting
997 c.EditGroupChat(
998 conversations_pb2.EditGroupChatReq(
999 group_chat_id=group_chat_id, only_admins_invite=wrappers_pb2.BoolValue(value=False)
1000 )
1001 )
1003 with conversations_session(token3) as c:
1004 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user2.id))
1005 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
1006 assert user2.id in res.member_user_ids
1009def test_group_chats_with_messages_before_join(db, moderator):
1010 """
1011 If user 1 and 2 have a group chat and send messages, then add user 3; user 3
1012 should still see the group chat!
1013 """
1014 user1, token1 = generate_user()
1015 user2, token2 = generate_user()
1016 user3, token3 = generate_user()
1017 user4, token4 = generate_user()
1019 make_friends(user1, user2)
1020 make_friends(user1, user3)
1021 make_friends(user2, user3)
1022 make_friends(user1, user4)
1024 with conversations_session(token1) as c:
1025 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id]))
1026 group_chat_id = res.group_chat_id
1027 moderator.approve_group_chat(group_chat_id)
1028 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
1030 with conversations_session(token2) as c:
1031 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 2"))
1033 with conversations_session(token1) as c:
1034 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 3"))
1036 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
1038 with conversations_session(token3) as c:
1039 # should work
1040 c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
1042 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
1043 assert len(res.group_chats) == 1
1046def test_invite_to_dm(db):
1047 user1, token1 = generate_user()
1048 user2, token2 = generate_user()
1049 user3, token3 = generate_user()
1051 make_friends(user1, user2)
1052 make_friends(user1, user3)
1053 make_friends(user2, user3)
1055 with conversations_session(token1) as c:
1056 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
1057 group_chat_id = res.group_chat_id
1058 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
1060 # dm, shou;dn't be able to invite someone else
1061 with pytest.raises(grpc.RpcError) as e:
1062 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
1063 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1064 assert e.value.details() == "You can't invite other users to a direct message."
1067def test_sole_admin_leaves(db, moderator):
1068 user1, token1 = generate_user()
1069 user2, token2 = generate_user()
1070 user3, token3 = generate_user()
1072 make_friends(user1, user2)
1073 make_friends(user1, user3)
1074 make_friends(user2, user3)
1076 with conversations_session(token1) as c:
1077 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
1078 group_chat_id = res.group_chat_id
1079 moderator.approve_group_chat(group_chat_id)
1080 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
1082 # sole admin can't leave group chat
1083 with pytest.raises(grpc.RpcError) as e:
1084 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
1085 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1086 assert e.value.details() == "The last admin can't leave a group chat."
1088 with conversations_session(token2) as c:
1089 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
1091 with conversations_session(token3) as c:
1092 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
1094 # sole admin can leave when last in chat
1095 with conversations_session(token1) as c:
1096 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
1099def test_search_messages(db, moderator):
1100 user1, token1 = generate_user()
1101 user2, token2 = generate_user()
1102 user3, token3 = generate_user()
1104 make_friends(user1, user2)
1105 make_friends(user1, user3)
1107 with conversations_session(token1) as c:
1108 # create some threads with messages
1109 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
1110 gc1_id = res.group_chat_id
1111 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gc1_id, text="Test message 1"))
1112 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gc1_id, text="Test message 2"))
1113 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
1114 gc2_id = res.group_chat_id
1115 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gc2_id, text="Test group message 3"))
1116 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gc2_id, text="Test group message 4"))
1118 # Approve group chats so they appear in search results
1119 moderator.approve_group_chat(gc1_id)
1120 moderator.approve_group_chat(gc2_id)
1122 with conversations_session(token1) as c:
1123 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="message "))
1124 assert len(res.results) == 4
1125 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="group "))
1126 assert len(res.results) == 2
1127 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="message 5"))
1128 assert len(res.results) == 0
1130 # outside user doesn't get results
1131 with conversations_session(token3) as c:
1132 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message"))
1133 assert len(res.results) == 0
1136def test_search_messages_left_joined(db, moderator):
1137 user1, token1 = generate_user()
1138 user2, token2 = generate_user()
1139 user3, token3 = generate_user()
1140 user4, token4 = generate_user()
1141 make_friends(user1, user2)
1142 make_friends(user1, user3)
1143 make_friends(user1, user4)
1145 with conversations_session(token1) as c:
1146 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id]))
1147 group_chat_id = res.group_chat_id
1148 moderator.approve_group_chat(group_chat_id)
1149 for i in range(10):
1150 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message " + str(i)))
1152 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
1153 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 10"))
1154 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message"))
1156 assert len(res.results) == 11
1158 with conversations_session(token3) as c:
1159 # can only see last message after invited
1160 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message"))
1162 assert len(res.results) == 1
1163 assert res.results[0].message.text.text == "Test message 10"
1165 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
1167 with conversations_session(token1) as c:
1168 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 11"))
1169 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 12"))
1170 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
1171 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 13"))
1172 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 14"))
1174 with conversations_session(token3) as c:
1175 # can only see last message after invited
1176 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message"))
1177 assert len(res.results) == 3
1178 assert res.results[0].message.text.text == "Test message 14"
1179 assert res.results[1].message.text.text == "Test message 13"
1180 assert res.results[2].message.text.text == "Test message 10"
1183def test_admin_behaviour(db, moderator):
1184 user1, token1 = generate_user()
1185 user2, token2 = generate_user()
1186 user3, token3 = generate_user()
1188 make_friends(user1, user2)
1189 make_friends(user1, user3)
1190 make_friends(user2, user3)
1192 with conversations_session(token1) as c:
1193 gcid = c.CreateGroupChat(
1194 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])
1195 ).group_chat_id
1196 moderator.approve_group_chat(gcid)
1197 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user2.id))
1198 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1199 assert len(res.admin_user_ids) == 2
1200 assert user1.id in res.admin_user_ids
1201 assert user2.id in res.admin_user_ids
1203 with conversations_session(token3) as c:
1204 with pytest.raises(grpc.RpcError) as e:
1205 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1206 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1207 with pytest.raises(grpc.RpcError) as e:
1208 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id))
1209 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1210 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1211 assert len(res.admin_user_ids) == 2
1212 assert user1.id in res.admin_user_ids
1213 assert user2.id in res.admin_user_ids
1215 with conversations_session(token2) as c:
1216 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1217 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1218 assert len(res.admin_user_ids) == 3
1219 assert user1.id in res.admin_user_ids
1220 assert user2.id in res.admin_user_ids
1221 assert user3.id in res.admin_user_ids
1223 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id))
1224 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1225 assert len(res.admin_user_ids) == 2
1226 assert user2.id in res.admin_user_ids
1227 assert user3.id in res.admin_user_ids
1229 with conversations_session(token1) as c:
1230 with pytest.raises(grpc.RpcError):
1231 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id))
1232 with pytest.raises(grpc.RpcError):
1233 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1234 with pytest.raises(grpc.RpcError):
1235 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user2.id))
1236 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1237 assert len(res.admin_user_ids) == 2
1238 assert user2.id in res.admin_user_ids
1239 assert user3.id in res.admin_user_ids
1241 with conversations_session(token2) as c:
1242 # can demote self if there are other admins
1243 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user2.id))
1244 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1245 assert len(res.admin_user_ids) == 1
1246 assert user3.id in res.admin_user_ids
1248 with conversations_session(token3) as c:
1249 with pytest.raises(grpc.RpcError) as e:
1250 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1251 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1252 assert e.value.details() == "You can't remove the last admin."
1253 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1254 assert len(res.admin_user_ids) == 1
1255 assert user3.id in res.admin_user_ids
1257 # last admin can't leave
1258 with pytest.raises(grpc.RpcError) as e:
1259 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid))
1260 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1261 assert e.value.details() == "The last admin can't leave a group chat."
1263 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id))
1265 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid))
1267 with conversations_session(token2) as c:
1268 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid))
1270 # last participant must be admin but can leave to orphan chat
1271 with conversations_session(token1) as c:
1272 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid))
1275def test_add_remove_admin_failures(db):
1276 user1, token1 = generate_user()
1277 user2, token2 = generate_user()
1278 user3, token3 = generate_user()
1279 user4, token4 = generate_user()
1280 user5, token5 = generate_user()
1282 make_friends(user1, user2)
1283 make_friends(user1, user3)
1284 make_friends(user1, user4)
1285 make_friends(user1, user5)
1287 with conversations_session(token1) as c:
1288 gcid = c.CreateGroupChat(
1289 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id, user4.id, user5.id])
1290 ).group_chat_id
1292 make_user_invisible(user3.id)
1293 make_user_block(user1, user4)
1294 make_user_block(user5, user1)
1296 # make non-existent user admin
1297 with pytest.raises(grpc.RpcError) as e:
1298 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=999))
1299 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1300 assert e.value.details() == "Couldn't find that user."
1302 # make invisible user admin
1303 with pytest.raises(grpc.RpcError) as e:
1304 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1305 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1306 assert e.value.details() == "Couldn't find that user."
1308 # make blocked user admin
1309 with pytest.raises(grpc.RpcError) as e:
1310 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user4.id))
1311 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1312 assert e.value.details() == "Couldn't find that user."
1314 # make blocking user admin
1315 with pytest.raises(grpc.RpcError) as e:
1316 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user5.id))
1317 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1318 assert e.value.details() == "Couldn't find that user."
1320 with session_scope() as session:
1321 subscriptions = (
1322 session.execute(
1323 select(GroupChatSubscription)
1324 .where(GroupChatSubscription.group_chat_id == gcid)
1325 .where(GroupChatSubscription.role == GroupChatRole.participant)
1326 )
1327 .scalars()
1328 .all()
1329 )
1331 for subscription in subscriptions:
1332 subscription.role = GroupChatRole.admin
1334 with conversations_session(token1) as c:
1335 # remove non-existent user admin
1336 with pytest.raises(grpc.RpcError) as e:
1337 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=999))
1338 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1339 assert e.value.details() == "Couldn't find that user."
1341 # remove invisible admin
1342 with pytest.raises(grpc.RpcError) as e:
1343 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1344 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1345 assert e.value.details() == "Couldn't find that user."
1347 # remove blocked admin
1348 with pytest.raises(grpc.RpcError) as e:
1349 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user4.id))
1350 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1351 assert e.value.details() == "Couldn't find that user."
1353 # remove blocking admin
1354 with pytest.raises(grpc.RpcError) as e:
1355 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user5.id))
1356 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1357 assert e.value.details() == "Couldn't find that user."
1360def test_last_seen(db, moderator):
1361 user1, token1 = generate_user()
1362 user2, token2 = generate_user()
1363 user3, token3 = generate_user()
1365 make_friends(user1, user2)
1366 make_friends(user1, user3)
1367 make_friends(user2, user3)
1369 with conversations_session(token3) as c:
1370 # this is just here to mess up any issues we get if we pretend there's only one group chat ever
1371 gcid_distraction = c.CreateGroupChat(
1372 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user1.id])
1373 ).group_chat_id
1374 moderator.approve_group_chat(gcid_distraction)
1376 with conversations_session(token1) as c:
1377 gcid = c.CreateGroupChat(
1378 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])
1379 ).group_chat_id
1380 moderator.approve_group_chat(gcid)
1382 message_ids = []
1384 for i in range(6):
1385 c.SendMessage(
1386 conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text=f"gibberish message... {i}")
1387 )
1388 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}"))
1389 c.SendMessage(
1390 conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text=f"gibberish message {i}")
1391 )
1393 message_ids.append(
1394 c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)).latest_message.message_id
1395 )
1397 # messages are automatically marked as seen when you send a new message
1398 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1399 assert res.unseen_message_count == 0
1401 with conversations_session(token2) as c:
1402 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1403 # created + 6 normal
1404 assert res.unseen_message_count == 7
1406 backward_offset = 3
1407 c.MarkLastSeenGroupChat(
1408 conversations_pb2.MarkLastSeenGroupChatReq(
1409 group_chat_id=gcid, last_seen_message_id=message_ids[-backward_offset - 1]
1410 )
1411 )
1413 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1414 assert res.unseen_message_count == backward_offset
1416 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="test message ..."))
1418 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1419 assert res.unseen_message_count == 0
1421 with conversations_session(token3) as c:
1422 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1423 # created + 7 normal
1424 assert res.unseen_message_count == 8
1426 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="test message ..."))
1428 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1429 assert res.unseen_message_count == 0
1432def test_mark_last_seen_clears_notifications(db, moderator):
1433 user1, token1 = generate_user()
1434 user2, token2 = generate_user()
1436 with conversations_session(token1) as c:
1437 gcid = c.CreateGroupChat(
1438 conversations_pb2.CreateGroupChatReq(
1439 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test chat")
1440 )
1441 ).group_chat_id
1443 moderator.approve_group_chat(gcid)
1445 with conversations_session(token1) as c:
1446 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="Hello"))
1448 process_jobs()
1450 def unseen_notification_count(user_id):
1451 with session_scope() as session:
1452 return session.execute(
1453 select(func.count())
1454 .select_from(Notification)
1455 .where(Notification.user_id == user_id)
1456 .where(Notification.key == str(gcid))
1457 .where(Notification.is_seen == False)
1458 ).scalar_one()
1460 assert unseen_notification_count(user2.id) > 0
1462 with conversations_session(token2) as c:
1463 c.MarkLastSeenGroupChat(conversations_pb2.MarkLastSeenGroupChatReq(group_chat_id=gcid, last_seen_message_id=1))
1465 assert unseen_notification_count(user2.id) == 0
1468def test_one_dm_per_pair(db, moderator):
1469 user1, token1 = generate_user()
1470 user2, token2 = generate_user()
1471 user3, token3 = generate_user()
1473 make_friends(user1, user2)
1474 make_friends(user1, user3)
1475 make_friends(user2, user3)
1477 with conversations_session(token1) as c:
1478 # create DM with user 2
1479 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
1480 assert res.is_dm
1481 dm_with_user2 = res.group_chat_id
1483 # create DM with user 3
1484 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
1485 assert res.is_dm
1486 dm_with_user3 = res.group_chat_id
1488 # can't create another group chat with just user 2
1489 with pytest.raises(grpc.RpcError) as e:
1490 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
1491 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1493 # can't create another group chat with just user 3
1494 with pytest.raises(grpc.RpcError) as e:
1495 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
1496 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1498 # can create joined group chat
1499 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
1500 assert not res.is_dm
1502 # Approve the DMs so user2 can see them (otherwise they're SHADOWED and only visible to creator)
1503 moderator.approve_group_chat(dm_with_user2)
1505 with conversations_session(token2) as c:
1506 # can create DM with user 3
1507 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
1508 assert res.is_dm
1510 # can't create another group chat with just user 1 (DM was approved, so user2 can see it)
1511 with pytest.raises(grpc.RpcError) as e:
1512 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user1.id]))
1513 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1516def test_GetDirectMessage(db):
1517 user1, token1 = generate_user()
1518 user2, token2 = generate_user()
1519 user3, token3 = generate_user()
1521 make_friends(user1, user2)
1522 make_friends(user1, user3)
1523 make_friends(user2, user3)
1525 with conversations_session(token1) as c:
1526 # no group chat with user 2
1527 with pytest.raises(grpc.RpcError) as e:
1528 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user2.id))
1529 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1531 # no group chat with nor user 3
1532 with pytest.raises(grpc.RpcError) as e:
1533 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user3.id))
1534 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1536 # create DM with user 2
1537 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
1538 assert res.is_dm
1539 gcid = res.group_chat_id
1541 # now should exist
1542 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user2.id))
1543 assert res.group_chat_id == gcid
1544 assert not res.is_archived
1546 # create DM with user 3
1547 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
1548 assert res.is_dm
1550 # can create joined group chat
1551 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
1552 assert not res.is_dm
1554 with conversations_session(token2) as c:
1555 # can create DM with user 3
1556 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
1557 assert res.is_dm
1558 assert res.can_message
1559 gcid = res.group_chat_id
1561 # DM with 3 should exist, but can't message after being blocked
1562 make_user_block(user3, user2)
1563 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user3.id))
1564 assert res.group_chat_id == gcid
1565 assert not res.can_message
1568def test_total_unseen(db, moderator):
1569 user1, token1 = generate_user()
1570 user2, token2 = generate_user()
1571 user3, token3 = generate_user()
1573 # distractions
1574 user4, token4 = generate_user()
1576 make_friends(user1, user2)
1577 make_friends(user1, user3)
1578 make_friends(user2, user3)
1580 # distractions
1581 make_friends(user1, user4)
1583 with conversations_session(token1) as c:
1584 # distractions
1585 gcid_distraction = c.CreateGroupChat(
1586 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user4.id])
1587 ).group_chat_id
1588 moderator.approve_group_chat(gcid_distraction)
1589 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction..."))
1591 gcid = c.CreateGroupChat(
1592 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])
1593 ).group_chat_id
1594 moderator.approve_group_chat(gcid)
1596 for i in range(6):
1597 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}"))
1599 # distractions
1600 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction..."))
1602 # messages are automatically marked as seen when you send a new message
1603 with api_session(token1) as api:
1604 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0
1606 with api_session(token2) as api:
1607 # chat created + 6 normal messages
1608 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 7
1610 # now leave chat with user2
1611 with conversations_session(token2) as c:
1612 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid))
1614 with api_session(token2) as api:
1615 # seen messages becomes 0 when leaving
1616 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0
1618 with conversations_session(token1) as c:
1619 # distractions
1620 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction..."))
1622 # send more stuff without user 2
1623 for i in range(3):
1624 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}"))
1626 # distractions
1627 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction..."))
1629 with api_session(token2) as api:
1630 # seen messages becomes 0 when leaving
1631 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0
1633 with conversations_session(token1) as c:
1634 # add user 2 back
1635 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=gcid, user_id=user2.id))
1637 # send more stuff with user 2
1638 for i in range(12):
1639 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}"))
1641 # distractions
1642 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction..."))
1644 with api_session(token2) as api:
1645 # joined + 12 normal
1646 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 13
1649def test_regression_ListGroupChats_pagination(db, moderator):
1650 user1, token1 = generate_user()
1651 user2, token2 = generate_user()
1652 user3, token3 = generate_user()
1654 make_friends(user1, user2)
1655 make_friends(user1, user3)
1657 with conversations_session(token1) as c:
1658 # tuples of (group_chat_id, message_id)
1659 group_chat_and_message_ids = []
1660 for i in range(50):
1661 res1 = c.CreateGroupChat(
1662 conversations_pb2.CreateGroupChatReq(
1663 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value=f"Chat {i}")
1664 )
1665 )
1667 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res1.group_chat_id, text=f"Test message {i}"))
1669 res2 = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=res1.group_chat_id))
1671 group_chat_and_message_ids.append((res2.group_chat_id, res2.latest_message.message_id))
1672 moderator.approve_group_chat(res1.group_chat_id)
1674 seen_group_chat_ids = []
1676 last_message_id = 0
1677 more = True
1678 while more:
1679 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(last_message_id=last_message_id))
1680 last_message_id = res.last_message_id
1681 more = not res.no_more
1683 seen_group_chat_ids.extend([chat.group_chat_id for chat in res.group_chats])
1685 assert set(seen_group_chat_ids) == {x[0] for x in group_chat_and_message_ids}, "Not all group chats returned"
1688def test_muting(db, moderator):
1689 user1, token1 = generate_user()
1690 user2, token2 = generate_user()
1691 user3, token3 = generate_user()
1693 make_friends(user1, user2)
1694 make_friends(user1, user3)
1695 make_friends(user2, user3)
1697 with conversations_session(token3) as c:
1698 # this is just here to mess up any issues we get if we pretend there's only one group chat ever
1699 gcid_distraction = c.CreateGroupChat(
1700 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user1.id])
1701 ).group_chat_id
1702 moderator.approve_group_chat(gcid_distraction)
1704 with conversations_session(token1) as c:
1705 gcid = c.CreateGroupChat(
1706 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])
1707 ).group_chat_id
1708 moderator.approve_group_chat(gcid)
1710 with conversations_session(token2) as c:
1711 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1712 assert not res.mute_info.muted
1713 assert not res.mute_info.HasField("muted_until")
1715 c.MuteGroupChat(conversations_pb2.MuteGroupChatReq(group_chat_id=gcid, forever=True))
1716 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1717 assert res.mute_info.muted
1718 assert not res.mute_info.HasField("muted_until")
1720 c.MuteGroupChat(conversations_pb2.MuteGroupChatReq(group_chat_id=gcid, unmute=True))
1721 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1722 assert not res.mute_info.muted
1723 assert not res.mute_info.HasField("muted_until")
1725 c.MuteGroupChat(
1726 conversations_pb2.MuteGroupChatReq(
1727 group_chat_id=gcid, for_duration=Duration_from_timedelta(timedelta(hours=2))
1728 )
1729 )
1730 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1731 assert res.mute_info.muted
1732 assert res.mute_info.HasField("muted_until")
1733 assert to_aware_datetime(res.mute_info.muted_until) >= now() + timedelta(hours=1, minutes=59)
1734 assert to_aware_datetime(res.mute_info.muted_until) <= now() + timedelta(hours=2, minutes=1)
1737def test_archiving(db, moderator):
1738 """Test SetGroupChatArchiveStatus RPC with GetGroupChat and ListGroupChats"""
1739 user1, token1 = generate_user()
1740 user2, token2 = generate_user()
1741 user3, token3 = generate_user()
1743 make_friends(user1, user2)
1744 make_friends(user1, user3)
1745 make_friends(user2, user3)
1747 # Create a distraction chat to ensure we're testing the right one
1748 with conversations_session(token3) as c:
1749 gcid_distraction = c.CreateGroupChat(
1750 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user1.id])
1751 ).group_chat_id
1752 moderator.approve_group_chat(gcid_distraction)
1754 with conversations_session(token1) as c:
1755 gcid = c.CreateGroupChat(
1756 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])
1757 ).group_chat_id
1758 moderator.approve_group_chat(gcid)
1760 # Test basic archive/unarchive functionality
1761 with conversations_session(token2) as c:
1762 # Initially not archived
1763 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1764 assert not res.is_archived
1766 # Archive the chat
1767 archive_res = c.SetGroupChatArchiveStatus(
1768 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True)
1769 )
1770 assert archive_res.group_chat_id == gcid
1771 assert archive_res.is_archived
1773 # Verify archived via GetGroupChat
1774 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1775 assert res.is_archived
1777 # Unarchive the chat
1778 archive_res = c.SetGroupChatArchiveStatus(
1779 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=False)
1780 )
1781 assert archive_res.group_chat_id == gcid
1782 assert not archive_res.is_archived
1784 # Verify unarchived via GetGroupChat
1785 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1786 assert not res.is_archived
1789def test_archiving_per_user(db, moderator):
1790 """Test that archiving is per-user - one user archiving doesn't affect others"""
1791 user1, token1 = generate_user()
1792 user2, token2 = generate_user()
1794 make_friends(user1, user2)
1796 with conversations_session(token1) as c:
1797 gcid = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])).group_chat_id
1798 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="Hello"))
1799 moderator.approve_group_chat(gcid)
1801 # User1 archives the chat
1802 with conversations_session(token1) as c:
1803 c.SetGroupChatArchiveStatus(
1804 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True)
1805 )
1806 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1807 assert res.is_archived
1809 # User2 should NOT see it as archived
1810 with conversations_session(token2) as c:
1811 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1812 assert not res.is_archived
1814 # User2 archives it too
1815 with conversations_session(token2) as c:
1816 c.SetGroupChatArchiveStatus(
1817 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True)
1818 )
1819 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1820 assert res.is_archived
1822 # User1 unarchives - user2 should still see it as archived
1823 with conversations_session(token1) as c:
1824 c.SetGroupChatArchiveStatus(
1825 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=False)
1826 )
1827 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1828 assert not res.is_archived
1830 with conversations_session(token2) as c:
1831 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1832 assert res.is_archived
1835def test_archiving_with_list_group_chats(db, moderator):
1836 """Test archive filtering with ListGroupChats endpoint"""
1837 user1, token1 = generate_user()
1838 user2, token2 = generate_user()
1839 user3, token3 = generate_user()
1841 make_friends(user1, user2)
1842 make_friends(user1, user3)
1844 with conversations_session(token1) as c:
1845 # Create 3 chats
1846 gcid1 = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])).group_chat_id
1847 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid1, text="Chat 1"))
1848 moderator.approve_group_chat(gcid1)
1850 gcid2 = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])).group_chat_id
1851 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid2, text="Chat 2"))
1852 moderator.approve_group_chat(gcid2)
1854 gcid3 = c.CreateGroupChat(
1855 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])
1856 ).group_chat_id
1857 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid3, text="Chat 3"))
1858 moderator.approve_group_chat(gcid3)
1860 with conversations_session(token1) as c:
1861 # Initially all 3 chats should be visible
1862 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
1863 assert len(res.group_chats) == 3
1865 # All should be non-archived
1866 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False))
1867 assert len(res.group_chats) == 3
1869 # None should be archived
1870 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True))
1871 assert len(res.group_chats) == 0
1873 # Archive chat 1
1874 c.SetGroupChatArchiveStatus(
1875 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid1, is_archived=True)
1876 )
1878 # Without filter, still see all 3
1879 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
1880 assert len(res.group_chats) == 3
1882 # Non-archived should show 2
1883 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False))
1884 assert len(res.group_chats) == 2
1885 assert gcid1 not in [gc.group_chat_id for gc in res.group_chats]
1887 # Archived should show 1
1888 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True))
1889 assert len(res.group_chats) == 1
1890 assert res.group_chats[0].group_chat_id == gcid1
1891 assert res.group_chats[0].is_archived
1893 # Archive chat 2 as well
1894 c.SetGroupChatArchiveStatus(
1895 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid2, is_archived=True)
1896 )
1898 # Non-archived should show 1
1899 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False))
1900 assert len(res.group_chats) == 1
1901 assert res.group_chats[0].group_chat_id == gcid3
1903 # Archived should show 2
1904 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True))
1905 assert len(res.group_chats) == 2
1906 archived_ids = {gc.group_chat_id for gc in res.group_chats}
1907 assert archived_ids == {gcid1, gcid2}
1909 # Unarchive chat 1
1910 c.SetGroupChatArchiveStatus(
1911 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid1, is_archived=False)
1912 )
1914 # Non-archived should show 2
1915 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False))
1916 assert len(res.group_chats) == 2
1918 # Archived should show 1
1919 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True))
1920 assert len(res.group_chats) == 1
1921 assert res.group_chats[0].group_chat_id == gcid2
1924def test_archiving_chat_not_found(db, moderator):
1925 """Test that archiving a non-existent or non-accessible chat fails"""
1926 user1, token1 = generate_user()
1927 user2, token2 = generate_user()
1928 user3, token3 = generate_user()
1930 make_friends(user1, user2)
1932 with conversations_session(token1) as c:
1933 gcid = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])).group_chat_id
1934 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="Hello"))
1935 moderator.approve_group_chat(gcid)
1937 # User3 is not in the chat - should get NOT_FOUND
1938 with conversations_session(token3) as c:
1939 with pytest.raises(grpc.RpcError) as e:
1940 c.SetGroupChatArchiveStatus(
1941 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True)
1942 )
1943 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1945 # Non-existent chat ID should fail
1946 with conversations_session(token1) as c:
1947 with pytest.raises(grpc.RpcError) as e:
1948 c.SetGroupChatArchiveStatus(
1949 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=99999, is_archived=True)
1950 )
1951 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1954def test_archiving_after_leaving_chat(db, moderator):
1955 """Test that you can't archive a chat after leaving it"""
1956 user1, token1 = generate_user()
1957 user2, token2 = generate_user()
1958 user3, token3 = generate_user()
1960 make_friends(user1, user2)
1961 make_friends(user1, user3)
1962 make_friends(user2, user3)
1964 with conversations_session(token1) as c:
1965 gcid = c.CreateGroupChat(
1966 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])
1967 ).group_chat_id
1968 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="Hello"))
1969 moderator.approve_group_chat(gcid)
1971 # User2 leaves the chat
1972 with conversations_session(token2) as c:
1973 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid))
1975 # User2 should not be able to archive it now
1976 with conversations_session(token2) as c:
1977 with pytest.raises(grpc.RpcError) as e:
1978 c.SetGroupChatArchiveStatus(
1979 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True)
1980 )
1981 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1984def test_archiving_dm(db, moderator):
1985 """Test that archiving works for DMs as well as group chats"""
1986 user1, token1 = generate_user()
1987 user2, token2 = generate_user()
1989 make_friends(user1, user2)
1991 with conversations_session(token1) as c:
1992 # Create a DM
1993 gcid = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])).group_chat_id
1994 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="Hello"))
1995 moderator.approve_group_chat(gcid)
1997 # Verify it's a DM
1998 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1999 assert res.is_dm
2000 assert not res.is_archived
2002 # Archive the DM
2003 c.SetGroupChatArchiveStatus(
2004 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True)
2005 )
2007 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
2008 assert res.is_archived
2010 # Unarchive it
2011 c.SetGroupChatArchiveStatus(
2012 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=False)
2013 )
2015 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
2016 assert not res.is_archived
2019def test_archiving_idempotent(db, moderator):
2020 """Test that archiving/unarchiving is idempotent"""
2021 user1, token1 = generate_user()
2022 user2, token2 = generate_user()
2024 make_friends(user1, user2)
2026 with conversations_session(token1) as c:
2027 gcid = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])).group_chat_id
2028 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="Hello"))
2029 moderator.approve_group_chat(gcid)
2031 # Archive twice - should work without error
2032 c.SetGroupChatArchiveStatus(
2033 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True)
2034 )
2035 c.SetGroupChatArchiveStatus(
2036 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True)
2037 )
2038 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
2039 assert res.is_archived
2041 # Unarchive twice - should work without error
2042 c.SetGroupChatArchiveStatus(
2043 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=False)
2044 )
2045 c.SetGroupChatArchiveStatus(
2046 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=False)
2047 )
2048 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
2049 assert not res.is_archived
2052def test_chat_notifications(db, moderator):
2053 user1, token1 = generate_user()
2054 user2, token2 = generate_user()
2055 # notifs off
2056 user3, token3 = generate_user()
2057 user4, token4 = generate_user()
2058 user5, token5 = generate_user()
2059 user6, token6 = generate_user()
2061 make_friends(user1, user2)
2062 make_friends(user1, user3)
2063 make_friends(user1, user4)
2064 make_friends(user4, user5)
2065 make_friends(user4, user6)
2067 # have some of them enable/disable notifs
2068 topic_action = NotificationTopicAction.chat__message
2069 for token, enabled in [
2070 (token1, True),
2071 (token2, True),
2072 (token3, False),
2073 (token4, True),
2074 (token5, True),
2075 (token6, True),
2076 ]:
2077 with notifications_session(token) as notifications:
2078 notifications.SetNotificationSettings(
2079 notifications_pb2.SetNotificationSettingsReq(
2080 preferences=[
2081 notifications_pb2.SingleNotificationPreference(
2082 topic=topic_action.topic,
2083 action=topic_action.action,
2084 delivery_method=delivery_method,
2085 enabled=enabled,
2086 )
2087 for delivery_method in ["push", "email", "digest"]
2088 ],
2089 )
2090 )
2092 group_chat_id = None
2094 def send_msg(c, i):
2095 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=f"Test message {i}"))
2097 with conversations_session(token1) as c:
2098 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id, user4.id]))
2099 group_chat_id = res.group_chat_id
2100 moderator.approve_group_chat(group_chat_id)
2101 c.EditGroupChat(
2102 conversations_pb2.EditGroupChatReq(
2103 group_chat_id=group_chat_id, only_admins_invite=wrappers_pb2.BoolValue(value=False)
2104 )
2105 )
2106 send_msg(c, i=1)
2107 send_msg(c, i=2)
2109 with conversations_session(token4) as c:
2110 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user5.id))
2111 send_msg(c, i=3)
2112 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user6.id))
2113 send_msg(c, i=4)
2114 send_msg(c, i=5)
2116 with conversations_session(token3) as c:
2117 send_msg(c, i=6)
2118 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
2120 with conversations_session(token2) as c:
2121 send_msg(c, i=7)
2122 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
2124 with conversations_session(token6) as c:
2125 send_msg(c, i=8)
2127 # go through all bg jobs
2128 while process_job():
2129 pass
2131 # now check notifs...
2132 expected_notifs = [
2133 (user1, "user1", [3, 4, 5, 6, 7, 8]),
2134 (user2, "user2", [1, 2, 3, 4, 5, 6]),
2135 (user3, "user3", []), # notifs off
2136 (user4, "user4", [1, 2, 6, 7, 8]),
2137 (user5, "user5", [3, 4, 5, 6, 7, 8]),
2138 (user6, "user6", [4, 5, 6, 7]),
2139 ]
2141 with session_scope() as session:
2142 for user, label, expected_msgs in expected_notifs:
2143 deliv = (
2144 session.execute(
2145 select(Notification.data)
2146 .join(NotificationDelivery, NotificationDelivery.notification_id == Notification.id)
2147 .where(Notification.user_id == user.id)
2148 .where(Notification.topic_action == topic_action)
2149 .where(NotificationDelivery.delivery_type == NotificationDeliveryType.push)
2150 .order_by(Notification.created)
2151 )
2152 .scalars()
2153 .all()
2154 )
2156 def parse_message_payload(data):
2157 return notification_data_pb2.ChatMessage.FromString(data).text
2159 contents = [parse_message_payload(d) for d in deliv]
2161 print(contents)
2163 assert [f"Test message {i}" for i in expected_msgs] == contents, f"Wrong messages for {label}"
2166def test_incomplete_profile(db):
2167 user1, token1 = generate_user(complete_profile=True)
2168 user2, token2 = generate_user(complete_profile=False)
2169 user3, token3 = generate_user(complete_profile=True)
2170 make_friends(user1, user2)
2171 make_friends(user1, user3)
2173 # user 1 can make a chat
2174 with conversations_session(token1) as c:
2175 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
2176 group_chat_id = res.group_chat_id
2177 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
2178 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
2179 assert res.messages[0].text.text == "Test message 1"
2180 assert to_aware_datetime(res.messages[0].time) <= now()
2181 assert res.messages[0].author_user_id == user1.id
2183 # user 2 cannot
2184 with conversations_session(token2) as c:
2185 with pytest.raises(grpc.RpcError) as e:
2186 c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
2187 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
2188 assert e.value.details() == "You have to complete your profile before you can send a message."