Coverage for app / backend / src / tests / test_references.py: 99%
607 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-03 06:18 +0000
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-03 06:18 +0000
1from datetime import date, datetime, timedelta
2from unittest.mock import patch
4import grpc
5import pytest
6from google.protobuf import empty_pb2
7from sqlalchemy import select, update
8from sqlalchemy.orm import Session
10from couchers.db import session_scope
11from couchers.materialized_views import refresh_materialized_views_rapid
12from couchers.models import (
13 Conversation,
14 FriendRelationship,
15 FriendStatus,
16 HostRequest,
17 HostRequestStatus,
18 Message,
19 MessageType,
20 ModerationObjectType,
21 Reference,
22 ReferenceType,
23 User,
24)
25from couchers.moderation.utils import create_moderation
26from couchers.proto import conversations_pb2, references_pb2, requests_pb2
27from couchers.utils import create_coordinate, now, to_aware_datetime, today
28from tests.fixtures.db import generate_user, make_friends, make_user_block
29from tests.fixtures.misc import PushCollector, email_fields, mock_notification_email
30from tests.fixtures.sessions import account_session, references_session, requests_session
31from tests.test_requests import valid_request_text
34@pytest.fixture(autouse=True)
35def _(testconfig):
36 pass
39def create_host_request(
40 session: Session,
41 surfer_user_id: int,
42 host_user_id: int,
43 host_request_age: timedelta = timedelta(days=15),
44 status: HostRequestStatus = HostRequestStatus.confirmed,
45 host_reason_didnt_meetup: str | None = None,
46 surfer_reason_didnt_meetup: str | None = None,
47) -> int:
48 """
49 Create a host request that's `host_request_age` old
50 """
51 from_date = today() - host_request_age - timedelta(days=2)
52 to_date = today() - host_request_age
53 fake_created = now() - host_request_age - timedelta(days=3)
54 conversation = Conversation()
55 session.add(conversation)
56 session.flush()
58 msg1 = Message(
59 conversation_id=conversation.id,
60 author_id=surfer_user_id,
61 message_type=MessageType.chat_created,
62 )
63 msg1.time = fake_created + timedelta(seconds=1)
64 session.add(msg1)
66 msg2 = Message(
67 conversation_id=conversation.id,
68 author_id=surfer_user_id,
69 text="Hi, I'm requesting to be hosted.",
70 message_type=MessageType.text,
71 )
72 msg2.time = fake_created + timedelta(seconds=2)
73 session.add(msg2)
74 session.flush()
76 moderation_state = create_moderation(
77 session,
78 ModerationObjectType.HOST_REQUEST,
79 conversation.id,
80 surfer_user_id,
81 )
83 host_request = HostRequest(
84 conversation_id=conversation.id,
85 surfer_user_id=surfer_user_id,
86 host_user_id=host_user_id,
87 from_date=from_date,
88 to_date=to_date,
89 status=status,
90 surfer_last_seen_message_id=msg2.id,
91 host_reason_didnt_meetup=host_reason_didnt_meetup,
92 surfer_reason_didnt_meetup=surfer_reason_didnt_meetup,
93 hosting_city="Test City",
94 hosting_location=create_coordinate(0, 0),
95 hosting_radius=10,
96 moderation_state_id=moderation_state.id,
97 )
98 session.add(host_request)
99 session.commit()
100 return host_request.conversation_id
103def create_host_request_by_date(
104 session: Session,
105 surfer_user_id: int,
106 host_user_id: int,
107 from_date: date,
108 to_date: date,
109 status: HostRequestStatus,
110 host_sent_request_reminders: int,
111 last_sent_request_reminder_time: datetime,
112) -> int:
113 conversation = Conversation()
114 session.add(conversation)
115 session.flush()
117 msg1 = Message(
118 conversation_id=conversation.id,
119 author_id=surfer_user_id,
120 message_type=MessageType.chat_created,
121 )
122 msg1.time = from_date + timedelta(seconds=1) # type: ignore[assignment]
123 session.add(msg1)
125 # Unused for now, but every host request must have a message.
126 msg2 = Message(
127 conversation_id=conversation.id,
128 author_id=surfer_user_id,
129 text="Hi, I'm requesting to be hosted.",
130 message_type=MessageType.text,
131 )
132 msg2.time = from_date + timedelta(seconds=2) # type: ignore[assignment]
133 session.add(msg2)
134 session.flush()
136 moderation_state = create_moderation(
137 session,
138 ModerationObjectType.HOST_REQUEST,
139 conversation.id,
140 surfer_user_id,
141 )
143 host_request = HostRequest(
144 conversation_id=conversation.id,
145 surfer_user_id=surfer_user_id,
146 host_user_id=host_user_id,
147 from_date=from_date,
148 to_date=to_date,
149 status=status,
150 hosting_city="Test City",
151 hosting_location=create_coordinate(0, 0),
152 hosting_radius=10,
153 moderation_state_id=moderation_state.id,
154 )
155 host_request.host_sent_request_reminders = host_sent_request_reminders
156 host_request.last_sent_request_reminder_time = last_sent_request_reminder_time
158 session.add(host_request)
159 session.commit()
160 return host_request.conversation_id
163def create_host_reference(
164 session: Session,
165 from_user_id: int,
166 to_user_id: int,
167 reference_age: timedelta,
168 *,
169 surfing: bool = True,
170 host_request_id: int | None = None,
171) -> tuple[int, int]:
172 if host_request_id:
173 actual_host_request_id = host_request_id
174 else:
175 if surfing:
176 actual_host_request_id = host_request_id or create_host_request(
177 session, from_user_id, to_user_id, reference_age + timedelta(days=1)
178 )
179 else:
180 actual_host_request_id = host_request_id or create_host_request(
181 session, to_user_id, from_user_id, reference_age + timedelta(days=1)
182 )
184 host_request = session.execute(
185 select(HostRequest).where(HostRequest.conversation_id == actual_host_request_id)
186 ).scalar_one()
188 if host_request.surfer_user_id == from_user_id:
189 reference_type = ReferenceType.surfed
190 to_user_id = host_request.host_user_id
191 assert from_user_id == host_request.surfer_user_id
192 else:
193 reference_type = ReferenceType.hosted
194 to_user_id = host_request.surfer_user_id
195 assert from_user_id == host_request.host_user_id
197 reference = Reference(
198 from_user_id=from_user_id,
199 to_user_id=to_user_id,
200 host_request_id=host_request.conversation_id,
201 text="Dummy reference",
202 rating=0.5,
203 was_appropriate=True,
204 reference_type=reference_type,
205 )
206 reference.time = now() - reference_age
208 session.add(reference)
209 session.commit()
210 return reference.id, actual_host_request_id
213def create_friend_reference(session: Session, from_user_id: int, to_user_id: int, reference_age: timedelta) -> int:
214 reference = Reference(
215 from_user_id=from_user_id,
216 to_user_id=to_user_id,
217 reference_type=ReferenceType.friend,
218 text="Test friend request",
219 rating=0.4,
220 was_appropriate=True,
221 )
222 reference.time = now() - reference_age
223 session.add(reference)
224 session.commit()
225 return reference.id
228def test_ListPagination(db):
229 user1, token1 = generate_user()
230 user2, token2 = generate_user()
231 user3, token3 = generate_user()
232 user4, token4 = generate_user()
233 user5, token5 = generate_user()
234 user6, token6 = generate_user()
235 user7, token7 = generate_user()
236 user8, token8 = generate_user()
237 user9, token9 = generate_user()
239 with session_scope() as session:
240 # bidirectional references
241 ref2, hr2 = create_host_reference(session, user2.id, user1.id, timedelta(days=16, seconds=110), surfing=True)
242 ref2b, _ = create_host_reference(
243 session, user1.id, user2.id, timedelta(days=16, seconds=100), host_request_id=hr2
244 )
246 ref3, _ = create_host_reference(session, user3.id, user1.id, timedelta(days=16, seconds=90), surfing=False)
247 ref4, _ = create_host_reference(session, user4.id, user1.id, timedelta(days=16, seconds=80), surfing=True)
248 ref4b = create_friend_reference(session, user1.id, user4.id, timedelta(days=16, seconds=70))
250 ref5, hr5 = create_host_reference(session, user5.id, user1.id, timedelta(days=16, seconds=60), surfing=False)
251 ref5b, _ = create_host_reference(
252 session, user1.id, user5.id, timedelta(days=16, seconds=50), host_request_id=hr5
253 )
255 ref6, _ = create_host_reference(session, user6.id, user1.id, timedelta(days=16, seconds=40), surfing=True)
257 ref7 = create_friend_reference(session, user7.id, user1.id, timedelta(days=16, seconds=30))
259 ref8, _ = create_host_reference(session, user8.id, user1.id, timedelta(days=16, seconds=20), surfing=False)
260 ref9, _ = create_host_reference(session, user9.id, user1.id, timedelta(days=16, seconds=10), surfing=False)
262 # should be visible even under 2 weeks
263 ref7b = create_friend_reference(session, user1.id, user7.id, timedelta(days=9))
265 # hidden because it's less than 2 weeks
266 ref6hidden, _ = create_host_reference(session, user6.id, user1.id, timedelta(days=5), surfing=False)
268 # visible because both were written
269 ref8b, hr8 = create_host_reference(session, user8.id, user1.id, timedelta(days=3, seconds=20), surfing=False)
270 ref8c, _ = create_host_reference(
271 session, user1.id, user8.id, timedelta(days=3, seconds=10), host_request_id=hr8
272 )
274 # note that visibility tests don't really test real logic
276 # these check the right refs are in the right requests and appear in the right order (latest first)
278 with references_session(token2) as api:
279 # written by user1
280 res = api.ListReferences(references_pb2.ListReferencesReq(from_user_id=user1.id, page_size=2))
281 assert [ref.reference_id for ref in res.references] == [ref8c, ref7b]
283 res = api.ListReferences(
284 references_pb2.ListReferencesReq(from_user_id=user1.id, page_token=res.next_page_token, page_size=2)
285 )
286 assert [ref.reference_id for ref in res.references] == [ref5b, ref4b]
288 res = api.ListReferences(
289 references_pb2.ListReferencesReq(from_user_id=user1.id, page_token=res.next_page_token, page_size=2)
290 )
291 assert [ref.reference_id for ref in res.references] == [ref2b]
292 assert not res.next_page_token
294 # received by user1
295 res = api.ListReferences(references_pb2.ListReferencesReq(to_user_id=user1.id, page_size=5))
296 assert [ref.reference_id for ref in res.references] == [ref8b, ref9, ref8, ref7, ref6]
298 res = api.ListReferences(
299 references_pb2.ListReferencesReq(to_user_id=user1.id, page_token=res.next_page_token, page_size=5)
300 )
301 assert [ref.reference_id for ref in res.references] == [ref5, ref4, ref3, ref2]
302 assert not res.next_page_token
304 # same thing but with filters
305 res = api.ListReferences(
306 references_pb2.ListReferencesReq(
307 to_user_id=user1.id,
308 reference_type_filter=[
309 references_pb2.REFERENCE_TYPE_HOSTED,
310 references_pb2.REFERENCE_TYPE_SURFED,
311 references_pb2.REFERENCE_TYPE_FRIEND,
312 ],
313 page_size=5,
314 )
315 )
316 assert [ref.reference_id for ref in res.references] == [ref8b, ref9, ref8, ref7, ref6]
318 res = api.ListReferences(
319 references_pb2.ListReferencesReq(
320 to_user_id=user1.id,
321 reference_type_filter=[
322 references_pb2.REFERENCE_TYPE_HOSTED,
323 references_pb2.REFERENCE_TYPE_SURFED,
324 references_pb2.REFERENCE_TYPE_FRIEND,
325 ],
326 page_token=res.next_page_token,
327 page_size=5,
328 )
329 )
330 assert [ref.reference_id for ref in res.references] == [ref5, ref4, ref3, ref2]
331 assert not res.next_page_token
333 # received hosting references
334 res = api.ListReferences(
335 references_pb2.ListReferencesReq(
336 to_user_id=user1.id, reference_type_filter=[references_pb2.REFERENCE_TYPE_HOSTED], page_size=3
337 )
338 )
339 assert [ref.reference_id for ref in res.references] == [ref8b, ref9, ref8]
341 res = api.ListReferences(
342 references_pb2.ListReferencesReq(
343 to_user_id=user1.id,
344 reference_type_filter=[references_pb2.REFERENCE_TYPE_HOSTED],
345 page_token=res.next_page_token,
346 page_size=3,
347 )
348 )
349 assert [ref.reference_id for ref in res.references] == [ref5, ref3]
350 assert not res.next_page_token
352 # written friend references
353 res = api.ListReferences(
354 references_pb2.ListReferencesReq(
355 from_user_id=user1.id, reference_type_filter=[references_pb2.REFERENCE_TYPE_FRIEND]
356 )
357 )
358 assert [ref.reference_id for ref in res.references] == [ref7b, ref4b]
359 assert not res.next_page_token
361 # written surfing references
362 res = api.ListReferences(
363 references_pb2.ListReferencesReq(
364 from_user_id=user1.id, reference_type_filter=[references_pb2.REFERENCE_TYPE_SURFED]
365 )
366 )
367 assert [ref.reference_id for ref in res.references] == [ref8c, ref5b]
368 assert not res.next_page_token
370 with references_session(token7) as api:
371 # need to set at least one of from or to user
372 with pytest.raises(grpc.RpcError) as e:
373 api.ListReferences(
374 references_pb2.ListReferencesReq(reference_type_filter=[references_pb2.REFERENCE_TYPE_SURFED])
375 )
376 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
377 assert e.value.details() == "You need to specify at least one user."
379 with references_session(token5) as api:
380 # from user1 to user2
381 res = api.ListReferences(references_pb2.ListReferencesReq(from_user_id=user1.id, to_user_id=user2.id))
382 assert [ref.reference_id for ref in res.references] == [ref2b]
383 assert not res.next_page_token
385 # from user5 to user1
386 res = api.ListReferences(references_pb2.ListReferencesReq(from_user_id=user5.id, to_user_id=user1.id))
387 assert [ref.reference_id for ref in res.references] == [ref5]
388 assert not res.next_page_token
391def test_ListReference_banned_deleted_users(db):
392 user1, token1 = generate_user()
393 user2, token2 = generate_user()
394 user3, token3 = generate_user()
396 with session_scope() as session:
397 create_friend_reference(session, user2.id, user1.id, timedelta(days=15))
398 create_friend_reference(session, user3.id, user1.id, timedelta(days=16))
399 create_friend_reference(session, user1.id, user2.id, timedelta(days=15))
400 create_friend_reference(session, user1.id, user3.id, timedelta(days=16))
402 with references_session(token1) as api:
403 refs_rec = api.ListReferences(references_pb2.ListReferencesReq(to_user_id=user1.id)).references
404 refs_sent = api.ListReferences(references_pb2.ListReferencesReq(from_user_id=user1.id)).references
405 assert len(refs_rec) == 2
406 assert len(refs_sent) == 2
408 # ban user2
409 with session_scope() as session:
410 session.execute(update(User).where(User.username == user2.username).values(is_banned=True))
412 # reference to and from banned user is hidden
413 with references_session(token1) as api:
414 refs_rec = api.ListReferences(references_pb2.ListReferencesReq(to_user_id=user1.id)).references
415 refs_sent = api.ListReferences(references_pb2.ListReferencesReq(from_user_id=user1.id)).references
416 assert len(refs_rec) == 1
417 assert len(refs_sent) == 1
419 # delete user3
420 with session_scope() as session:
421 session.execute(update(User).where(User.username == user3.username).values(is_deleted=True))
423 # doesn't change; references to and from deleted users remain
424 with references_session(token1) as api:
425 refs_rec = api.ListReferences(references_pb2.ListReferencesReq(to_user_id=user1.id)).references
426 refs_sent = api.ListReferences(references_pb2.ListReferencesReq(from_user_id=user1.id)).references
427 assert len(refs_rec) == 1
428 assert len(refs_sent) == 1
431def test_WriteFriendReference(db):
432 user1, token1 = generate_user()
433 user2, token2 = generate_user()
434 user3, token3 = generate_user()
436 # Make user1 and user2 friends
437 make_friends(user1, user2)
439 with references_session(token1) as api:
440 # can write normal friend reference
441 res = api.WriteFriendReference(
442 references_pb2.WriteFriendReferenceReq(
443 to_user_id=user2.id,
444 text="A test reference",
445 was_appropriate=True,
446 rating=0.5,
447 )
448 )
449 assert res.from_user_id == user1.id
450 assert res.to_user_id == user2.id
451 assert res.reference_type == references_pb2.REFERENCE_TYPE_FRIEND
452 assert res.text == "A test reference"
453 assert now() - timedelta(hours=24) <= to_aware_datetime(res.written_time) <= now()
454 assert not res.host_request_id
456 with references_session(token3) as api:
457 # check it shows up
458 res = api.ListReferences(
459 references_pb2.ListReferencesReq(
460 from_user_id=user1.id, to_user_id=user2.id, reference_type_filter=[references_pb2.REFERENCE_TYPE_FRIEND]
461 )
462 )
463 assert len(res.references) == 1
464 ref = res.references[0]
465 assert ref.from_user_id == user1.id
466 assert ref.to_user_id == user2.id
467 assert ref.reference_type == references_pb2.REFERENCE_TYPE_FRIEND
468 assert ref.text == "A test reference"
469 assert now() - timedelta(hours=24) <= to_aware_datetime(ref.written_time) <= now()
470 assert not ref.host_request_id
472 with references_session(token1) as api:
473 # can't write a second friend reference
474 with pytest.raises(grpc.RpcError) as e:
475 api.WriteFriendReference(
476 references_pb2.WriteFriendReferenceReq(
477 to_user_id=user2.id,
478 text="A test reference",
479 was_appropriate=True,
480 rating=0.5,
481 )
482 )
483 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
484 assert e.value.details() == "Reference already given."
486 with references_session(token2) as api:
487 # can't write a reference about yourself
488 with pytest.raises(grpc.RpcError) as e:
489 api.WriteFriendReference(
490 references_pb2.WriteFriendReferenceReq(
491 to_user_id=user2.id,
492 text="I'm really awesome",
493 was_appropriate=True,
494 rating=1.0,
495 )
496 )
497 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
498 assert e.value.details() == "You can't refer yourself."
501def test_WriteFriendReference_with_empty_text(db):
502 user1, token1 = generate_user()
503 user2, token2 = generate_user()
505 with references_session(token1) as api:
506 with pytest.raises(grpc.RpcError) as e:
507 api.WriteFriendReference(
508 references_pb2.WriteFriendReferenceReq(to_user_id=user2.id, text=" ", was_appropriate=True, rating=0.8)
509 )
510 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
511 assert e.value.details() == "The text of a reference must not be empty"
514def test_WriteFriendReference_with_private_text(db, push_collector: PushCollector):
515 user1, token1 = generate_user()
516 user2, token2 = generate_user()
518 # Make users friends
519 make_friends(user1, user2)
521 with references_session(token1) as api:
522 with patch("couchers.email.queue_email") as mock1:
523 with mock_notification_email() as mock2: 523 ↛ anywhereline 523 didn't jump anywhere: it always raised an exception.
524 api.WriteFriendReference(
525 references_pb2.WriteFriendReferenceReq(
526 to_user_id=user2.id,
527 text="They were nice!",
528 was_appropriate=True,
529 rating=0.6,
530 private_text="A bit of an odd ball, but a nice person nonetheless.",
531 )
532 )
534 # make sure an email was sent to the user receiving the ref as well as the mods
535 assert mock1.call_count == 1
536 assert mock2.call_count == 1
537 e = email_fields(mock2)
538 assert e.subject == f"[TEST] You've received a friend reference from {user1.name}!"
539 assert e.recipient == user2.email
541 push = push_collector.pop_for_user(user2.id, last=True)
542 assert push.content.title == f"New friend reference from {user1.name}"
543 assert push.content.body == "They were nice!"
546def test_WriteFriendReference_requires_friendship(db):
547 """Test that users must be friends to write friend references"""
548 user1, token1 = generate_user()
549 user2, token2 = generate_user()
551 # Try to write friend reference without being friends
552 with references_session(token1) as api:
553 with pytest.raises(grpc.RpcError) as e:
554 api.WriteFriendReference(
555 references_pb2.WriteFriendReferenceReq(
556 to_user_id=user2.id,
557 text="A test reference",
558 was_appropriate=True,
559 rating=0.5,
560 )
561 )
562 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
563 assert e.value.details() == "You can only write friend references for confirmed friends."
565 # Now make them friends
566 make_friends(user1, user2)
568 # Should now be able to write a reference
569 with references_session(token1) as api:
570 res = api.WriteFriendReference(
571 references_pb2.WriteFriendReferenceReq(
572 to_user_id=user2.id,
573 text="A test reference",
574 was_appropriate=True,
575 rating=0.5,
576 )
577 )
578 assert res.from_user_id == user1.id
579 assert res.to_user_id == user2.id
581 # Test the unfriending scenario: delete the friendship
582 with session_scope() as session:
583 # Change the friendship status to cancelled (simulating unfriending)
584 session.execute(
585 update(FriendRelationship)
586 .where(FriendRelationship.from_user_id == user1.id, FriendRelationship.to_user_id == user2.id)
587 .values(status=FriendStatus.cancelled)
588 )
590 # Try to write another friend reference after unfriending
591 # (Note: This assumes user1 didn't already write a reference, or we test with user2 writing to user1)
592 with references_session(token2) as api:
593 with pytest.raises(grpc.RpcError) as e:
594 api.WriteFriendReference(
595 references_pb2.WriteFriendReferenceReq(
596 to_user_id=user1.id,
597 text="Another test reference",
598 was_appropriate=True,
599 rating=0.8,
600 )
601 )
602 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
603 assert e.value.details() == "You can only write friend references for confirmed friends."
606def test_host_request_states_references(db, moderator):
607 user1, token1 = generate_user()
608 user2, token2 = generate_user()
610 with session_scope() as session:
611 # can't write ref
612 hr1 = create_host_request(session, user2.id, user1.id, timedelta(days=10), status=HostRequestStatus.pending)
613 # can write ref
614 hr2 = create_host_request(session, user2.id, user1.id, timedelta(days=10), status=HostRequestStatus.accepted)
615 # can't write ref
616 hr3 = create_host_request(session, user2.id, user1.id, timedelta(days=10), status=HostRequestStatus.rejected)
617 # can write ref
618 hr4 = create_host_request(session, user2.id, user1.id, timedelta(days=10), status=HostRequestStatus.confirmed)
619 # can't write ref
620 hr5 = create_host_request(session, user2.id, user1.id, timedelta(days=10), status=HostRequestStatus.cancelled)
622 # Approve host requests so both participants can see them
623 moderator.approve_host_request(hr1)
624 moderator.approve_host_request(hr2)
625 moderator.approve_host_request(hr3)
626 moderator.approve_host_request(hr4)
627 moderator.approve_host_request(hr5)
629 with references_session(token1) as api:
630 # pending
631 api.WriteHostRequestReference(
632 references_pb2.WriteHostRequestReferenceReq(
633 host_request_id=hr2,
634 text="Should work!",
635 was_appropriate=True,
636 rating=0.9,
637 )
638 )
640 # accepted
641 api.WriteHostRequestReference(
642 references_pb2.WriteHostRequestReferenceReq(
643 host_request_id=hr4,
644 text="Should work!",
645 was_appropriate=True,
646 rating=0.9,
647 )
648 )
650 # rejected
651 with pytest.raises(grpc.RpcError) as e:
652 api.WriteHostRequestReference(
653 references_pb2.WriteHostRequestReferenceReq(
654 host_request_id=hr1,
655 text="Shouldn't work...",
656 was_appropriate=True,
657 rating=0.9,
658 )
659 )
660 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
661 assert e.value.details() == "You can't write a reference for that host request, or it wasn't found."
663 # confirmed
664 with pytest.raises(grpc.RpcError) as e:
665 api.WriteHostRequestReference(
666 references_pb2.WriteHostRequestReferenceReq(
667 host_request_id=hr3,
668 text="Shouldn't work...",
669 was_appropriate=True,
670 rating=0.9,
671 )
672 )
673 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
674 assert e.value.details() == "You can't write a reference for that host request, or it wasn't found."
676 # cancelled
677 with pytest.raises(grpc.RpcError) as e:
678 api.WriteHostRequestReference(
679 references_pb2.WriteHostRequestReferenceReq(
680 host_request_id=hr5,
681 text="Shouldn't work...",
682 was_appropriate=True,
683 rating=0.9,
684 )
685 )
686 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
687 assert e.value.details() == "You can't write a reference for that host request, or it wasn't found."
690def test_WriteHostRequestReference(db, moderator):
691 user1, token1 = generate_user()
692 user2, token2 = generate_user()
693 user3, token3 = generate_user()
694 user4, token4 = generate_user()
696 with session_scope() as session:
697 # too old
698 hr1 = create_host_request(session, user3.id, user1.id, timedelta(days=20))
699 # valid host req, surfer said we didn't show up but we can still write a req
700 hr2 = create_host_request(session, user3.id, user1.id, timedelta(days=10), surfer_reason_didnt_meetup="No show")
701 # valid surfing req
702 hr3 = create_host_request(session, user1.id, user3.id, timedelta(days=7))
703 # not yet complete
704 hr4 = create_host_request(session, user2.id, user1.id, timedelta(days=1), status=HostRequestStatus.pending)
705 # we indicated we didn't meet
706 hr5 = create_host_request(session, user4.id, user1.id, timedelta(days=7), host_reason_didnt_meetup="")
707 # we will indicate we didn't meet
708 hr6 = create_host_request(session, user4.id, user1.id, timedelta(days=8))
710 # Approve host requests so both participants can see them
711 moderator.approve_host_request(hr1)
712 moderator.approve_host_request(hr2)
713 moderator.approve_host_request(hr3)
714 moderator.approve_host_request(hr4)
715 moderator.approve_host_request(hr5)
716 moderator.approve_host_request(hr6)
718 with references_session(token3) as api:
719 # can write for this one
720 api.WriteHostRequestReference(
721 references_pb2.WriteHostRequestReferenceReq(
722 host_request_id=hr3,
723 text="Should work!",
724 was_appropriate=True,
725 rating=0.9,
726 )
727 )
729 with references_session(token1) as api:
730 # can't write reference for a HR that's not yet finished
731 with pytest.raises(grpc.RpcError) as e:
732 api.WriteHostRequestReference(
733 references_pb2.WriteHostRequestReferenceReq(
734 host_request_id=hr4,
735 text="Shouldn't work...",
736 was_appropriate=True,
737 rating=0.9,
738 )
739 )
740 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
741 assert e.value.details() == "You can't write a reference for that host request, or it wasn't found."
743 # can't write reference that's more than 2 weeks old
744 with pytest.raises(grpc.RpcError) as e:
745 api.WriteHostRequestReference(
746 references_pb2.WriteHostRequestReferenceReq(
747 host_request_id=hr1,
748 text="Shouldn't work...",
749 was_appropriate=True,
750 rating=0.9,
751 )
752 )
753 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
754 assert e.value.details() == "You can't write a reference for that host request, or it wasn't found."
756 # can write for this one
757 api.WriteHostRequestReference(
758 references_pb2.WriteHostRequestReferenceReq(
759 host_request_id=hr2,
760 text="Should work!",
761 was_appropriate=True,
762 rating=0.9,
763 )
764 )
766 # but can't write a second one for the same one
767 with pytest.raises(grpc.RpcError) as e:
768 api.WriteHostRequestReference(
769 references_pb2.WriteHostRequestReferenceReq(
770 host_request_id=hr2,
771 text="Shouldn't work...",
772 was_appropriate=True,
773 rating=0.9,
774 )
775 )
776 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
777 assert e.value.details() == "Reference already given."
779 # can write for this one too
780 api.WriteHostRequestReference(
781 references_pb2.WriteHostRequestReferenceReq(
782 host_request_id=hr3,
783 text="Should work!",
784 was_appropriate=True,
785 rating=0.9,
786 )
787 )
789 # can't write reference for a HR that we indicated we didn't show up
790 with pytest.raises(grpc.RpcError) as e:
791 api.WriteHostRequestReference(
792 references_pb2.WriteHostRequestReferenceReq(
793 host_request_id=hr5,
794 text="Shouldn't work...",
795 was_appropriate=True,
796 rating=0.9,
797 )
798 )
799 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
800 assert (
801 e.value.details()
802 == "You can't write a reference for that host request because you indicated that you didn't meet up."
803 )
805 # can't write reference for a HR that we indicate we didn't show up for
806 api.HostRequestIndicateDidntMeetup(
807 references_pb2.HostRequestIndicateDidntMeetupReq(
808 host_request_id=hr6,
809 reason_didnt_meetup="No clue?",
810 )
811 )
813 with pytest.raises(grpc.RpcError) as e:
814 api.WriteHostRequestReference(
815 references_pb2.WriteHostRequestReferenceReq(
816 host_request_id=hr6,
817 text="Shouldn't work...",
818 was_appropriate=True,
819 rating=0.9,
820 )
821 )
822 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
823 assert (
824 e.value.details()
825 == "You can't write a reference for that host request because you indicated that you didn't meet up."
826 )
828 with references_session(token4) as api:
829 # they can still write one
830 api.WriteHostRequestReference(
831 references_pb2.WriteHostRequestReferenceReq(
832 host_request_id=hr6,
833 text="Should work!",
834 was_appropriate=True,
835 rating=0.9,
836 )
837 )
840def test_WriteHostRequestReference_private_text(db, push_collector: PushCollector):
841 user1, token1 = generate_user()
842 user2, token2 = generate_user()
844 with session_scope() as session:
845 hr = create_host_request(session, user1.id, user2.id, timedelta(days=10))
847 with references_session(token1) as api:
848 with patch("couchers.email.queue_email") as mock1:
849 with mock_notification_email() as mock2: 849 ↛ anywhereline 849 didn't jump anywhere: it always raised an exception.
850 api.WriteHostRequestReference(
851 references_pb2.WriteHostRequestReferenceReq(
852 host_request_id=hr,
853 text="Should work!",
854 was_appropriate=True,
855 rating=0.9,
856 private_text="Something",
857 )
858 )
860 # make sure an email was sent to the user receiving the ref as well as the mods
861 assert mock1.call_count == 1
862 assert mock2.call_count == 1
864 e = email_fields(mock2)
865 assert e.subject == f"[TEST] You've received a reference from {user1.name}!"
866 assert e.recipient == user2.email
868 push = push_collector.pop_for_user(user2.id, last=True)
869 assert push.content.title == f"New reference from {user1.name}"
870 assert push.content.body == f"{user1.name} left you a reference, now it's your turn to write theirs!"
873def test_GetHostRequestReferenceStatus(db, moderator):
874 user1, token1 = generate_user()
875 user2, token2 = generate_user()
877 # user1 writes; RPC returns has_given True
878 with session_scope() as session:
879 hr1 = create_host_request(session, user1.id, user2.id, timedelta(days=7))
880 moderator.approve_host_request(hr1)
881 with references_session(token1) as api:
882 api.WriteHostRequestReference(
883 references_pb2.WriteHostRequestReferenceReq(
884 host_request_id=hr1, text="Great stay!", was_appropriate=True, rating=0.9
885 )
886 )
887 res = api.GetHostRequestReferenceStatus(references_pb2.GetHostRequestReferenceStatusReq(host_request_id=hr1))
888 assert res.has_given is True
890 # false: no reference written yet
891 with session_scope() as session:
892 hr2 = create_host_request(session, user1.id, user2.id, timedelta(days=7))
893 moderator.approve_host_request(hr2)
894 with references_session(token1) as api:
895 res = api.GetHostRequestReferenceStatus(references_pb2.GetHostRequestReferenceStatusReq(host_request_id=hr2))
896 assert res.has_given is False
898 # false: other user wrote a reference
899 with session_scope() as session:
900 hr3 = create_host_request(session, user1.id, user2.id, timedelta(days=7))
901 moderator.approve_host_request(hr3)
902 with references_session(token2) as api:
903 api.WriteHostRequestReference(
904 references_pb2.WriteHostRequestReferenceReq(
905 host_request_id=hr3, text="Lovely guest!", was_appropriate=True, rating=0.95
906 )
907 )
908 with references_session(token1) as api:
909 res = api.GetHostRequestReferenceStatus(references_pb2.GetHostRequestReferenceStatusReq(host_request_id=hr3))
910 assert res.has_given is False
912 # false: nonexistent host request id
913 with references_session(token1) as api:
914 res = api.GetHostRequestReferenceStatus(references_pb2.GetHostRequestReferenceStatusReq(host_request_id=999999))
915 assert res.has_given is False
917 # Additional status flags
918 with session_scope() as session:
919 # expired (too old)
920 hr_expired = create_host_request(session, user2.id, user1.id, timedelta(days=20))
921 # current user (host) indicated didn't meet up
922 hr_didnt_stay_host = create_host_request(
923 session, user2.id, user1.id, timedelta(days=10), host_reason_didnt_meetup=""
924 )
925 # other user (surfer) indicated didn't meet up
926 hr_other_didnt_stay = create_host_request(
927 session, user2.id, user1.id, timedelta(days=10), surfer_reason_didnt_meetup="No show"
928 )
930 moderator.approve_host_request(hr_expired)
931 moderator.approve_host_request(hr_didnt_stay_host)
932 moderator.approve_host_request(hr_other_didnt_stay)
934 # expired: is_expired true, can_write false, didnt_stay false
935 with references_session(token1) as api:
936 res = api.GetHostRequestReferenceStatus(
937 references_pb2.GetHostRequestReferenceStatusReq(host_request_id=hr_expired)
938 )
939 assert res.has_given is False
940 assert res.is_expired is True
941 assert res.can_write is False
942 assert res.didnt_stay is False
944 # current user indicated didn't meet up: didnt_stay true, can_write false, not expired
945 with references_session(token1) as api:
946 res = api.GetHostRequestReferenceStatus(
947 references_pb2.GetHostRequestReferenceStatusReq(host_request_id=hr_didnt_stay_host)
948 )
949 assert res.has_given is False
950 assert res.is_expired is False
951 assert res.didnt_stay is True
952 assert res.can_write is False
954 # other party indicated didn't meet up: didnt_stay false, can_write true (within window), not expired
955 with references_session(token1) as api:
956 res = api.GetHostRequestReferenceStatus(
957 references_pb2.GetHostRequestReferenceStatusReq(host_request_id=hr_other_didnt_stay)
958 )
959 assert res.has_given is False
960 assert res.is_expired is False
961 assert res.didnt_stay is False
962 assert res.can_write is True
965def test_AvailableWriteReferences_and_ListPendingReferencesToWrite(db, moderator):
966 user1, token1 = generate_user()
967 user2, token2 = generate_user()
968 user3, token3 = generate_user()
969 user4, token4 = generate_user()
970 user5, token5 = generate_user(delete_user=True)
971 user6, token6 = generate_user()
972 user7, token7 = generate_user()
973 user8, token8 = generate_user()
974 user9, token9 = generate_user()
975 user10, token10 = generate_user()
976 user11, token11 = generate_user()
977 make_user_block(user1, user6)
978 make_user_block(user7, user1)
980 with session_scope() as session:
981 # too old
982 hr1 = create_host_request(session, user3.id, user1.id, timedelta(days=20))
984 # already wrote friend ref to user3
985 create_friend_reference(session, user1.id, user3.id, timedelta(days=15, seconds=70))
987 # already given
988 _, hr2 = create_host_reference(session, user2.id, user1.id, timedelta(days=10, seconds=110), surfing=True)
989 create_host_reference(session, user1.id, user2.id, timedelta(days=10, seconds=100), host_request_id=hr2)
991 # valid hosted
992 hr3 = create_host_request(session, user3.id, user1.id, timedelta(days=8))
994 # valid surfed
995 hr4 = create_host_request(session, user1.id, user4.id, timedelta(days=5))
997 # not yet complete
998 hr5 = create_host_request(session, user2.id, user1.id, timedelta(days=2), status=HostRequestStatus.pending)
1000 # already wrote friend ref to user2
1001 create_friend_reference(session, user1.id, user2.id, timedelta(days=1))
1003 # user5 deleted, reference won't show up as pending
1004 hr_user5 = create_host_request(session, user1.id, user5.id, timedelta(days=5))
1006 # user6 blocked, reference won't show up as pending
1007 hr_user6 = create_host_request(session, user1.id, user6.id, timedelta(days=5))
1009 # user7 blocking, reference won't show up as pending
1010 hr_user7 = create_host_request(session, user1.id, user7.id, timedelta(days=5))
1012 # hosted but we indicated we didn't meet up, no reason; should not show up
1013 hr_user8 = create_host_request(session, user8.id, user1.id, timedelta(days=11), host_reason_didnt_meetup="")
1015 # surfed but we indicated we didn't meet up, has reason; should not show up
1016 hr_user9 = create_host_request(
1017 session, user1.id, user9.id, timedelta(days=10), surfer_reason_didnt_meetup="They never showed up!"
1018 )
1020 # surfed but they indicated we didn't meet up, no reason; should show up
1021 hr6 = create_host_request(session, user1.id, user10.id, timedelta(days=4), host_reason_didnt_meetup="")
1023 # hosted but they indicated we didn't meet up, has reason; should show up
1024 hr7 = create_host_request(
1025 session, user11.id, user1.id, timedelta(days=3), surfer_reason_didnt_meetup="They never showed up!!"
1026 )
1028 # Approve all host requests so both participants can see them
1029 moderator.approve_host_request(hr1)
1030 moderator.approve_host_request(hr2)
1031 moderator.approve_host_request(hr3)
1032 moderator.approve_host_request(hr4)
1033 moderator.approve_host_request(hr5)
1034 moderator.approve_host_request(hr_user5)
1035 moderator.approve_host_request(hr_user6)
1036 moderator.approve_host_request(hr_user7)
1037 moderator.approve_host_request(hr_user8)
1038 moderator.approve_host_request(hr_user9)
1039 moderator.approve_host_request(hr6)
1040 moderator.approve_host_request(hr7)
1042 refresh_materialized_views_rapid(empty_pb2.Empty())
1044 with references_session(token1) as api:
1045 # can't write reference for invisible user
1046 with pytest.raises(grpc.RpcError) as e:
1047 api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user5.id))
1048 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1049 assert e.value.details() == "Couldn't find that user."
1051 # can't write reference for blocking user
1052 with pytest.raises(grpc.RpcError) as e:
1053 api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user7.id))
1054 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1055 assert e.value.details() == "Couldn't find that user."
1057 # can't write reference for blocked user
1058 with pytest.raises(grpc.RpcError) as e:
1059 api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user6.id))
1060 assert e.value.code() == grpc.StatusCode.NOT_FOUND
1061 assert e.value.details() == "Couldn't find that user."
1063 # can't write anything to myself
1064 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user1.id))
1065 assert not res.can_write_friend_reference
1066 assert len(res.available_write_references) == 0
1068 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user2.id))
1069 # can't write friend ref to user2
1070 assert not res.can_write_friend_reference
1071 # none we can write for user2
1072 assert len(res.available_write_references) == 0
1074 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user3.id))
1075 # can't write friend ref to user3
1076 assert not res.can_write_friend_reference
1077 # can write one reference because we hosted user3
1078 assert len(res.available_write_references) == 1
1079 w = res.available_write_references[0]
1080 assert w.host_request_id == hr3
1081 assert w.reference_type == references_pb2.REFERENCE_TYPE_HOSTED
1082 assert now() + timedelta(days=6) <= to_aware_datetime(w.time_expires) <= now() + timedelta(days=7)
1084 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user4.id))
1085 # can write friend ref to user4
1086 assert res.can_write_friend_reference
1087 # can write one reference because we surfed with user4
1088 assert len(res.available_write_references) == 1
1089 w = res.available_write_references[0]
1090 assert w.host_request_id == hr4
1091 assert w.reference_type == references_pb2.REFERENCE_TYPE_SURFED
1092 assert now() + timedelta(days=9) <= to_aware_datetime(w.time_expires) <= now() + timedelta(days=10)
1094 # can't write a req if we indicated we didn't meet up
1095 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user8.id))
1096 assert len(res.available_write_references) == 0
1097 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user9.id))
1098 assert len(res.available_write_references) == 0
1100 # can still write ref if the other person indicated we didn't meet up
1101 # surfed with them
1102 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user10.id))
1103 assert len(res.available_write_references) == 1
1104 w = res.available_write_references[0]
1105 assert w.host_request_id == hr6
1106 assert w.reference_type == references_pb2.REFERENCE_TYPE_SURFED
1107 assert now() + timedelta(days=10) <= to_aware_datetime(w.time_expires) <= now() + timedelta(days=11)
1108 # hosted them
1109 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user11.id))
1110 assert len(res.available_write_references) == 1
1111 w = res.available_write_references[0]
1112 assert w.host_request_id == hr7
1113 assert w.reference_type == references_pb2.REFERENCE_TYPE_HOSTED
1114 assert now() + timedelta(days=11) <= to_aware_datetime(w.time_expires) <= now() + timedelta(days=12)
1116 # finally check the general list
1117 res = api.ListPendingReferencesToWrite(empty_pb2.Empty())
1118 assert len(res.pending_references) == 4
1119 w = res.pending_references[0]
1120 assert w.host_request_id == hr3
1121 assert w.reference_type == references_pb2.REFERENCE_TYPE_HOSTED
1122 assert now() + timedelta(days=6) <= to_aware_datetime(w.time_expires) <= now() + timedelta(days=7)
1123 w = res.pending_references[1]
1124 assert w.host_request_id == hr4
1125 assert w.reference_type == references_pb2.REFERENCE_TYPE_SURFED
1126 assert now() + timedelta(days=9) <= to_aware_datetime(w.time_expires) <= now() + timedelta(days=10)
1127 w = res.pending_references[2]
1128 assert w.host_request_id == hr6
1129 assert w.reference_type == references_pb2.REFERENCE_TYPE_SURFED
1130 assert now() + timedelta(days=10) <= to_aware_datetime(w.time_expires) <= now() + timedelta(days=11)
1131 w = res.pending_references[3]
1132 assert w.host_request_id == hr7
1133 assert w.reference_type == references_pb2.REFERENCE_TYPE_HOSTED
1134 assert now() + timedelta(days=11) <= to_aware_datetime(w.time_expires) <= now() + timedelta(days=12)
1136 with account_session(token1) as account:
1137 reminders = account.GetReminders(empty_pb2.Empty()).reminders
1138 assert [reminder.WhichOneof("reminder") for reminder in reminders] == [
1139 "write_reference_reminder",
1140 "write_reference_reminder",
1141 "write_reference_reminder",
1142 "write_reference_reminder",
1143 "complete_verification_reminder",
1144 ]
1145 assert reminders[0].write_reference_reminder.host_request_id == hr3
1146 assert reminders[0].write_reference_reminder.reference_type == references_pb2.REFERENCE_TYPE_HOSTED
1147 assert reminders[0].write_reference_reminder.other_user.user_id == user3.id
1148 assert reminders[1].write_reference_reminder.host_request_id == hr4
1149 assert reminders[1].write_reference_reminder.reference_type == references_pb2.REFERENCE_TYPE_SURFED
1150 assert reminders[1].write_reference_reminder.other_user.user_id == user4.id
1151 assert reminders[2].write_reference_reminder.host_request_id == hr6
1152 assert reminders[2].write_reference_reminder.reference_type == references_pb2.REFERENCE_TYPE_SURFED
1153 assert reminders[2].write_reference_reminder.other_user.user_id == user10.id
1154 assert reminders[3].write_reference_reminder.host_request_id == hr7
1155 assert reminders[3].write_reference_reminder.reference_type == references_pb2.REFERENCE_TYPE_HOSTED
1156 assert reminders[3].write_reference_reminder.other_user.user_id == user11.id
1159@pytest.mark.parametrize("hs", ["host", "surfer"])
1160def test_regression_disappearing_refs(db, hs, moderator):
1161 """
1162 Roughly the reproduction steps are:
1163 * Send a host request, then have both host and surfer accept
1164 * Wait for it to elapse (or hack it with SQL like what you told me to do)
1165 * On the surfer account, leave a reference
1166 * Then on the host account, the option to leave a reference is then not available
1167 """
1168 user1, token1 = generate_user()
1169 user2, token2 = generate_user()
1170 req_start = (today() + timedelta(days=2)).isoformat()
1171 req_end = (today() + timedelta(days=3)).isoformat()
1172 with requests_session(token1) as api:
1173 res = api.CreateHostRequest(
1174 requests_pb2.CreateHostRequestReq(
1175 host_user_id=user2.id, from_date=req_start, to_date=req_end, text=valid_request_text()
1176 )
1177 )
1178 host_request_id = res.host_request_id
1180 moderator.approve_host_request(host_request_id)
1182 assert (
1183 api.ListHostRequests(requests_pb2.ListHostRequestsReq(only_sent=True))
1184 .host_requests[0]
1185 .latest_message.text.text
1186 == valid_request_text()
1187 )
1189 with requests_session(token2) as api:
1190 api.RespondHostRequest(
1191 requests_pb2.RespondHostRequestReq(
1192 host_request_id=host_request_id, status=conversations_pb2.HOST_REQUEST_STATUS_ACCEPTED
1193 )
1194 )
1196 with requests_session(token1) as api:
1197 api.RespondHostRequest(
1198 requests_pb2.RespondHostRequestReq(
1199 host_request_id=host_request_id, status=conversations_pb2.HOST_REQUEST_STATUS_CONFIRMED
1200 )
1201 )
1203 refresh_materialized_views_rapid(empty_pb2.Empty())
1205 with references_session(token1) as api:
1206 res = api.ListPendingReferencesToWrite(empty_pb2.Empty())
1207 assert len(res.pending_references) == 0
1208 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user2.id))
1209 assert len(res.available_write_references) == 0
1211 with references_session(token2) as api:
1212 res = api.ListPendingReferencesToWrite(empty_pb2.Empty())
1213 assert len(res.pending_references) == 0
1214 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user1.id))
1215 assert len(res.available_write_references) == 0
1217 # hack the time backwards
1218 hack_req_start = today() - timedelta(days=10) + timedelta(days=2)
1219 hack_req_end = today() - timedelta(days=10) + timedelta(days=3)
1220 with session_scope() as session:
1221 host_request = session.execute(select(HostRequest)).scalar_one()
1222 assert host_request.conversation_id == host_request_id
1223 host_request.from_date = hack_req_start
1224 host_request.to_date = hack_req_end
1226 with references_session(token1) as api:
1227 res = api.ListPendingReferencesToWrite(empty_pb2.Empty())
1228 assert len(res.pending_references) == 1
1229 assert res.pending_references[0].host_request_id == host_request_id
1230 assert res.pending_references[0].reference_type == references_pb2.REFERENCE_TYPE_SURFED
1232 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user2.id))
1233 assert len(res.available_write_references) == 1
1234 assert res.available_write_references[0].host_request_id == host_request_id
1235 assert res.available_write_references[0].reference_type == references_pb2.REFERENCE_TYPE_SURFED
1237 with references_session(token2) as api:
1238 res = api.ListPendingReferencesToWrite(empty_pb2.Empty())
1239 assert len(res.pending_references) == 1
1240 assert res.pending_references[0].host_request_id == host_request_id
1241 assert res.pending_references[0].reference_type == references_pb2.REFERENCE_TYPE_HOSTED
1243 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user1.id))
1244 assert len(res.available_write_references) == 1
1245 assert res.available_write_references[0].host_request_id == host_request_id
1246 assert res.available_write_references[0].reference_type == references_pb2.REFERENCE_TYPE_HOSTED
1248 if hs == "host":
1249 with references_session(token2) as api:
1250 api.WriteHostRequestReference(
1251 references_pb2.WriteHostRequestReferenceReq(
1252 host_request_id=host_request_id,
1253 text="Good stuff",
1254 was_appropriate=True,
1255 rating=0.86,
1256 )
1257 )
1259 with references_session(token2) as api:
1260 res = api.ListPendingReferencesToWrite(empty_pb2.Empty())
1261 assert len(res.pending_references) == 0
1263 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user2.id))
1264 assert len(res.available_write_references) == 0
1266 with references_session(token1) as api:
1267 res = api.ListPendingReferencesToWrite(empty_pb2.Empty())
1268 assert len(res.pending_references) == 1
1269 assert res.pending_references[0].host_request_id == host_request_id
1270 assert res.pending_references[0].reference_type == references_pb2.REFERENCE_TYPE_SURFED
1272 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user2.id))
1273 assert len(res.available_write_references) == 1
1274 assert res.available_write_references[0].host_request_id == host_request_id
1275 assert res.available_write_references[0].reference_type == references_pb2.REFERENCE_TYPE_SURFED
1276 else:
1277 with references_session(token1) as api:
1278 api.WriteHostRequestReference(
1279 references_pb2.WriteHostRequestReferenceReq(
1280 host_request_id=host_request_id,
1281 text="Good stuff",
1282 was_appropriate=True,
1283 rating=0.86,
1284 )
1285 )
1287 with references_session(token1) as api:
1288 res = api.ListPendingReferencesToWrite(empty_pb2.Empty())
1289 assert len(res.pending_references) == 0
1291 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user1.id))
1292 assert len(res.available_write_references) == 0
1294 with references_session(token2) as api:
1295 res = api.ListPendingReferencesToWrite(empty_pb2.Empty())
1296 assert len(res.pending_references) == 1
1297 assert res.pending_references[0].host_request_id == host_request_id
1298 assert res.pending_references[0].reference_type == references_pb2.REFERENCE_TYPE_HOSTED
1300 res = api.AvailableWriteReferences(references_pb2.AvailableWriteReferencesReq(to_user_id=user1.id))
1301 assert len(res.available_write_references) == 1
1302 assert res.available_write_references[0].host_request_id == host_request_id
1303 assert res.available_write_references[0].reference_type == references_pb2.REFERENCE_TYPE_HOSTED