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

1from datetime import timedelta 

2 

3import grpc 

4import pytest 

5from google.protobuf import wrappers_pb2 

6 

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) 

35 

36 

37@pytest.fixture(autouse=True) 

38def _(testconfig): 

39 pass 

40 

41 

42def test_list_group_chats(db): 

43 user1, token1 = generate_user() 

44 user2, token2 = generate_user() 

45 user3, token3 = generate_user() 

46 

47 make_friends(user2, user1) 

48 make_friends(user1, user3) 

49 

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 

54 

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")) 

66 

67 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

68 assert len(res.group_chats) == 2 

69 assert res.no_more 

70 

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 

75 

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 

80 

81 

82def test_list_empty_group_chats(db): 

83 user1, token1 = generate_user() 

84 user2, token2 = generate_user() 

85 user3, token3 = generate_user() 

86 

87 make_friends(user1, user3) 

88 make_friends(user2, user1) 

89 make_friends(user2, user3) 

90 

91 with conversations_session(token1) as c: 

92 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

93 assert len(res.group_chats) == 0 

94 

95 c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])) 

96 c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id])) 

97 

98 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

99 assert len(res.group_chats) == 2 

100 assert res.no_more 

101 

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 

106 

107 c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])) 

108 

109 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

110 assert len(res.group_chats) == 3 

111 assert res.no_more 

112 

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 

117 

118 

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() 

125 

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) 

132 

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")) 

152 

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")) 

160 

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" 

175 

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 ) 

182 

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" 

192 

193 

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() 

202 

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) 

209 

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")) 

231 

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")) 

239 

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")) 

247 

248 # leave chat 

249 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=left_chat_id)) 

250 

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")) 

254 

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" 

265 

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" 

275 

276 

277def test_get_group_chat_messages(db): 

278 user1, token1 = generate_user() 

279 user2, token2 = generate_user() 

280 user3, token3 = generate_user() 

281 

282 make_friends(user1, user2) 

283 

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")) 

290 

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 

295 

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" 

299 

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 

304 

305 

306def test_get_group_chat_messages_pagination(db): 

307 user1, token1 = generate_user() 

308 user2, token2 = generate_user() 

309 make_friends(user1, user2) 

310 

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))) 

316 

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 

333 

334 

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) 

343 

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 

347 

348 for i in range(10): 

349 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=str(i))) 

350 

351 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)) 

352 

353 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="10")) 

354 

355 res = c.GetGroupChatMessages(conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id)) 

356 

357 # created + 10 normal + invited + normal 

358 assert len(res.messages) == 13 

359 

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" 

366 

367 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

368 

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")) 

372 

373 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)) 

374 

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")) 

377 

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" 

389 

390 

391def test_get_group_chat_info(db): 

392 user1, token1 = generate_user() 

393 user2, token2 = generate_user() 

394 user3, token3 = generate_user() 

395 

396 make_friends(user1, user2) 

397 make_friends(user3, user1) 

398 

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 

413 

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 

421 

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 

430 

431 

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() 

437 

438 make_friends(user1, user2) 

439 make_friends(user3, user1) 

440 

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")) 

450 

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 

455 

456 

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() 

462 

463 make_friends(user1, user2) 

464 make_friends(user3, user1) 

465 make_friends(user1, user4) 

466 

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")) 

476 

477 with conversations_session(token3) as c: 

478 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

479 

480 with conversations_session(token1) as c: 

481 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user4.id)) 

482 

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 

491 

492 

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) 

500 

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 

510 

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 

514 

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 

521 

522 

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) 

528 

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 

537 

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 

548 

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 

560 

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 

572 

573 

574def test_make_remove_group_chat_admin(db): 

575 user1, token1 = generate_user() 

576 user2, token2 = generate_user() 

577 user3, token3 = generate_user() 

578 

579 make_friends(user1, user2) 

580 make_friends(user1, user3) 

581 make_friends(user2, user3) 

582 

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 

587 

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 

595 

596 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user2.id)) 

597 

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 

603 

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 

608 

609 with conversations_session(token1) as c: 

610 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user2.id)) 

611 

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 

615 

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 

621 

622 

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) 

629 

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 

638 

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 

644 

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 

650 

651 

652def test_send_direct_message(db): 

653 user1, token1 = generate_user(complete_profile=True) 

654 user2, token2 = generate_user(complete_profile=True) 

655 

656 make_friends(user1, user2) 

657 

658 message1 = "Hello, user2!" 

659 message2 = "One more message." 

660 

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)) 

664 

665 c1.SendDirectMessage(conversations_pb2.SendDirectMessageReq(recipient_user_id=user2.id, text=message2)) 

666 

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)) 

670 

671 assert chat.is_dm 

672 group_chat_id = chat.group_chat_id 

673 

674 # Verify that the messages was received 

675 messages = c2.GetGroupChatMessages( 

676 conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id) 

677 ).messages 

678 

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 

683 

684 

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])) 

695 

696 assert mock_email.call_count == 0 

697 recipient_user, _ = generate_user() 

698 _ = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[recipient_user.id])) 

699 

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 ) 

705 

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])) 

711 

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 

718 

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 

725 

726 

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() 

736 

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) 

746 

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")) 

751 

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 

765 

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 

769 

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)) 

777 

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 

799 

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 

805 

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 ) 

812 

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 

817 

818 

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() 

828 

829 make_friends(user1, user2) 

830 make_friends(user1, user3) 

831 make_friends(user2, user3) 

832 make_friends(user1, user4) 

833 

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")) 

838 

839 with conversations_session(token2) as c: 

840 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 2")) 

841 

842 with conversations_session(token1) as c: 

843 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 3")) 

844 

845 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id)) 

846 

847 with conversations_session(token3) as c: 

848 # should work 

849 c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

850 

851 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq()) 

852 assert len(res.group_chats) == 1 

853 

854 

855def test_invite_to_dm(db): 

856 user1, token1 = generate_user() 

857 user2, token2 = generate_user() 

858 user3, token3 = generate_user() 

859 

860 make_friends(user1, user2) 

861 make_friends(user1, user3) 

862 make_friends(user2, user3) 

863 

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")) 

868 

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 

874 

875 

876def test_sole_admin_leaves(db): 

877 user1, token1 = generate_user() 

878 user2, token2 = generate_user() 

879 user3, token3 = generate_user() 

880 

881 make_friends(user1, user2) 

882 make_friends(user1, user3) 

883 make_friends(user2, user3) 

884 

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")) 

889 

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 

895 

896 with conversations_session(token2) as c: 

897 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

898 

899 with conversations_session(token3) as c: 

900 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

901 

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)) 

905 

906 

907def test_search_messages(db): 

908 user1, token1 = generate_user() 

909 user2, token2 = generate_user() 

910 user3, token3 = generate_user() 

911 

912 make_friends(user1, user2) 

913 make_friends(user1, user3) 

914 

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")) 

923 

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 

930 

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 

935 

936 

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) 

945 

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))) 

951 

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")) 

955 

956 assert len(res.results) == 11 

957 

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")) 

961 

962 assert len(res.results) == 1 

963 assert res.results[0].message.text.text == "Test message 10" 

964 

965 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

966 

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")) 

973 

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" 

981 

982 

983def test_admin_behaviour(db): 

984 user1, token1 = generate_user() 

985 user2, token2 = generate_user() 

986 user3, token3 = generate_user() 

987 

988 make_friends(user1, user2) 

989 make_friends(user1, user3) 

990 make_friends(user2, user3) 

991 

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 

1001 

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 

1013 

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 

1021 

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 

1027 

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 

1039 

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 

1046 

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 

1055 

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 

1061 

1062 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id)) 

1063 

1064 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid)) 

1065 

1066 with conversations_session(token2) as c: 

1067 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid)) 

1068 

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)) 

1072 

1073 

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() 

1080 

1081 make_friends(user1, user2) 

1082 make_friends(user1, user3) 

1083 make_friends(user1, user4) 

1084 make_friends(user1, user5) 

1085 

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 

1090 

1091 make_user_invisible(user3.id) 

1092 make_user_block(user1, user4) 

1093 make_user_block(user5, user1) 

1094 

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 

1100 

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 

1106 

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 

1112 

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 

1118 

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 ) 

1129 

1130 for subscription in subscriptions: 

1131 subscription.role = GroupChatRole.admin 

1132 

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 

1139 

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 

1145 

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 

1151 

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 

1157 

1158 

1159def test_last_seen(db): 

1160 user1, token1 = generate_user() 

1161 user2, token2 = generate_user() 

1162 user3, token3 = generate_user() 

1163 

1164 make_friends(user1, user2) 

1165 make_friends(user1, user3) 

1166 make_friends(user2, user3) 

1167 

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 

1173 

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 

1178 

1179 message_ids = [] 

1180 

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 ) 

1189 

1190 message_ids.append( 

1191 c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)).latest_message.message_id 

1192 ) 

1193 

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 

1197 

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 

1202 

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 ) 

1209 

1210 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1211 assert res.unseen_message_count == backward_offset 

1212 

1213 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="test message ...")) 

1214 

1215 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1216 assert res.unseen_message_count == 0 

1217 

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 

1222 

1223 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="test message ...")) 

1224 

1225 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=gcid)) 

1226 assert res.unseen_message_count == 0 

1227 

1228 

1229def test_one_dm_per_pair(db): 

1230 user1, token1 = generate_user() 

1231 user2, token2 = generate_user() 

1232 user3, token3 = generate_user() 

1233 

1234 make_friends(user1, user2) 

1235 make_friends(user1, user3) 

1236 make_friends(user2, user3) 

1237 

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 

1242 

1243 # create DM with user 3 

1244 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])) 

1245 assert res.is_dm 

1246 

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 

1251 

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 

1256 

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 

1260 

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 

1265 

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 

1270 

1271 

1272def test_GetDirectMessage(db): 

1273 user1, token1 = generate_user() 

1274 user2, token2 = generate_user() 

1275 user3, token3 = generate_user() 

1276 

1277 make_friends(user1, user2) 

1278 make_friends(user1, user3) 

1279 make_friends(user2, user3) 

1280 

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 

1286 

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 

1291 

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 

1296 

1297 # now should exist 

1298 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user2.id)) 

1299 assert res.group_chat_id == gcid 

1300 

1301 # create DM with user 3 

1302 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])) 

1303 assert res.is_dm 

1304 

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 

1308 

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 

1315 

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 

1321 

1322 

1323def test_total_unseen(db): 

1324 user1, token1 = generate_user() 

1325 user2, token2 = generate_user() 

1326 user3, token3 = generate_user() 

1327 

1328 # distractions 

1329 user4, token4 = generate_user() 

1330 

1331 make_friends(user1, user2) 

1332 make_friends(user1, user3) 

1333 make_friends(user2, user3) 

1334 

1335 # distractions 

1336 make_friends(user1, user4) 

1337 

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...")) 

1344 

1345 gcid = c.CreateGroupChat( 

1346 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id]) 

1347 ).group_chat_id 

1348 

1349 for i in range(6): 

1350 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text=f"test message {i}")) 

1351 

1352 # distractions 

1353 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction...")) 

1354 

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 

1358 

1359 with api_session(token2) as api: 

1360 # chat created + 6 normal messages 

1361 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 7 

1362 

1363 # now leave chat with user2 

1364 with conversations_session(token2) as c: 

1365 c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=gcid)) 

1366 

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 

1370 

1371 with conversations_session(token1) as c: 

1372 # distractions 

1373 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction...")) 

1374 

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}")) 

1378 

1379 # distractions 

1380 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction...")) 

1381 

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 

1385 

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)) 

1389 

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}")) 

1393 

1394 # distractions 

1395 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text="distraction...")) 

1396 

1397 with api_session(token2) as api: 

1398 # joined + 12 normal 

1399 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 13 

1400 

1401 

1402def test_regression_ListGroupChats_pagination(db): 

1403 user1, token1 = generate_user() 

1404 user2, token2 = generate_user() 

1405 user3, token3 = generate_user() 

1406 

1407 make_friends(user1, user2) 

1408 make_friends(user1, user3) 

1409 

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 ) 

1419 

1420 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res1.group_chat_id, text=f"Test message {i}")) 

1421 

1422 res2 = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=res1.group_chat_id)) 

1423 

1424 group_chat_and_message_ids.append((res2.group_chat_id, res2.latest_message.message_id)) 

1425 

1426 seen_group_chat_ids = [] 

1427 

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 

1434 

1435 seen_group_chat_ids.extend([chat.group_chat_id for chat in res.group_chats]) 

1436 

1437 assert set(seen_group_chat_ids) == {x[0] for x in group_chat_and_message_ids}, "Not all group chats returned" 

1438 

1439 

1440def test_muting(db): 

1441 user1, token1 = generate_user() 

1442 user2, token2 = generate_user() 

1443 user3, token3 = generate_user() 

1444 

1445 make_friends(user1, user2) 

1446 make_friends(user1, user3) 

1447 make_friends(user2, user3) 

1448 

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 

1454 

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 

1459 

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") 

1464 

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") 

1469 

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") 

1474 

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) 

1485 

1486 

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() 

1495 

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) 

1501 

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 ) 

1526 

1527 group_chat_id = None 

1528 

1529 def send_msg(c, i): 

1530 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text=f"Test message {i}")) 

1531 

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) 

1542 

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) 

1549 

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)) 

1553 

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)) 

1557 

1558 with conversations_session(token6) as c: 

1559 send_msg(c, i=8) 

1560 

1561 # go through all bg jobs 

1562 while process_job(): 

1563 pass 

1564 

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 ] 

1574 

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 ) 

1589 

1590 def parse_message_payload(data): 

1591 return notification_data_pb2.ChatMessage.FromString(data).text 

1592 

1593 contents = [parse_message_payload(d) for d in deliv] 

1594 

1595 print(contents) 

1596 

1597 assert [f"Test message {i}" for i in expected_msgs] == contents, f"Wrong messages for {label}" 

1598 

1599 

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) 

1606 

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 

1616 

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