Coverage for app / backend / src / tests / test_conversations.py: 100%

1228 statements  

« prev     ^ index     » next       coverage.py v7.13.2, created at 2026-02-03 06:18 +0000

1from datetime import timedelta 

2 

3import grpc 

4import pytest 

5from google.protobuf import wrappers_pb2 

6from sqlalchemy import select 

7 

8from couchers.db import session_scope 

9from couchers.jobs.worker import process_job 

10from couchers.models import ( 

11 GroupChatRole, 

12 GroupChatSubscription, 

13 Notification, 

14 NotificationDelivery, 

15 NotificationDeliveryType, 

16 NotificationTopicAction, 

17 RateLimitAction, 

18) 

19from couchers.proto import api_pb2, conversations_pb2, notification_data_pb2, notifications_pb2 

20from couchers.rate_limits.definitions import RATE_LIMIT_DEFINITIONS, RATE_LIMIT_HOURS 

21from couchers.utils import Duration_from_timedelta, now, to_aware_datetime 

22from tests.fixtures.db import generate_user, make_friends, make_user_block, make_user_invisible 

23from tests.fixtures.misc import email_fields, mock_notification_email 

24from tests.fixtures.sessions import api_session, conversations_session, notifications_session 

25 

26 

27@pytest.fixture(autouse=True) 

28def _(testconfig): 

29 pass 

30 

31 

32def test_list_group_chats(db, moderator): 

33 user1, token1 = generate_user() 

34 user2, token2 = generate_user() 

35 user3, token3 = generate_user() 

36 

37 make_friends(user2, user1) 

38 make_friends(user1, user3) 

39 

40 with conversations_session(token1) as c: 

41 # no threads initially 

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

43 assert len(res.group_chats) == 0 

44 

45 # create some group chats with messages 

46 res = c.CreateGroupChat( 

47 conversations_pb2.CreateGroupChatReq( 

48 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title") 

49 ) 

50 ) 

51 group_chat1_id = res.group_chat_id 

52 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1")) 

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

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

55 group_chat2_id = res.group_chat_id 

56 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 1")) 

57 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 2")) 

58 

59 moderator.approve_group_chat(group_chat1_id) 

60 moderator.approve_group_chat(group_chat2_id) 

61 

62 with conversations_session(token1) as c: 

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

64 assert len(res.group_chats) == 2 

65 assert res.no_more 

66 

67 with conversations_session(token2) as c: 

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

69 assert len(res.group_chats) == 2 

70 assert res.no_more 

71 

72 with conversations_session(token3) as c: 

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

74 assert len(res.group_chats) == 1 

75 assert res.no_more 

76 

77 # Test archive filtering: archive group_chat1 for user1 

78 with conversations_session(token1) as c: 

79 res = c.SetGroupChatArchiveStatus( 

80 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=group_chat1_id, is_archived=True) 

81 ) 

82 assert res.group_chat_id == group_chat1_id 

83 assert res.is_archived 

84 

85 with conversations_session(token1) as c: 

86 # Without filter, returns all chats 

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

88 assert len(res.group_chats) == 2 

89 

90 # only_archived=False returns non-archived chats only 

91 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False)) 

92 assert len(res.group_chats) == 1 

93 

94 # only_archived=True returns archived chats only 

95 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True)) 

96 assert len(res.group_chats) == 1 

97 

98 # user2 should still see both as non-archived (archive is per-user) 

99 with conversations_session(token2) as c: 

100 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False)) 

101 assert len(res.group_chats) == 2 

102 

103 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True)) 

104 assert len(res.group_chats) == 0 

105 

106 

107def test_list_empty_group_chats(db, moderator): 

108 user1, token1 = generate_user() 

109 user2, token2 = generate_user() 

110 user3, token3 = generate_user() 

111 

112 make_friends(user1, user3) 

113 make_friends(user2, user1) 

114 make_friends(user2, user3) 

115 

116 with conversations_session(token1) as c: 

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

118 assert len(res.group_chats) == 0 

119 

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

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

122 

123 moderator.approve_group_chat(res1.group_chat_id) 

124 moderator.approve_group_chat(res2.group_chat_id) 

125 

126 with conversations_session(token1) as c: 

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

128 assert len(res.group_chats) == 2 

129 assert res.no_more 

130 

131 with conversations_session(token2) as c: 

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

133 assert len(res.group_chats) == 2 

134 assert res.no_more 

135 

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

137 moderator.approve_group_chat(res3.group_chat_id) 

138 

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

140 assert len(res.group_chats) == 3 

141 assert res.no_more 

142 

143 with conversations_session(token3) as c: 

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

145 assert len(res.group_chats) == 2 

146 assert res.no_more 

147 

148 

149def test_list_group_chats_ordering(db, moderator): 

150 # user is member of 5 group chats, order them correctly 

151 user, token = generate_user() 

152 user2, token2 = generate_user() 

153 user3, token3 = generate_user() 

154 user4, token4 = generate_user() 

155 

156 make_friends(user2, user) 

157 make_friends(user2, user3) 

158 make_friends(user2, user4) 

159 make_friends(user3, user) 

160 make_friends(user3, user4) 

161 make_friends(user, user4) 

162 

163 chat_ids = [] 

164 

165 with conversations_session(token2) as c: 

166 res = c.CreateGroupChat( 

167 conversations_pb2.CreateGroupChatReq( 

168 recipient_user_ids=[user.id], title=wrappers_pb2.StringValue(value="Chat 0") 

169 ) 

170 ) 

171 chat_ids.append(res.group_chat_id) 

172 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

173 res = c.CreateGroupChat( 

174 conversations_pb2.CreateGroupChatReq( 

175 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 1") 

176 ) 

177 ) 

178 chat_ids.append(res.group_chat_id) 

179 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

180 res = c.CreateGroupChat( 

181 conversations_pb2.CreateGroupChatReq( 

182 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 2") 

183 ) 

184 ) 

185 chat_ids.append(res.group_chat_id) 

186 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

187 

188 with conversations_session(token3) as c: 

189 res = c.CreateGroupChat( 

190 conversations_pb2.CreateGroupChatReq( 

191 recipient_user_ids=[user.id, user2.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 3") 

192 ) 

193 ) 

194 chat_ids.append(res.group_chat_id) 

195 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

196 

197 for chat_id in chat_ids: 

198 moderator.approve_group_chat(chat_id) 

199 

200 with conversations_session(token) as c: 

201 res = c.CreateGroupChat( 

202 conversations_pb2.CreateGroupChatReq( 

203 recipient_user_ids=[user2.id, user3.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 4") 

204 ) 

205 ) 

206 moderator.approve_group_chat(res.group_chat_id) 

207 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

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

209 assert len(res.group_chats) == 5 

210 assert res.group_chats[0].title == "Chat 4" 

211 assert res.group_chats[1].title == "Chat 3" 

212 assert res.group_chats[2].title == "Chat 2" 

213 assert res.group_chats[3].title == "Chat 1" 

214 assert res.group_chats[4].title == "Chat 0" 

215 

216 c.SendMessage( 

217 conversations_pb2.SendMessageReq(group_chat_id=res.group_chats[3].group_chat_id, text="Test message 2a") 

218 ) 

219 c.SendMessage( 

220 conversations_pb2.SendMessageReq(group_chat_id=res.group_chats[2].group_chat_id, text="Test message 2b") 

221 ) 

222 

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

224 assert len(res.group_chats) == 5 

225 assert res.group_chats[0].title == "Chat 2" 

226 assert res.group_chats[0].latest_message.text.text == "Test message 2b" 

227 assert res.group_chats[1].title == "Chat 1" 

228 assert res.group_chats[1].latest_message.text.text == "Test message 2a" 

229 assert res.group_chats[2].title == "Chat 4" 

230 assert res.group_chats[3].title == "Chat 3" 

231 assert res.group_chats[4].title == "Chat 0" 

232 

233 

234def test_list_group_chats_ordering_after_left(db, moderator): 

235 # user is member to 4 group chats, and has left one. 

236 # The one user left has the most recent message, but user left before then, 

237 # this should display as e.g. 3rd most recent depending on last message when they were in the chat 

238 user, token = generate_user() 

239 user2, token2 = generate_user() 

240 user3, token3 = generate_user() 

241 user4, token4 = generate_user() 

242 

243 make_friends(user2, user) 

244 make_friends(user2, user3) 

245 make_friends(user2, user4) 

246 make_friends(user3, user) 

247 make_friends(user3, user4) 

248 make_friends(user, user4) 

249 

250 chat_ids = [] 

251 

252 with conversations_session(token2) as c: 

253 res = c.CreateGroupChat( 

254 conversations_pb2.CreateGroupChatReq( 

255 recipient_user_ids=[user.id], title=wrappers_pb2.StringValue(value="Chat 0") 

256 ) 

257 ) 

258 chat_ids.append(res.group_chat_id) 

259 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

260 res = c.CreateGroupChat( 

261 conversations_pb2.CreateGroupChatReq( 

262 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Left Chat 1") 

263 ) 

264 ) 

265 left_chat_id = res.group_chat_id 

266 chat_ids.append(left_chat_id) 

267 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Test message")) 

268 res = c.CreateGroupChat( 

269 conversations_pb2.CreateGroupChatReq( 

270 recipient_user_ids=[user.id, user3.id], title=wrappers_pb2.StringValue(value="Chat 2") 

271 ) 

272 ) 

273 chat2_id = res.group_chat_id 

274 chat_ids.append(chat2_id) 

275 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=chat2_id, text="Test message")) 

276 

277 with conversations_session(token3) as c: 

278 res = c.CreateGroupChat( 

279 conversations_pb2.CreateGroupChatReq( 

280 recipient_user_ids=[user.id, user2.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 3") 

281 ) 

282 ) 

283 chat_ids.append(res.group_chat_id) 

284 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

285 

286 for chat_id in chat_ids: 

287 moderator.approve_group_chat(chat_id) 

288 

289 with conversations_session(token) as c: 

290 res = c.CreateGroupChat( 

291 conversations_pb2.CreateGroupChatReq( 

292 recipient_user_ids=[user2.id, user3.id, user4.id], title=wrappers_pb2.StringValue(value="Chat 4") 

293 ) 

294 ) 

295 moderator.approve_group_chat(res.group_chat_id) 

296 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message")) 

297 

298 # leave chat 

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

300 

301 with conversations_session(token3) as c: 

302 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=chat2_id, text="Test message")) 

303 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Test message")) 

304 

305 with conversations_session(token2) as c: 

306 # other user sends a message to that chat 

307 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=left_chat_id, text="Another test message")) 

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

309 assert len(res.group_chats) == 5 

310 assert res.group_chats[0].title == "Left Chat 1" 

311 assert res.group_chats[1].title == "Chat 2" 

312 assert res.group_chats[2].title == "Chat 4" 

313 assert res.group_chats[3].title == "Chat 3" 

314 assert res.group_chats[4].title == "Chat 0" 

315 

316 with conversations_session(token) as c: 

317 # we can't see the new message since we left before it was sent 

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

319 assert len(res.group_chats) == 5 

320 assert res.group_chats[0].title == "Chat 2" 

321 assert res.group_chats[1].title == "Left Chat 1" 

322 assert res.group_chats[2].title == "Chat 4" 

323 assert res.group_chats[3].title == "Chat 3" 

324 assert res.group_chats[4].title == "Chat 0" 

325 

326 

327def test_get_group_chat_messages(db): 

328 user1, token1 = generate_user() 

329 user2, token2 = generate_user() 

330 user3, token3 = generate_user() 

331 

332 make_friends(user1, user2) 

333 

334 with conversations_session(token1) as c: 

335 # create some threads with messages 

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

337 group_chat_id = res.group_chat_id 

338 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1")) 

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

340 

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

342 # created + 2 normal 

343 assert len(res.messages) == 3 

344 assert res.no_more 

345 

346 assert res.messages[0].text.text == "Test message 2" 

347 assert res.messages[1].text.text == "Test message 1" 

348 assert res.messages[2].WhichOneof("content") == "chat_created" 

349 

350 # test that another user can't access the thread 

351 with conversations_session(token3) as c: 

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

353 assert len(res.messages) == 0 

354 

355 

356def test_get_group_chat_messages_pagination(db, moderator): 

357 user1, token1 = generate_user() 

358 user2, token2 = generate_user() 

359 make_friends(user1, user2) 

360 

361 with conversations_session(token1) as c: 

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

363 group_chat_id = res.group_chat_id 

364 for i in range(30): 

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

366 

367 moderator.approve_group_chat(group_chat_id) 

368 

369 with conversations_session(token2) as c: 

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

371 # pagination 

372 assert len(res.messages) == 20 

373 assert res.messages[0].text.text == "29" 

374 assert res.messages[19].text.text == "10" 

375 assert not res.no_more 

376 res = c.GetGroupChatMessages( 

377 conversations_pb2.GetGroupChatMessagesReq( 

378 group_chat_id=group_chat_id, last_message_id=res.messages[19].message_id 

379 ) 

380 ) 

381 assert len(res.messages) == 11 

382 assert res.messages[0].text.text == "9" 

383 assert res.messages[9].text.text == "0" 

384 assert res.no_more 

385 

386 

387def test_get_group_chat_messages_joined_left(db, moderator): 

388 user1, token1 = generate_user() 

389 user2, token2 = generate_user() 

390 user3, token3 = generate_user() 

391 user4, token4 = generate_user() 

392 make_friends(user1, user2) 

393 make_friends(user1, user3) 

394 make_friends(user1, user4) 

395 

396 with conversations_session(token1) as c: 

397 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id])) 

398 group_chat_id = res.group_chat_id 

399 moderator.approve_group_chat(group_chat_id) 

400 

401 for i in range(10): 

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

403 

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

405 

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

407 

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

409 

410 # created + 10 normal + invited + normal 

411 assert len(res.messages) == 13 

412 

413 with conversations_session(token3) as c: 

414 # can only see last message after invited 

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

416 # joined + normal 

417 assert len(res.messages) == 2 

418 assert res.messages[0].text.text == "10" 

419 

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

421 

422 with conversations_session(token1) as c: 

423 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="11")) 

424 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="12")) 

425 

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

427 

428 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="13")) 

429 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="14")) 

430 

431 with conversations_session(token3) as c: 

432 # can only see last message after invited 

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

434 # joined + normal + left + invite + 2 normal 

435 assert len(res.messages) == 6 

436 assert res.messages[0].text.text == "14" 

437 assert res.messages[1].text.text == "13" 

438 assert res.messages[2].WhichOneof("content") == "user_invited" 

439 assert res.messages[3].WhichOneof("content") == "user_left" 

440 assert res.messages[4].text.text == "10" 

441 assert res.messages[5].WhichOneof("content") == "user_invited" 

442 

443 

444def test_get_group_chat_info(db): 

445 user1, token1 = generate_user() 

446 user2, token2 = generate_user() 

447 user3, token3 = generate_user() 

448 

449 make_friends(user1, user2) 

450 make_friends(user3, user1) 

451 

452 with conversations_session(token1) as c: 

453 # create some threads with messages 

454 res = c.CreateGroupChat( 

455 conversations_pb2.CreateGroupChatReq( 

456 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title") 

457 ) 

458 ) 

459 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test message 1")) 

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

461 group_chat1_id = res.group_chat_id 

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

463 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 1")) 

464 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=res.group_chat_id, text="Test group message 2")) 

465 group_chat2_id = res.group_chat_id 

466 

467 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat1_id)) 

468 assert res.title == "Test title" 

469 assert user2.id in res.member_user_ids 

470 assert user1.id in res.admin_user_ids 

471 assert to_aware_datetime(res.created) <= now() 

472 assert res.only_admins_invite 

473 assert res.is_dm 

474 assert not res.is_archived 

475 

476 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat2_id)) 

477 assert not res.title 

478 assert user2.id in res.member_user_ids 

479 assert user3.id in res.member_user_ids 

480 assert user1.id in res.admin_user_ids 

481 assert to_aware_datetime(res.created) <= now() 

482 assert res.only_admins_invite 

483 assert not res.is_dm 

484 assert not res.is_archived 

485 

486 

487def test_get_group_chat_info_denied(db): 

488 user1, token1 = generate_user() 

489 user2, token2 = generate_user() 

490 user3, token3 = generate_user() 

491 user4, token4 = generate_user() 

492 

493 make_friends(user1, user2) 

494 make_friends(user3, user1) 

495 

496 with conversations_session(token1) as c: 

497 # create a group chat with messages 

498 res = c.CreateGroupChat( 

499 conversations_pb2.CreateGroupChatReq( 

500 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title") 

501 ) 

502 ) 

503 group_chat_id = res.group_chat_id 

504 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

505 

506 with conversations_session(token4) as c: 

507 with pytest.raises(grpc.RpcError) as e: 

508 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

509 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

510 

511 

512def test_get_group_chat_info_left(db, moderator): 

513 user1, token1 = generate_user() 

514 user2, token2 = generate_user() 

515 user3, token3 = generate_user() 

516 user4, token4 = generate_user() 

517 

518 make_friends(user1, user2) 

519 make_friends(user3, user1) 

520 make_friends(user1, user4) 

521 

522 with conversations_session(token1) as c: 

523 # create a group chat with messages 

524 res = c.CreateGroupChat( 

525 conversations_pb2.CreateGroupChatReq( 

526 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title") 

527 ) 

528 ) 

529 group_chat_id = res.group_chat_id 

530 moderator.approve_group_chat(group_chat_id) 

531 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

532 

533 with conversations_session(token3) as c: 

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

535 

536 with conversations_session(token1) as c: 

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

538 

539 with conversations_session(token3) as c: 

540 # this user left when user4 wasn't a member, 

541 # so the returned members should be user1, user2, and user3 only 

542 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

543 assert len(res.member_user_ids) == 3 

544 assert user1.id in res.member_user_ids 

545 assert user2.id in res.member_user_ids 

546 assert user3.id in res.member_user_ids 

547 

548 

549def test_remove_group_chat_user(db): 

550 # create 3 uses and connect them 

551 user1, token1 = generate_user() 

552 user2, token2 = generate_user() 

553 user3, token3 = generate_user() 

554 make_friends(user1, user2) 

555 make_friends(user1, user3) 

556 

557 # using user token, create a Conversations API for testing 

558 with conversations_session(token1) as c: 

559 # create a group chat 

560 res = c.CreateGroupChat( 

561 conversations_pb2.CreateGroupChatReq( 

562 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value="Test title") 

563 ) 

564 ) 

565 group_chat_id = res.group_chat_id 

566 

567 # remove a user from group 

568 c.RemoveGroupChatUser(conversations_pb2.RemoveGroupChatUserReq(group_chat_id=group_chat_id, user_id=user2.id)) 

569 assert user3.id in res.member_user_ids # other users are still in the group 

570 

571 # can't remove the same user twice 

572 with pytest.raises(grpc.RpcError) as e: 

573 c.RemoveGroupChatUser( 

574 conversations_pb2.RemoveGroupChatUserReq(group_chat_id=group_chat_id, user_id=user2.id) 

575 ) 

576 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

577 

578 

579def test_edit_group_chat(db, moderator): 

580 user1, token1 = generate_user() 

581 user2, token2 = generate_user() 

582 user3, token3 = generate_user() 

583 make_friends(user1, user2) 

584 

585 with conversations_session(token1) as c: 

586 # create some threads with messages 

587 res = c.CreateGroupChat( 

588 conversations_pb2.CreateGroupChatReq( 

589 recipient_user_ids=[user2.id], title=wrappers_pb2.StringValue(value="Test title") 

590 ) 

591 ) 

592 group_chat_id = res.group_chat_id 

593 moderator.approve_group_chat(group_chat_id) 

594 

595 c.EditGroupChat( 

596 conversations_pb2.EditGroupChatReq( 

597 group_chat_id=group_chat_id, 

598 title=wrappers_pb2.StringValue(value="Modified title"), 

599 only_admins_invite=wrappers_pb2.BoolValue(value=False), 

600 ) 

601 ) 

602 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

603 assert res.title == "Modified title" 

604 assert not res.only_admins_invite 

605 

606 # make sure non-admin is not allowed to modify 

607 with conversations_session(token2) as c: 

608 with pytest.raises(grpc.RpcError) as e: 

609 c.EditGroupChat( 

610 conversations_pb2.EditGroupChatReq( 

611 group_chat_id=group_chat_id, 

612 title=wrappers_pb2.StringValue(value="Other title"), 

613 only_admins_invite=wrappers_pb2.BoolValue(value=True), 

614 ) 

615 ) 

616 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

617 

618 # make sure non-recipient is not allowed to modify 

619 with conversations_session(token3) as c: 

620 with pytest.raises(grpc.RpcError) as e: 

621 c.EditGroupChat( 

622 conversations_pb2.EditGroupChatReq( 

623 group_chat_id=group_chat_id, 

624 title=wrappers_pb2.StringValue(value="Other title"), 

625 only_admins_invite=wrappers_pb2.BoolValue(value=True), 

626 ) 

627 ) 

628 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

629 

630 

631def test_make_remove_group_chat_admin(db, moderator): 

632 user1, token1 = generate_user() 

633 user2, token2 = generate_user() 

634 user3, token3 = generate_user() 

635 

636 make_friends(user1, user2) 

637 make_friends(user1, user3) 

638 make_friends(user2, user3) 

639 

640 with conversations_session(token1) as c: 

641 # create some threads with messages 

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

643 group_chat_id = res.group_chat_id 

644 moderator.approve_group_chat(group_chat_id) 

645 

646 # shouldn't be able to remove only admin 

647 with pytest.raises(grpc.RpcError) as e: 

648 c.RemoveGroupChatAdmin( 

649 conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user1.id) 

650 ) 

651 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

652 assert e.value.details() == "You can't remove the last admin." 

653 

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

655 

656 # shouldn't be able to make admin again 

657 with pytest.raises(grpc.RpcError) as e: 

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

659 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

660 assert e.value.details() == "That user is already an admin." 

661 

662 with conversations_session(token2) as c: 

663 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

664 assert user1.id in res.admin_user_ids 

665 assert user2.id in res.admin_user_ids 

666 

667 with conversations_session(token1) as c: 

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

669 

670 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

671 assert user1.id in res.admin_user_ids 

672 assert user2.id not in res.admin_user_ids 

673 

674 with conversations_session(token2) as c: 

675 # shouldn't be able to make admin if not admin 

676 with pytest.raises(grpc.RpcError) as e: 

677 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=group_chat_id, user_id=user3.id)) 

678 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

679 

680 

681def test_send_message(db): 

682 user1, token1 = generate_user() 

683 user2, token2 = generate_user() 

684 user3, token3 = generate_user() 

685 make_friends(user1, user2) 

686 make_friends(user1, user3) 

687 

688 with conversations_session(token1) as c: 

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

690 group_chat_id = res.group_chat_id 

691 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

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

693 assert res.messages[0].text.text == "Test message 1" 

694 assert to_aware_datetime(res.messages[0].time) <= now() 

695 assert res.messages[0].author_user_id == user1.id 

696 

697 # can't send message if not in chat 

698 with conversations_session(token3) as c: 

699 with pytest.raises(grpc.RpcError) as e: 

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

701 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

702 

703 make_user_block(user2, user1) 

704 with conversations_session(token1) as c: 

705 with pytest.raises(grpc.RpcError) as e: 

706 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Message after block")) 

707 assert e.value.details() == "You can't send a message in this chat." 

708 

709 

710def test_send_direct_message(db, moderator): 

711 user1, token1 = generate_user(complete_profile=True) 

712 user2, token2 = generate_user(complete_profile=True) 

713 

714 make_friends(user1, user2) 

715 

716 message1 = "Hello, user2!" 

717 message2 = "One more message." 

718 

719 with conversations_session(token1) as c1: 

720 # Send a DM from user1 to user2 

721 res = c1.SendDirectMessage(conversations_pb2.SendDirectMessageReq(recipient_user_id=user2.id, text=message1)) 

722 moderator.approve_group_chat(res.group_chat_id) 

723 

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

725 

726 with conversations_session(token2) as c2: 

727 # Fetch the chat by ID returned from SendDirectMessage 

728 chat = c2.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=res.group_chat_id)) 

729 

730 assert chat.is_dm 

731 group_chat_id = chat.group_chat_id 

732 

733 # Verify that the messages was received 

734 messages = c2.GetGroupChatMessages( 

735 conversations_pb2.GetGroupChatMessagesReq(group_chat_id=group_chat_id) 

736 ).messages 

737 

738 assert len(messages) == 2 

739 assert messages[0].text.text == message2 

740 assert messages[1].text.text == message1 

741 assert messages[0].author_user_id == user1.id 

742 

743 

744def test_excessive_chat_initiations_are_reported(db): 

745 """Test that excessive chat initiations are first reported in a warning email and finally lead blocking of further contacting other users.""" 

746 user, token = generate_user() 

747 rate_limit_definition = RATE_LIMIT_DEFINITIONS[RateLimitAction.chat_initiation] 

748 with conversations_session(token) as c: 

749 # Test warning email 

750 with mock_notification_email() as mock_email: 

751 for _ in range(rate_limit_definition.warning_limit): 

752 recipient_user, _ = generate_user() 

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

754 

755 assert mock_email.call_count == 0 

756 recipient_user, _ = generate_user() 

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

758 

759 assert mock_email.call_count == 1 

760 email = email_fields(mock_email).plain 

761 assert email.startswith( 

762 f"User {user.username} has sent {rate_limit_definition.warning_limit} chat initiations in the past {RATE_LIMIT_HOURS} hours." 

763 ) 

764 

765 # Test new chat initiations fail after exceeding CHAT_INITIATION_HARD_LIMIT 

766 with mock_notification_email() as mock_email: 

767 for _ in range(rate_limit_definition.hard_limit - rate_limit_definition.warning_limit - 1): 

768 recipient_user, _ = generate_user() 

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

770 

771 assert mock_email.call_count == 0 

772 recipient_user, _ = generate_user() 

773 with pytest.raises(grpc.RpcError) as exc_info: 

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

775 assert exc_info.value.code() == grpc.StatusCode.RESOURCE_EXHAUSTED 

776 assert ( 

777 exc_info.value.details() 

778 == "You have messaged a lot of users in the past 24 hours. To avoid spam, you can't contact any more users for now." 

779 ) 

780 

781 assert mock_email.call_count == 1 

782 email = email_fields(mock_email).plain 

783 assert email.startswith( 

784 f"User {user.username} has sent {rate_limit_definition.hard_limit} chat initiations in the past {RATE_LIMIT_HOURS} hours." 

785 ) 

786 assert "The user has been blocked from sending further chat initiations for now." in email 

787 

788 

789def test_leave_invite_to_group_chat(db, moderator): 

790 user1, token1 = generate_user() 

791 user2, token2 = generate_user() 

792 user3, token3 = generate_user() 

793 user4, token4 = generate_user() 

794 user5, token5 = generate_user() 

795 user6, token6 = generate_user(delete_user=True) 

796 user7, token7 = generate_user() 

797 user8, token8 = generate_user() 

798 

799 make_friends(user1, user2) 

800 make_friends(user1, user3) 

801 make_friends(user1, user5) 

802 make_friends(user1, user7) 

803 make_friends(user1, user8) 

804 make_friends(user2, user3) 

805 make_friends(user4, user3) 

806 make_user_block(user1, user7) 

807 make_user_block(user8, user1) 

808 

809 with conversations_session(token1) as c: 

810 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user5.id])) 

811 group_chat_id = res.group_chat_id 

812 moderator.approve_group_chat(group_chat_id) 

813 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

814 

815 # other user not in chat 

816 with conversations_session(token3) as c: 

817 with pytest.raises(grpc.RpcError) as e: 

818 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

819 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

820 with pytest.raises(grpc.RpcError) as e: 

821 res = c.InviteToGroupChat( 

822 conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user4.id) 

823 ) 

824 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

825 with pytest.raises(grpc.RpcError) as e: 

826 res = c.LeaveGroupChat(conversations_pb2.LeaveGroupChatReq(group_chat_id=group_chat_id)) 

827 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

828 

829 with conversations_session(token2) as c: 

830 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

831 assert user3.id not in res.member_user_ids 

832 

833 # only_admins_invite defaults to true so shouldn't be able to invite 

834 with pytest.raises(grpc.RpcError) as e: 

835 res = c.InviteToGroupChat( 

836 conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user3.id) 

837 ) 

838 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

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

840 

841 with conversations_session(token1) as c: 

842 # invite invisible user fails 

843 with pytest.raises(grpc.RpcError) as e: 

844 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user6.id)) 

845 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

846 assert e.value.details() == "Couldn't find that user." 

847 # invite fake user fails 

848 with pytest.raises(grpc.RpcError) as e: 

849 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=999)) 

850 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

851 assert e.value.details() == "Couldn't find that user." 

852 # invite blocked user fails 

853 with pytest.raises(grpc.RpcError) as e: 

854 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user7.id)) 

855 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

856 assert e.value.details() == "Couldn't find that user." 

857 # invite blocking user fails 

858 with pytest.raises(grpc.RpcError) as e: 

859 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user8.id)) 

860 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

861 assert e.value.details() == "Couldn't find that user." 

862 

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

864 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

865 assert user1.id in res.member_user_ids 

866 assert user5.id in res.member_user_ids 

867 assert user3.id in res.member_user_ids 

868 

869 # test non-admin inviting 

870 c.EditGroupChat( 

871 conversations_pb2.EditGroupChatReq( 

872 group_chat_id=group_chat_id, only_admins_invite=wrappers_pb2.BoolValue(value=False) 

873 ) 

874 ) 

875 

876 with conversations_session(token3) as c: 

877 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user2.id)) 

878 res = c.GetGroupChat(conversations_pb2.GetGroupChatReq(group_chat_id=group_chat_id)) 

879 assert user2.id in res.member_user_ids 

880 

881 

882def test_group_chats_with_messages_before_join(db, moderator): 

883 """ 

884 If user 1 and 2 have a group chat and send messages, then add user 3; user 3 

885 should still see the group chat! 

886 """ 

887 user1, token1 = generate_user() 

888 user2, token2 = generate_user() 

889 user3, token3 = generate_user() 

890 user4, token4 = generate_user() 

891 

892 make_friends(user1, user2) 

893 make_friends(user1, user3) 

894 make_friends(user2, user3) 

895 make_friends(user1, user4) 

896 

897 with conversations_session(token1) as c: 

898 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id])) 

899 group_chat_id = res.group_chat_id 

900 moderator.approve_group_chat(group_chat_id) 

901 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

902 

903 with conversations_session(token2) as c: 

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

905 

906 with conversations_session(token1) as c: 

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

908 

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

910 

911 with conversations_session(token3) as c: 

912 # should work 

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

914 

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

916 assert len(res.group_chats) == 1 

917 

918 

919def test_invite_to_dm(db): 

920 user1, token1 = generate_user() 

921 user2, token2 = generate_user() 

922 user3, token3 = generate_user() 

923 

924 make_friends(user1, user2) 

925 make_friends(user1, user3) 

926 make_friends(user2, user3) 

927 

928 with conversations_session(token1) as c: 

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

930 group_chat_id = res.group_chat_id 

931 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

932 

933 # dm, shou;dn't be able to invite someone else 

934 with pytest.raises(grpc.RpcError) as e: 

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

936 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

937 assert e.value.details() == "You can't invite other users to a direct message." 

938 

939 

940def test_sole_admin_leaves(db, moderator): 

941 user1, token1 = generate_user() 

942 user2, token2 = generate_user() 

943 user3, token3 = generate_user() 

944 

945 make_friends(user1, user2) 

946 make_friends(user1, user3) 

947 make_friends(user2, user3) 

948 

949 with conversations_session(token1) as c: 

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

951 group_chat_id = res.group_chat_id 

952 moderator.approve_group_chat(group_chat_id) 

953 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

954 

955 # sole admin can't leave group chat 

956 with pytest.raises(grpc.RpcError) as e: 

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

958 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

959 assert e.value.details() == "The last admin can't leave a group chat." 

960 

961 with conversations_session(token2) as c: 

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

963 

964 with conversations_session(token3) as c: 

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

966 

967 # sole admin can leave when last in chat 

968 with conversations_session(token1) as c: 

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

970 

971 

972def test_search_messages(db, moderator): 

973 user1, token1 = generate_user() 

974 user2, token2 = generate_user() 

975 user3, token3 = generate_user() 

976 

977 make_friends(user1, user2) 

978 make_friends(user1, user3) 

979 

980 with conversations_session(token1) as c: 

981 # create some threads with messages 

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

983 gc1_id = res.group_chat_id 

984 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gc1_id, text="Test message 1")) 

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

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

987 gc2_id = res.group_chat_id 

988 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gc2_id, text="Test group message 3")) 

989 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gc2_id, text="Test group message 4")) 

990 

991 # Approve group chats so they appear in search results 

992 moderator.approve_group_chat(gc1_id) 

993 moderator.approve_group_chat(gc2_id) 

994 

995 with conversations_session(token1) as c: 

996 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="message ")) 

997 assert len(res.results) == 4 

998 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="group ")) 

999 assert len(res.results) == 2 

1000 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="message 5")) 

1001 assert len(res.results) == 0 

1002 

1003 # outside user doesn't get results 

1004 with conversations_session(token3) as c: 

1005 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message")) 

1006 assert len(res.results) == 0 

1007 

1008 

1009def test_search_messages_left_joined(db, moderator): 

1010 user1, token1 = generate_user() 

1011 user2, token2 = generate_user() 

1012 user3, token3 = generate_user() 

1013 user4, token4 = generate_user() 

1014 make_friends(user1, user2) 

1015 make_friends(user1, user3) 

1016 make_friends(user1, user4) 

1017 

1018 with conversations_session(token1) as c: 

1019 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user4.id])) 

1020 group_chat_id = res.group_chat_id 

1021 moderator.approve_group_chat(group_chat_id) 

1022 for i in range(10): 

1023 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message " + str(i))) 

1024 

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

1026 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 10")) 

1027 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message")) 

1028 

1029 assert len(res.results) == 11 

1030 

1031 with conversations_session(token3) as c: 

1032 # can only see last message after invited 

1033 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message")) 

1034 

1035 assert len(res.results) == 1 

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

1037 

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

1039 

1040 with conversations_session(token1) as c: 

1041 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 11")) 

1042 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 12")) 

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

1044 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 13")) 

1045 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 14")) 

1046 

1047 with conversations_session(token3) as c: 

1048 # can only see last message after invited 

1049 res = c.SearchMessages(conversations_pb2.SearchMessagesReq(query="Test message")) 

1050 assert len(res.results) == 3 

1051 assert res.results[0].message.text.text == "Test message 14" 

1052 assert res.results[1].message.text.text == "Test message 13" 

1053 assert res.results[2].message.text.text == "Test message 10" 

1054 

1055 

1056def test_admin_behaviour(db, moderator): 

1057 user1, token1 = generate_user() 

1058 user2, token2 = generate_user() 

1059 user3, token3 = generate_user() 

1060 

1061 make_friends(user1, user2) 

1062 make_friends(user1, user3) 

1063 make_friends(user2, user3) 

1064 

1065 with conversations_session(token1) as c: 

1066 gcid = c.CreateGroupChat( 

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

1068 ).group_chat_id 

1069 moderator.approve_group_chat(gcid) 

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

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

1072 assert len(res.admin_user_ids) == 2 

1073 assert user1.id in res.admin_user_ids 

1074 assert user2.id in res.admin_user_ids 

1075 

1076 with conversations_session(token3) as c: 

1077 with pytest.raises(grpc.RpcError) as e: 

1078 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

1079 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

1080 with pytest.raises(grpc.RpcError) as e: 

1081 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id)) 

1082 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED 

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

1084 assert len(res.admin_user_ids) == 2 

1085 assert user1.id in res.admin_user_ids 

1086 assert user2.id in res.admin_user_ids 

1087 

1088 with conversations_session(token2) as c: 

1089 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

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

1091 assert len(res.admin_user_ids) == 3 

1092 assert user1.id in res.admin_user_ids 

1093 assert user2.id in res.admin_user_ids 

1094 assert user3.id in res.admin_user_ids 

1095 

1096 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user1.id)) 

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

1098 assert len(res.admin_user_ids) == 2 

1099 assert user2.id in res.admin_user_ids 

1100 assert user3.id in res.admin_user_ids 

1101 

1102 with conversations_session(token1) as c: 

1103 with pytest.raises(grpc.RpcError): 

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

1105 with pytest.raises(grpc.RpcError): 

1106 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

1107 with pytest.raises(grpc.RpcError): 

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

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

1110 assert len(res.admin_user_ids) == 2 

1111 assert user2.id in res.admin_user_ids 

1112 assert user3.id in res.admin_user_ids 

1113 

1114 with conversations_session(token2) as c: 

1115 # can demote self if there are other admins 

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

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

1118 assert len(res.admin_user_ids) == 1 

1119 assert user3.id in res.admin_user_ids 

1120 

1121 with conversations_session(token3) as c: 

1122 with pytest.raises(grpc.RpcError) as e: 

1123 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

1124 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

1125 assert e.value.details() == "You can't remove the last admin." 

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

1127 assert len(res.admin_user_ids) == 1 

1128 assert user3.id in res.admin_user_ids 

1129 

1130 # last admin can't leave 

1131 with pytest.raises(grpc.RpcError) as e: 

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

1133 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

1134 assert e.value.details() == "The last admin can't leave a group chat." 

1135 

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

1137 

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

1139 

1140 with conversations_session(token2) as c: 

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

1142 

1143 # last participant must be admin but can leave to orphan chat 

1144 with conversations_session(token1) as c: 

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

1146 

1147 

1148def test_add_remove_admin_failures(db): 

1149 user1, token1 = generate_user() 

1150 user2, token2 = generate_user() 

1151 user3, token3 = generate_user() 

1152 user4, token4 = generate_user() 

1153 user5, token5 = generate_user() 

1154 

1155 make_friends(user1, user2) 

1156 make_friends(user1, user3) 

1157 make_friends(user1, user4) 

1158 make_friends(user1, user5) 

1159 

1160 with conversations_session(token1) as c: 

1161 gcid = c.CreateGroupChat( 

1162 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id, user4.id, user5.id]) 

1163 ).group_chat_id 

1164 

1165 make_user_invisible(user3.id) 

1166 make_user_block(user1, user4) 

1167 make_user_block(user5, user1) 

1168 

1169 # make non-existent user admin 

1170 with pytest.raises(grpc.RpcError) as e: 

1171 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=999)) 

1172 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1173 assert e.value.details() == "Couldn't find that user." 

1174 

1175 # make invisible user admin 

1176 with pytest.raises(grpc.RpcError) as e: 

1177 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

1178 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1179 assert e.value.details() == "Couldn't find that user." 

1180 

1181 # make blocked user admin 

1182 with pytest.raises(grpc.RpcError) as e: 

1183 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user4.id)) 

1184 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1185 assert e.value.details() == "Couldn't find that user." 

1186 

1187 # make blocking user admin 

1188 with pytest.raises(grpc.RpcError) as e: 

1189 c.MakeGroupChatAdmin(conversations_pb2.MakeGroupChatAdminReq(group_chat_id=gcid, user_id=user5.id)) 

1190 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1191 assert e.value.details() == "Couldn't find that user." 

1192 

1193 with session_scope() as session: 

1194 subscriptions = ( 

1195 session.execute( 

1196 select(GroupChatSubscription) 

1197 .where(GroupChatSubscription.group_chat_id == gcid) 

1198 .where(GroupChatSubscription.role == GroupChatRole.participant) 

1199 ) 

1200 .scalars() 

1201 .all() 

1202 ) 

1203 

1204 for subscription in subscriptions: 

1205 subscription.role = GroupChatRole.admin 

1206 

1207 with conversations_session(token1) as c: 

1208 # remove non-existent user admin 

1209 with pytest.raises(grpc.RpcError) as e: 

1210 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=999)) 

1211 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1212 assert e.value.details() == "Couldn't find that user." 

1213 

1214 # remove invisible admin 

1215 with pytest.raises(grpc.RpcError) as e: 

1216 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user3.id)) 

1217 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1218 assert e.value.details() == "Couldn't find that user." 

1219 

1220 # remove blocked admin 

1221 with pytest.raises(grpc.RpcError) as e: 

1222 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user4.id)) 

1223 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1224 assert e.value.details() == "Couldn't find that user." 

1225 

1226 # remove blocking admin 

1227 with pytest.raises(grpc.RpcError) as e: 

1228 c.RemoveGroupChatAdmin(conversations_pb2.RemoveGroupChatAdminReq(group_chat_id=gcid, user_id=user5.id)) 

1229 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1230 assert e.value.details() == "Couldn't find that user." 

1231 

1232 

1233def test_last_seen(db, moderator): 

1234 user1, token1 = generate_user() 

1235 user2, token2 = generate_user() 

1236 user3, token3 = generate_user() 

1237 

1238 make_friends(user1, user2) 

1239 make_friends(user1, user3) 

1240 make_friends(user2, user3) 

1241 

1242 with conversations_session(token3) as c: 

1243 # this is just here to mess up any issues we get if we pretend there's only one group chat ever 

1244 gcid_distraction = c.CreateGroupChat( 

1245 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user1.id]) 

1246 ).group_chat_id 

1247 moderator.approve_group_chat(gcid_distraction) 

1248 

1249 with conversations_session(token1) as c: 

1250 gcid = c.CreateGroupChat( 

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

1252 ).group_chat_id 

1253 moderator.approve_group_chat(gcid) 

1254 

1255 message_ids = [] 

1256 

1257 for i in range(6): 

1258 c.SendMessage( 

1259 conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text=f"gibberish message... {i}") 

1260 ) 

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

1262 c.SendMessage( 

1263 conversations_pb2.SendMessageReq(group_chat_id=gcid_distraction, text=f"gibberish message {i}") 

1264 ) 

1265 

1266 message_ids.append( 

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

1268 ) 

1269 

1270 # messages are automatically marked as seen when you send a new message 

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

1272 assert res.unseen_message_count == 0 

1273 

1274 with conversations_session(token2) as c: 

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

1276 # created + 6 normal 

1277 assert res.unseen_message_count == 7 

1278 

1279 backward_offset = 3 

1280 c.MarkLastSeenGroupChat( 

1281 conversations_pb2.MarkLastSeenGroupChatReq( 

1282 group_chat_id=gcid, last_seen_message_id=message_ids[-backward_offset - 1] 

1283 ) 

1284 ) 

1285 

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

1287 assert res.unseen_message_count == backward_offset 

1288 

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

1290 

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

1292 assert res.unseen_message_count == 0 

1293 

1294 with conversations_session(token3) as c: 

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

1296 # created + 7 normal 

1297 assert res.unseen_message_count == 8 

1298 

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

1300 

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

1302 assert res.unseen_message_count == 0 

1303 

1304 

1305def test_one_dm_per_pair(db, moderator): 

1306 user1, token1 = generate_user() 

1307 user2, token2 = generate_user() 

1308 user3, token3 = generate_user() 

1309 

1310 make_friends(user1, user2) 

1311 make_friends(user1, user3) 

1312 make_friends(user2, user3) 

1313 

1314 with conversations_session(token1) as c: 

1315 # create DM with user 2 

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

1317 assert res.is_dm 

1318 dm_with_user2 = res.group_chat_id 

1319 

1320 # create DM with user 3 

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

1322 assert res.is_dm 

1323 dm_with_user3 = res.group_chat_id 

1324 

1325 # can't create another group chat with just user 2 

1326 with pytest.raises(grpc.RpcError) as e: 

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

1328 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

1329 

1330 # can't create another group chat with just user 3 

1331 with pytest.raises(grpc.RpcError) as e: 

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

1333 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

1334 

1335 # can create joined group chat 

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

1337 assert not res.is_dm 

1338 

1339 # Approve the DMs so user2 can see them (otherwise they're SHADOWED and only visible to creator) 

1340 moderator.approve_group_chat(dm_with_user2) 

1341 

1342 with conversations_session(token2) as c: 

1343 # can create DM with user 3 

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

1345 assert res.is_dm 

1346 

1347 # can't create another group chat with just user 1 (DM was approved, so user2 can see it) 

1348 with pytest.raises(grpc.RpcError) as e: 

1349 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user1.id])) 

1350 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

1351 

1352 

1353def test_GetDirectMessage(db): 

1354 user1, token1 = generate_user() 

1355 user2, token2 = generate_user() 

1356 user3, token3 = generate_user() 

1357 

1358 make_friends(user1, user2) 

1359 make_friends(user1, user3) 

1360 make_friends(user2, user3) 

1361 

1362 with conversations_session(token1) as c: 

1363 # no group chat with user 2 

1364 with pytest.raises(grpc.RpcError) as e: 

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

1366 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1367 

1368 # no group chat with nor user 3 

1369 with pytest.raises(grpc.RpcError) as e: 

1370 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user3.id)) 

1371 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1372 

1373 # create DM with user 2 

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

1375 assert res.is_dm 

1376 gcid = res.group_chat_id 

1377 

1378 # now should exist 

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

1380 assert res.group_chat_id == gcid 

1381 assert not res.is_archived 

1382 

1383 # create DM with user 3 

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

1385 assert res.is_dm 

1386 

1387 # can create joined group chat 

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

1389 assert not res.is_dm 

1390 

1391 with conversations_session(token2) as c: 

1392 # can create DM with user 3 

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

1394 assert res.is_dm 

1395 assert res.can_message 

1396 gcid = res.group_chat_id 

1397 

1398 # DM with 3 should exist, but can't message after being blocked 

1399 make_user_block(user3, user2) 

1400 res = c.GetDirectMessage(conversations_pb2.GetDirectMessageReq(user_id=user3.id)) 

1401 assert res.group_chat_id == gcid 

1402 assert not res.can_message 

1403 

1404 

1405def test_total_unseen(db, moderator): 

1406 user1, token1 = generate_user() 

1407 user2, token2 = generate_user() 

1408 user3, token3 = generate_user() 

1409 

1410 # distractions 

1411 user4, token4 = generate_user() 

1412 

1413 make_friends(user1, user2) 

1414 make_friends(user1, user3) 

1415 make_friends(user2, user3) 

1416 

1417 # distractions 

1418 make_friends(user1, user4) 

1419 

1420 with conversations_session(token1) as c: 

1421 # distractions 

1422 gcid_distraction = c.CreateGroupChat( 

1423 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user4.id]) 

1424 ).group_chat_id 

1425 moderator.approve_group_chat(gcid_distraction) 

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

1427 

1428 gcid = c.CreateGroupChat( 

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

1430 ).group_chat_id 

1431 moderator.approve_group_chat(gcid) 

1432 

1433 for i in range(6): 

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

1435 

1436 # distractions 

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

1438 

1439 # messages are automatically marked as seen when you send a new message 

1440 with api_session(token1) as api: 

1441 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0 

1442 

1443 with api_session(token2) as api: 

1444 # chat created + 6 normal messages 

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

1446 

1447 # now leave chat with user2 

1448 with conversations_session(token2) as c: 

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

1450 

1451 with api_session(token2) as api: 

1452 # seen messages becomes 0 when leaving 

1453 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0 

1454 

1455 with conversations_session(token1) as c: 

1456 # distractions 

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

1458 

1459 # send more stuff without user 2 

1460 for i in range(3): 

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

1462 

1463 # distractions 

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

1465 

1466 with api_session(token2) as api: 

1467 # seen messages becomes 0 when leaving 

1468 assert api.Ping(api_pb2.PingReq()).unseen_message_count == 0 

1469 

1470 with conversations_session(token1) as c: 

1471 # add user 2 back 

1472 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=gcid, user_id=user2.id)) 

1473 

1474 # send more stuff with user 2 

1475 for i in range(12): 

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

1477 

1478 # distractions 

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

1480 

1481 with api_session(token2) as api: 

1482 # joined + 12 normal 

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

1484 

1485 

1486def test_regression_ListGroupChats_pagination(db, moderator): 

1487 user1, token1 = generate_user() 

1488 user2, token2 = generate_user() 

1489 user3, token3 = generate_user() 

1490 

1491 make_friends(user1, user2) 

1492 make_friends(user1, user3) 

1493 

1494 with conversations_session(token1) as c: 

1495 # tuples of (group_chat_id, message_id) 

1496 group_chat_and_message_ids = [] 

1497 for i in range(50): 

1498 res1 = c.CreateGroupChat( 

1499 conversations_pb2.CreateGroupChatReq( 

1500 recipient_user_ids=[user2.id, user3.id], title=wrappers_pb2.StringValue(value=f"Chat {i}") 

1501 ) 

1502 ) 

1503 

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

1505 

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

1507 

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

1509 moderator.approve_group_chat(res1.group_chat_id) 

1510 

1511 seen_group_chat_ids = [] 

1512 

1513 last_message_id = 0 

1514 more = True 

1515 while more: 

1516 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(last_message_id=last_message_id)) 

1517 last_message_id = res.last_message_id 

1518 more = not res.no_more 

1519 

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

1521 

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

1523 

1524 

1525def test_muting(db, moderator): 

1526 user1, token1 = generate_user() 

1527 user2, token2 = generate_user() 

1528 user3, token3 = generate_user() 

1529 

1530 make_friends(user1, user2) 

1531 make_friends(user1, user3) 

1532 make_friends(user2, user3) 

1533 

1534 with conversations_session(token3) as c: 

1535 # this is just here to mess up any issues we get if we pretend there's only one group chat ever 

1536 gcid_distraction = c.CreateGroupChat( 

1537 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user1.id]) 

1538 ).group_chat_id 

1539 moderator.approve_group_chat(gcid_distraction) 

1540 

1541 with conversations_session(token1) as c: 

1542 gcid = c.CreateGroupChat( 

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

1544 ).group_chat_id 

1545 moderator.approve_group_chat(gcid) 

1546 

1547 with conversations_session(token2) as c: 

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

1549 assert not res.mute_info.muted 

1550 assert not res.mute_info.HasField("muted_until") 

1551 

1552 c.MuteGroupChat(conversations_pb2.MuteGroupChatReq(group_chat_id=gcid, forever=True)) 

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

1554 assert res.mute_info.muted 

1555 assert not res.mute_info.HasField("muted_until") 

1556 

1557 c.MuteGroupChat(conversations_pb2.MuteGroupChatReq(group_chat_id=gcid, unmute=True)) 

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

1559 assert not res.mute_info.muted 

1560 assert not res.mute_info.HasField("muted_until") 

1561 

1562 c.MuteGroupChat( 

1563 conversations_pb2.MuteGroupChatReq( 

1564 group_chat_id=gcid, for_duration=Duration_from_timedelta(timedelta(hours=2)) 

1565 ) 

1566 ) 

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

1568 assert res.mute_info.muted 

1569 assert res.mute_info.HasField("muted_until") 

1570 assert to_aware_datetime(res.mute_info.muted_until) >= now() + timedelta(hours=1, minutes=59) 

1571 assert to_aware_datetime(res.mute_info.muted_until) <= now() + timedelta(hours=2, minutes=1) 

1572 

1573 

1574def test_archiving(db, moderator): 

1575 """Test SetGroupChatArchiveStatus RPC with GetGroupChat and ListGroupChats""" 

1576 user1, token1 = generate_user() 

1577 user2, token2 = generate_user() 

1578 user3, token3 = generate_user() 

1579 

1580 make_friends(user1, user2) 

1581 make_friends(user1, user3) 

1582 make_friends(user2, user3) 

1583 

1584 # Create a distraction chat to ensure we're testing the right one 

1585 with conversations_session(token3) as c: 

1586 gcid_distraction = c.CreateGroupChat( 

1587 conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user1.id]) 

1588 ).group_chat_id 

1589 moderator.approve_group_chat(gcid_distraction) 

1590 

1591 with conversations_session(token1) as c: 

1592 gcid = c.CreateGroupChat( 

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

1594 ).group_chat_id 

1595 moderator.approve_group_chat(gcid) 

1596 

1597 # Test basic archive/unarchive functionality 

1598 with conversations_session(token2) as c: 

1599 # Initially not archived 

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

1601 assert not res.is_archived 

1602 

1603 # Archive the chat 

1604 archive_res = c.SetGroupChatArchiveStatus( 

1605 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True) 

1606 ) 

1607 assert archive_res.group_chat_id == gcid 

1608 assert archive_res.is_archived 

1609 

1610 # Verify archived via GetGroupChat 

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

1612 assert res.is_archived 

1613 

1614 # Unarchive the chat 

1615 archive_res = c.SetGroupChatArchiveStatus( 

1616 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=False) 

1617 ) 

1618 assert archive_res.group_chat_id == gcid 

1619 assert not archive_res.is_archived 

1620 

1621 # Verify unarchived via GetGroupChat 

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

1623 assert not res.is_archived 

1624 

1625 

1626def test_archiving_per_user(db, moderator): 

1627 """Test that archiving is per-user - one user archiving doesn't affect others""" 

1628 user1, token1 = generate_user() 

1629 user2, token2 = generate_user() 

1630 

1631 make_friends(user1, user2) 

1632 

1633 with conversations_session(token1) as c: 

1634 gcid = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])).group_chat_id 

1635 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="Hello")) 

1636 moderator.approve_group_chat(gcid) 

1637 

1638 # User1 archives the chat 

1639 with conversations_session(token1) as c: 

1640 c.SetGroupChatArchiveStatus( 

1641 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True) 

1642 ) 

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

1644 assert res.is_archived 

1645 

1646 # User2 should NOT see it as archived 

1647 with conversations_session(token2) as c: 

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

1649 assert not res.is_archived 

1650 

1651 # User2 archives it too 

1652 with conversations_session(token2) as c: 

1653 c.SetGroupChatArchiveStatus( 

1654 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True) 

1655 ) 

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

1657 assert res.is_archived 

1658 

1659 # User1 unarchives - user2 should still see it as archived 

1660 with conversations_session(token1) as c: 

1661 c.SetGroupChatArchiveStatus( 

1662 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=False) 

1663 ) 

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

1665 assert not res.is_archived 

1666 

1667 with conversations_session(token2) as c: 

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

1669 assert res.is_archived 

1670 

1671 

1672def test_archiving_with_list_group_chats(db, moderator): 

1673 """Test archive filtering with ListGroupChats endpoint""" 

1674 user1, token1 = generate_user() 

1675 user2, token2 = generate_user() 

1676 user3, token3 = generate_user() 

1677 

1678 make_friends(user1, user2) 

1679 make_friends(user1, user3) 

1680 

1681 with conversations_session(token1) as c: 

1682 # Create 3 chats 

1683 gcid1 = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])).group_chat_id 

1684 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid1, text="Chat 1")) 

1685 moderator.approve_group_chat(gcid1) 

1686 

1687 gcid2 = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user3.id])).group_chat_id 

1688 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid2, text="Chat 2")) 

1689 moderator.approve_group_chat(gcid2) 

1690 

1691 gcid3 = c.CreateGroupChat( 

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

1693 ).group_chat_id 

1694 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid3, text="Chat 3")) 

1695 moderator.approve_group_chat(gcid3) 

1696 

1697 with conversations_session(token1) as c: 

1698 # Initially all 3 chats should be visible 

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

1700 assert len(res.group_chats) == 3 

1701 

1702 # All should be non-archived 

1703 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False)) 

1704 assert len(res.group_chats) == 3 

1705 

1706 # None should be archived 

1707 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True)) 

1708 assert len(res.group_chats) == 0 

1709 

1710 # Archive chat 1 

1711 c.SetGroupChatArchiveStatus( 

1712 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid1, is_archived=True) 

1713 ) 

1714 

1715 # Without filter, still see all 3 

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

1717 assert len(res.group_chats) == 3 

1718 

1719 # Non-archived should show 2 

1720 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False)) 

1721 assert len(res.group_chats) == 2 

1722 assert gcid1 not in [gc.group_chat_id for gc in res.group_chats] 

1723 

1724 # Archived should show 1 

1725 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True)) 

1726 assert len(res.group_chats) == 1 

1727 assert res.group_chats[0].group_chat_id == gcid1 

1728 assert res.group_chats[0].is_archived 

1729 

1730 # Archive chat 2 as well 

1731 c.SetGroupChatArchiveStatus( 

1732 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid2, is_archived=True) 

1733 ) 

1734 

1735 # Non-archived should show 1 

1736 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False)) 

1737 assert len(res.group_chats) == 1 

1738 assert res.group_chats[0].group_chat_id == gcid3 

1739 

1740 # Archived should show 2 

1741 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True)) 

1742 assert len(res.group_chats) == 2 

1743 archived_ids = {gc.group_chat_id for gc in res.group_chats} 

1744 assert archived_ids == {gcid1, gcid2} 

1745 

1746 # Unarchive chat 1 

1747 c.SetGroupChatArchiveStatus( 

1748 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid1, is_archived=False) 

1749 ) 

1750 

1751 # Non-archived should show 2 

1752 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=False)) 

1753 assert len(res.group_chats) == 2 

1754 

1755 # Archived should show 1 

1756 res = c.ListGroupChats(conversations_pb2.ListGroupChatsReq(only_archived=True)) 

1757 assert len(res.group_chats) == 1 

1758 assert res.group_chats[0].group_chat_id == gcid2 

1759 

1760 

1761def test_archiving_chat_not_found(db, moderator): 

1762 """Test that archiving a non-existent or non-accessible chat fails""" 

1763 user1, token1 = generate_user() 

1764 user2, token2 = generate_user() 

1765 user3, token3 = generate_user() 

1766 

1767 make_friends(user1, user2) 

1768 

1769 with conversations_session(token1) as c: 

1770 gcid = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])).group_chat_id 

1771 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="Hello")) 

1772 moderator.approve_group_chat(gcid) 

1773 

1774 # User3 is not in the chat - should get NOT_FOUND 

1775 with conversations_session(token3) as c: 

1776 with pytest.raises(grpc.RpcError) as e: 

1777 c.SetGroupChatArchiveStatus( 

1778 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True) 

1779 ) 

1780 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1781 

1782 # Non-existent chat ID should fail 

1783 with conversations_session(token1) as c: 

1784 with pytest.raises(grpc.RpcError) as e: 

1785 c.SetGroupChatArchiveStatus( 

1786 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=99999, is_archived=True) 

1787 ) 

1788 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1789 

1790 

1791def test_archiving_after_leaving_chat(db, moderator): 

1792 """Test that you can't archive a chat after leaving it""" 

1793 user1, token1 = generate_user() 

1794 user2, token2 = generate_user() 

1795 user3, token3 = generate_user() 

1796 

1797 make_friends(user1, user2) 

1798 make_friends(user1, user3) 

1799 make_friends(user2, user3) 

1800 

1801 with conversations_session(token1) as c: 

1802 gcid = c.CreateGroupChat( 

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

1804 ).group_chat_id 

1805 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="Hello")) 

1806 moderator.approve_group_chat(gcid) 

1807 

1808 # User2 leaves the chat 

1809 with conversations_session(token2) as c: 

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

1811 

1812 # User2 should not be able to archive it now 

1813 with conversations_session(token2) as c: 

1814 with pytest.raises(grpc.RpcError) as e: 

1815 c.SetGroupChatArchiveStatus( 

1816 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True) 

1817 ) 

1818 assert e.value.code() == grpc.StatusCode.NOT_FOUND 

1819 

1820 

1821def test_archiving_dm(db, moderator): 

1822 """Test that archiving works for DMs as well as group chats""" 

1823 user1, token1 = generate_user() 

1824 user2, token2 = generate_user() 

1825 

1826 make_friends(user1, user2) 

1827 

1828 with conversations_session(token1) as c: 

1829 # Create a DM 

1830 gcid = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])).group_chat_id 

1831 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="Hello")) 

1832 moderator.approve_group_chat(gcid) 

1833 

1834 # Verify it's a DM 

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

1836 assert res.is_dm 

1837 assert not res.is_archived 

1838 

1839 # Archive the DM 

1840 c.SetGroupChatArchiveStatus( 

1841 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True) 

1842 ) 

1843 

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

1845 assert res.is_archived 

1846 

1847 # Unarchive it 

1848 c.SetGroupChatArchiveStatus( 

1849 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=False) 

1850 ) 

1851 

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

1853 assert not res.is_archived 

1854 

1855 

1856def test_archiving_idempotent(db, moderator): 

1857 """Test that archiving/unarchiving is idempotent""" 

1858 user1, token1 = generate_user() 

1859 user2, token2 = generate_user() 

1860 

1861 make_friends(user1, user2) 

1862 

1863 with conversations_session(token1) as c: 

1864 gcid = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id])).group_chat_id 

1865 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=gcid, text="Hello")) 

1866 moderator.approve_group_chat(gcid) 

1867 

1868 # Archive twice - should work without error 

1869 c.SetGroupChatArchiveStatus( 

1870 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True) 

1871 ) 

1872 c.SetGroupChatArchiveStatus( 

1873 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=True) 

1874 ) 

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

1876 assert res.is_archived 

1877 

1878 # Unarchive twice - should work without error 

1879 c.SetGroupChatArchiveStatus( 

1880 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=False) 

1881 ) 

1882 c.SetGroupChatArchiveStatus( 

1883 conversations_pb2.SetGroupChatArchiveStatusReq(group_chat_id=gcid, is_archived=False) 

1884 ) 

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

1886 assert not res.is_archived 

1887 

1888 

1889def test_chat_notifications(db, moderator): 

1890 user1, token1 = generate_user() 

1891 user2, token2 = generate_user() 

1892 # notifs off 

1893 user3, token3 = generate_user() 

1894 user4, token4 = generate_user() 

1895 user5, token5 = generate_user() 

1896 user6, token6 = generate_user() 

1897 

1898 make_friends(user1, user2) 

1899 make_friends(user1, user3) 

1900 make_friends(user1, user4) 

1901 make_friends(user4, user5) 

1902 make_friends(user4, user6) 

1903 

1904 # have some of them enable/disable notifs 

1905 topic_action = NotificationTopicAction.chat__message 

1906 for token, enabled in [ 

1907 (token1, True), 

1908 (token2, True), 

1909 (token3, False), 

1910 (token4, True), 

1911 (token5, True), 

1912 (token6, True), 

1913 ]: 

1914 with notifications_session(token) as notifications: 

1915 notifications.SetNotificationSettings( 

1916 notifications_pb2.SetNotificationSettingsReq( 

1917 preferences=[ 

1918 notifications_pb2.SingleNotificationPreference( 

1919 topic=topic_action.topic, 

1920 action=topic_action.action, 

1921 delivery_method=delivery_method, 

1922 enabled=enabled, 

1923 ) 

1924 for delivery_method in ["push", "email", "digest"] 

1925 ], 

1926 ) 

1927 ) 

1928 

1929 group_chat_id = None 

1930 

1931 def send_msg(c, i): 

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

1933 

1934 with conversations_session(token1) as c: 

1935 res = c.CreateGroupChat(conversations_pb2.CreateGroupChatReq(recipient_user_ids=[user2.id, user3.id, user4.id])) 

1936 group_chat_id = res.group_chat_id 

1937 moderator.approve_group_chat(group_chat_id) 

1938 c.EditGroupChat( 

1939 conversations_pb2.EditGroupChatReq( 

1940 group_chat_id=group_chat_id, only_admins_invite=wrappers_pb2.BoolValue(value=False) 

1941 ) 

1942 ) 

1943 send_msg(c, i=1) 

1944 send_msg(c, i=2) 

1945 

1946 with conversations_session(token4) as c: 

1947 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user5.id)) 

1948 send_msg(c, i=3) 

1949 c.InviteToGroupChat(conversations_pb2.InviteToGroupChatReq(group_chat_id=group_chat_id, user_id=user6.id)) 

1950 send_msg(c, i=4) 

1951 send_msg(c, i=5) 

1952 

1953 with conversations_session(token3) as c: 

1954 send_msg(c, i=6) 

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

1956 

1957 with conversations_session(token2) as c: 

1958 send_msg(c, i=7) 

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

1960 

1961 with conversations_session(token6) as c: 

1962 send_msg(c, i=8) 

1963 

1964 # go through all bg jobs 

1965 while process_job(): 

1966 pass 

1967 

1968 # now check notifs... 

1969 expected_notifs = [ 

1970 (user1, "user1", [3, 4, 5, 6, 7, 8]), 

1971 (user2, "user2", [1, 2, 3, 4, 5, 6]), 

1972 (user3, "user3", []), # notifs off 

1973 (user4, "user4", [1, 2, 6, 7, 8]), 

1974 (user5, "user5", [3, 4, 5, 6, 7, 8]), 

1975 (user6, "user6", [4, 5, 6, 7]), 

1976 ] 

1977 

1978 with session_scope() as session: 

1979 for user, label, expected_msgs in expected_notifs: 

1980 deliv = ( 

1981 session.execute( 

1982 select(Notification.data) 

1983 .join(NotificationDelivery, NotificationDelivery.notification_id == Notification.id) 

1984 .where(Notification.user_id == user.id) 

1985 .where(Notification.topic_action == topic_action) 

1986 .where(NotificationDelivery.delivery_type == NotificationDeliveryType.push) 

1987 .order_by(Notification.created) 

1988 ) 

1989 .scalars() 

1990 .all() 

1991 ) 

1992 

1993 def parse_message_payload(data): 

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

1995 

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

1997 

1998 print(contents) 

1999 

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

2001 

2002 

2003def test_incomplete_profile(db): 

2004 user1, token1 = generate_user(complete_profile=True) 

2005 user2, token2 = generate_user(complete_profile=False) 

2006 user3, token3 = generate_user(complete_profile=True) 

2007 make_friends(user1, user2) 

2008 make_friends(user1, user3) 

2009 

2010 # user 1 can make a chat 

2011 with conversations_session(token1) as c: 

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

2013 group_chat_id = res.group_chat_id 

2014 c.SendMessage(conversations_pb2.SendMessageReq(group_chat_id=group_chat_id, text="Test message 1")) 

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

2016 assert res.messages[0].text.text == "Test message 1" 

2017 assert to_aware_datetime(res.messages[0].time) <= now() 

2018 assert res.messages[0].author_user_id == user1.id 

2019 

2020 # user 2 cannot 

2021 with conversations_session(token2) as c: 

2022 with pytest.raises(grpc.RpcError) as e: 

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

2024 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION 

2025 assert e.value.details() == "You have to complete your profile before you can send a message."