Coverage for src/tests/test_requests.py: 100%

497 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-07-20 21:46 +0000

1from datetime import timedelta 

2 

3import grpc 

4import pytest 

5from sqlalchemy.sql import select 

6 

7from couchers import errors 

8from couchers.db import session_scope 

9from couchers.models import Message, MessageType 

10from couchers.templates.v2 import v2date 

11from couchers.utils import now, today 

12from proto import api_pb2, conversations_pb2, requests_pb2 

13from tests.test_fixtures import ( # noqa 

14 api_session, 

15 db, 

16 email_fields, 

17 generate_user, 

18 mock_notification_email, 

19 push_collector, 

20 requests_session, 

21 testconfig, 

22) 

23 

24 

25@pytest.fixture(autouse=True) 

26def _(testconfig): 

27 pass 

28 

29 

30def test_create_request(db): 

31 user1, token1 = generate_user() 

32 user2, token2 = generate_user() 

33 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

34 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

35 today_minus_2 = (today() - timedelta(days=2)).isoformat() 

36 today_minus_3 = (today() - timedelta(days=3)).isoformat() 

37 with requests_session(token1) as api: 

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

39 api.CreateHostRequest( 

40 requests_pb2.CreateHostRequestReq( 

41 host_user_id=user1.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request" 

42 ) 

43 ) 

44 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

45 assert e.value.details() == errors.CANT_REQUEST_SELF 

46 

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

48 api.CreateHostRequest( 

49 requests_pb2.CreateHostRequestReq( 

50 host_user_id=999, from_date=today_plus_2, to_date=today_plus_3, text="Test request" 

51 ) 

52 ) 

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

54 assert e.value.details() == errors.USER_NOT_FOUND 

55 

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

57 api.CreateHostRequest( 

58 requests_pb2.CreateHostRequestReq( 

59 host_user_id=user2.id, from_date=today_plus_3, to_date=today_plus_2, text="Test request" 

60 ) 

61 ) 

62 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

63 assert e.value.details() == errors.DATE_FROM_AFTER_TO 

64 

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

66 api.CreateHostRequest( 

67 requests_pb2.CreateHostRequestReq( 

68 host_user_id=user2.id, from_date=today_minus_3, to_date=today_plus_2, text="Test request" 

69 ) 

70 ) 

71 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

72 assert e.value.details() == errors.DATE_FROM_BEFORE_TODAY 

73 

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

75 api.CreateHostRequest( 

76 requests_pb2.CreateHostRequestReq( 

77 host_user_id=user2.id, from_date=today_plus_2, to_date=today_minus_2, text="Test request" 

78 ) 

79 ) 

80 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

81 assert e.value.details() == errors.DATE_FROM_AFTER_TO 

82 

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

84 api.CreateHostRequest( 

85 requests_pb2.CreateHostRequestReq( 

86 host_user_id=user2.id, from_date="2020-00-06", to_date=today_minus_2, text="Test request" 

87 ) 

88 ) 

89 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

90 assert e.value.details() == errors.INVALID_DATE 

91 

92 res = api.CreateHostRequest( 

93 requests_pb2.CreateHostRequestReq( 

94 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request" 

95 ) 

96 ) 

97 assert ( 

98 api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_sent=True)) 

99 .host_requests[0] 

100 .latest_message.text.text 

101 == "Test request" 

102 ) 

103 

104 today_ = today() 

105 today_plus_one_year = today_ + timedelta(days=365) 

106 today_plus_one_year_plus_2 = (today_plus_one_year + timedelta(days=2)).isoformat() 

107 today_plus_one_year_plus_3 = (today_plus_one_year + timedelta(days=3)).isoformat() 

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

109 api.CreateHostRequest( 

110 requests_pb2.CreateHostRequestReq( 

111 host_user_id=user2.id, 

112 from_date=today_plus_one_year_plus_2, 

113 to_date=today_plus_one_year_plus_3, 

114 text="Test from date after one year", 

115 ) 

116 ) 

117 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

118 assert e.value.details() == errors.DATE_FROM_AFTER_ONE_YEAR 

119 

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

121 api.CreateHostRequest( 

122 requests_pb2.CreateHostRequestReq( 

123 host_user_id=user2.id, 

124 from_date=today_plus_2, 

125 to_date=today_plus_one_year_plus_3, 

126 text="Test to date one year after from date", 

127 ) 

128 ) 

129 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

130 assert e.value.details() == errors.DATE_TO_AFTER_ONE_YEAR 

131 

132 

133def add_message(db, text, author_id, conversation_id): 

134 with session_scope() as session: 

135 message = Message( 

136 conversation_id=conversation_id, author_id=author_id, text=text, message_type=MessageType.text 

137 ) 

138 

139 session.add(message) 

140 

141 

142def test_GetHostRequest(db): 

143 user1, token1 = generate_user() 

144 user2, token2 = generate_user() 

145 user3, token3 = generate_user() 

146 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

147 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

148 with requests_session(token1) as api: 

149 host_request_id = api.CreateHostRequest( 

150 requests_pb2.CreateHostRequestReq( 

151 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1" 

152 ) 

153 ).host_request_id 

154 

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

156 api.GetHostRequest(requests_pb2.GetHostRequestReq(host_request_id=999)) 

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

158 assert e.value.details() == errors.HOST_REQUEST_NOT_FOUND 

159 

160 api.SendHostRequestMessage( 

161 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 1") 

162 ) 

163 

164 res = api.GetHostRequest(requests_pb2.GetHostRequestReq(host_request_id=host_request_id)) 

165 assert res.latest_message.text.text == "Test message 1" 

166 

167 

168def test_ListHostRequests(db): 

169 user1, token1 = generate_user() 

170 user2, token2 = generate_user() 

171 user3, token3 = generate_user() 

172 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

173 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

174 with requests_session(token1) as api: 

175 host_request_1 = api.CreateHostRequest( 

176 requests_pb2.CreateHostRequestReq( 

177 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1" 

178 ) 

179 ).host_request_id 

180 

181 host_request_2 = api.CreateHostRequest( 

182 requests_pb2.CreateHostRequestReq( 

183 host_user_id=user3.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 2" 

184 ) 

185 ).host_request_id 

186 

187 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_sent=True)) 

188 assert res.no_more 

189 assert len(res.host_requests) == 2 

190 

191 with requests_session(token2) as api: 

192 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True)) 

193 assert res.no_more 

194 assert len(res.host_requests) == 1 

195 assert res.host_requests[0].latest_message.text.text == "Test request 1" 

196 assert res.host_requests[0].surfer_user_id == user1.id 

197 assert res.host_requests[0].host_user_id == user2.id 

198 assert res.host_requests[0].status == conversations_pb2.HOST_REQUEST_STATUS_PENDING 

199 

200 add_message(db, "Test request 1 message 1", user2.id, host_request_1) 

201 add_message(db, "Test request 1 message 2", user2.id, host_request_1) 

202 add_message(db, "Test request 1 message 3", user2.id, host_request_1) 

203 

204 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True)) 

205 assert res.host_requests[0].latest_message.text.text == "Test request 1 message 3" 

206 

207 api.CreateHostRequest( 

208 requests_pb2.CreateHostRequestReq( 

209 host_user_id=user1.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 3" 

210 ) 

211 ) 

212 

213 add_message(db, "Test request 2 message 1", user1.id, host_request_2) 

214 add_message(db, "Test request 2 message 2", user3.id, host_request_2) 

215 

216 with requests_session(token3) as api: 

217 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True)) 

218 assert res.no_more 

219 assert len(res.host_requests) == 1 

220 assert res.host_requests[0].latest_message.text.text == "Test request 2 message 2" 

221 

222 with requests_session(token1) as api: 

223 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True)) 

224 assert len(res.host_requests) == 1 

225 

226 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq()) 

227 assert len(res.host_requests) == 3 

228 

229 

230def test_ListHostRequests_pagination_regression(db): 

231 """ 

232 ListHostRequests was skipping a request when getting multiple pages 

233 """ 

234 user1, token1 = generate_user() 

235 user2, token2 = generate_user() 

236 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

237 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

238 with requests_session(token1) as api: 

239 host_request_1 = api.CreateHostRequest( 

240 requests_pb2.CreateHostRequestReq( 

241 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1" 

242 ) 

243 ).host_request_id 

244 

245 host_request_2 = api.CreateHostRequest( 

246 requests_pb2.CreateHostRequestReq( 

247 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 2" 

248 ) 

249 ).host_request_id 

250 

251 host_request_3 = api.CreateHostRequest( 

252 requests_pb2.CreateHostRequestReq( 

253 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 3" 

254 ) 

255 ).host_request_id 

256 

257 with requests_session(token2) as api: 

258 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True)) 

259 assert res.no_more 

260 assert len(res.host_requests) == 3 

261 assert res.host_requests[0].latest_message.text.text == "Test request 3" 

262 assert res.host_requests[1].latest_message.text.text == "Test request 2" 

263 assert res.host_requests[2].latest_message.text.text == "Test request 1" 

264 

265 with requests_session(token2) as api: 

266 api.RespondHostRequest( 

267 requests_pb2.RespondHostRequestReq( 

268 host_request_id=host_request_2, 

269 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED, 

270 text="Accepting host request 2", 

271 ) 

272 ) 

273 api.RespondHostRequest( 

274 requests_pb2.RespondHostRequestReq( 

275 host_request_id=host_request_1, 

276 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED, 

277 text="Accepting host request 1", 

278 ) 

279 ) 

280 api.RespondHostRequest( 

281 requests_pb2.RespondHostRequestReq( 

282 host_request_id=host_request_3, 

283 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED, 

284 text="Accepting host request 3", 

285 ) 

286 ) 

287 

288 with requests_session(token2) as api: 

289 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True)) 

290 assert res.no_more 

291 assert len(res.host_requests) == 3 

292 assert res.host_requests[0].latest_message.text.text == "Accepting host request 3" 

293 assert res.host_requests[1].latest_message.text.text == "Accepting host request 1" 

294 assert res.host_requests[2].latest_message.text.text == "Accepting host request 2" 

295 

296 with requests_session(token2) as api: 

297 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True, number=1)) 

298 assert not res.no_more 

299 assert len(res.host_requests) == 1 

300 assert res.host_requests[0].latest_message.text.text == "Accepting host request 3" 

301 res = api.ListHostRequests( 

302 requests_pb2.ListHostRequestsReq(only_received=True, number=1, last_request_id=res.last_request_id) 

303 ) 

304 assert not res.no_more 

305 assert len(res.host_requests) == 1 

306 assert res.host_requests[0].latest_message.text.text == "Accepting host request 1" 

307 res = api.ListHostRequests( 

308 requests_pb2.ListHostRequestsReq(only_received=True, number=1, last_request_id=res.last_request_id) 

309 ) 

310 assert res.no_more 

311 assert len(res.host_requests) == 1 

312 assert res.host_requests[0].latest_message.text.text == "Accepting host request 2" 

313 

314 

315def test_ListHostRequests_active_filter(db): 

316 user1, token1 = generate_user() 

317 user2, token2 = generate_user() 

318 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

319 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

320 

321 with requests_session(token1) as api: 

322 request_id = api.CreateHostRequest( 

323 requests_pb2.CreateHostRequestReq( 

324 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1" 

325 ) 

326 ).host_request_id 

327 api.RespondHostRequest( 

328 requests_pb2.RespondHostRequestReq( 

329 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED 

330 ) 

331 ) 

332 

333 with requests_session(token2) as api: 

334 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True)) 

335 assert len(res.host_requests) == 1 

336 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_active=True)) 

337 assert len(res.host_requests) == 0 

338 

339 

340def test_RespondHostRequests(db): 

341 user1, token1 = generate_user() 

342 user2, token2 = generate_user() 

343 user3, token3 = generate_user() 

344 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

345 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

346 

347 with requests_session(token1) as api: 

348 request_id = api.CreateHostRequest( 

349 requests_pb2.CreateHostRequestReq( 

350 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1" 

351 ) 

352 ).host_request_id 

353 

354 # another user can't access 

355 with requests_session(token3) as api: 

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

357 api.RespondHostRequest( 

358 requests_pb2.RespondHostRequestReq( 

359 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED 

360 ) 

361 ) 

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

363 assert e.value.details() == errors.HOST_REQUEST_NOT_FOUND 

364 

365 with requests_session(token1) as api: 

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

367 api.RespondHostRequest( 

368 requests_pb2.RespondHostRequestReq( 

369 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED 

370 ) 

371 ) 

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

373 assert e.value.details() == errors.NOT_THE_HOST 

374 

375 with requests_session(token2) as api: 

376 # non existing id 

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

378 api.RespondHostRequest( 

379 requests_pb2.RespondHostRequestReq( 

380 host_request_id=9999, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED 

381 ) 

382 ) 

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

384 

385 # host can't confirm or cancel (host should accept/reject) 

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

387 api.RespondHostRequest( 

388 requests_pb2.RespondHostRequestReq( 

389 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED 

390 ) 

391 ) 

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

393 assert e.value.details() == errors.INVALID_HOST_REQUEST_STATUS 

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

395 api.RespondHostRequest( 

396 requests_pb2.RespondHostRequestReq( 

397 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED 

398 ) 

399 ) 

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

401 assert e.value.details() == errors.INVALID_HOST_REQUEST_STATUS 

402 

403 api.RespondHostRequest( 

404 requests_pb2.RespondHostRequestReq( 

405 host_request_id=request_id, 

406 status=conversations_pb2.HOST_REQUEST_STATUS_REJECTED, 

407 text="Test rejection message", 

408 ) 

409 ) 

410 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=request_id)) 

411 assert res.messages[0].text.text == "Test rejection message" 

412 assert res.messages[1].WhichOneof("content") == "host_request_status_changed" 

413 assert res.messages[1].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_REJECTED 

414 # should be able to move from rejected -> accepted 

415 api.RespondHostRequest( 

416 requests_pb2.RespondHostRequestReq( 

417 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED 

418 ) 

419 ) 

420 

421 with requests_session(token1) as api: 

422 # can't make pending 

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

424 api.RespondHostRequest( 

425 requests_pb2.RespondHostRequestReq( 

426 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_PENDING 

427 ) 

428 ) 

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

430 assert e.value.details() == errors.INVALID_HOST_REQUEST_STATUS 

431 

432 # can confirm then cancel 

433 api.RespondHostRequest( 

434 requests_pb2.RespondHostRequestReq( 

435 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED 

436 ) 

437 ) 

438 

439 api.RespondHostRequest( 

440 requests_pb2.RespondHostRequestReq( 

441 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED 

442 ) 

443 ) 

444 

445 # can't confirm after having cancelled 

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

447 api.RespondHostRequest( 

448 requests_pb2.RespondHostRequestReq( 

449 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED 

450 ) 

451 ) 

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

453 assert e.value.details() == errors.INVALID_HOST_REQUEST_STATUS 

454 

455 # at this point there should be 7 messages 

456 # 2 for creation, 2 for the status change with message, 3 for the other status changed 

457 with requests_session(token1) as api: 

458 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=request_id)) 

459 assert len(res.messages) == 7 

460 assert res.messages[0].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED 

461 assert res.messages[1].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED 

462 assert res.messages[2].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED 

463 assert res.messages[4].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_REJECTED 

464 assert res.messages[6].WhichOneof("content") == "chat_created" 

465 

466 

467def test_get_host_request_messages(db): 

468 user1, token1 = generate_user() 

469 user2, token2 = generate_user() 

470 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

471 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

472 with requests_session(token1) as api: 

473 res = api.CreateHostRequest( 

474 requests_pb2.CreateHostRequestReq( 

475 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1" 

476 ) 

477 ) 

478 conversation_id = res.host_request_id 

479 

480 add_message(db, "Test request 1 message 1", user1.id, conversation_id) 

481 add_message(db, "Test request 1 message 2", user1.id, conversation_id) 

482 add_message(db, "Test request 1 message 3", user1.id, conversation_id) 

483 

484 with requests_session(token2) as api: 

485 api.RespondHostRequest( 

486 requests_pb2.RespondHostRequestReq( 

487 host_request_id=conversation_id, status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED 

488 ) 

489 ) 

490 

491 add_message(db, "Test request 1 message 4", user2.id, conversation_id) 

492 add_message(db, "Test request 1 message 5", user2.id, conversation_id) 

493 

494 api.RespondHostRequest( 

495 requests_pb2.RespondHostRequestReq( 

496 host_request_id=conversation_id, status=conversations_pb2.HOST_REQUEST_STATUS_REJECTED 

497 ) 

498 ) 

499 

500 with requests_session(token1) as api: 

501 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=conversation_id)) 

502 # 9 including initial message 

503 assert len(res.messages) == 9 

504 assert res.no_more 

505 

506 res = api.GetHostRequestMessages( 

507 requests_pb2.GetHostRequestMessagesReq(host_request_id=conversation_id, number=3) 

508 ) 

509 assert not res.no_more 

510 assert len(res.messages) == 3 

511 assert res.messages[0].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_REJECTED 

512 assert res.messages[0].WhichOneof("content") == "host_request_status_changed" 

513 assert res.messages[1].text.text == "Test request 1 message 5" 

514 assert res.messages[2].text.text == "Test request 1 message 4" 

515 

516 res = api.GetHostRequestMessages( 

517 requests_pb2.GetHostRequestMessagesReq( 

518 host_request_id=conversation_id, last_message_id=res.messages[2].message_id, number=6 

519 ) 

520 ) 

521 assert res.no_more 

522 assert len(res.messages) == 6 

523 assert res.messages[0].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED 

524 assert res.messages[0].WhichOneof("content") == "host_request_status_changed" 

525 assert res.messages[1].text.text == "Test request 1 message 3" 

526 assert res.messages[2].text.text == "Test request 1 message 2" 

527 assert res.messages[3].text.text == "Test request 1 message 1" 

528 assert res.messages[4].text.text == "Test request 1" 

529 assert res.messages[5].WhichOneof("content") == "chat_created" 

530 

531 

532def test_SendHostRequestMessage(db): 

533 user1, token1 = generate_user() 

534 user2, token2 = generate_user() 

535 user3, token3 = generate_user() 

536 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

537 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

538 with requests_session(token1) as api: 

539 host_request_id = api.CreateHostRequest( 

540 requests_pb2.CreateHostRequestReq( 

541 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1" 

542 ) 

543 ).host_request_id 

544 

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

546 api.SendHostRequestMessage( 

547 requests_pb2.SendHostRequestMessageReq(host_request_id=999, text="Test message 1") 

548 ) 

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

550 

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

552 api.SendHostRequestMessage(requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="")) 

553 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

554 assert e.value.details() == errors.INVALID_MESSAGE 

555 

556 api.SendHostRequestMessage( 

557 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 1") 

558 ) 

559 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=host_request_id)) 

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

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

562 

563 with requests_session(token3) as api: 

564 # other user can't send 

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

566 api.SendHostRequestMessage( 

567 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 2") 

568 ) 

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

570 assert e.value.details() == errors.HOST_REQUEST_NOT_FOUND 

571 

572 with requests_session(token2) as api: 

573 api.SendHostRequestMessage( 

574 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 2") 

575 ) 

576 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=host_request_id)) 

577 # including 2 for creation control message and message 

578 assert len(res.messages) == 4 

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

580 assert res.messages[0].author_user_id == user2.id 

581 

582 # can't send messages to a rejected, confirmed or cancelled request, but can for accepted 

583 api.RespondHostRequest( 

584 requests_pb2.RespondHostRequestReq( 

585 host_request_id=host_request_id, status=conversations_pb2.HOST_REQUEST_STATUS_REJECTED 

586 ) 

587 ) 

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

589 api.SendHostRequestMessage( 

590 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 3") 

591 ) 

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

593 assert e.value.details() == errors.HOST_REQUEST_CLOSED 

594 

595 api.RespondHostRequest( 

596 requests_pb2.RespondHostRequestReq( 

597 host_request_id=host_request_id, status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED 

598 ) 

599 ) 

600 

601 with requests_session(token1) as api: 

602 api.RespondHostRequest( 

603 requests_pb2.RespondHostRequestReq( 

604 host_request_id=host_request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED 

605 ) 

606 ) 

607 api.SendHostRequestMessage( 

608 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 3") 

609 ) 

610 

611 api.RespondHostRequest( 

612 requests_pb2.RespondHostRequestReq( 

613 host_request_id=host_request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED 

614 ) 

615 ) 

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

617 api.SendHostRequestMessage( 

618 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 3") 

619 ) 

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

621 assert e.value.details() == errors.HOST_REQUEST_CLOSED 

622 

623 

624def test_get_updates(db): 

625 user1, token1 = generate_user() 

626 user2, token2 = generate_user() 

627 user3, token3 = generate_user() 

628 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

629 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

630 with requests_session(token1) as api: 

631 host_request_id = api.CreateHostRequest( 

632 requests_pb2.CreateHostRequestReq( 

633 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test message 0" 

634 ) 

635 ).host_request_id 

636 

637 api.SendHostRequestMessage( 

638 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 1") 

639 ) 

640 api.SendHostRequestMessage( 

641 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 2") 

642 ) 

643 api.RespondHostRequest( 

644 requests_pb2.RespondHostRequestReq( 

645 host_request_id=host_request_id, 

646 status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED, 

647 text="Test message 3", 

648 ) 

649 ) 

650 

651 api.CreateHostRequest( 

652 requests_pb2.CreateHostRequestReq( 

653 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test message 4" 

654 ) 

655 ) 

656 

657 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=host_request_id)) 

658 assert len(res.messages) == 6 

659 assert res.messages[0].text.text == "Test message 3" 

660 assert res.messages[1].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED 

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

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

663 assert res.messages[4].text.text == "Test message 0" 

664 message_id_3 = res.messages[0].message_id 

665 message_id_cancel = res.messages[1].message_id 

666 message_id_2 = res.messages[2].message_id 

667 message_id_1 = res.messages[3].message_id 

668 message_id_0 = res.messages[4].message_id 

669 

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

671 api.GetHostRequestUpdates(requests_pb2.GetHostRequestUpdatesReq(newest_message_id=0)) 

672 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT 

673 

674 res = api.GetHostRequestUpdates(requests_pb2.GetHostRequestUpdatesReq(newest_message_id=message_id_1)) 

675 assert res.no_more 

676 assert len(res.updates) == 5 

677 assert res.updates[0].message.text.text == "Test message 2" 

678 assert ( 

679 res.updates[1].message.host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED 

680 ) 

681 assert res.updates[1].status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED 

682 assert res.updates[2].message.text.text == "Test message 3" 

683 assert res.updates[3].message.WhichOneof("content") == "chat_created" 

684 assert res.updates[3].status == conversations_pb2.HOST_REQUEST_STATUS_PENDING 

685 assert res.updates[4].message.text.text == "Test message 4" 

686 

687 res = api.GetHostRequestUpdates(requests_pb2.GetHostRequestUpdatesReq(newest_message_id=message_id_1, number=1)) 

688 assert not res.no_more 

689 assert len(res.updates) == 1 

690 assert res.updates[0].message.text.text == "Test message 2" 

691 assert res.updates[0].status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED 

692 

693 with requests_session(token3) as api: 

694 # other user can't access 

695 res = api.GetHostRequestUpdates(requests_pb2.GetHostRequestUpdatesReq(newest_message_id=message_id_1)) 

696 assert len(res.updates) == 0 

697 

698 

699def test_mark_last_seen(db): 

700 user1, token1 = generate_user() 

701 user2, token2 = generate_user() 

702 user3, token3 = generate_user() 

703 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

704 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

705 with requests_session(token1) as api: 

706 host_request_id = api.CreateHostRequest( 

707 requests_pb2.CreateHostRequestReq( 

708 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test message 0" 

709 ) 

710 ).host_request_id 

711 

712 host_request_id_2 = api.CreateHostRequest( 

713 requests_pb2.CreateHostRequestReq( 

714 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test message 0a" 

715 ) 

716 ).host_request_id 

717 

718 api.SendHostRequestMessage( 

719 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 1") 

720 ) 

721 api.SendHostRequestMessage( 

722 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 2") 

723 ) 

724 api.RespondHostRequest( 

725 requests_pb2.RespondHostRequestReq( 

726 host_request_id=host_request_id, 

727 status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED, 

728 text="Test message 3", 

729 ) 

730 ) 

731 

732 # test Ping unseen host request count, should be automarked after sending 

733 with api_session(token1) as api: 

734 assert api.Ping(api_pb2.PingReq()).unseen_received_host_request_count == 0 

735 assert api.Ping(api_pb2.PingReq()).unseen_sent_host_request_count == 0 

736 

737 with api_session(token2) as api: 

738 assert api.Ping(api_pb2.PingReq()).unseen_received_host_request_count == 2 

739 assert api.Ping(api_pb2.PingReq()).unseen_sent_host_request_count == 0 

740 

741 with requests_session(token2) as api: 

742 assert api.ListHostRequests(requests_pb2.ListHostRequestsReq()).host_requests[0].last_seen_message_id == 0 

743 

744 api.MarkLastSeenHostRequest( 

745 requests_pb2.MarkLastSeenHostRequestReq(host_request_id=host_request_id, last_seen_message_id=3) 

746 ) 

747 

748 assert api.ListHostRequests(requests_pb2.ListHostRequestsReq()).host_requests[0].last_seen_message_id == 3 

749 

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

751 api.MarkLastSeenHostRequest( 

752 requests_pb2.MarkLastSeenHostRequestReq(host_request_id=host_request_id, last_seen_message_id=1) 

753 ) 

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

755 assert e.value.details() == errors.CANT_UNSEE_MESSAGES 

756 

757 # this will be used to test sent request notifications 

758 host_request_id_3 = api.CreateHostRequest( 

759 requests_pb2.CreateHostRequestReq( 

760 host_user_id=user1.id, from_date=today_plus_2, to_date=today_plus_3, text="Another test request" 

761 ) 

762 ).host_request_id 

763 

764 # this should make id_2 all read 

765 api.SendHostRequestMessage( 

766 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id_2, text="Test") 

767 ) 

768 

769 with api_session(token2) as api: 

770 assert api.Ping(api_pb2.PingReq()).unseen_received_host_request_count == 1 

771 assert api.Ping(api_pb2.PingReq()).unseen_sent_host_request_count == 0 

772 

773 # make sure sent and received count for unseen notifications 

774 with requests_session(token1) as api: 

775 api.SendHostRequestMessage( 

776 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id_3, text="Test message") 

777 ) 

778 

779 with api_session(token2) as api: 

780 assert api.Ping(api_pb2.PingReq()).unseen_received_host_request_count == 1 

781 assert api.Ping(api_pb2.PingReq()).unseen_sent_host_request_count == 1 

782 

783 

784def test_response_rate(db): 

785 user1, token1 = generate_user() 

786 user2, token2 = generate_user() 

787 

788 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

789 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

790 

791 with requests_session(token1) as api: 

792 # no requests: insufficient 

793 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id)) 

794 assert res.HasField("insufficient_data") 

795 

796 # send a request and back date it by 36 hours 

797 host_request_1 = api.CreateHostRequest( 

798 requests_pb2.CreateHostRequestReq( 

799 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request" 

800 ) 

801 ).host_request_id 

802 with session_scope() as session: 

803 session.execute( 

804 select(Message) 

805 .where(Message.conversation_id == host_request_1) 

806 .where(Message.message_type == MessageType.chat_created) 

807 ).scalar_one().time = now() - timedelta(hours=36) 

808 

809 # still insufficient 

810 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id)) 

811 assert res.HasField("insufficient_data") 

812 

813 # send a request and back date it by 35 hours 

814 host_request_2 = api.CreateHostRequest( 

815 requests_pb2.CreateHostRequestReq( 

816 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request" 

817 ) 

818 ).host_request_id 

819 with session_scope() as session: 

820 session.execute( 

821 select(Message) 

822 .where(Message.conversation_id == host_request_2) 

823 .where(Message.message_type == MessageType.chat_created) 

824 ).scalar_one().time = now() - timedelta(hours=35) 

825 

826 # still insufficient 

827 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id)) 

828 assert res.HasField("insufficient_data") 

829 

830 # send a request and back date it by 34 hours 

831 host_request_3 = api.CreateHostRequest( 

832 requests_pb2.CreateHostRequestReq( 

833 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request" 

834 ) 

835 ).host_request_id 

836 with session_scope() as session: 

837 session.execute( 

838 select(Message) 

839 .where(Message.conversation_id == host_request_3) 

840 .where(Message.message_type == MessageType.chat_created) 

841 ).scalar_one().time = now() - timedelta(hours=34) 

842 

843 # now low 

844 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id)) 

845 assert res.HasField("low") 

846 

847 with requests_session(token2) as api: 

848 # accept a host req 

849 api.RespondHostRequest( 

850 requests_pb2.RespondHostRequestReq( 

851 host_request_id=host_request_2, 

852 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED, 

853 text="Accepting host request", 

854 ) 

855 ) 

856 

857 with requests_session(token1) as api: 

858 # now some w p33 = 35h 

859 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id)) 

860 assert res.HasField("some") 

861 assert res.some.response_time_p33.ToTimedelta() == timedelta(hours=35) 

862 

863 with requests_session(token2) as api: 

864 # accept another host req 

865 api.RespondHostRequest( 

866 requests_pb2.RespondHostRequestReq( 

867 host_request_id=host_request_3, 

868 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED, 

869 text="Accepting host request", 

870 ) 

871 ) 

872 

873 with requests_session(token1) as api: 

874 # now most w p33 = 34h, p66 = 35h 

875 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id)) 

876 assert res.HasField("most") 

877 assert res.most.response_time_p33.ToTimedelta() == timedelta(hours=34) 

878 assert res.most.response_time_p66.ToTimedelta() == timedelta(hours=35) 

879 

880 with requests_session(token2) as api: 

881 # accept last host req 

882 api.RespondHostRequest( 

883 requests_pb2.RespondHostRequestReq( 

884 host_request_id=host_request_1, 

885 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED, 

886 text="Accepting host request", 

887 ) 

888 ) 

889 

890 with requests_session(token1) as api: 

891 # now all w p33 = 34h, p66 = 35h 

892 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id)) 

893 assert res.HasField("almost_all") 

894 assert res.almost_all.response_time_p33.ToTimedelta() == timedelta(hours=34) 

895 assert res.almost_all.response_time_p66.ToTimedelta() == timedelta(hours=35) 

896 

897 # send a request and back date it by 2 hours 

898 host_request_4 = api.CreateHostRequest( 

899 requests_pb2.CreateHostRequestReq( 

900 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request" 

901 ) 

902 ).host_request_id 

903 with session_scope() as session: 

904 session.execute( 

905 select(Message) 

906 .where(Message.conversation_id == host_request_4) 

907 .where(Message.message_type == MessageType.chat_created) 

908 ).scalar_one().time = now() - timedelta(hours=2) 

909 

910 # send a request and back date it by 4 hours 

911 host_request_5 = api.CreateHostRequest( 

912 requests_pb2.CreateHostRequestReq( 

913 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request" 

914 ) 

915 ).host_request_id 

916 with session_scope() as session: 

917 session.execute( 

918 select(Message) 

919 .where(Message.conversation_id == host_request_5) 

920 .where(Message.message_type == MessageType.chat_created) 

921 ).scalar_one().time = now() - timedelta(hours=4) 

922 

923 # now some w p33 = 35h 

924 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id)) 

925 assert res.HasField("some") 

926 assert res.some.response_time_p33.ToTimedelta() == timedelta(hours=35) 

927 

928 with requests_session(token2) as api: 

929 # accept host req 

930 api.RespondHostRequest( 

931 requests_pb2.RespondHostRequestReq( 

932 host_request_id=host_request_5, 

933 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED, 

934 text="Accepting host request", 

935 ) 

936 ) 

937 

938 with requests_session(token1) as api: 

939 # now most w p33 = 34h, p66 = 36h 

940 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id)) 

941 assert res.HasField("most") 

942 assert res.most.response_time_p33.ToTimedelta() == timedelta(hours=34) 

943 assert res.most.response_time_p66.ToTimedelta() == timedelta(hours=36) 

944 

945 with requests_session(token2) as api: 

946 # accept host req 

947 api.RespondHostRequest( 

948 requests_pb2.RespondHostRequestReq( 

949 host_request_id=host_request_4, 

950 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED, 

951 text="Accepting host request", 

952 ) 

953 ) 

954 

955 with requests_session(token1) as api: 

956 # now most w p33 = 4h, p66 = 35h 

957 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id)) 

958 assert res.HasField("almost_all") 

959 assert res.almost_all.response_time_p33.ToTimedelta() == timedelta(hours=4) 

960 assert res.almost_all.response_time_p66.ToTimedelta() == timedelta(hours=35) 

961 

962 

963def test_request_notifications(db, push_collector): 

964 host, host_token = generate_user(complete_profile=True) 

965 surfer, surfer_token = generate_user(complete_profile=True) 

966 

967 today_plus_2 = (today() + timedelta(days=2)).isoformat() 

968 today_plus_3 = (today() + timedelta(days=3)).isoformat() 

969 

970 with requests_session(surfer_token) as api: 

971 with mock_notification_email() as mock: 

972 hr_id = api.CreateHostRequest( 

973 requests_pb2.CreateHostRequestReq( 

974 host_user_id=host.id, 

975 from_date=today_plus_2, 

976 to_date=today_plus_3, 

977 text="can i stay plz", 

978 ) 

979 ).host_request_id 

980 

981 mock.assert_called_once() 

982 e = email_fields(mock) 

983 assert e.recipient == host.email 

984 assert "host request" in e.subject.lower() 

985 assert host.name in e.plain 

986 assert host.name in e.html 

987 assert surfer.name in e.plain 

988 assert surfer.name in e.html 

989 assert v2date(today_plus_2, host) in e.plain 

990 assert v2date(today_plus_2, host) in e.html 

991 assert v2date(today_plus_3, host) in e.plain 

992 assert v2date(today_plus_3, host) in e.html 

993 assert "http://localhost:5000/img/thumbnail/" not in e.plain 

994 assert "http://localhost:5000/img/thumbnail/" in e.html 

995 assert f"http://localhost:3000/messages/request/{hr_id}" in e.plain 

996 assert f"http://localhost:3000/messages/request/{hr_id}" in e.html 

997 

998 push_collector.assert_user_has_single_matching( 

999 host.id, 

1000 title=f"{surfer.name} sent you a host request", 

1001 ) 

1002 

1003 with requests_session(host_token) as api: 

1004 with mock_notification_email() as mock: 

1005 api.RespondHostRequest( 

1006 requests_pb2.RespondHostRequestReq( 

1007 host_request_id=hr_id, 

1008 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED, 

1009 text="Accepting host request", 

1010 ) 

1011 ) 

1012 

1013 e = email_fields(mock) 

1014 assert e.recipient == surfer.email 

1015 assert "host request" in e.subject.lower() 

1016 assert host.name in e.plain 

1017 assert host.name in e.html 

1018 assert surfer.name in e.plain 

1019 assert surfer.name in e.html 

1020 assert v2date(today_plus_2, surfer) in e.plain 

1021 assert v2date(today_plus_2, surfer) in e.html 

1022 assert v2date(today_plus_3, surfer) in e.plain 

1023 assert v2date(today_plus_3, surfer) in e.html 

1024 assert "http://localhost:5000/img/thumbnail/" not in e.plain 

1025 assert "http://localhost:5000/img/thumbnail/" in e.html 

1026 assert f"http://localhost:3000/messages/request/{hr_id}" in e.plain 

1027 assert f"http://localhost:3000/messages/request/{hr_id}" in e.html 

1028 

1029 push_collector.assert_user_has_single_matching( 

1030 surfer.id, 

1031 title=f"{host.name} accepted your host request", 

1032 )