Coverage for src/tests/test_requests.py: 100%
507 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-12-20 18:03 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2024-12-20 18:03 +0000
1from datetime import timedelta
3import grpc
4import pytest
5from sqlalchemy.sql import select
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)
25@pytest.fixture(autouse=True)
26def _(testconfig):
27 pass
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
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
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
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
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
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
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 )
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
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
133def test_create_request_incomplete_profile(db):
134 user1, token1 = generate_user(complete_profile=False)
135 user2, _ = generate_user()
136 today_plus_2 = (today() + timedelta(days=2)).isoformat()
137 today_plus_3 = (today() + timedelta(days=3)).isoformat()
138 with requests_session(token1) as api:
139 with pytest.raises(grpc.RpcError) as e:
140 api.CreateHostRequest(
141 requests_pb2.CreateHostRequestReq(
142 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request"
143 )
144 )
145 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
146 assert e.value.details() == errors.INCOMPLETE_PROFILE_SEND_REQUEST
149def add_message(db, text, author_id, conversation_id):
150 with session_scope() as session:
151 message = Message(
152 conversation_id=conversation_id, author_id=author_id, text=text, message_type=MessageType.text
153 )
155 session.add(message)
158def test_GetHostRequest(db):
159 user1, token1 = generate_user()
160 user2, token2 = generate_user()
161 user3, token3 = generate_user()
162 today_plus_2 = (today() + timedelta(days=2)).isoformat()
163 today_plus_3 = (today() + timedelta(days=3)).isoformat()
164 with requests_session(token1) as api:
165 host_request_id = api.CreateHostRequest(
166 requests_pb2.CreateHostRequestReq(
167 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1"
168 )
169 ).host_request_id
171 with pytest.raises(grpc.RpcError) as e:
172 api.GetHostRequest(requests_pb2.GetHostRequestReq(host_request_id=999))
173 assert e.value.code() == grpc.StatusCode.NOT_FOUND
174 assert e.value.details() == errors.HOST_REQUEST_NOT_FOUND
176 api.SendHostRequestMessage(
177 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 1")
178 )
180 res = api.GetHostRequest(requests_pb2.GetHostRequestReq(host_request_id=host_request_id))
181 assert res.latest_message.text.text == "Test message 1"
184def test_ListHostRequests(db):
185 user1, token1 = generate_user()
186 user2, token2 = generate_user()
187 user3, token3 = generate_user()
188 today_plus_2 = (today() + timedelta(days=2)).isoformat()
189 today_plus_3 = (today() + timedelta(days=3)).isoformat()
190 with requests_session(token1) as api:
191 host_request_1 = api.CreateHostRequest(
192 requests_pb2.CreateHostRequestReq(
193 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1"
194 )
195 ).host_request_id
197 host_request_2 = api.CreateHostRequest(
198 requests_pb2.CreateHostRequestReq(
199 host_user_id=user3.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 2"
200 )
201 ).host_request_id
203 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_sent=True))
204 assert res.no_more
205 assert len(res.host_requests) == 2
207 with requests_session(token2) as api:
208 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True))
209 assert res.no_more
210 assert len(res.host_requests) == 1
211 assert res.host_requests[0].latest_message.text.text == "Test request 1"
212 assert res.host_requests[0].surfer_user_id == user1.id
213 assert res.host_requests[0].host_user_id == user2.id
214 assert res.host_requests[0].status == conversations_pb2.HOST_REQUEST_STATUS_PENDING
216 add_message(db, "Test request 1 message 1", user2.id, host_request_1)
217 add_message(db, "Test request 1 message 2", user2.id, host_request_1)
218 add_message(db, "Test request 1 message 3", user2.id, host_request_1)
220 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True))
221 assert res.host_requests[0].latest_message.text.text == "Test request 1 message 3"
223 api.CreateHostRequest(
224 requests_pb2.CreateHostRequestReq(
225 host_user_id=user1.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 3"
226 )
227 )
229 add_message(db, "Test request 2 message 1", user1.id, host_request_2)
230 add_message(db, "Test request 2 message 2", user3.id, host_request_2)
232 with requests_session(token3) as api:
233 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True))
234 assert res.no_more
235 assert len(res.host_requests) == 1
236 assert res.host_requests[0].latest_message.text.text == "Test request 2 message 2"
238 with requests_session(token1) as api:
239 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True))
240 assert len(res.host_requests) == 1
242 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq())
243 assert len(res.host_requests) == 3
246def test_ListHostRequests_pagination_regression(db):
247 """
248 ListHostRequests was skipping a request when getting multiple pages
249 """
250 user1, token1 = generate_user()
251 user2, token2 = generate_user()
252 today_plus_2 = (today() + timedelta(days=2)).isoformat()
253 today_plus_3 = (today() + timedelta(days=3)).isoformat()
254 with requests_session(token1) as api:
255 host_request_1 = api.CreateHostRequest(
256 requests_pb2.CreateHostRequestReq(
257 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1"
258 )
259 ).host_request_id
261 host_request_2 = api.CreateHostRequest(
262 requests_pb2.CreateHostRequestReq(
263 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 2"
264 )
265 ).host_request_id
267 host_request_3 = api.CreateHostRequest(
268 requests_pb2.CreateHostRequestReq(
269 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 3"
270 )
271 ).host_request_id
273 with requests_session(token2) as api:
274 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True))
275 assert res.no_more
276 assert len(res.host_requests) == 3
277 assert res.host_requests[0].latest_message.text.text == "Test request 3"
278 assert res.host_requests[1].latest_message.text.text == "Test request 2"
279 assert res.host_requests[2].latest_message.text.text == "Test request 1"
281 with requests_session(token2) as api:
282 api.RespondHostRequest(
283 requests_pb2.RespondHostRequestReq(
284 host_request_id=host_request_2,
285 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED,
286 text="Accepting host request 2",
287 )
288 )
289 api.RespondHostRequest(
290 requests_pb2.RespondHostRequestReq(
291 host_request_id=host_request_1,
292 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED,
293 text="Accepting host request 1",
294 )
295 )
296 api.RespondHostRequest(
297 requests_pb2.RespondHostRequestReq(
298 host_request_id=host_request_3,
299 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED,
300 text="Accepting host request 3",
301 )
302 )
304 with requests_session(token2) as api:
305 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True))
306 assert res.no_more
307 assert len(res.host_requests) == 3
308 assert res.host_requests[0].latest_message.text.text == "Accepting host request 3"
309 assert res.host_requests[1].latest_message.text.text == "Accepting host request 1"
310 assert res.host_requests[2].latest_message.text.text == "Accepting host request 2"
312 with requests_session(token2) as api:
313 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True, number=1))
314 assert not res.no_more
315 assert len(res.host_requests) == 1
316 assert res.host_requests[0].latest_message.text.text == "Accepting host request 3"
317 res = api.ListHostRequests(
318 requests_pb2.ListHostRequestsReq(only_received=True, number=1, last_request_id=res.last_request_id)
319 )
320 assert not res.no_more
321 assert len(res.host_requests) == 1
322 assert res.host_requests[0].latest_message.text.text == "Accepting host request 1"
323 res = api.ListHostRequests(
324 requests_pb2.ListHostRequestsReq(only_received=True, number=1, last_request_id=res.last_request_id)
325 )
326 assert res.no_more
327 assert len(res.host_requests) == 1
328 assert res.host_requests[0].latest_message.text.text == "Accepting host request 2"
331def test_ListHostRequests_active_filter(db):
332 user1, token1 = generate_user()
333 user2, token2 = generate_user()
334 today_plus_2 = (today() + timedelta(days=2)).isoformat()
335 today_plus_3 = (today() + timedelta(days=3)).isoformat()
337 with requests_session(token1) as api:
338 request_id = api.CreateHostRequest(
339 requests_pb2.CreateHostRequestReq(
340 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1"
341 )
342 ).host_request_id
343 api.RespondHostRequest(
344 requests_pb2.RespondHostRequestReq(
345 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED
346 )
347 )
349 with requests_session(token2) as api:
350 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_received=True))
351 assert len(res.host_requests) == 1
352 res = api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_active=True))
353 assert len(res.host_requests) == 0
356def test_RespondHostRequests(db):
357 user1, token1 = generate_user()
358 user2, token2 = generate_user()
359 user3, token3 = generate_user()
360 today_plus_2 = (today() + timedelta(days=2)).isoformat()
361 today_plus_3 = (today() + timedelta(days=3)).isoformat()
363 with requests_session(token1) as api:
364 request_id = api.CreateHostRequest(
365 requests_pb2.CreateHostRequestReq(
366 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1"
367 )
368 ).host_request_id
370 # another user can't access
371 with requests_session(token3) as api:
372 with pytest.raises(grpc.RpcError) as e:
373 api.RespondHostRequest(
374 requests_pb2.RespondHostRequestReq(
375 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED
376 )
377 )
378 assert e.value.code() == grpc.StatusCode.NOT_FOUND
379 assert e.value.details() == errors.HOST_REQUEST_NOT_FOUND
381 with requests_session(token1) as api:
382 with pytest.raises(grpc.RpcError) as e:
383 api.RespondHostRequest(
384 requests_pb2.RespondHostRequestReq(
385 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED
386 )
387 )
388 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
389 assert e.value.details() == errors.NOT_THE_HOST
391 with requests_session(token2) as api:
392 # non existing id
393 with pytest.raises(grpc.RpcError) as e:
394 api.RespondHostRequest(
395 requests_pb2.RespondHostRequestReq(
396 host_request_id=9999, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED
397 )
398 )
399 assert e.value.code() == grpc.StatusCode.NOT_FOUND
401 # host can't confirm or cancel (host should accept/reject)
402 with pytest.raises(grpc.RpcError) as e:
403 api.RespondHostRequest(
404 requests_pb2.RespondHostRequestReq(
405 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED
406 )
407 )
408 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
409 assert e.value.details() == errors.INVALID_HOST_REQUEST_STATUS
410 with pytest.raises(grpc.RpcError) as e:
411 api.RespondHostRequest(
412 requests_pb2.RespondHostRequestReq(
413 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED
414 )
415 )
416 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
417 assert e.value.details() == errors.INVALID_HOST_REQUEST_STATUS
419 api.RespondHostRequest(
420 requests_pb2.RespondHostRequestReq(
421 host_request_id=request_id,
422 status=conversations_pb2.HOST_REQUEST_STATUS_REJECTED,
423 text="Test rejection message",
424 )
425 )
426 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=request_id))
427 assert res.messages[0].text.text == "Test rejection message"
428 assert res.messages[1].WhichOneof("content") == "host_request_status_changed"
429 assert res.messages[1].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_REJECTED
430 # should be able to move from rejected -> accepted
431 api.RespondHostRequest(
432 requests_pb2.RespondHostRequestReq(
433 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED
434 )
435 )
437 with requests_session(token1) as api:
438 # can't make pending
439 with pytest.raises(grpc.RpcError) as e:
440 api.RespondHostRequest(
441 requests_pb2.RespondHostRequestReq(
442 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_PENDING
443 )
444 )
445 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
446 assert e.value.details() == errors.INVALID_HOST_REQUEST_STATUS
448 # can confirm then cancel
449 api.RespondHostRequest(
450 requests_pb2.RespondHostRequestReq(
451 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED
452 )
453 )
455 api.RespondHostRequest(
456 requests_pb2.RespondHostRequestReq(
457 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED
458 )
459 )
461 # can't confirm after having cancelled
462 with pytest.raises(grpc.RpcError) as e:
463 api.RespondHostRequest(
464 requests_pb2.RespondHostRequestReq(
465 host_request_id=request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED
466 )
467 )
468 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
469 assert e.value.details() == errors.INVALID_HOST_REQUEST_STATUS
471 # at this point there should be 7 messages
472 # 2 for creation, 2 for the status change with message, 3 for the other status changed
473 with requests_session(token1) as api:
474 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=request_id))
475 assert len(res.messages) == 7
476 assert res.messages[0].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED
477 assert res.messages[1].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED
478 assert res.messages[2].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED
479 assert res.messages[4].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_REJECTED
480 assert res.messages[6].WhichOneof("content") == "chat_created"
483def test_get_host_request_messages(db):
484 user1, token1 = generate_user()
485 user2, token2 = generate_user()
486 today_plus_2 = (today() + timedelta(days=2)).isoformat()
487 today_plus_3 = (today() + timedelta(days=3)).isoformat()
488 with requests_session(token1) as api:
489 res = api.CreateHostRequest(
490 requests_pb2.CreateHostRequestReq(
491 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1"
492 )
493 )
494 conversation_id = res.host_request_id
496 add_message(db, "Test request 1 message 1", user1.id, conversation_id)
497 add_message(db, "Test request 1 message 2", user1.id, conversation_id)
498 add_message(db, "Test request 1 message 3", user1.id, conversation_id)
500 with requests_session(token2) as api:
501 api.RespondHostRequest(
502 requests_pb2.RespondHostRequestReq(
503 host_request_id=conversation_id, status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED
504 )
505 )
507 add_message(db, "Test request 1 message 4", user2.id, conversation_id)
508 add_message(db, "Test request 1 message 5", user2.id, conversation_id)
510 api.RespondHostRequest(
511 requests_pb2.RespondHostRequestReq(
512 host_request_id=conversation_id, status=conversations_pb2.HOST_REQUEST_STATUS_REJECTED
513 )
514 )
516 with requests_session(token1) as api:
517 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=conversation_id))
518 # 9 including initial message
519 assert len(res.messages) == 9
520 assert res.no_more
522 res = api.GetHostRequestMessages(
523 requests_pb2.GetHostRequestMessagesReq(host_request_id=conversation_id, number=3)
524 )
525 assert not res.no_more
526 assert len(res.messages) == 3
527 assert res.messages[0].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_REJECTED
528 assert res.messages[0].WhichOneof("content") == "host_request_status_changed"
529 assert res.messages[1].text.text == "Test request 1 message 5"
530 assert res.messages[2].text.text == "Test request 1 message 4"
532 res = api.GetHostRequestMessages(
533 requests_pb2.GetHostRequestMessagesReq(
534 host_request_id=conversation_id, last_message_id=res.messages[2].message_id, number=6
535 )
536 )
537 assert res.no_more
538 assert len(res.messages) == 6
539 assert res.messages[0].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED
540 assert res.messages[0].WhichOneof("content") == "host_request_status_changed"
541 assert res.messages[1].text.text == "Test request 1 message 3"
542 assert res.messages[2].text.text == "Test request 1 message 2"
543 assert res.messages[3].text.text == "Test request 1 message 1"
544 assert res.messages[4].text.text == "Test request 1"
545 assert res.messages[5].WhichOneof("content") == "chat_created"
548def test_SendHostRequestMessage(db):
549 user1, token1 = generate_user()
550 user2, token2 = generate_user()
551 user3, token3 = generate_user()
552 today_plus_2 = (today() + timedelta(days=2)).isoformat()
553 today_plus_3 = (today() + timedelta(days=3)).isoformat()
554 with requests_session(token1) as api:
555 host_request_id = api.CreateHostRequest(
556 requests_pb2.CreateHostRequestReq(
557 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request 1"
558 )
559 ).host_request_id
561 with pytest.raises(grpc.RpcError) as e:
562 api.SendHostRequestMessage(
563 requests_pb2.SendHostRequestMessageReq(host_request_id=999, text="Test message 1")
564 )
565 assert e.value.code() == grpc.StatusCode.NOT_FOUND
567 with pytest.raises(grpc.RpcError) as e:
568 api.SendHostRequestMessage(requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text=""))
569 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
570 assert e.value.details() == errors.INVALID_MESSAGE
572 api.SendHostRequestMessage(
573 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 1")
574 )
575 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=host_request_id))
576 assert res.messages[0].text.text == "Test message 1"
577 assert res.messages[0].author_user_id == user1.id
579 with requests_session(token3) as api:
580 # other user can't send
581 with pytest.raises(grpc.RpcError) as e:
582 api.SendHostRequestMessage(
583 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 2")
584 )
585 assert e.value.code() == grpc.StatusCode.NOT_FOUND
586 assert e.value.details() == errors.HOST_REQUEST_NOT_FOUND
588 with requests_session(token2) as api:
589 api.SendHostRequestMessage(
590 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 2")
591 )
592 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=host_request_id))
593 # including 2 for creation control message and message
594 assert len(res.messages) == 4
595 assert res.messages[0].text.text == "Test message 2"
596 assert res.messages[0].author_user_id == user2.id
598 # can't send messages to a rejected, confirmed or cancelled request, but can for accepted
599 api.RespondHostRequest(
600 requests_pb2.RespondHostRequestReq(
601 host_request_id=host_request_id, status=conversations_pb2.HOST_REQUEST_STATUS_REJECTED
602 )
603 )
604 with pytest.raises(grpc.RpcError) as e:
605 api.SendHostRequestMessage(
606 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 3")
607 )
608 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
609 assert e.value.details() == errors.HOST_REQUEST_CLOSED
611 api.RespondHostRequest(
612 requests_pb2.RespondHostRequestReq(
613 host_request_id=host_request_id, status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED
614 )
615 )
617 with requests_session(token1) as api:
618 api.RespondHostRequest(
619 requests_pb2.RespondHostRequestReq(
620 host_request_id=host_request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED
621 )
622 )
623 api.SendHostRequestMessage(
624 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 3")
625 )
627 api.RespondHostRequest(
628 requests_pb2.RespondHostRequestReq(
629 host_request_id=host_request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED
630 )
631 )
632 with pytest.raises(grpc.RpcError) as e:
633 api.SendHostRequestMessage(
634 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 3")
635 )
636 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
637 assert e.value.details() == errors.HOST_REQUEST_CLOSED
640def test_get_updates(db):
641 user1, token1 = generate_user()
642 user2, token2 = generate_user()
643 user3, token3 = generate_user()
644 today_plus_2 = (today() + timedelta(days=2)).isoformat()
645 today_plus_3 = (today() + timedelta(days=3)).isoformat()
646 with requests_session(token1) as api:
647 host_request_id = api.CreateHostRequest(
648 requests_pb2.CreateHostRequestReq(
649 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test message 0"
650 )
651 ).host_request_id
653 api.SendHostRequestMessage(
654 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 1")
655 )
656 api.SendHostRequestMessage(
657 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 2")
658 )
659 api.RespondHostRequest(
660 requests_pb2.RespondHostRequestReq(
661 host_request_id=host_request_id,
662 status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED,
663 text="Test message 3",
664 )
665 )
667 api.CreateHostRequest(
668 requests_pb2.CreateHostRequestReq(
669 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test message 4"
670 )
671 )
673 res = api.GetHostRequestMessages(requests_pb2.GetHostRequestMessagesReq(host_request_id=host_request_id))
674 assert len(res.messages) == 6
675 assert res.messages[0].text.text == "Test message 3"
676 assert res.messages[1].host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED
677 assert res.messages[2].text.text == "Test message 2"
678 assert res.messages[3].text.text == "Test message 1"
679 assert res.messages[4].text.text == "Test message 0"
680 message_id_3 = res.messages[0].message_id
681 message_id_cancel = res.messages[1].message_id
682 message_id_2 = res.messages[2].message_id
683 message_id_1 = res.messages[3].message_id
684 message_id_0 = res.messages[4].message_id
686 with pytest.raises(grpc.RpcError) as e:
687 api.GetHostRequestUpdates(requests_pb2.GetHostRequestUpdatesReq(newest_message_id=0))
688 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
690 res = api.GetHostRequestUpdates(requests_pb2.GetHostRequestUpdatesReq(newest_message_id=message_id_1))
691 assert res.no_more
692 assert len(res.updates) == 5
693 assert res.updates[0].message.text.text == "Test message 2"
694 assert (
695 res.updates[1].message.host_request_status_changed.status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED
696 )
697 assert res.updates[1].status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED
698 assert res.updates[2].message.text.text == "Test message 3"
699 assert res.updates[3].message.WhichOneof("content") == "chat_created"
700 assert res.updates[3].status == conversations_pb2.HOST_REQUEST_STATUS_PENDING
701 assert res.updates[4].message.text.text == "Test message 4"
703 res = api.GetHostRequestUpdates(requests_pb2.GetHostRequestUpdatesReq(newest_message_id=message_id_1, number=1))
704 assert not res.no_more
705 assert len(res.updates) == 1
706 assert res.updates[0].message.text.text == "Test message 2"
707 assert res.updates[0].status == conversations_pb2.HOST_REQUEST_STATUS_CANCELLED
709 with requests_session(token3) as api:
710 # other user can't access
711 res = api.GetHostRequestUpdates(requests_pb2.GetHostRequestUpdatesReq(newest_message_id=message_id_1))
712 assert len(res.updates) == 0
715def test_mark_last_seen(db):
716 user1, token1 = generate_user()
717 user2, token2 = generate_user()
718 user3, token3 = generate_user()
719 today_plus_2 = (today() + timedelta(days=2)).isoformat()
720 today_plus_3 = (today() + timedelta(days=3)).isoformat()
721 with requests_session(token1) as api:
722 host_request_id = api.CreateHostRequest(
723 requests_pb2.CreateHostRequestReq(
724 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test message 0"
725 )
726 ).host_request_id
728 host_request_id_2 = api.CreateHostRequest(
729 requests_pb2.CreateHostRequestReq(
730 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test message 0a"
731 )
732 ).host_request_id
734 api.SendHostRequestMessage(
735 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 1")
736 )
737 api.SendHostRequestMessage(
738 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id, text="Test message 2")
739 )
740 api.RespondHostRequest(
741 requests_pb2.RespondHostRequestReq(
742 host_request_id=host_request_id,
743 status=conversations_pb2.HOST_REQUEST_STATUS_CANCELLED,
744 text="Test message 3",
745 )
746 )
748 # test Ping unseen host request count, should be automarked after sending
749 with api_session(token1) as api:
750 assert api.Ping(api_pb2.PingReq()).unseen_received_host_request_count == 0
751 assert api.Ping(api_pb2.PingReq()).unseen_sent_host_request_count == 0
753 with api_session(token2) as api:
754 assert api.Ping(api_pb2.PingReq()).unseen_received_host_request_count == 2
755 assert api.Ping(api_pb2.PingReq()).unseen_sent_host_request_count == 0
757 with requests_session(token2) as api:
758 assert api.ListHostRequests(requests_pb2.ListHostRequestsReq()).host_requests[0].last_seen_message_id == 0
760 api.MarkLastSeenHostRequest(
761 requests_pb2.MarkLastSeenHostRequestReq(host_request_id=host_request_id, last_seen_message_id=3)
762 )
764 assert api.ListHostRequests(requests_pb2.ListHostRequestsReq()).host_requests[0].last_seen_message_id == 3
766 with pytest.raises(grpc.RpcError) as e:
767 api.MarkLastSeenHostRequest(
768 requests_pb2.MarkLastSeenHostRequestReq(host_request_id=host_request_id, last_seen_message_id=1)
769 )
770 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
771 assert e.value.details() == errors.CANT_UNSEE_MESSAGES
773 # this will be used to test sent request notifications
774 host_request_id_3 = api.CreateHostRequest(
775 requests_pb2.CreateHostRequestReq(
776 host_user_id=user1.id, from_date=today_plus_2, to_date=today_plus_3, text="Another test request"
777 )
778 ).host_request_id
780 # this should make id_2 all read
781 api.SendHostRequestMessage(
782 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id_2, text="Test")
783 )
785 with api_session(token2) as api:
786 assert api.Ping(api_pb2.PingReq()).unseen_received_host_request_count == 1
787 assert api.Ping(api_pb2.PingReq()).unseen_sent_host_request_count == 0
789 # make sure sent and received count for unseen notifications
790 with requests_session(token1) as api:
791 api.SendHostRequestMessage(
792 requests_pb2.SendHostRequestMessageReq(host_request_id=host_request_id_3, text="Test message")
793 )
795 with api_session(token2) as api:
796 assert api.Ping(api_pb2.PingReq()).unseen_received_host_request_count == 1
797 assert api.Ping(api_pb2.PingReq()).unseen_sent_host_request_count == 1
800def test_response_rate(db):
801 user1, token1 = generate_user()
802 user2, token2 = generate_user()
804 today_plus_2 = (today() + timedelta(days=2)).isoformat()
805 today_plus_3 = (today() + timedelta(days=3)).isoformat()
807 with requests_session(token1) as api:
808 # no requests: insufficient
809 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id))
810 assert res.HasField("insufficient_data")
812 # send a request and back date it by 36 hours
813 host_request_1 = api.CreateHostRequest(
814 requests_pb2.CreateHostRequestReq(
815 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request"
816 )
817 ).host_request_id
818 with session_scope() as session:
819 session.execute(
820 select(Message)
821 .where(Message.conversation_id == host_request_1)
822 .where(Message.message_type == MessageType.chat_created)
823 ).scalar_one().time = now() - timedelta(hours=36)
825 # still insufficient
826 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id))
827 assert res.HasField("insufficient_data")
829 # send a request and back date it by 35 hours
830 host_request_2 = api.CreateHostRequest(
831 requests_pb2.CreateHostRequestReq(
832 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request"
833 )
834 ).host_request_id
835 with session_scope() as session:
836 session.execute(
837 select(Message)
838 .where(Message.conversation_id == host_request_2)
839 .where(Message.message_type == MessageType.chat_created)
840 ).scalar_one().time = now() - timedelta(hours=35)
842 # still insufficient
843 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id))
844 assert res.HasField("insufficient_data")
846 # send a request and back date it by 34 hours
847 host_request_3 = api.CreateHostRequest(
848 requests_pb2.CreateHostRequestReq(
849 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request"
850 )
851 ).host_request_id
852 with session_scope() as session:
853 session.execute(
854 select(Message)
855 .where(Message.conversation_id == host_request_3)
856 .where(Message.message_type == MessageType.chat_created)
857 ).scalar_one().time = now() - timedelta(hours=34)
859 # now low
860 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id))
861 assert res.HasField("low")
863 with requests_session(token2) as api:
864 # accept a host req
865 api.RespondHostRequest(
866 requests_pb2.RespondHostRequestReq(
867 host_request_id=host_request_2,
868 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED,
869 text="Accepting host request",
870 )
871 )
873 with requests_session(token1) as api:
874 # now some w p33 = 35h
875 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id))
876 assert res.HasField("some")
877 assert res.some.response_time_p33.ToTimedelta() == timedelta(hours=35)
879 with requests_session(token2) as api:
880 # accept another host req
881 api.RespondHostRequest(
882 requests_pb2.RespondHostRequestReq(
883 host_request_id=host_request_3,
884 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED,
885 text="Accepting host request",
886 )
887 )
889 with requests_session(token1) as api:
890 # now most w p33 = 34h, p66 = 35h
891 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id))
892 assert res.HasField("most")
893 assert res.most.response_time_p33.ToTimedelta() == timedelta(hours=34)
894 assert res.most.response_time_p66.ToTimedelta() == timedelta(hours=35)
896 with requests_session(token2) as api:
897 # accept last host req
898 api.RespondHostRequest(
899 requests_pb2.RespondHostRequestReq(
900 host_request_id=host_request_1,
901 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED,
902 text="Accepting host request",
903 )
904 )
906 with requests_session(token1) as api:
907 # now all w p33 = 34h, p66 = 35h
908 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id))
909 assert res.HasField("almost_all")
910 assert res.almost_all.response_time_p33.ToTimedelta() == timedelta(hours=34)
911 assert res.almost_all.response_time_p66.ToTimedelta() == timedelta(hours=35)
913 # send a request and back date it by 2 hours
914 host_request_4 = api.CreateHostRequest(
915 requests_pb2.CreateHostRequestReq(
916 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request"
917 )
918 ).host_request_id
919 with session_scope() as session:
920 session.execute(
921 select(Message)
922 .where(Message.conversation_id == host_request_4)
923 .where(Message.message_type == MessageType.chat_created)
924 ).scalar_one().time = now() - timedelta(hours=2)
926 # send a request and back date it by 4 hours
927 host_request_5 = api.CreateHostRequest(
928 requests_pb2.CreateHostRequestReq(
929 host_user_id=user2.id, from_date=today_plus_2, to_date=today_plus_3, text="Test request"
930 )
931 ).host_request_id
932 with session_scope() as session:
933 session.execute(
934 select(Message)
935 .where(Message.conversation_id == host_request_5)
936 .where(Message.message_type == MessageType.chat_created)
937 ).scalar_one().time = now() - timedelta(hours=4)
939 # now some w p33 = 35h
940 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id))
941 assert res.HasField("some")
942 assert res.some.response_time_p33.ToTimedelta() == timedelta(hours=35)
944 with requests_session(token2) as api:
945 # accept host req
946 api.RespondHostRequest(
947 requests_pb2.RespondHostRequestReq(
948 host_request_id=host_request_5,
949 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED,
950 text="Accepting host request",
951 )
952 )
954 with requests_session(token1) as api:
955 # now most w p33 = 34h, p66 = 36h
956 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id))
957 assert res.HasField("most")
958 assert res.most.response_time_p33.ToTimedelta() == timedelta(hours=34)
959 assert res.most.response_time_p66.ToTimedelta() == timedelta(hours=36)
961 with requests_session(token2) as api:
962 # accept host req
963 api.RespondHostRequest(
964 requests_pb2.RespondHostRequestReq(
965 host_request_id=host_request_4,
966 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED,
967 text="Accepting host request",
968 )
969 )
971 with requests_session(token1) as api:
972 # now most w p33 = 4h, p66 = 35h
973 res = api.GetResponseRate(requests_pb2.GetResponseRateReq(user_id=user2.id))
974 assert res.HasField("almost_all")
975 assert res.almost_all.response_time_p33.ToTimedelta() == timedelta(hours=4)
976 assert res.almost_all.response_time_p66.ToTimedelta() == timedelta(hours=35)
979def test_request_notifications(db, push_collector):
980 host, host_token = generate_user(complete_profile=True)
981 surfer, surfer_token = generate_user(complete_profile=True)
983 today_plus_2 = (today() + timedelta(days=2)).isoformat()
984 today_plus_3 = (today() + timedelta(days=3)).isoformat()
986 with requests_session(surfer_token) as api:
987 with mock_notification_email() as mock:
988 hr_id = api.CreateHostRequest(
989 requests_pb2.CreateHostRequestReq(
990 host_user_id=host.id,
991 from_date=today_plus_2,
992 to_date=today_plus_3,
993 text="can i stay plz",
994 )
995 ).host_request_id
997 mock.assert_called_once()
998 e = email_fields(mock)
999 assert e.recipient == host.email
1000 assert "host request" in e.subject.lower()
1001 assert host.name in e.plain
1002 assert host.name in e.html
1003 assert surfer.name in e.plain
1004 assert surfer.name in e.html
1005 assert v2date(today_plus_2, host) in e.plain
1006 assert v2date(today_plus_2, host) in e.html
1007 assert v2date(today_plus_3, host) in e.plain
1008 assert v2date(today_plus_3, host) in e.html
1009 assert "http://localhost:5001/img/thumbnail/" not in e.plain
1010 assert "http://localhost:5001/img/thumbnail/" in e.html
1011 assert f"http://localhost:3000/messages/request/{hr_id}" in e.plain
1012 assert f"http://localhost:3000/messages/request/{hr_id}" in e.html
1014 push_collector.assert_user_has_single_matching(
1015 host.id,
1016 title=f"{surfer.name} sent you a host request",
1017 )
1019 with requests_session(host_token) as api:
1020 with mock_notification_email() as mock:
1021 api.RespondHostRequest(
1022 requests_pb2.RespondHostRequestReq(
1023 host_request_id=hr_id,
1024 status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED,
1025 text="Accepting host request",
1026 )
1027 )
1029 e = email_fields(mock)
1030 assert e.recipient == surfer.email
1031 assert "host request" in e.subject.lower()
1032 assert host.name in e.plain
1033 assert host.name in e.html
1034 assert surfer.name in e.plain
1035 assert surfer.name in e.html
1036 assert v2date(today_plus_2, surfer) in e.plain
1037 assert v2date(today_plus_2, surfer) in e.html
1038 assert v2date(today_plus_3, surfer) in e.plain
1039 assert v2date(today_plus_3, surfer) in e.html
1040 assert "http://localhost:5001/img/thumbnail/" not in e.plain
1041 assert "http://localhost:5001/img/thumbnail/" in e.html
1042 assert f"http://localhost:3000/messages/request/{hr_id}" in e.plain
1043 assert f"http://localhost:3000/messages/request/{hr_id}" in e.html
1045 push_collector.assert_user_has_single_matching(
1046 surfer.id,
1047 title=f"{host.name} accepted your host request",
1048 )