Coverage for src/tests/test_conversations.py: 100%
990 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-08-28 14:55 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-08-28 14:55 +0000
1from datetime import timedelta
3import grpc
4import pytest
5from google.protobuf import wrappers_pb2
7from couchers import errors
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.rate_limits.definitions import RATE_LIMIT_DEFINITIONS, RATE_LIMIT_INTERVAL_STRING
20from couchers.sql import couchers_select as select
21from couchers.utils import Duration_from_timedelta, now, to_aware_datetime
22from proto import api_pb2, conversations_pb2, notification_data_pb2, notifications_pb2
23from tests.test_fixtures import ( # noqa
24 api_session,
25 conversations_session,
26 db,
27 generate_user,
28 make_friends,
29 make_user_block,
30 make_user_invisible,
31 mock_notification_email,
32 notifications_session,
33 testconfig,
34)
37@pytest.fixture(autouse=True)
38def _(testconfig):
39 pass
42def test_list_group_chats(db):
43 user1, token1 = generate_user()
44 user2, token2 = generate_user()
45 user3, token3 = generate_user()
47 make_friends(user2, user1)
48 make_friends(user1, user3)
50 with conversations_session(token1) as c:
51 # no threads initially
52 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
53 assert len(res.group_chats) == 0
55 # create some group chats with messages
56 res = c.CreateGroupChat(
57 conversations_pb2.CreateGroupChatReq(
58 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title")
59 )
60 )
61 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1"))
62 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 2"))
63 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
64 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 1"))
65 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 2"))
67 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
68 assert len(res.group_chats) == 2
69 assert res.no_more
71 with conversations_session(token2) as c:
72 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
73 assert len(res.group_chats) == 2
74 assert res.no_more
76 with conversations_session(token3) as c:
77 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
78 assert len(res.group_chats) == 1
79 assert res.no_more
82def test_list_empty_group_chats(db):
83 user1, token1 = generate_user()
84 user2, token2 = generate_user()
85 user3, token3 = generate_user()
87 make_friends(user1, user3)
88 make_friends(user2, user1)
89 make_friends(user2, user3)
91 with conversations_session(token1) as c:
92 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
93 assert len(res.group_chats) == 0
95 c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
96 c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
98 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
99 assert len(res.group_chats) == 2
100 assert res.no_more
102 with conversations_session(token2) as c:
103 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
104 assert len(res.group_chats) == 2
105 assert res.no_more
107 c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
109 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
110 assert len(res.group_chats) == 3
111 assert res.no_more
113 with conversations_session(token3) as c:
114 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
115 assert len(res.group_chats) == 2
116 assert res.no_more
119def test_list_group_chats_ordering(db):
120 # user is member of 5 group chats, order them correctly
121 user, token = generate_user()
122 user2, token2 = generate_user()
123 user3, token3 = generate_user()
124 user4, token4 = generate_user()
126 make_friends(user2, user)
127 make_friends(user2, user3)
128 make_friends(user2, user4)
129 make_friends(user3, user)
130 make_friends(user3, user4)
131 make_friends(user, user4)
133 with conversations_session(token2) as c:
134 res = c.CreateGroupChat(
135 conversations_pb2.CreateGroupChatReq(
136 recipient_user_ids=[user.id], title=wrappers_pb2.StringValue(value="Chat 0")
137 )
138 )
139 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
140 res = c.CreateGroupChat(
141 conversations_pb2.CreateGroupChatReq(
142 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 1")
143 )
144 )
145 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
146 res = c.CreateGroupChat(
147 conversations_pb2.CreateGroupChatReq(
148 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 2")
149 )
150 )
151 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
153 with conversations_session(token3) as c:
154 res = c.CreateGroupChat(
155 conversations_pb2.CreateGroupChatReq(
156 recipient_user_ids=[user.id, user2.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 3")
157 )
158 )
159 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
161 with conversations_session(token) as c:
162 res = c.CreateGroupChat(
163 conversations_pb2.CreateGroupChatReq(
164 recipient_user_ids=[user2.id, user3.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 4")
165 )
166 )
167 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
168 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
169 assert len(res.group_chats) == 5
170 assert res.group_chats[0].title == "Chat 4"
171 assert res.group_chats[1].title == "Chat 3"
172 assert res.group_chats[2].title == "Chat 2"
173 assert res.group_chats[3].title == "Chat 1"
174 assert res.group_chats[4].title == "Chat 0"
176 c.SendMessage(
177 conversations_pb2.SendMessageReq(group_chat_id=res.group_chats[3].group_chat_id, text="Test message 2a")
178 )
179 c.SendMessage(
180 conversations_pb2.SendMessageReq(group_chat_id=res.group_chats[2].group_chat_id, text="Test message 2b")
181 )
183 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
184 assert len(res.group_chats) == 5
185 assert res.group_chats[0].title == "Chat 2"
186 assert res.group_chats[0].latest_message.text.text == "Test message 2b"
187 assert res.group_chats[1].title == "Chat 1"
188 assert res.group_chats[1].latest_message.text.text == "Test message 2a"
189 assert res.group_chats[2].title == "Chat 4"
190 assert res.group_chats[3].title == "Chat 3"
191 assert res.group_chats[4].title == "Chat 0"
194def test_list_group_chats_ordering_after_left(db):
195 # user is member to 4 group chats, and has left one.
196 # The one user left has the most recent message, but user left before then,
197 # this should display as e.g. 3rd most recent depending on last message when they were in the chat
198 user, token = generate_user()
199 user2, token2 = generate_user()
200 user3, token3 = generate_user()
201 user4, token4 = generate_user()
203 make_friends(user2, user)
204 make_friends(user2, user3)
205 make_friends(user2, user4)
206 make_friends(user3, user)
207 make_friends(user3, user4)
208 make_friends(user, user4)
210 with conversations_session(token2) as c:
211 res = c.CreateGroupChat(
212 conversations_pb2.CreateGroupChatReq(
213 recipient_user_ids=[user.id], title=wrappers_pb2.StringValue(value="Chat 0")
214 )
215 )
216 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
217 res = c.CreateGroupChat(
218 conversations_pb2.CreateGroupChatReq(
219 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Left Chat 1")
220 )
221 )
222 left_chat_id = res.group_chat_id
223 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Test message"))
224 res = c.CreateGroupChat(
225 conversations_pb2.CreateGroupChatReq(
226 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 2")
227 )
228 )
229 chat2_id = res.group_chat_id
230 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=chat2_id, text="Test message"))
232 with conversations_session(token3) as c:
233 res = c.CreateGroupChat(
234 conversations_pb2.CreateGroupChatReq(
235 recipient_user_ids=[user.id, user2.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 3")
236 )
237 )
238 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
240 with conversations_session(token) as c:
241 res = c.CreateGroupChat(
242 conversations_pb2.CreateGroupChatReq(
243 recipient_user_ids=[user2.id, user3.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 4")
244 )
245 )
246 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message"))
248 # leave chat
249 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=left_chat_id))
251 with conversations_session(token3) as c:
252 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=chat2_id, text="Test message"))
253 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Test message"))
255 with conversations_session(token2) as c:
256 # other user sends a message to that chat
257 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Another test message"))
258 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
259 assert len(res.group_chats) == 5
260 assert res.group_chats[0].title == "Left Chat 1"
261 assert res.group_chats[1].title == "Chat 2"
262 assert res.group_chats[2].title == "Chat 4"
263 assert res.group_chats[3].title == "Chat 3"
264 assert res.group_chats[4].title == "Chat 0"
266 with conversations_session(token) as c:
267 # we can't see the new message since we left before it was sent
268 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
269 assert len(res.group_chats) == 5
270 assert res.group_chats[0].title == "Chat 2"
271 assert res.group_chats[1].title == "Left Chat 1"
272 assert res.group_chats[2].title == "Chat 4"
273 assert res.group_chats[3].title == "Chat 3"
274 assert res.group_chats[4].title == "Chat 0"
277def test_get_group_chat_messages(db):
278 user1, token1 = generate_user()
279 user2, token2 = generate_user()
280 user3, token3 = generate_user()
282 make_friends(user1, user2)
284 with conversations_session(token1) as c:
285 # create some threads with messages
286 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
287 group_chat_id = res.group_chat_id
288 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1"))
289 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 2"))
291 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
292 # created + 2 normal
293 assert len(res.messages) == 3
294 assert res.no_more
296 assert res.messages[0].text.text == "Test message 2"
297 assert res.messages[1].text.text == "Test message 1"
298 assert res.messages[2].WhichOneof("content") == "chat_created"
300 # test that another user can't access the thread
301 with conversations_session(token3) as c:
302 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
303 assert len(res.messages) == 0
306def test_get_group_chat_messages_pagination(db):
307 user1, token1 = generate_user()
308 user2, token2 = generate_user()
309 make_friends(user1, user2)
311 with conversations_session(token1) as c:
312 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
313 group_chat_id = res.group_chat_id
314 for i in range(30):
315 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=str(i)))
317 with conversations_session(token2) as c:
318 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
319 # pagination
320 assert len(res.messages) == 20
321 assert res.messages[0].text.text == "29"
322 assert res.messages[19].text.text == "10"
323 assert not res.no_more
324 res = c.GetGroupChatMessages(
325 conversations_pb2.GetGroupChatMessagesReq(
326 group_chat_id=group_chat_id, last_message_id=res.messages[19].message_id
327 )
328 )
329 assert len(res.messages) == 11
330 assert res.messages[0].text.text == "9"
331 assert res.messages[9].text.text == "0"
332 assert res.no_more
335def test_get_group_chat_messages_joined_left(db):
336 user1, token1 = generate_user()
337 user2, token2 = generate_user()
338 user3, token3 = generate_user()
339 user4, token4 = generate_user()
340 make_friends(user1, user2)
341 make_friends(user1, user3)
342 make_friends(user1, user4)
344 with conversations_session(token1) as c:
345 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id]))
346 group_chat_id = res.group_chat_id
348 for i in range(10):
349 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=str(i)))
351 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
353 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="10"))
355 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
357 # created + 10 normal + invited + normal
358 assert len(res.messages) == 13
360 with conversations_session(token3) as c:
361 # can only see last message after invited
362 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
363 # joined + normal
364 assert len(res.messages) == 2
365 assert res.messages[0].text.text == "10"
367 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
369 with conversations_session(token1) as c:
370 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="11"))
371 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="12"))
373 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
375 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="13"))
376 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="14"))
378 with conversations_session(token3) as c:
379 # can only see last message after invited
380 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
381 # joined + normal + left + invite + 2 normal
382 assert len(res.messages) == 6
383 assert res.messages[0].text.text == "14"
384 assert res.messages[1].text.text == "13"
385 assert res.messages[2].WhichOneof("content") == "user_invited"
386 assert res.messages[3].WhichOneof("content") == "user_left"
387 assert res.messages[4].text.text == "10"
388 assert res.messages[5].WhichOneof("content") == "user_invited"
391def test_get_group_chat_info(db):
392 user1, token1 = generate_user()
393 user2, token2 = generate_user()
394 user3, token3 = generate_user()
396 make_friends(user1, user2)
397 make_friends(user3, user1)
399 with conversations_session(token1) as c:
400 # create some threads with messages
401 res = c.CreateGroupChat(
402 conversations_pb2.CreateGroupChatReq(
403 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title")
404 )
405 )
406 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1"))
407 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 2"))
408 group_chat1_id = res.group_chat_id
409 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
410 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 1"))
411 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 2"))
412 group_chat2_id = res.group_chat_id
414 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat1_id))
415 assert res.title == "Test title"
416 assert user2.id in res.member_user_ids
417 assert user1.id in res.admin_user_ids
418 assert to_aware_datetime(res.created) <= now()
419 assert res.only_admins_invite
420 assert res.is_dm
422 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat2_id))
423 assert not res.title
424 assert user2.id in res.member_user_ids
425 assert user3.id in res.member_user_ids
426 assert user1.id in res.admin_user_ids
427 assert to_aware_datetime(res.created) <= now()
428 assert res.only_admins_invite
429 assert not res.is_dm
432def test_get_group_chat_info_denied(db):
433 user1, token1 = generate_user()
434 user2, token2 = generate_user()
435 user3, token3 = generate_user()
436 user4, token4 = generate_user()
438 make_friends(user1, user2)
439 make_friends(user3, user1)
441 with conversations_session(token1) as c:
442 # create a group chat with messages
443 res = c.CreateGroupChat(
444 conversations_pb2.CreateGroupChatReq(
445 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title")
446 )
447 )
448 group_chat_id = res.group_chat_id
449 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
451 with conversations_session(token4) as c:
452 with pytest.raises(grpc.RpcError) as e:
453 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
454 assert e.value.code() == grpc.StatusCode.NOT_FOUND
457def test_get_group_chat_info_left(db):
458 user1, token1 = generate_user()
459 user2, token2 = generate_user()
460 user3, token3 = generate_user()
461 user4, token4 = generate_user()
463 make_friends(user1, user2)
464 make_friends(user3, user1)
465 make_friends(user1, user4)
467 with conversations_session(token1) as c:
468 # create a group chat with messages
469 res = c.CreateGroupChat(
470 conversations_pb2.CreateGroupChatReq(
471 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title")
472 )
473 )
474 group_chat_id = res.group_chat_id
475 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
477 with conversations_session(token3) as c:
478 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
480 with conversations_session(token1) as c:
481 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user4.id))
483 with conversations_session(token3) as c:
484 # this user left when user4 wasn't a member,
485 # so the returned members should be user1, user2, and user3 only
486 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
487 assert len(res.member_user_ids) == 3
488 assert user1.id in res.member_user_ids
489 assert user2.id in res.member_user_ids
490 assert user3.id in res.member_user_ids
493def test_remove_group_chat_user(db):
494 # create 3 uses and connect them
495 user1, token1 = generate_user()
496 user2, token2 = generate_user()
497 user3, token3 = generate_user()
498 make_friends(user1, user2)
499 make_friends(user1, user3)
501 # using user token, create a Conversations API for testing
502 with conversations_session(token1) as c:
503 # create a group chat
504 res = c.CreateGroupChat(
505 conversations_pb2.CreateGroupChatReq(
506 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title")
507 )
508 )
509 group_chat_id = res.group_chat_id
511 # remove a user from group
512 c.RemoveGroupChatUser(conversations_pb2.RemoveGroupChatUserReq(group_chat_id=group_chat_id, user_id=user2.id))
513 assert user3.id in res.member_user_ids # other users are still in the group
515 # can't remove the same user twice
516 with pytest.raises(grpc.RpcError) as e:
517 c.RemoveGroupChatUser(
518 conversations_pb2.RemoveGroupChatUserReq(group_chat_id=group_chat_id, user_id=user2.id)
519 )
520 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
523def test_edit_group_chat(db):
524 user1, token1 = generate_user()
525 user2, token2 = generate_user()
526 user3, token3 = generate_user()
527 make_friends(user1, user2)
529 with conversations_session(token1) as c:
530 # create some threads with messages
531 res = c.CreateGroupChat(
532 conversations_pb2.CreateGroupChatReq(
533 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title")
534 )
535 )
536 group_chat_id = res.group_chat_id
538 c.EditGroupChat(
539 conversations_pb2.EditGroupChatReq(
540 group_chat_id=group_chat_id,
541 title=wrappers_pb2.StringValue(value="Modified title"),
542 only_admins_invite=wrappers_pb2.BoolValue(value=False),
543 )
544 )
545 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
546 assert res.title == "Modified title"
547 assert not res.only_admins_invite
549 # make sure non-admin is not allowed to modify
550 with conversations_session(token2) as c:
551 with pytest.raises(grpc.RpcError) as e:
552 c.EditGroupChat(
553 conversations_pb2.EditGroupChatReq(
554 group_chat_id=group_chat_id,
555 title=wrappers_pb2.StringValue(value="Other title"),
556 only_admins_invite=wrappers_pb2.BoolValue(value=True),
557 )
558 )
559 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
561 # make sure non-recipient is not allowed to modify
562 with conversations_session(token3) as c:
563 with pytest.raises(grpc.RpcError) as e:
564 c.EditGroupChat(
565 conversations_pb2.EditGroupChatReq(
566 group_chat_id=group_chat_id,
567 title=wrappers_pb2.StringValue(value="Other title"),
568 only_admins_invite=wrappers_pb2.BoolValue(value=True),
569 )
570 )
571 assert e.value.code() == grpc.StatusCode.NOT_FOUND
574def test_make_remove_group_chat_admin(db):
575 user1, token1 = generate_user()
576 user2, token2 = generate_user()
577 user3, token3 = generate_user()
579 make_friends(user1, user2)
580 make_friends(user1, user3)
581 make_friends(user2, user3)
583 with conversations_session(token1) as c:
584 # create some threads with messages
585 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
586 group_chat_id = res.group_chat_id
588 # shouldn't be able to remove only admin
589 with pytest.raises(grpc.RpcError) as e:
590 c.RemoveGroupChatAdmin(
591 conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user1.id)
592 )
593 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
594 assert e.value.details() == errors.CANT_REMOVE_LAST_ADMIN
596 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user2.id))
598 # shouldn't be able to make admin again
599 with pytest.raises(grpc.RpcError) as e:
600 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user2.id))
601 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
602 assert e.value.details() == errors.ALREADY_ADMIN
604 with conversations_session(token2) as c:
605 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
606 assert user1.id in res.admin_user_ids
607 assert user2.id in res.admin_user_ids
609 with conversations_session(token1) as c:
610 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user2.id))
612 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
613 assert user1.id in res.admin_user_ids
614 assert user2.id not in res.admin_user_ids
616 with conversations_session(token2) as c:
617 # shouldn't be able to make admin if not admin
618 with pytest.raises(grpc.RpcError) as e:
619 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user3.id))
620 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
623def test_send_message(db):
624 user1, token1 = generate_user()
625 user2, token2 = generate_user()
626 user3, token3 = generate_user()
627 make_friends(user1, user2)
628 make_friends(user1, user3)
630 with conversations_session(token1) as c:
631 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
632 group_chat_id = res.group_chat_id
633 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
634 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
635 assert res.messages[0].text.text == "Test message 1"
636 assert to_aware_datetime(res.messages[0].time) <= now()
637 assert res.messages[0].author_user_id == user1.id
639 # can't send message if not in chat
640 with conversations_session(token3) as c:
641 with pytest.raises(grpc.RpcError) as e:
642 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 2"))
643 assert e.value.code() == grpc.StatusCode.NOT_FOUND
645 make_user_block(user2, user1)
646 with conversations_session(token1) as c:
647 with pytest.raises(grpc.RpcError) as e:
648 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Message after block"))
649 assert e.value.details() == errors.CANT_MESSAGE_IN_CHAT
652def test_send_direct_message(db):
653 user1, token1 = generate_user(complete_profile=True)
654 user2, token2 = generate_user(complete_profile=True)
656 make_friends(user1, user2)
658 message1 = "Hello, user2!"
659 message2 = "One more message."
661 with conversations_session(token1) as c1:
662 # Send a DM from user1 to user2
663 res = c1.SendDirectMessage(conversations_pb2.SendDirectMessageReq(recipient_user_id=user2.id, text=message1))
665 c1.SendDirectMessage(conversations_pb2.SendDirectMessageReq(recipient_user_id=user2.id, text=message2))
667 with conversations_session(token2) as c2:
668 # Fetch the chat by ID returned from SendDirectMessage
669 chat = c2.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=res.group_chat_id))
671 assert chat.is_dm
672 group_chat_id = chat.group_chat_id
674 # Verify that the messages was received
675 messages = c2.GetGroupChatMessages(
676 conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id)
677 ).messages
679 assert len(messages) == 2
680 assert messages[0].text.text == message2
681 assert messages[1].text.text == message1
682 assert messages[0].author_user_id == user1.id
685def test_excessive_chat_initiations_are_reported(db):
686 """Test that excessive chat initiations are first reported in a warning email and finally lead blocking of further contacting other users."""
687 user, token = generate_user()
688 rate_limit_definition = RATE_LIMIT_DEFINITIONS[RateLimitAction.chat_initiation]
689 with conversations_session(token) as c:
690 # Test warning email
691 with mock_notification_email() as mock_email:
692 for _ in range(rate_limit_definition.warning_limit):
693 recipient_user, _ = generate_user()
694 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id]))
696 assert mock_email.call_count == 0
697 recipient_user, _ = generate_user()
698 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id]))
700 assert mock_email.call_count == 1
701 email = mock_email.mock_calls[0].kwargs["plain"]
702 assert email.startswith(
703 f"User {user.username} has sent {rate_limit_definition.warning_limit} chat initiations in the past {RATE_LIMIT_INTERVAL_STRING}."
704 )
706 # Test new chat initiations fail after exceeding CHAT_INITIATION_HARD_LIMIT
707 with mock_notification_email() as mock_email:
708 for _ in range(rate_limit_definition.hard_limit - rate_limit_definition.warning_limit - 1):
709 recipient_user, _ = generate_user()
710 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id]))
712 assert mock_email.call_count == 0
713 recipient_user, _ = generate_user()
714 with pytest.raises(grpc.RpcError) as exc_info:
715 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id]))
716 assert exc_info.value.code() == grpc.StatusCode.RESOURCE_EXHAUSTED
717 assert exc_info.value.details() == errors.CHAT_INITIATION_RATE_LIMIT
719 assert mock_email.call_count == 1
720 email = mock_email.mock_calls[0].kwargs["plain"]
721 assert email.startswith(
722 f"User {user.username} has sent {rate_limit_definition.hard_limit} chat initiations in the past {RATE_LIMIT_INTERVAL_STRING}."
723 )
724 assert "The user has been blocked from sending further chat initiations for now." in email
727def test_leave_invite_to_group_chat(db):
728 user1, token1 = generate_user()
729 user2, token2 = generate_user()
730 user3, token3 = generate_user()
731 user4, token4 = generate_user()
732 user5, token5 = generate_user()
733 user6, token6 = generate_user(delete_user=True)
734 user7, token7 = generate_user()
735 user8, token8 = generate_user()
737 make_friends(user1, user2)
738 make_friends(user1, user3)
739 make_friends(user1, user5)
740 make_friends(user1, user7)
741 make_friends(user1, user8)
742 make_friends(user2, user3)
743 make_friends(user4, user3)
744 make_user_block(user1, user7)
745 make_user_block(user8, user1)
747 with conversations_session(token1) as c:
748 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user5.id]))
749 group_chat_id = res.group_chat_id
750 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
752 # other user not in chat
753 with conversations_session(token3) as c:
754 with pytest.raises(grpc.RpcError) as e:
755 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
756 assert e.value.code() == grpc.StatusCode.NOT_FOUND
757 with pytest.raises(grpc.RpcError) as e:
758 res = c.InviteToGroupChat(
759 conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user4.id)
760 )
761 assert e.value.code() == grpc.StatusCode.NOT_FOUND
762 with pytest.raises(grpc.RpcError) as e:
763 res = c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
764 assert e.value.code() == grpc.StatusCode.NOT_FOUND
766 with conversations_session(token2) as c:
767 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
768 assert user3.id not in res.member_user_ids
770 # only_admins_invite defaults to true so shouldn't be able to invite
771 with pytest.raises(grpc.RpcError) as e:
772 res = c.InviteToGroupChat(
773 conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)
774 )
775 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
776 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
778 with conversations_session(token1) as c:
779 # invite invisible user fails
780 with pytest.raises(grpc.RpcError) as e:
781 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user6.id))
782 assert e.value.code() == grpc.StatusCode.NOT_FOUND
783 assert e.value.details() == errors.USER_NOT_FOUND
784 # invite fake user fails
785 with pytest.raises(grpc.RpcError) as e:
786 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=999))
787 assert e.value.code() == grpc.StatusCode.NOT_FOUND
788 assert e.value.details() == errors.USER_NOT_FOUND
789 # invite blocked user fails
790 with pytest.raises(grpc.RpcError) as e:
791 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user7.id))
792 assert e.value.code() == grpc.StatusCode.NOT_FOUND
793 assert e.value.details() == errors.USER_NOT_FOUND
794 # invite blocking user fails
795 with pytest.raises(grpc.RpcError) as e:
796 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user8.id))
797 assert e.value.code() == grpc.StatusCode.NOT_FOUND
798 assert e.value.details() == errors.USER_NOT_FOUND
800 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
801 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
802 assert user1.id in res.member_user_ids
803 assert user5.id in res.member_user_ids
804 assert user3.id in res.member_user_ids
806 # test non-admin inviting
807 c.EditGroupChat(
808 conversations_pb2.EditGroupChatReq(
809 group_chat_id=group_chat_id, only_admins_invite=wrappers_pb2.BoolValue(value=False)
810 )
811 )
813 with conversations_session(token3) as c:
814 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user2.id))
815 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
816 assert user2.id in res.member_user_ids
819def test_group_chats_with_messages_before_join(db):
820 """
821 If user 1 and 2 have a group chat and send messages, then add user 3; user 3
822 should still see the group chat!
823 """
824 user1, token1 = generate_user()
825 user2, token2 = generate_user()
826 user3, token3 = generate_user()
827 user4, token4 = generate_user()
829 make_friends(user1, user2)
830 make_friends(user1, user3)
831 make_friends(user2, user3)
832 make_friends(user1, user4)
834 with conversations_session(token1) as c:
835 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id]))
836 group_chat_id = res.group_chat_id
837 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
839 with conversations_session(token2) as c:
840 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 2"))
842 with conversations_session(token1) as c:
843 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 3"))
845 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
847 with conversations_session(token3) as c:
848 # should work
849 c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id))
851 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq())
852 assert len(res.group_chats) == 1
855def test_invite_to_dm(db):
856 user1, token1 = generate_user()
857 user2, token2 = generate_user()
858 user3, token3 = generate_user()
860 make_friends(user1, user2)
861 make_friends(user1, user3)
862 make_friends(user2, user3)
864 with conversations_session(token1) as c:
865 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
866 group_chat_id = res.group_chat_id
867 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
869 # dm, shou;dn't be able to invite someone else
870 with pytest.raises(grpc.RpcError) as e:
871 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
872 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
873 assert e.value.details() == errors.CANT_INVITE_TO_DM
876def test_sole_admin_leaves(db):
877 user1, token1 = generate_user()
878 user2, token2 = generate_user()
879 user3, token3 = generate_user()
881 make_friends(user1, user2)
882 make_friends(user1, user3)
883 make_friends(user2, user3)
885 with conversations_session(token1) as c:
886 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
887 group_chat_id = res.group_chat_id
888 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
890 # sole admin can't leave group chat
891 with pytest.raises(grpc.RpcError) as e:
892 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
893 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
894 assert e.value.details() == errors.LAST_ADMIN_CANT_LEAVE
896 with conversations_session(token2) as c:
897 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
899 with conversations_session(token3) as c:
900 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
902 # sole admin can leave when last in chat
903 with conversations_session(token1) as c:
904 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
907def test_search_messages(db):
908 user1, token1 = generate_user()
909 user2, token2 = generate_user()
910 user3, token3 = generate_user()
912 make_friends(user1, user2)
913 make_friends(user1, user3)
915 with conversations_session(token1) as c:
916 # create some threads with messages
917 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
918 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1"))
919 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 2"))
920 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
921 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 3"))
922 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 4"))
924 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="message "))
925 assert len(res.results) == 4
926 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="group "))
927 assert len(res.results) == 2
928 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="message 5"))
929 assert len(res.results) == 0
931 # outside user doesn't get results
932 with conversations_session(token3) as c:
933 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message"))
934 assert len(res.results) == 0
937def test_search_messages_left_joined(db):
938 user1, token1 = generate_user()
939 user2, token2 = generate_user()
940 user3, token3 = generate_user()
941 user4, token4 = generate_user()
942 make_friends(user1, user2)
943 make_friends(user1, user3)
944 make_friends(user1, user4)
946 with conversations_session(token1) as c:
947 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id]))
948 group_chat_id = res.group_chat_id
949 for i in range(10):
950 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message " + str(i)))
952 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
953 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 10"))
954 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message"))
956 assert len(res.results) == 11
958 with conversations_session(token3) as c:
959 # can only see last message after invited
960 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message"))
962 assert len(res.results) == 1
963 assert res.results[0].message.text.text == "Test message 10"
965 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
967 with conversations_session(token1) as c:
968 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 11"))
969 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 12"))
970 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id))
971 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 13"))
972 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 14"))
974 with conversations_session(token3) as c:
975 # can only see last message after invited
976 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message"))
977 assert len(res.results) == 3
978 assert res.results[0].message.text.text == "Test message 14"
979 assert res.results[1].message.text.text == "Test message 13"
980 assert res.results[2].message.text.text == "Test message 10"
983def test_admin_behaviour(db):
984 user1, token1 = generate_user()
985 user2, token2 = generate_user()
986 user3, token3 = generate_user()
988 make_friends(user1, user2)
989 make_friends(user1, user3)
990 make_friends(user2, user3)
992 with conversations_session(token1) as c:
993 gcid = c.CreateGroupChat(
994 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])
995 ).group_chat_id
996 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user2.id))
997 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
998 assert len(res.admin_user_ids) == 2
999 assert user1.id in res.admin_user_ids
1000 assert user2.id in res.admin_user_ids
1002 with conversations_session(token3) as c:
1003 with pytest.raises(grpc.RpcError) as e:
1004 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1005 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1006 with pytest.raises(grpc.RpcError) as e:
1007 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id))
1008 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1009 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1010 assert len(res.admin_user_ids) == 2
1011 assert user1.id in res.admin_user_ids
1012 assert user2.id in res.admin_user_ids
1014 with conversations_session(token2) as c:
1015 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1016 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1017 assert len(res.admin_user_ids) == 3
1018 assert user1.id in res.admin_user_ids
1019 assert user2.id in res.admin_user_ids
1020 assert user3.id in res.admin_user_ids
1022 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id))
1023 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1024 assert len(res.admin_user_ids) == 2
1025 assert user2.id in res.admin_user_ids
1026 assert user3.id in res.admin_user_ids
1028 with conversations_session(token1) as c:
1029 with pytest.raises(grpc.RpcError):
1030 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id))
1031 with pytest.raises(grpc.RpcError):
1032 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1033 with pytest.raises(grpc.RpcError):
1034 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user2.id))
1035 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1036 assert len(res.admin_user_ids) == 2
1037 assert user2.id in res.admin_user_ids
1038 assert user3.id in res.admin_user_ids
1040 with conversations_session(token2) as c:
1041 # can demote self if there are other admins
1042 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user2.id))
1043 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1044 assert len(res.admin_user_ids) == 1
1045 assert user3.id in res.admin_user_ids
1047 with conversations_session(token3) as c:
1048 with pytest.raises(grpc.RpcError) as e:
1049 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1050 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1051 assert e.value.details() == errors.CANT_REMOVE_LAST_ADMIN
1052 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1053 assert len(res.admin_user_ids) == 1
1054 assert user3.id in res.admin_user_ids
1056 # last admin can't leave
1057 with pytest.raises(grpc.RpcError) as e:
1058 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid))
1059 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1060 assert e.value.details() == errors.LAST_ADMIN_CANT_LEAVE
1062 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id))
1064 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid))
1066 with conversations_session(token2) as c:
1067 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid))
1069 # last participant must be admin but can leave to orphan chat
1070 with conversations_session(token1) as c:
1071 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid))
1074def test_add_remove_admin_failures(db):
1075 user1, token1 = generate_user()
1076 user2, token2 = generate_user()
1077 user3, token3 = generate_user()
1078 user4, token4 = generate_user()
1079 user5, token5 = generate_user()
1081 make_friends(user1, user2)
1082 make_friends(user1, user3)
1083 make_friends(user1, user4)
1084 make_friends(user1, user5)
1086 with conversations_session(token1) as c:
1087 gcid = c.CreateGroupChat(
1088 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id, user4.id, user5.id])
1089 ).group_chat_id
1091 make_user_invisible(user3.id)
1092 make_user_block(user1, user4)
1093 make_user_block(user5, user1)
1095 # make non-existent user admin
1096 with pytest.raises(grpc.RpcError) as e:
1097 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=999))
1098 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1099 assert e.value.details() == errors.USER_NOT_FOUND
1101 # make invisible user admin
1102 with pytest.raises(grpc.RpcError) as e:
1103 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1104 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1105 assert e.value.details() == errors.USER_NOT_FOUND
1107 # make blocked user admin
1108 with pytest.raises(grpc.RpcError) as e:
1109 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user4.id))
1110 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1111 assert e.value.details() == errors.USER_NOT_FOUND
1113 # make blocking user admin
1114 with pytest.raises(grpc.RpcError) as e:
1115 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user5.id))
1116 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1117 assert e.value.details() == errors.USER_NOT_FOUND
1119 with session_scope() as session:
1120 subscriptions = (
1121 session.execute(
1122 select(GroupChatSubscription)
1123 .where(GroupChatSubscription.group_chat_id == gcid)
1124 .where(GroupChatSubscription.role == GroupChatRole.participant)
1125 )
1126 .scalars()
1127 .all()
1128 )
1130 for subscription in subscriptions:
1131 subscription.role = GroupChatRole.admin
1133 with conversations_session(token1) as c:
1134 # remove non-existent user admin
1135 with pytest.raises(grpc.RpcError) as e:
1136 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=999))
1137 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1138 assert e.value.details() == errors.USER_NOT_FOUND
1140 # remove invisible admin
1141 with pytest.raises(grpc.RpcError) as e:
1142 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id))
1143 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1144 assert e.value.details() == errors.USER_NOT_FOUND
1146 # remove blocked admin
1147 with pytest.raises(grpc.RpcError) as e:
1148 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user4.id))
1149 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1150 assert e.value.details() == errors.USER_NOT_FOUND
1152 # remove blocking admin
1153 with pytest.raises(grpc.RpcError) as e:
1154 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user5.id))
1155 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1156 assert e.value.details() == errors.USER_NOT_FOUND
1159def test_last_seen(db):
1160 user1, token1 = generate_user()
1161 user2, token2 = generate_user()
1162 user3, token3 = generate_user()
1164 make_friends(user1, user2)
1165 make_friends(user1, user3)
1166 make_friends(user2, user3)
1168 with conversations_session(token3) as c:
1169 # this is just here to mess up any issues we get if we pretend there's only one group chat ever
1170 gcid_distraction = c.CreateGroupChat(
1171 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user1.id])
1172 ).group_chat_id
1174 with conversations_session(token1) as c:
1175 gcid = c.CreateGroupChat(
1176 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])
1177 ).group_chat_id
1179 message_ids = []
1181 for i in range(6):
1182 c.SendMessage(
1183 conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text=f"gibberish message... {i}")
1184 )
1185 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}"))
1186 c.SendMessage(
1187 conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text=f"gibberish message {i}")
1188 )
1190 message_ids.append(
1191 c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)).latest_message.message_id
1192 )
1194 # messages are automatically marked as seen when you send a new message
1195 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1196 assert res.unseen_message_count == 0
1198 with conversations_session(token2) as c:
1199 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1200 # created + 6 normal
1201 assert res.unseen_message_count == 7
1203 backward_offset = 3
1204 c.MarkLastSeenGroupChat(
1205 conversations_pb2.MarkLastSeenGroupChatReq(
1206 group_chat_id=gcid, last_seen_message_id=message_ids[-backward_offset - 1]
1207 )
1208 )
1210 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1211 assert res.unseen_message_count == backward_offset
1213 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="test message ..."))
1215 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1216 assert res.unseen_message_count == 0
1218 with conversations_session(token3) as c:
1219 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1220 # created + 7 normal
1221 assert res.unseen_message_count == 8
1223 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="test message ..."))
1225 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1226 assert res.unseen_message_count == 0
1229def test_one_dm_per_pair(db):
1230 user1, token1 = generate_user()
1231 user2, token2 = generate_user()
1232 user3, token3 = generate_user()
1234 make_friends(user1, user2)
1235 make_friends(user1, user3)
1236 make_friends(user2, user3)
1238 with conversations_session(token1) as c:
1239 # create DM with user 2
1240 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
1241 assert res.is_dm
1243 # create DM with user 3
1244 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
1245 assert res.is_dm
1247 # can't create another group chat with just user 2
1248 with pytest.raises(grpc.RpcError) as e:
1249 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
1250 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1252 # can't create another group chat with just user 3
1253 with pytest.raises(grpc.RpcError) as e:
1254 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
1255 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1257 # can create joined group chat
1258 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
1259 assert not res.is_dm
1261 with conversations_session(token2) as c:
1262 # can create DM with user 3
1263 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
1264 assert res.is_dm
1266 # can't create another group chat with just user 1
1267 with pytest.raises(grpc.RpcError) as e:
1268 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user1.id]))
1269 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1272def test_GetDirectMessage(db):
1273 user1, token1 = generate_user()
1274 user2, token2 = generate_user()
1275 user3, token3 = generate_user()
1277 make_friends(user1, user2)
1278 make_friends(user1, user3)
1279 make_friends(user2, user3)
1281 with conversations_session(token1) as c:
1282 # no group chat with user 2
1283 with pytest.raises(grpc.RpcError) as e:
1284 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user2.id))
1285 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1287 # no group chat with nor user 3
1288 with pytest.raises(grpc.RpcError) as e:
1289 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user3.id))
1290 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1292 # create DM with user 2
1293 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
1294 assert res.is_dm
1295 gcid = res.group_chat_id
1297 # now should exist
1298 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user2.id))
1299 assert res.group_chat_id == gcid
1301 # create DM with user 3
1302 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
1303 assert res.is_dm
1305 # can create joined group chat
1306 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]))
1307 assert not res.is_dm
1309 with conversations_session(token2) as c:
1310 # can create DM with user 3
1311 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
1312 assert res.is_dm
1313 assert res.can_message
1314 gcid = res.group_chat_id
1316 # DM with 3 should exist, but can't message after being blocked
1317 make_user_block(user3, user2)
1318 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user3.id))
1319 assert res.group_chat_id == gcid
1320 assert not res.can_message
1323def test_total_unseen(db):
1324 user1, token1 = generate_user()
1325 user2, token2 = generate_user()
1326 user3, token3 = generate_user()
1328 # distractions
1329 user4, token4 = generate_user()
1331 make_friends(user1, user2)
1332 make_friends(user1, user3)
1333 make_friends(user2, user3)
1335 # distractions
1336 make_friends(user1, user4)
1338 with conversations_session(token1) as c:
1339 # distractions
1340 gcid_distraction = c.CreateGroupChat(
1341 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user4.id])
1342 ).group_chat_id
1343 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction..."))
1345 gcid = c.CreateGroupChat(
1346 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])
1347 ).group_chat_id
1349 for i in range(6):
1350 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}"))
1352 # distractions
1353 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction..."))
1355 # messages are automatically marked as seen when you send a new message
1356 with api_session(token1) as api:
1357 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0
1359 with api_session(token2) as api:
1360 # chat created + 6 normal messages
1361 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 7
1363 # now leave chat with user2
1364 with conversations_session(token2) as c:
1365 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid))
1367 with api_session(token2) as api:
1368 # seen messages becomes 0 when leaving
1369 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0
1371 with conversations_session(token1) as c:
1372 # distractions
1373 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction..."))
1375 # send more stuff without user 2
1376 for i in range(3):
1377 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}"))
1379 # distractions
1380 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction..."))
1382 with api_session(token2) as api:
1383 # seen messages becomes 0 when leaving
1384 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0
1386 with conversations_session(token1) as c:
1387 # add user 2 back
1388 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=gcid, user_id=user2.id))
1390 # send more stuff with user 2
1391 for i in range(12):
1392 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}"))
1394 # distractions
1395 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction..."))
1397 with api_session(token2) as api:
1398 # joined + 12 normal
1399 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 13
1402def test_regression_ListGroupChats_pagination(db):
1403 user1, token1 = generate_user()
1404 user2, token2 = generate_user()
1405 user3, token3 = generate_user()
1407 make_friends(user1, user2)
1408 make_friends(user1, user3)
1410 with conversations_session(token1) as c:
1411 # tuples of (group_chat_id, message_id)
1412 group_chat_and_message_ids = []
1413 for i in range(50):
1414 res1 = c.CreateGroupChat(
1415 conversations_pb2.CreateGroupChatReq(
1416 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value=f"Chat {i}")
1417 )
1418 )
1420 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res1.group_chat_id, text=f"Test message {i}"))
1422 res2 = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=res1.group_chat_id))
1424 group_chat_and_message_ids.append((res2.group_chat_id, res2.latest_message.message_id))
1426 seen_group_chat_ids = []
1428 last_message_id = 0
1429 more = True
1430 while more:
1431 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(last_message_id=last_message_id))
1432 last_message_id = res.last_message_id
1433 more = not res.no_more
1435 seen_group_chat_ids.extend([chat.group_chat_id for chat in res.group_chats])
1437 assert set(seen_group_chat_ids) == {x[0] for x in group_chat_and_message_ids}, "Not all group chats returned"
1440def test_muting(db):
1441 user1, token1 = generate_user()
1442 user2, token2 = generate_user()
1443 user3, token3 = generate_user()
1445 make_friends(user1, user2)
1446 make_friends(user1, user3)
1447 make_friends(user2, user3)
1449 with conversations_session(token3) as c:
1450 # this is just here to mess up any issues we get if we pretend there's only one group chat ever
1451 gcid_distraction = c.CreateGroupChat(
1452 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user1.id])
1453 ).group_chat_id
1455 with conversations_session(token1) as c:
1456 gcid = c.CreateGroupChat(
1457 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])
1458 ).group_chat_id
1460 with conversations_session(token2) as c:
1461 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1462 assert not res.mute_info.muted
1463 assert not res.mute_info.HasField("muted_until")
1465 c.MuteGroupChat(conversations_pb2.MuteGroupChatReq(group_chat_id=gcid, forever=True))
1466 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1467 assert res.mute_info.muted
1468 assert not res.mute_info.HasField("muted_until")
1470 c.MuteGroupChat(conversations_pb2.MuteGroupChatReq(group_chat_id=gcid, unmute=True))
1471 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1472 assert not res.mute_info.muted
1473 assert not res.mute_info.HasField("muted_until")
1475 c.MuteGroupChat(
1476 conversations_pb2.MuteGroupChatReq(
1477 group_chat_id=gcid, for_duration=Duration_from_timedelta(timedelta(hours=2))
1478 )
1479 )
1480 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid))
1481 assert res.mute_info.muted
1482 assert res.mute_info.HasField("muted_until")
1483 assert to_aware_datetime(res.mute_info.muted_until) >= now() + timedelta(hours=1, minutes=59)
1484 assert to_aware_datetime(res.mute_info.muted_until) <= now() + timedelta(hours=2, minutes=1)
1487def test_chat_notifications(db):
1488 user1, token1 = generate_user()
1489 user2, token2 = generate_user()
1490 # notifs off
1491 user3, token3 = generate_user()
1492 user4, token4 = generate_user()
1493 user5, token5 = generate_user()
1494 user6, token6 = generate_user()
1496 make_friends(user1, user2)
1497 make_friends(user1, user3)
1498 make_friends(user1, user4)
1499 make_friends(user4, user5)
1500 make_friends(user4, user6)
1502 # have some of them enable/disable notifs
1503 topic_action = NotificationTopicAction.chat__message
1504 for token, enabled in [
1505 (token1, True),
1506 (token2, True),
1507 (token3, False),
1508 (token4, True),
1509 (token5, True),
1510 (token6, True),
1511 ]:
1512 with notifications_session(token) as notifications:
1513 notifications.SetNotificationSettings(
1514 notifications_pb2.SetNotificationSettingsReq(
1515 preferences=[
1516 notifications_pb2.SingleNotificationPreference(
1517 topic=topic_action.topic,
1518 action=topic_action.action,
1519 delivery_method=delivery_method,
1520 enabled=enabled,
1521 )
1522 for delivery_method in ["push", "email", "digest"]
1523 ],
1524 )
1525 )
1527 group_chat_id = None
1529 def send_msg(c, i):
1530 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=f"Test message {i}"))
1532 with conversations_session(token1) as c:
1533 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id, user4.id]))
1534 group_chat_id = res.group_chat_id
1535 c.EditGroupChat(
1536 conversations_pb2.EditGroupChatReq(
1537 group_chat_id=group_chat_id, only_admins_invite=wrappers_pb2.BoolValue(value=False)
1538 )
1539 )
1540 send_msg(c, i=1)
1541 send_msg(c, i=2)
1543 with conversations_session(token4) as c:
1544 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user5.id))
1545 send_msg(c, i=3)
1546 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user6.id))
1547 send_msg(c, i=4)
1548 send_msg(c, i=5)
1550 with conversations_session(token3) as c:
1551 send_msg(c, i=6)
1552 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
1554 with conversations_session(token2) as c:
1555 send_msg(c, i=7)
1556 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id))
1558 with conversations_session(token6) as c:
1559 send_msg(c, i=8)
1561 # go through all bg jobs
1562 while process_job():
1563 pass
1565 # now check notifs...
1566 expected_notifs = [
1567 (user1, "user1", [3, 4, 5, 6, 7, 8]),
1568 (user2, "user2", [1, 2, 3, 4, 5, 6]),
1569 (user3, "user3", []), # notifs off
1570 (user4, "user4", [1, 2, 6, 7, 8]),
1571 (user5, "user5", [3, 4, 5, 6, 7, 8]),
1572 (user6, "user6", [4, 5, 6, 7]),
1573 ]
1575 with session_scope() as session:
1576 for user, label, expected_msgs in expected_notifs:
1577 deliv = (
1578 session.execute(
1579 select(Notification.data)
1580 .join(NotificationDelivery, NotificationDelivery.notification_id == Notification.id)
1581 .where(Notification.user_id == user.id)
1582 .where(Notification.topic_action == topic_action)
1583 .where(NotificationDelivery.delivery_type == NotificationDeliveryType.push)
1584 .order_by(Notification.created)
1585 )
1586 .scalars()
1587 .all()
1588 )
1590 def parse_message_payload(data):
1591 return notification_data_pb2.ChatMessage.FromString(data).text
1593 contents = [parse_message_payload(d) for d in deliv]
1595 print(contents)
1597 assert [f"Test message {i}" for i in expected_msgs] == contents, f"Wrong messages for {label}"
1600def test_incomplete_profile(db):
1601 user1, token1 = generate_user(complete_profile=True)
1602 user2, token2 = generate_user(complete_profile=False)
1603 user3, token3 = generate_user(complete_profile=True)
1604 make_friends(user1, user2)
1605 make_friends(user1, user3)
1607 # user 1 can make a chat
1608 with conversations_session(token1) as c:
1609 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id]))
1610 group_chat_id = res.group_chat_id
1611 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1"))
1612 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id))
1613 assert res.messages[0].text.text == "Test message 1"
1614 assert to_aware_datetime(res.messages[0].time) <= now()
1615 assert res.messages[0].author_user_id == user1.id
1617 # user 2 cannot
1618 with conversations_session(token2) as c:
1619 with pytest.raises(grpc.RpcError) as e:
1620 c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id]))
1621 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1622 assert e.value.details() == errors.INCOMPLETE_PROFILE_SEND_MESSAGE