Coverage for src/tests/test_events.py: 100%
1159 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-12-02 20:27 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2024-12-02 20:27 +0000
1from datetime import timedelta
3import grpc
4import pytest
5from google.protobuf import wrappers_pb2
6from psycopg2.extras import DateTimeTZRange
7from sqlalchemy.sql.expression import update
9from couchers import errors
10from couchers.db import session_scope
11from couchers.models import EventOccurrence
12from couchers.tasks import enforce_community_memberships
13from couchers.utils import Timestamp_from_datetime, now, to_aware_datetime
14from proto import admin_pb2, events_pb2, threads_pb2
15from tests.test_communities import create_community, create_group
16from tests.test_fixtures import ( # noqa
17 db,
18 email_fields,
19 events_session,
20 generate_user,
21 mock_notification_email,
22 real_admin_session,
23 testconfig,
24 threads_session,
25)
28@pytest.fixture(autouse=True)
29def _(testconfig):
30 pass
33def test_CreateEvent(db):
34 # test cases:
35 # can create event
36 # cannot create event with missing details
37 # can create online event
38 # can create in person event
39 # can't create event that starts in the past
40 # can create in different timezones
42 # event creator
43 user1, token1 = generate_user()
44 # community moderator
45 user2, token2 = generate_user()
46 # third party
47 user3, token3 = generate_user()
49 with session_scope() as session:
50 c_id = create_community(session, 0, 2, "Community", [user2], [], None).id
52 time_before = now()
53 start_time = now() + timedelta(hours=2)
54 end_time = start_time + timedelta(hours=3)
56 with events_session(token1) as api:
57 # in person event
58 res = api.CreateEvent(
59 events_pb2.CreateEventReq(
60 title="Dummy Title",
61 content="Dummy content.",
62 photo_key=None,
63 offline_information=events_pb2.OfflineEventInformation(
64 address="Near Null Island",
65 lat=0.1,
66 lng=0.2,
67 ),
68 start_time=Timestamp_from_datetime(start_time),
69 end_time=Timestamp_from_datetime(end_time),
70 timezone="UTC",
71 )
72 )
74 assert res.is_next
75 assert res.title == "Dummy Title"
76 assert res.slug == "dummy-title"
77 assert res.content == "Dummy content."
78 assert not res.photo_url
79 assert res.WhichOneof("mode") == "offline_information"
80 assert res.offline_information.lat == 0.1
81 assert res.offline_information.lng == 0.2
82 assert res.offline_information.address == "Near Null Island"
83 assert time_before <= to_aware_datetime(res.created) <= now()
84 assert time_before <= to_aware_datetime(res.last_edited) <= now()
85 assert res.creator_user_id == user1.id
86 assert to_aware_datetime(res.start_time) == start_time
87 assert to_aware_datetime(res.end_time) == end_time
88 # assert res.timezone == "UTC"
89 assert res.start_time_display
90 assert res.end_time_display
91 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_GOING
92 assert res.organizer
93 assert res.subscriber
94 assert res.going_count == 1
95 assert res.maybe_count == 0
96 assert res.organizer_count == 1
97 assert res.subscriber_count == 1
98 assert res.owner_user_id == user1.id
99 assert not res.owner_community_id
100 assert not res.owner_group_id
101 assert res.thread.thread_id
102 assert res.can_edit
103 assert not res.can_moderate
105 event_id = res.event_id
107 with events_session(token2) as api:
108 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
110 assert res.is_next
111 assert res.title == "Dummy Title"
112 assert res.slug == "dummy-title"
113 assert res.content == "Dummy content."
114 assert not res.photo_url
115 assert res.WhichOneof("mode") == "offline_information"
116 assert res.offline_information.lat == 0.1
117 assert res.offline_information.lng == 0.2
118 assert res.offline_information.address == "Near Null Island"
119 assert time_before <= to_aware_datetime(res.created) <= now()
120 assert time_before <= to_aware_datetime(res.last_edited) <= now()
121 assert res.creator_user_id == user1.id
122 assert to_aware_datetime(res.start_time) == start_time
123 assert to_aware_datetime(res.end_time) == end_time
124 # assert res.timezone == "UTC"
125 assert res.start_time_display
126 assert res.end_time_display
127 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_NOT_GOING
128 assert not res.organizer
129 assert not res.subscriber
130 assert res.going_count == 1
131 assert res.maybe_count == 0
132 assert res.organizer_count == 1
133 assert res.subscriber_count == 1
134 assert res.owner_user_id == user1.id
135 assert not res.owner_community_id
136 assert not res.owner_group_id
137 assert res.thread.thread_id
138 assert res.can_edit
139 assert res.can_moderate
141 with events_session(token3) as api:
142 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
144 assert res.is_next
145 assert res.title == "Dummy Title"
146 assert res.slug == "dummy-title"
147 assert res.content == "Dummy content."
148 assert not res.photo_url
149 assert res.WhichOneof("mode") == "offline_information"
150 assert res.offline_information.lat == 0.1
151 assert res.offline_information.lng == 0.2
152 assert res.offline_information.address == "Near Null Island"
153 assert time_before <= to_aware_datetime(res.created) <= now()
154 assert time_before <= to_aware_datetime(res.last_edited) <= now()
155 assert res.creator_user_id == user1.id
156 assert to_aware_datetime(res.start_time) == start_time
157 assert to_aware_datetime(res.end_time) == end_time
158 # assert res.timezone == "UTC"
159 assert res.start_time_display
160 assert res.end_time_display
161 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_NOT_GOING
162 assert not res.organizer
163 assert not res.subscriber
164 assert res.going_count == 1
165 assert res.maybe_count == 0
166 assert res.organizer_count == 1
167 assert res.subscriber_count == 1
168 assert res.owner_user_id == user1.id
169 assert not res.owner_community_id
170 assert not res.owner_group_id
171 assert res.thread.thread_id
172 assert not res.can_edit
173 assert not res.can_moderate
175 with events_session(token1) as api:
176 # online only event
177 res = api.CreateEvent(
178 events_pb2.CreateEventReq(
179 title="Dummy Title",
180 content="Dummy content.",
181 photo_key=None,
182 online_information=events_pb2.OnlineEventInformation(
183 link="https://couchers.org/meet/",
184 ),
185 parent_community_id=c_id,
186 start_time=Timestamp_from_datetime(start_time),
187 end_time=Timestamp_from_datetime(end_time),
188 timezone="UTC",
189 )
190 )
192 assert res.is_next
193 assert res.title == "Dummy Title"
194 assert res.slug == "dummy-title"
195 assert res.content == "Dummy content."
196 assert not res.photo_url
197 assert res.WhichOneof("mode") == "online_information"
198 assert res.online_information.link == "https://couchers.org/meet/"
199 assert time_before <= to_aware_datetime(res.created) <= now()
200 assert time_before <= to_aware_datetime(res.last_edited) <= now()
201 assert res.creator_user_id == user1.id
202 assert to_aware_datetime(res.start_time) == start_time
203 assert to_aware_datetime(res.end_time) == end_time
204 # assert res.timezone == "UTC"
205 assert res.start_time_display
206 assert res.end_time_display
207 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_GOING
208 assert res.organizer
209 assert res.subscriber
210 assert res.going_count == 1
211 assert res.maybe_count == 0
212 assert res.organizer_count == 1
213 assert res.subscriber_count == 1
214 assert res.owner_user_id == user1.id
215 assert not res.owner_community_id
216 assert not res.owner_group_id
217 assert res.thread.thread_id
218 assert res.can_edit
219 assert not res.can_moderate
221 event_id = res.event_id
223 with events_session(token2) as api:
224 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
226 assert res.is_next
227 assert res.title == "Dummy Title"
228 assert res.slug == "dummy-title"
229 assert res.content == "Dummy content."
230 assert not res.photo_url
231 assert res.WhichOneof("mode") == "online_information"
232 assert res.online_information.link == "https://couchers.org/meet/"
233 assert time_before <= to_aware_datetime(res.created) <= now()
234 assert time_before <= to_aware_datetime(res.last_edited) <= now()
235 assert res.creator_user_id == user1.id
236 assert to_aware_datetime(res.start_time) == start_time
237 assert to_aware_datetime(res.end_time) == end_time
238 # assert res.timezone == "UTC"
239 assert res.start_time_display
240 assert res.end_time_display
241 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_NOT_GOING
242 assert not res.organizer
243 assert not res.subscriber
244 assert res.going_count == 1
245 assert res.maybe_count == 0
246 assert res.organizer_count == 1
247 assert res.subscriber_count == 1
248 assert res.owner_user_id == user1.id
249 assert not res.owner_community_id
250 assert not res.owner_group_id
251 assert res.thread.thread_id
252 assert res.can_edit
253 assert res.can_moderate
255 with events_session(token3) as api:
256 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
258 assert res.is_next
259 assert res.title == "Dummy Title"
260 assert res.slug == "dummy-title"
261 assert res.content == "Dummy content."
262 assert not res.photo_url
263 assert res.WhichOneof("mode") == "online_information"
264 assert res.online_information.link == "https://couchers.org/meet/"
265 assert time_before <= to_aware_datetime(res.created) <= now()
266 assert time_before <= to_aware_datetime(res.last_edited) <= now()
267 assert res.creator_user_id == user1.id
268 assert to_aware_datetime(res.start_time) == start_time
269 assert to_aware_datetime(res.end_time) == end_time
270 # assert res.timezone == "UTC"
271 assert res.start_time_display
272 assert res.end_time_display
273 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_NOT_GOING
274 assert not res.organizer
275 assert not res.subscriber
276 assert res.going_count == 1
277 assert res.maybe_count == 0
278 assert res.organizer_count == 1
279 assert res.subscriber_count == 1
280 assert res.owner_user_id == user1.id
281 assert not res.owner_community_id
282 assert not res.owner_group_id
283 assert res.thread.thread_id
284 assert not res.can_edit
285 assert not res.can_moderate
287 with events_session(token1) as api:
288 with pytest.raises(grpc.RpcError) as e:
289 api.CreateEvent(
290 events_pb2.CreateEventReq(
291 title="Dummy Title",
292 content="Dummy content.",
293 photo_key=None,
294 online_information=events_pb2.OnlineEventInformation(
295 link="https://couchers.org/meet/",
296 ),
297 start_time=Timestamp_from_datetime(start_time),
298 end_time=Timestamp_from_datetime(end_time),
299 timezone="UTC",
300 )
301 )
302 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
303 assert e.value.details() == errors.ONLINE_EVENT_MISSING_PARENT_COMMUNITY
305 with pytest.raises(grpc.RpcError) as e:
306 api.CreateEvent(
307 events_pb2.CreateEventReq(
308 # title="Dummy Title",
309 content="Dummy content.",
310 photo_key=None,
311 offline_information=events_pb2.OfflineEventInformation(
312 address="Near Null Island",
313 lat=0.1,
314 lng=0.1,
315 ),
316 start_time=Timestamp_from_datetime(start_time),
317 end_time=Timestamp_from_datetime(end_time),
318 timezone="UTC",
319 )
320 )
321 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
322 assert e.value.details() == errors.MISSING_EVENT_TITLE
324 with pytest.raises(grpc.RpcError) as e:
325 api.CreateEvent(
326 events_pb2.CreateEventReq(
327 title="Dummy Title",
328 # content="Dummy content.",
329 photo_key=None,
330 offline_information=events_pb2.OfflineEventInformation(
331 address="Near Null Island",
332 lat=0.1,
333 lng=0.1,
334 ),
335 start_time=Timestamp_from_datetime(start_time),
336 end_time=Timestamp_from_datetime(end_time),
337 timezone="UTC",
338 )
339 )
340 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
341 assert e.value.details() == errors.MISSING_EVENT_CONTENT
343 with pytest.raises(grpc.RpcError) as e:
344 api.CreateEvent(
345 events_pb2.CreateEventReq(
346 title="Dummy Title",
347 content="Dummy content.",
348 photo_key="nonexistent",
349 offline_information=events_pb2.OfflineEventInformation(
350 address="Near Null Island",
351 lat=0.1,
352 lng=0.1,
353 ),
354 start_time=Timestamp_from_datetime(start_time),
355 end_time=Timestamp_from_datetime(end_time),
356 timezone="UTC",
357 )
358 )
359 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
360 assert e.value.details() == errors.PHOTO_NOT_FOUND
362 with pytest.raises(grpc.RpcError) as e:
363 api.CreateEvent(
364 events_pb2.CreateEventReq(
365 title="Dummy Title",
366 content="Dummy content.",
367 photo_key=None,
368 offline_information=events_pb2.OfflineEventInformation(
369 address="Near Null Island",
370 ),
371 start_time=Timestamp_from_datetime(start_time),
372 end_time=Timestamp_from_datetime(end_time),
373 timezone="UTC",
374 )
375 )
376 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
377 assert e.value.details() == errors.MISSING_EVENT_ADDRESS_OR_LOCATION
379 with pytest.raises(grpc.RpcError) as e:
380 api.CreateEvent(
381 events_pb2.CreateEventReq(
382 title="Dummy Title",
383 content="Dummy content.",
384 photo_key=None,
385 offline_information=events_pb2.OfflineEventInformation(
386 lat=0.1,
387 lng=0.1,
388 ),
389 start_time=Timestamp_from_datetime(start_time),
390 end_time=Timestamp_from_datetime(end_time),
391 timezone="UTC",
392 )
393 )
394 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
395 assert e.value.details() == errors.MISSING_EVENT_ADDRESS_OR_LOCATION
397 with pytest.raises(grpc.RpcError) as e:
398 api.CreateEvent(
399 events_pb2.CreateEventReq(
400 title="Dummy Title",
401 content="Dummy content.",
402 photo_key=None,
403 online_information=events_pb2.OnlineEventInformation(),
404 start_time=Timestamp_from_datetime(start_time),
405 end_time=Timestamp_from_datetime(end_time),
406 timezone="UTC",
407 )
408 )
409 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
410 assert e.value.details() == errors.ONLINE_EVENT_REQUIRES_LINK
412 with pytest.raises(grpc.RpcError) as e:
413 api.CreateEvent(
414 events_pb2.CreateEventReq(
415 title="Dummy Title",
416 content="Dummy content.",
417 parent_community_id=c_id,
418 online_information=events_pb2.OnlineEventInformation(
419 link="https://couchers.org/meet/",
420 ),
421 start_time=Timestamp_from_datetime(now() - timedelta(hours=2)),
422 end_time=Timestamp_from_datetime(end_time),
423 timezone="UTC",
424 )
425 )
426 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
427 assert e.value.details() == errors.EVENT_IN_PAST
429 with pytest.raises(grpc.RpcError) as e:
430 api.CreateEvent(
431 events_pb2.CreateEventReq(
432 title="Dummy Title",
433 content="Dummy content.",
434 parent_community_id=c_id,
435 online_information=events_pb2.OnlineEventInformation(
436 link="https://couchers.org/meet/",
437 ),
438 start_time=Timestamp_from_datetime(end_time),
439 end_time=Timestamp_from_datetime(start_time),
440 timezone="UTC",
441 )
442 )
443 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
444 assert e.value.details() == errors.EVENT_ENDS_BEFORE_STARTS
446 with pytest.raises(grpc.RpcError) as e:
447 api.CreateEvent(
448 events_pb2.CreateEventReq(
449 title="Dummy Title",
450 content="Dummy content.",
451 parent_community_id=c_id,
452 online_information=events_pb2.OnlineEventInformation(
453 link="https://couchers.org/meet/",
454 ),
455 start_time=Timestamp_from_datetime(now() + timedelta(days=500, hours=2)),
456 end_time=Timestamp_from_datetime(now() + timedelta(days=500, hours=5)),
457 timezone="UTC",
458 )
459 )
460 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
461 assert e.value.details() == errors.EVENT_TOO_FAR_IN_FUTURE
463 with pytest.raises(grpc.RpcError) as e:
464 api.CreateEvent(
465 events_pb2.CreateEventReq(
466 title="Dummy Title",
467 content="Dummy content.",
468 parent_community_id=c_id,
469 online_information=events_pb2.OnlineEventInformation(
470 link="https://couchers.org/meet/",
471 ),
472 start_time=Timestamp_from_datetime(start_time),
473 end_time=Timestamp_from_datetime(now() + timedelta(days=100)),
474 timezone="UTC",
475 )
476 )
477 assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT
478 assert e.value.details() == errors.EVENT_TOO_LONG
481def test_CreateEvent_incomplete_profile(db):
482 user1, token1 = generate_user(complete_profile=False)
483 user2, token2 = generate_user()
485 with session_scope() as session:
486 c_id = create_community(session, 0, 2, "Community", [user2], [], None).id
488 start_time = now() + timedelta(hours=2)
489 end_time = start_time + timedelta(hours=3)
491 with events_session(token1) as api:
492 with pytest.raises(grpc.RpcError) as e:
493 api.CreateEvent(
494 events_pb2.CreateEventReq(
495 title="Dummy Title",
496 content="Dummy content.",
497 photo_key=None,
498 offline_information=events_pb2.OfflineEventInformation(
499 address="Near Null Island",
500 lat=0.1,
501 lng=0.2,
502 ),
503 start_time=Timestamp_from_datetime(start_time),
504 end_time=Timestamp_from_datetime(end_time),
505 timezone="UTC",
506 )
507 )
508 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
509 assert e.value.details() == errors.INCOMPLETE_PROFILE_CREATE_EVENT
512def test_ScheduleEvent(db):
513 # test cases:
514 # can schedule a new event occurrence
516 user, token = generate_user()
518 with session_scope() as session:
519 c_id = create_community(session, 0, 2, "Community", [user], [], None).id
521 time_before = now()
522 start_time = now() + timedelta(hours=2)
523 end_time = start_time + timedelta(hours=3)
525 with events_session(token) as api:
526 res = api.CreateEvent(
527 events_pb2.CreateEventReq(
528 title="Dummy Title",
529 content="Dummy content.",
530 parent_community_id=c_id,
531 online_information=events_pb2.OnlineEventInformation(
532 link="https://couchers.org/meet/",
533 ),
534 start_time=Timestamp_from_datetime(start_time),
535 end_time=Timestamp_from_datetime(end_time),
536 timezone="UTC",
537 )
538 )
540 new_start_time = now() + timedelta(hours=6)
541 new_end_time = new_start_time + timedelta(hours=2)
543 res = api.ScheduleEvent(
544 events_pb2.ScheduleEventReq(
545 event_id=res.event_id,
546 content="New event occurrence",
547 offline_information=events_pb2.OfflineEventInformation(
548 address="A bit further but still near Null Island",
549 lat=0.3,
550 lng=0.2,
551 ),
552 start_time=Timestamp_from_datetime(new_start_time),
553 end_time=Timestamp_from_datetime(new_end_time),
554 timezone="UTC",
555 )
556 )
558 res = api.GetEvent(events_pb2.GetEventReq(event_id=res.event_id))
560 assert not res.is_next
561 assert res.title == "Dummy Title"
562 assert res.slug == "dummy-title"
563 assert res.content == "New event occurrence"
564 assert not res.photo_url
565 assert res.WhichOneof("mode") == "offline_information"
566 assert res.offline_information.lat == 0.3
567 assert res.offline_information.lng == 0.2
568 assert res.offline_information.address == "A bit further but still near Null Island"
569 assert time_before <= to_aware_datetime(res.created) <= now()
570 assert time_before <= to_aware_datetime(res.last_edited) <= now()
571 assert res.creator_user_id == user.id
572 assert to_aware_datetime(res.start_time) == new_start_time
573 assert to_aware_datetime(res.end_time) == new_end_time
574 # assert res.timezone == "UTC"
575 assert res.start_time_display
576 assert res.end_time_display
577 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_GOING
578 assert res.organizer
579 assert res.subscriber
580 assert res.going_count == 1
581 assert res.maybe_count == 0
582 assert res.organizer_count == 1
583 assert res.subscriber_count == 1
584 assert res.owner_user_id == user.id
585 assert not res.owner_community_id
586 assert not res.owner_group_id
587 assert res.thread.thread_id
588 assert res.can_edit
589 assert res.can_moderate
592def test_cannot_overlap_occurrences_schedule(db):
593 user, token = generate_user()
595 with session_scope() as session:
596 c_id = create_community(session, 0, 2, "Community", [user], [], None).id
598 start = now()
600 with events_session(token) as api:
601 res = api.CreateEvent(
602 events_pb2.CreateEventReq(
603 title="Dummy Title",
604 content="Dummy content.",
605 parent_community_id=c_id,
606 online_information=events_pb2.OnlineEventInformation(
607 link="https://couchers.org/meet/",
608 ),
609 start_time=Timestamp_from_datetime(start + timedelta(hours=1)),
610 end_time=Timestamp_from_datetime(start + timedelta(hours=3)),
611 timezone="UTC",
612 )
613 )
615 with pytest.raises(grpc.RpcError) as e:
616 api.ScheduleEvent(
617 events_pb2.ScheduleEventReq(
618 event_id=res.event_id,
619 content="New event occurrence",
620 offline_information=events_pb2.OfflineEventInformation(
621 address="A bit further but still near Null Island",
622 lat=0.3,
623 lng=0.2,
624 ),
625 start_time=Timestamp_from_datetime(start + timedelta(hours=2)),
626 end_time=Timestamp_from_datetime(start + timedelta(hours=6)),
627 timezone="UTC",
628 )
629 )
630 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
631 assert e.value.details() == errors.EVENT_CANT_OVERLAP
634def test_cannot_overlap_occurrences_update(db):
635 user, token = generate_user()
637 with session_scope() as session:
638 c_id = create_community(session, 0, 2, "Community", [user], [], None).id
640 start = now()
642 with events_session(token) as api:
643 res = api.CreateEvent(
644 events_pb2.CreateEventReq(
645 title="Dummy Title",
646 content="Dummy content.",
647 parent_community_id=c_id,
648 online_information=events_pb2.OnlineEventInformation(
649 link="https://couchers.org/meet/",
650 ),
651 start_time=Timestamp_from_datetime(start + timedelta(hours=1)),
652 end_time=Timestamp_from_datetime(start + timedelta(hours=3)),
653 timezone="UTC",
654 )
655 )
657 event_id = api.ScheduleEvent(
658 events_pb2.ScheduleEventReq(
659 event_id=res.event_id,
660 content="New event occurrence",
661 offline_information=events_pb2.OfflineEventInformation(
662 address="A bit further but still near Null Island",
663 lat=0.3,
664 lng=0.2,
665 ),
666 start_time=Timestamp_from_datetime(start + timedelta(hours=4)),
667 end_time=Timestamp_from_datetime(start + timedelta(hours=6)),
668 timezone="UTC",
669 )
670 ).event_id
672 # can overlap with this current existing occurrence
673 api.UpdateEvent(
674 events_pb2.UpdateEventReq(
675 event_id=event_id,
676 start_time=Timestamp_from_datetime(start + timedelta(hours=5)),
677 end_time=Timestamp_from_datetime(start + timedelta(hours=6)),
678 )
679 )
681 with pytest.raises(grpc.RpcError) as e:
682 api.UpdateEvent(
683 events_pb2.UpdateEventReq(
684 event_id=event_id,
685 start_time=Timestamp_from_datetime(start + timedelta(hours=2)),
686 end_time=Timestamp_from_datetime(start + timedelta(hours=4)),
687 )
688 )
689 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
690 assert e.value.details() == errors.EVENT_CANT_OVERLAP
693def test_UpdateEvent_single(db):
694 # test cases:
695 # owner can update
696 # community owner can update
697 # can't mess up online/in person dichotomy
698 # notifies attendees
700 # event creator
701 user1, token1 = generate_user()
702 # community moderator
703 user2, token2 = generate_user()
704 # third parties
705 user3, token3 = generate_user()
706 user4, token4 = generate_user()
707 user5, token5 = generate_user()
708 user6, token6 = generate_user()
710 with session_scope() as session:
711 c_id = create_community(session, 0, 2, "Community", [user2], [], None).id
713 time_before = now()
714 start_time = now() + timedelta(hours=2)
715 end_time = start_time + timedelta(hours=3)
717 with events_session(token1) as api:
718 res = api.CreateEvent(
719 events_pb2.CreateEventReq(
720 title="Dummy Title",
721 content="Dummy content.",
722 offline_information=events_pb2.OfflineEventInformation(
723 address="Near Null Island",
724 lat=0.1,
725 lng=0.2,
726 ),
727 start_time=Timestamp_from_datetime(start_time),
728 end_time=Timestamp_from_datetime(end_time),
729 timezone="UTC",
730 )
731 )
733 event_id = res.event_id
735 with events_session(token4) as api:
736 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=True))
738 with events_session(token5) as api:
739 api.SetEventAttendance(
740 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_GOING)
741 )
743 with events_session(token6) as api:
744 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=True))
745 api.SetEventAttendance(
746 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_MAYBE)
747 )
749 time_before_update = now()
751 with events_session(token1) as api:
752 res = api.UpdateEvent(
753 events_pb2.UpdateEventReq(
754 event_id=event_id,
755 )
756 )
758 with events_session(token1) as api:
759 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
761 assert res.is_next
762 assert res.title == "Dummy Title"
763 assert res.slug == "dummy-title"
764 assert res.content == "Dummy content."
765 assert not res.photo_url
766 assert res.WhichOneof("mode") == "offline_information"
767 assert res.offline_information.lat == 0.1
768 assert res.offline_information.lng == 0.2
769 assert res.offline_information.address == "Near Null Island"
770 assert time_before <= to_aware_datetime(res.created) <= time_before_update
771 assert time_before_update <= to_aware_datetime(res.last_edited) <= now()
772 assert res.creator_user_id == user1.id
773 assert to_aware_datetime(res.start_time) == start_time
774 assert to_aware_datetime(res.end_time) == end_time
775 # assert res.timezone == "UTC"
776 assert res.start_time_display
777 assert res.end_time_display
778 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_GOING
779 assert res.organizer
780 assert res.subscriber
781 assert res.going_count == 2
782 assert res.maybe_count == 1
783 assert res.organizer_count == 1
784 assert res.subscriber_count == 3
785 assert res.owner_user_id == user1.id
786 assert not res.owner_community_id
787 assert not res.owner_group_id
788 assert res.thread.thread_id
789 assert res.can_edit
790 assert not res.can_moderate
792 with events_session(token2) as api:
793 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
795 assert res.is_next
796 assert res.title == "Dummy Title"
797 assert res.slug == "dummy-title"
798 assert res.content == "Dummy content."
799 assert not res.photo_url
800 assert res.WhichOneof("mode") == "offline_information"
801 assert res.offline_information.lat == 0.1
802 assert res.offline_information.lng == 0.2
803 assert res.offline_information.address == "Near Null Island"
804 assert time_before <= to_aware_datetime(res.created) <= time_before_update
805 assert time_before_update <= to_aware_datetime(res.last_edited) <= now()
806 assert res.creator_user_id == user1.id
807 assert to_aware_datetime(res.start_time) == start_time
808 assert to_aware_datetime(res.end_time) == end_time
809 # assert res.timezone == "UTC"
810 assert res.start_time_display
811 assert res.end_time_display
812 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_NOT_GOING
813 assert not res.organizer
814 assert not res.subscriber
815 assert res.going_count == 2
816 assert res.maybe_count == 1
817 assert res.organizer_count == 1
818 assert res.subscriber_count == 3
819 assert res.owner_user_id == user1.id
820 assert not res.owner_community_id
821 assert not res.owner_group_id
822 assert res.thread.thread_id
823 assert res.can_edit
824 assert res.can_moderate
826 with events_session(token3) as api:
827 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
829 assert res.is_next
830 assert res.title == "Dummy Title"
831 assert res.slug == "dummy-title"
832 assert res.content == "Dummy content."
833 assert not res.photo_url
834 assert res.WhichOneof("mode") == "offline_information"
835 assert res.offline_information.lat == 0.1
836 assert res.offline_information.lng == 0.2
837 assert res.offline_information.address == "Near Null Island"
838 assert time_before <= to_aware_datetime(res.created) <= time_before_update
839 assert time_before_update <= to_aware_datetime(res.last_edited) <= now()
840 assert res.creator_user_id == user1.id
841 assert to_aware_datetime(res.start_time) == start_time
842 assert to_aware_datetime(res.end_time) == end_time
843 # assert res.timezone == "UTC"
844 assert res.start_time_display
845 assert res.end_time_display
846 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_NOT_GOING
847 assert not res.organizer
848 assert not res.subscriber
849 assert res.going_count == 2
850 assert res.maybe_count == 1
851 assert res.organizer_count == 1
852 assert res.subscriber_count == 3
853 assert res.owner_user_id == user1.id
854 assert not res.owner_community_id
855 assert not res.owner_group_id
856 assert res.thread.thread_id
857 assert not res.can_edit
858 assert not res.can_moderate
860 with events_session(token1) as api:
861 res = api.UpdateEvent(
862 events_pb2.UpdateEventReq(
863 event_id=event_id,
864 title=wrappers_pb2.StringValue(value="Dummy Title"),
865 content=wrappers_pb2.StringValue(value="Dummy content."),
866 online_information=events_pb2.OnlineEventInformation(link="https://couchers.org/meet/"),
867 start_time=Timestamp_from_datetime(start_time),
868 end_time=Timestamp_from_datetime(end_time),
869 timezone=wrappers_pb2.StringValue(value="UTC"),
870 )
871 )
873 assert res.is_next
874 assert res.title == "Dummy Title"
875 assert res.slug == "dummy-title"
876 assert res.content == "Dummy content."
877 assert not res.photo_url
878 assert res.WhichOneof("mode") == "online_information"
879 assert res.online_information.link == "https://couchers.org/meet/"
880 assert time_before <= to_aware_datetime(res.created) <= time_before_update
881 assert time_before_update <= to_aware_datetime(res.last_edited) <= now()
882 assert res.creator_user_id == user1.id
883 assert to_aware_datetime(res.start_time) == start_time
884 assert to_aware_datetime(res.end_time) == end_time
885 # assert res.timezone == "UTC"
886 assert res.start_time_display
887 assert res.end_time_display
888 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_GOING
889 assert res.organizer
890 assert res.subscriber
891 assert res.going_count == 2
892 assert res.maybe_count == 1
893 assert res.organizer_count == 1
894 assert res.subscriber_count == 3
895 assert res.owner_user_id == user1.id
896 assert not res.owner_community_id
897 assert not res.owner_group_id
898 assert res.thread.thread_id
899 assert res.can_edit
900 assert not res.can_moderate
902 event_id = res.event_id
904 with events_session(token2) as api:
905 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
907 assert res.is_next
908 assert res.title == "Dummy Title"
909 assert res.slug == "dummy-title"
910 assert res.content == "Dummy content."
911 assert not res.photo_url
912 assert res.WhichOneof("mode") == "online_information"
913 assert res.online_information.link == "https://couchers.org/meet/"
914 assert time_before <= to_aware_datetime(res.created) <= time_before_update
915 assert time_before_update <= to_aware_datetime(res.last_edited) <= now()
916 assert res.creator_user_id == user1.id
917 assert to_aware_datetime(res.start_time) == start_time
918 assert to_aware_datetime(res.end_time) == end_time
919 # assert res.timezone == "UTC"
920 assert res.start_time_display
921 assert res.end_time_display
922 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_NOT_GOING
923 assert not res.organizer
924 assert not res.subscriber
925 assert res.going_count == 2
926 assert res.maybe_count == 1
927 assert res.organizer_count == 1
928 assert res.subscriber_count == 3
929 assert res.owner_user_id == user1.id
930 assert not res.owner_community_id
931 assert not res.owner_group_id
932 assert res.thread.thread_id
933 assert res.can_edit
934 assert res.can_moderate
936 with events_session(token3) as api:
937 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
939 assert res.is_next
940 assert res.title == "Dummy Title"
941 assert res.slug == "dummy-title"
942 assert res.content == "Dummy content."
943 assert not res.photo_url
944 assert res.WhichOneof("mode") == "online_information"
945 assert res.online_information.link == "https://couchers.org/meet/"
946 assert time_before <= to_aware_datetime(res.created) <= time_before_update
947 assert time_before_update <= to_aware_datetime(res.last_edited) <= now()
948 assert res.creator_user_id == user1.id
949 assert to_aware_datetime(res.start_time) == start_time
950 assert to_aware_datetime(res.end_time) == end_time
951 # assert res.timezone == "UTC"
952 assert res.start_time_display
953 assert res.end_time_display
954 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_NOT_GOING
955 assert not res.organizer
956 assert not res.subscriber
957 assert res.going_count == 2
958 assert res.maybe_count == 1
959 assert res.organizer_count == 1
960 assert res.subscriber_count == 3
961 assert res.owner_user_id == user1.id
962 assert not res.owner_community_id
963 assert not res.owner_group_id
964 assert res.thread.thread_id
965 assert not res.can_edit
966 assert not res.can_moderate
968 with events_session(token1) as api:
969 res = api.UpdateEvent(
970 events_pb2.UpdateEventReq(
971 event_id=event_id,
972 offline_information=events_pb2.OfflineEventInformation(
973 address="Near Null Island",
974 lat=0.1,
975 lng=0.2,
976 ),
977 )
978 )
980 with events_session(token3) as api:
981 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
983 assert res.WhichOneof("mode") == "offline_information"
984 assert res.offline_information.address == "Near Null Island"
985 assert res.offline_information.lat == 0.1
986 assert res.offline_information.lng == 0.2
989def test_UpdateEvent_all(db):
990 # event creator
991 user1, token1 = generate_user()
992 # community moderator
993 user2, token2 = generate_user()
994 # third parties
995 user3, token3 = generate_user()
996 user4, token4 = generate_user()
997 user5, token5 = generate_user()
998 user6, token6 = generate_user()
1000 with session_scope() as session:
1001 c_id = create_community(session, 0, 2, "Community", [user2], [], None).id
1003 time_before = now()
1004 start_time = now() + timedelta(hours=1)
1005 end_time = start_time + timedelta(hours=1.5)
1007 event_ids = []
1009 with events_session(token1) as api:
1010 res = api.CreateEvent(
1011 events_pb2.CreateEventReq(
1012 title="Dummy Title",
1013 content="0th occurrence",
1014 offline_information=events_pb2.OfflineEventInformation(
1015 address="Near Null Island",
1016 lat=0.1,
1017 lng=0.2,
1018 ),
1019 start_time=Timestamp_from_datetime(start_time),
1020 end_time=Timestamp_from_datetime(end_time),
1021 timezone="UTC",
1022 )
1023 )
1025 event_id = res.event_id
1026 event_ids.append(event_id)
1028 with events_session(token4) as api:
1029 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=True))
1031 with events_session(token5) as api:
1032 api.SetEventAttendance(
1033 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_GOING)
1034 )
1036 with events_session(token6) as api:
1037 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=True))
1038 api.SetEventAttendance(
1039 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_MAYBE)
1040 )
1042 with events_session(token1) as api:
1043 for i in range(5):
1044 res = api.ScheduleEvent(
1045 events_pb2.ScheduleEventReq(
1046 event_id=event_ids[-1],
1047 content=f"{i+1}th occurrence",
1048 online_information=events_pb2.OnlineEventInformation(
1049 link="https://couchers.org/meet/",
1050 ),
1051 start_time=Timestamp_from_datetime(start_time + timedelta(hours=2 + i)),
1052 end_time=Timestamp_from_datetime(start_time + timedelta(hours=2.5 + i)),
1053 timezone="UTC",
1054 )
1055 )
1057 event_ids.append(res.event_id)
1059 updated_event_id = event_ids[3]
1061 time_before_update = now()
1063 with events_session(token1) as api:
1064 res = api.UpdateEvent(
1065 events_pb2.UpdateEventReq(
1066 event_id=updated_event_id,
1067 title=wrappers_pb2.StringValue(value="New Title"),
1068 content=wrappers_pb2.StringValue(value="New content."),
1069 online_information=events_pb2.OnlineEventInformation(link="https://couchers.org/meet/"),
1070 update_all_future=True,
1071 )
1072 )
1074 time_after_update = now()
1076 with events_session(token2) as api:
1077 for i in range(3):
1078 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_ids[i]))
1079 assert res.content == f"{i}th occurrence"
1080 assert time_before <= to_aware_datetime(res.last_edited) <= time_before_update
1082 for i in range(3, 6):
1083 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_ids[i]))
1084 assert res.content == "New content."
1085 assert time_before_update <= to_aware_datetime(res.last_edited) <= time_after_update
1088def test_GetEvent(db):
1089 # event creator
1090 user1, token1 = generate_user()
1091 # community moderator
1092 user2, token2 = generate_user()
1093 # third parties
1094 user3, token3 = generate_user()
1095 user4, token4 = generate_user()
1096 user5, token5 = generate_user()
1097 user6, token6 = generate_user()
1099 with session_scope() as session:
1100 c_id = create_community(session, 0, 2, "Community", [user2], [], None).id
1102 time_before = now()
1103 start_time = now() + timedelta(hours=2)
1104 end_time = start_time + timedelta(hours=3)
1106 with events_session(token1) as api:
1107 # in person event
1108 res = api.CreateEvent(
1109 events_pb2.CreateEventReq(
1110 title="Dummy Title",
1111 content="Dummy content.",
1112 offline_information=events_pb2.OfflineEventInformation(
1113 address="Near Null Island",
1114 lat=0.1,
1115 lng=0.2,
1116 ),
1117 start_time=Timestamp_from_datetime(start_time),
1118 end_time=Timestamp_from_datetime(end_time),
1119 timezone="UTC",
1120 )
1121 )
1123 event_id = res.event_id
1125 with events_session(token4) as api:
1126 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=True))
1128 with events_session(token5) as api:
1129 api.SetEventAttendance(
1130 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_GOING)
1131 )
1133 with events_session(token6) as api:
1134 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=True))
1135 api.SetEventAttendance(
1136 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_MAYBE)
1137 )
1139 with events_session(token1) as api:
1140 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
1142 assert res.is_next
1143 assert res.title == "Dummy Title"
1144 assert res.slug == "dummy-title"
1145 assert res.content == "Dummy content."
1146 assert not res.photo_url
1147 assert res.WhichOneof("mode") == "offline_information"
1148 assert res.offline_information.lat == 0.1
1149 assert res.offline_information.lng == 0.2
1150 assert res.offline_information.address == "Near Null Island"
1151 assert time_before <= to_aware_datetime(res.created) <= now()
1152 assert time_before <= to_aware_datetime(res.last_edited) <= now()
1153 assert res.creator_user_id == user1.id
1154 assert to_aware_datetime(res.start_time) == start_time
1155 assert to_aware_datetime(res.end_time) == end_time
1156 # assert res.timezone == "UTC"
1157 assert res.start_time_display
1158 assert res.end_time_display
1159 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_GOING
1160 assert res.organizer
1161 assert res.subscriber
1162 assert res.going_count == 2
1163 assert res.maybe_count == 1
1164 assert res.organizer_count == 1
1165 assert res.subscriber_count == 3
1166 assert res.owner_user_id == user1.id
1167 assert not res.owner_community_id
1168 assert not res.owner_group_id
1169 assert res.thread.thread_id
1170 assert res.can_edit
1171 assert not res.can_moderate
1173 with events_session(token2) as api:
1174 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
1176 assert res.is_next
1177 assert res.title == "Dummy Title"
1178 assert res.slug == "dummy-title"
1179 assert res.content == "Dummy content."
1180 assert not res.photo_url
1181 assert res.WhichOneof("mode") == "offline_information"
1182 assert res.offline_information.lat == 0.1
1183 assert res.offline_information.lng == 0.2
1184 assert res.offline_information.address == "Near Null Island"
1185 assert time_before <= to_aware_datetime(res.created) <= now()
1186 assert time_before <= to_aware_datetime(res.last_edited) <= now()
1187 assert res.creator_user_id == user1.id
1188 assert to_aware_datetime(res.start_time) == start_time
1189 assert to_aware_datetime(res.end_time) == end_time
1190 # assert res.timezone == "UTC"
1191 assert res.start_time_display
1192 assert res.end_time_display
1193 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_NOT_GOING
1194 assert not res.organizer
1195 assert not res.subscriber
1196 assert res.going_count == 2
1197 assert res.maybe_count == 1
1198 assert res.organizer_count == 1
1199 assert res.subscriber_count == 3
1200 assert res.owner_user_id == user1.id
1201 assert not res.owner_community_id
1202 assert not res.owner_group_id
1203 assert res.thread.thread_id
1204 assert res.can_edit
1205 assert res.can_moderate
1207 with events_session(token3) as api:
1208 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
1210 assert res.is_next
1211 assert res.title == "Dummy Title"
1212 assert res.slug == "dummy-title"
1213 assert res.content == "Dummy content."
1214 assert not res.photo_url
1215 assert res.WhichOneof("mode") == "offline_information"
1216 assert res.offline_information.lat == 0.1
1217 assert res.offline_information.lng == 0.2
1218 assert res.offline_information.address == "Near Null Island"
1219 assert time_before <= to_aware_datetime(res.created) <= now()
1220 assert time_before <= to_aware_datetime(res.last_edited) <= now()
1221 assert res.creator_user_id == user1.id
1222 assert to_aware_datetime(res.start_time) == start_time
1223 assert to_aware_datetime(res.end_time) == end_time
1224 # assert res.timezone == "UTC"
1225 assert res.start_time_display
1226 assert res.end_time_display
1227 assert res.attendance_state == events_pb2.ATTENDANCE_STATE_NOT_GOING
1228 assert not res.organizer
1229 assert not res.subscriber
1230 assert res.going_count == 2
1231 assert res.maybe_count == 1
1232 assert res.organizer_count == 1
1233 assert res.subscriber_count == 3
1234 assert res.owner_user_id == user1.id
1235 assert not res.owner_community_id
1236 assert not res.owner_group_id
1237 assert res.thread.thread_id
1238 assert not res.can_edit
1239 assert not res.can_moderate
1242def test_CancelEvent(db):
1243 # event creator
1244 user1, token1 = generate_user()
1245 # community moderator
1246 user2, token2 = generate_user()
1247 # third parties
1248 user3, token3 = generate_user()
1249 user4, token4 = generate_user()
1250 user5, token5 = generate_user()
1251 user6, token6 = generate_user()
1253 with session_scope() as session:
1254 c_id = create_community(session, 0, 2, "Community", [user2], [], None).id
1256 start_time = now() + timedelta(hours=2)
1257 end_time = start_time + timedelta(hours=3)
1259 with events_session(token1) as api:
1260 res = api.CreateEvent(
1261 events_pb2.CreateEventReq(
1262 title="Dummy Title",
1263 content="Dummy content.",
1264 offline_information=events_pb2.OfflineEventInformation(
1265 address="Near Null Island",
1266 lat=0.1,
1267 lng=0.2,
1268 ),
1269 start_time=Timestamp_from_datetime(start_time),
1270 end_time=Timestamp_from_datetime(end_time),
1271 timezone="UTC",
1272 )
1273 )
1275 event_id = res.event_id
1277 with events_session(token4) as api:
1278 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=True))
1280 with events_session(token5) as api:
1281 api.SetEventAttendance(
1282 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_GOING)
1283 )
1285 with events_session(token6) as api:
1286 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=True))
1287 api.SetEventAttendance(
1288 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_MAYBE)
1289 )
1291 with events_session(token1) as api:
1292 res = api.CancelEvent(
1293 events_pb2.CancelEventReq(
1294 event_id=event_id,
1295 )
1296 )
1298 with events_session(token1) as api:
1299 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
1300 assert res.is_cancelled
1302 with events_session(token1) as api:
1303 with pytest.raises(grpc.RpcError) as e:
1304 api.UpdateEvent(
1305 events_pb2.UpdateEventReq(
1306 event_id=event_id,
1307 title=wrappers_pb2.StringValue(value="New Title"),
1308 )
1309 )
1310 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1311 assert e.value.details() == errors.EVENT_CANT_UPDATE_CANCELLED_EVENT
1313 with pytest.raises(grpc.RpcError) as e:
1314 api.InviteEventOrganizer(
1315 events_pb2.InviteEventOrganizerReq(
1316 event_id=event_id,
1317 user_id=user3.id,
1318 )
1319 )
1320 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1321 assert e.value.details() == errors.EVENT_CANT_UPDATE_CANCELLED_EVENT
1323 with pytest.raises(grpc.RpcError) as e:
1324 api.TransferEvent(events_pb2.TransferEventReq(event_id=event_id, new_owner_community_id=c_id))
1325 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1326 assert e.value.details() == errors.EVENT_CANT_UPDATE_CANCELLED_EVENT
1328 with events_session(token3) as api:
1329 with pytest.raises(grpc.RpcError) as e:
1330 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=True))
1331 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1332 assert e.value.details() == errors.EVENT_CANT_UPDATE_CANCELLED_EVENT
1334 with pytest.raises(grpc.RpcError) as e:
1335 api.SetEventAttendance(
1336 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_GOING)
1337 )
1338 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1339 assert e.value.details() == errors.EVENT_CANT_UPDATE_CANCELLED_EVENT
1341 with events_session(token1) as api:
1342 for include_cancelled in [True, False]:
1343 res = api.ListEventOccurrences(
1344 events_pb2.ListEventOccurrencesReq(
1345 event_id=event_id,
1346 include_cancelled=include_cancelled,
1347 )
1348 )
1349 if include_cancelled:
1350 assert len(res.events) > 0
1351 else:
1352 assert len(res.events) == 0
1354 res = api.ListMyEvents(
1355 events_pb2.ListMyEventsReq(
1356 include_cancelled=include_cancelled,
1357 )
1358 )
1359 if include_cancelled:
1360 assert len(res.events) > 0
1361 else:
1362 assert len(res.events) == 0
1365def test_ListEventAttendees(db):
1366 # event creator
1367 user1, token1 = generate_user()
1368 # others
1369 user2, token2 = generate_user()
1370 user3, token3 = generate_user()
1371 user4, token4 = generate_user()
1372 user5, token5 = generate_user()
1373 user6, token6 = generate_user()
1375 with session_scope() as session:
1376 c_id = create_community(session, 0, 2, "Community", [user1], [], None).id
1378 with events_session(token1) as api:
1379 event_id = api.CreateEvent(
1380 events_pb2.CreateEventReq(
1381 title="Dummy Title",
1382 content="Dummy content.",
1383 offline_information=events_pb2.OfflineEventInformation(
1384 address="Near Null Island",
1385 lat=0.1,
1386 lng=0.2,
1387 ),
1388 start_time=Timestamp_from_datetime(now() + timedelta(hours=2)),
1389 end_time=Timestamp_from_datetime(now() + timedelta(hours=5)),
1390 timezone="UTC",
1391 )
1392 ).event_id
1394 for token in [token2, token3, token4, token5]:
1395 with events_session(token) as api:
1396 api.SetEventAttendance(
1397 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_GOING)
1398 )
1400 with events_session(token6) as api:
1401 assert api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).going_count == 5
1403 res = api.ListEventAttendees(events_pb2.ListEventAttendeesReq(event_id=event_id, page_size=2))
1404 assert res.attendee_user_ids == [user1.id, user2.id]
1406 res = api.ListEventAttendees(
1407 events_pb2.ListEventAttendeesReq(event_id=event_id, page_size=2, page_token=res.next_page_token)
1408 )
1409 assert res.attendee_user_ids == [user3.id, user4.id]
1411 res = api.ListEventAttendees(
1412 events_pb2.ListEventAttendeesReq(event_id=event_id, page_size=2, page_token=res.next_page_token)
1413 )
1414 assert res.attendee_user_ids == [user5.id]
1415 assert not res.next_page_token
1418def test_ListEventSubscribers(db):
1419 # event creator
1420 user1, token1 = generate_user()
1421 # others
1422 user2, token2 = generate_user()
1423 user3, token3 = generate_user()
1424 user4, token4 = generate_user()
1425 user5, token5 = generate_user()
1426 user6, token6 = generate_user()
1428 with session_scope() as session:
1429 c_id = create_community(session, 0, 2, "Community", [user1], [], None).id
1431 with events_session(token1) as api:
1432 event_id = api.CreateEvent(
1433 events_pb2.CreateEventReq(
1434 title="Dummy Title",
1435 content="Dummy content.",
1436 offline_information=events_pb2.OfflineEventInformation(
1437 address="Near Null Island",
1438 lat=0.1,
1439 lng=0.2,
1440 ),
1441 start_time=Timestamp_from_datetime(now() + timedelta(hours=2)),
1442 end_time=Timestamp_from_datetime(now() + timedelta(hours=5)),
1443 timezone="UTC",
1444 )
1445 ).event_id
1447 for token in [token2, token3, token4, token5]:
1448 with events_session(token) as api:
1449 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=True))
1451 with events_session(token6) as api:
1452 assert api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).subscriber_count == 5
1454 res = api.ListEventSubscribers(events_pb2.ListEventSubscribersReq(event_id=event_id, page_size=2))
1455 assert res.subscriber_user_ids == [user1.id, user2.id]
1457 res = api.ListEventSubscribers(
1458 events_pb2.ListEventSubscribersReq(event_id=event_id, page_size=2, page_token=res.next_page_token)
1459 )
1460 assert res.subscriber_user_ids == [user3.id, user4.id]
1462 res = api.ListEventSubscribers(
1463 events_pb2.ListEventSubscribersReq(event_id=event_id, page_size=2, page_token=res.next_page_token)
1464 )
1465 assert res.subscriber_user_ids == [user5.id]
1466 assert not res.next_page_token
1469def test_ListEventOrganizers(db):
1470 # event creator
1471 user1, token1 = generate_user()
1472 # others
1473 user2, token2 = generate_user()
1474 user3, token3 = generate_user()
1475 user4, token4 = generate_user()
1476 user5, token5 = generate_user()
1477 user6, token6 = generate_user()
1479 with session_scope() as session:
1480 c_id = create_community(session, 0, 2, "Community", [user1], [], None).id
1482 with events_session(token1) as api:
1483 event_id = api.CreateEvent(
1484 events_pb2.CreateEventReq(
1485 title="Dummy Title",
1486 content="Dummy content.",
1487 offline_information=events_pb2.OfflineEventInformation(
1488 address="Near Null Island",
1489 lat=0.1,
1490 lng=0.2,
1491 ),
1492 start_time=Timestamp_from_datetime(now() + timedelta(hours=2)),
1493 end_time=Timestamp_from_datetime(now() + timedelta(hours=5)),
1494 timezone="UTC",
1495 )
1496 ).event_id
1498 with events_session(token1) as api:
1499 for user_id in [user2.id, user3.id, user4.id, user5.id]:
1500 api.InviteEventOrganizer(events_pb2.InviteEventOrganizerReq(event_id=event_id, user_id=user_id))
1502 with events_session(token6) as api:
1503 assert api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).organizer_count == 5
1505 res = api.ListEventOrganizers(events_pb2.ListEventOrganizersReq(event_id=event_id, page_size=2))
1506 assert res.organizer_user_ids == [user1.id, user2.id]
1508 res = api.ListEventOrganizers(
1509 events_pb2.ListEventOrganizersReq(event_id=event_id, page_size=2, page_token=res.next_page_token)
1510 )
1511 assert res.organizer_user_ids == [user3.id, user4.id]
1513 res = api.ListEventOrganizers(
1514 events_pb2.ListEventOrganizersReq(event_id=event_id, page_size=2, page_token=res.next_page_token)
1515 )
1516 assert res.organizer_user_ids == [user5.id]
1517 assert not res.next_page_token
1520def test_TransferEvent(db):
1521 user1, token1 = generate_user()
1522 user2, token2 = generate_user()
1523 user3, token3 = generate_user()
1524 user4, token4 = generate_user()
1526 with session_scope() as session:
1527 c = create_community(session, 0, 2, "Community", [user3], [], None)
1528 h = create_group(session, "Group", [user4], [], c)
1529 c_id = c.id
1530 h_id = h.id
1532 with events_session(token1) as api:
1533 event_id = api.CreateEvent(
1534 events_pb2.CreateEventReq(
1535 title="Dummy Title",
1536 content="Dummy content.",
1537 offline_information=events_pb2.OfflineEventInformation(
1538 address="Near Null Island",
1539 lat=0.1,
1540 lng=0.2,
1541 ),
1542 start_time=Timestamp_from_datetime(now() + timedelta(hours=2)),
1543 end_time=Timestamp_from_datetime(now() + timedelta(hours=5)),
1544 timezone="UTC",
1545 )
1546 ).event_id
1548 api.TransferEvent(
1549 events_pb2.TransferEventReq(
1550 event_id=event_id,
1551 new_owner_community_id=c_id,
1552 )
1553 )
1555 with pytest.raises(grpc.RpcError) as e:
1556 api.TransferEvent(
1557 events_pb2.TransferEventReq(
1558 event_id=event_id,
1559 new_owner_group_id=h_id,
1560 )
1561 )
1562 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1563 assert e.value.details() == errors.EVENT_TRANSFER_PERMISSION_DENIED
1565 event_id = api.CreateEvent(
1566 events_pb2.CreateEventReq(
1567 title="Dummy Title",
1568 content="Dummy content.",
1569 offline_information=events_pb2.OfflineEventInformation(
1570 address="Near Null Island",
1571 lat=0.1,
1572 lng=0.2,
1573 ),
1574 start_time=Timestamp_from_datetime(now() + timedelta(hours=2)),
1575 end_time=Timestamp_from_datetime(now() + timedelta(hours=5)),
1576 timezone="UTC",
1577 )
1578 ).event_id
1580 api.TransferEvent(
1581 events_pb2.TransferEventReq(
1582 event_id=event_id,
1583 new_owner_group_id=h_id,
1584 )
1585 )
1587 with pytest.raises(grpc.RpcError) as e:
1588 api.TransferEvent(
1589 events_pb2.TransferEventReq(
1590 event_id=event_id,
1591 new_owner_community_id=c_id,
1592 )
1593 )
1594 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1595 assert e.value.details() == errors.EVENT_TRANSFER_PERMISSION_DENIED
1598def test_SetEventSubscription(db):
1599 user1, token1 = generate_user()
1600 user2, token2 = generate_user()
1602 with session_scope() as session:
1603 c_id = create_community(session, 0, 2, "Community", [user1], [], None).id
1605 with events_session(token1) as api:
1606 event_id = api.CreateEvent(
1607 events_pb2.CreateEventReq(
1608 title="Dummy Title",
1609 content="Dummy content.",
1610 offline_information=events_pb2.OfflineEventInformation(
1611 address="Near Null Island",
1612 lat=0.1,
1613 lng=0.2,
1614 ),
1615 start_time=Timestamp_from_datetime(now() + timedelta(hours=2)),
1616 end_time=Timestamp_from_datetime(now() + timedelta(hours=5)),
1617 timezone="UTC",
1618 )
1619 ).event_id
1621 with events_session(token2) as api:
1622 assert not api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).subscriber
1623 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=True))
1624 assert api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).subscriber
1625 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=event_id, subscribe=False))
1626 assert not api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).subscriber
1629def test_SetEventAttendance(db):
1630 user1, token1 = generate_user()
1631 user2, token2 = generate_user()
1633 with session_scope() as session:
1634 c_id = create_community(session, 0, 2, "Community", [user1], [], None).id
1636 with events_session(token1) as api:
1637 event_id = api.CreateEvent(
1638 events_pb2.CreateEventReq(
1639 title="Dummy Title",
1640 content="Dummy content.",
1641 offline_information=events_pb2.OfflineEventInformation(
1642 address="Near Null Island",
1643 lat=0.1,
1644 lng=0.2,
1645 ),
1646 start_time=Timestamp_from_datetime(now() + timedelta(hours=2)),
1647 end_time=Timestamp_from_datetime(now() + timedelta(hours=5)),
1648 timezone="UTC",
1649 )
1650 ).event_id
1652 with events_session(token2) as api:
1653 assert (
1654 api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).attendance_state
1655 == events_pb2.ATTENDANCE_STATE_NOT_GOING
1656 )
1657 api.SetEventAttendance(
1658 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_GOING)
1659 )
1660 assert (
1661 api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).attendance_state
1662 == events_pb2.ATTENDANCE_STATE_GOING
1663 )
1664 api.SetEventAttendance(
1665 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_MAYBE)
1666 )
1667 assert (
1668 api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).attendance_state
1669 == events_pb2.ATTENDANCE_STATE_MAYBE
1670 )
1671 api.SetEventAttendance(
1672 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_NOT_GOING)
1673 )
1674 assert (
1675 api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).attendance_state
1676 == events_pb2.ATTENDANCE_STATE_NOT_GOING
1677 )
1680def test_InviteEventOrganizer(db):
1681 user1, token1 = generate_user()
1682 user2, token2 = generate_user()
1684 with session_scope() as session:
1685 c_id = create_community(session, 0, 2, "Community", [user1], [], None).id
1687 with events_session(token1) as api:
1688 event_id = api.CreateEvent(
1689 events_pb2.CreateEventReq(
1690 title="Dummy Title",
1691 content="Dummy content.",
1692 offline_information=events_pb2.OfflineEventInformation(
1693 address="Near Null Island",
1694 lat=0.1,
1695 lng=0.2,
1696 ),
1697 start_time=Timestamp_from_datetime(now() + timedelta(hours=2)),
1698 end_time=Timestamp_from_datetime(now() + timedelta(hours=5)),
1699 timezone="UTC",
1700 )
1701 ).event_id
1703 with events_session(token2) as api:
1704 assert not api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).organizer
1706 with pytest.raises(grpc.RpcError) as e:
1707 api.InviteEventOrganizer(events_pb2.InviteEventOrganizerReq(event_id=event_id, user_id=user1.id))
1708 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
1709 assert e.value.details() == errors.EVENT_EDIT_PERMISSION_DENIED
1711 assert not api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).organizer
1713 with events_session(token1) as api:
1714 api.InviteEventOrganizer(events_pb2.InviteEventOrganizerReq(event_id=event_id, user_id=user2.id))
1716 with events_session(token2) as api:
1717 assert api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).organizer
1720def test_ListEventOccurrences(db):
1721 user1, token1 = generate_user()
1722 user2, token2 = generate_user()
1723 user3, token3 = generate_user()
1725 with session_scope() as session:
1726 c_id = create_community(session, 0, 2, "Community", [user2], [], None).id
1728 start = now()
1730 event_ids = []
1732 with events_session(token1) as api:
1733 res = api.CreateEvent(
1734 events_pb2.CreateEventReq(
1735 title="First occurrence",
1736 content="Dummy content.",
1737 parent_community_id=c_id,
1738 online_information=events_pb2.OnlineEventInformation(
1739 link="https://couchers.org/meet/",
1740 ),
1741 start_time=Timestamp_from_datetime(start + timedelta(hours=1)),
1742 end_time=Timestamp_from_datetime(start + timedelta(hours=1.5)),
1743 timezone="UTC",
1744 )
1745 )
1747 event_ids.append(res.event_id)
1749 for i in range(5):
1750 res = api.ScheduleEvent(
1751 events_pb2.ScheduleEventReq(
1752 event_id=event_ids[-1],
1753 content=f"{i}th occurrence",
1754 online_information=events_pb2.OnlineEventInformation(
1755 link="https://couchers.org/meet/",
1756 ),
1757 start_time=Timestamp_from_datetime(start + timedelta(hours=2 + i)),
1758 end_time=Timestamp_from_datetime(start + timedelta(hours=2.5 + i)),
1759 timezone="UTC",
1760 )
1761 )
1763 event_ids.append(res.event_id)
1765 res = api.ListEventOccurrences(events_pb2.ListEventOccurrencesReq(event_id=event_ids[-1], page_size=2))
1766 assert [event.event_id for event in res.events] == event_ids[:2]
1768 res = api.ListEventOccurrences(
1769 events_pb2.ListEventOccurrencesReq(event_id=event_ids[-1], page_size=2, page_token=res.next_page_token)
1770 )
1771 assert [event.event_id for event in res.events] == event_ids[2:4]
1773 res = api.ListEventOccurrences(
1774 events_pb2.ListEventOccurrencesReq(event_id=event_ids[-1], page_size=2, page_token=res.next_page_token)
1775 )
1776 assert [event.event_id for event in res.events] == event_ids[4:6]
1777 assert not res.next_page_token
1780def test_ListMyEvents(db):
1781 user1, token1 = generate_user()
1782 user2, token2 = generate_user()
1783 user3, token3 = generate_user()
1784 user4, token4 = generate_user()
1785 user5, token5 = generate_user()
1787 with session_scope() as session:
1788 c_id = create_community(session, 0, 2, "Community", [user3], [], None).id
1789 c2_id = create_community(session, 0, 2, "Community", [user4], [], None).id
1791 start = now()
1793 def new_event(hours_from_now, community_id, online=True):
1794 if online:
1795 return events_pb2.CreateEventReq(
1796 title="Dummy Online Title",
1797 content="Dummy content.",
1798 online_information=events_pb2.OnlineEventInformation(
1799 link="https://couchers.org/meet/",
1800 ),
1801 parent_community_id=community_id,
1802 timezone="UTC",
1803 start_time=Timestamp_from_datetime(start + timedelta(hours=hours_from_now)),
1804 end_time=Timestamp_from_datetime(start + timedelta(hours=hours_from_now + 0.5)),
1805 )
1806 else:
1807 return events_pb2.CreateEventReq(
1808 title="Dummy Offline Title",
1809 content="Dummy content.",
1810 offline_information=events_pb2.OfflineEventInformation(
1811 address="Near Null Island",
1812 lat=0.1,
1813 lng=0.2,
1814 ),
1815 timezone="UTC",
1816 start_time=Timestamp_from_datetime(start + timedelta(hours=hours_from_now)),
1817 end_time=Timestamp_from_datetime(start + timedelta(hours=hours_from_now + 0.5)),
1818 )
1820 with events_session(token1) as api:
1821 e2 = api.CreateEvent(new_event(2, c_id, True)).event_id
1823 with events_session(token2) as api:
1824 e1 = api.CreateEvent(new_event(1, c_id, False)).event_id
1826 with events_session(token1) as api:
1827 e3 = api.CreateEvent(new_event(3, c_id, False)).event_id
1829 with events_session(token2) as api:
1830 e5 = api.CreateEvent(new_event(5, c_id, True)).event_id
1832 with events_session(token3) as api:
1833 e4 = api.CreateEvent(new_event(4, c_id, True)).event_id
1835 with events_session(token4) as api:
1836 e6 = api.CreateEvent(new_event(6, c2_id, True)).event_id
1838 with events_session(token1) as api:
1839 api.InviteEventOrganizer(events_pb2.InviteEventOrganizerReq(event_id=e3, user_id=user3.id))
1841 with events_session(token1) as api:
1842 api.SetEventAttendance(
1843 events_pb2.SetEventAttendanceReq(event_id=e1, attendance_state=events_pb2.ATTENDANCE_STATE_MAYBE)
1844 )
1845 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=e4, subscribe=True))
1847 with events_session(token2) as api:
1848 api.SetEventAttendance(
1849 events_pb2.SetEventAttendanceReq(event_id=e3, attendance_state=events_pb2.ATTENDANCE_STATE_GOING)
1850 )
1852 with events_session(token3) as api:
1853 api.SetEventSubscription(events_pb2.SetEventSubscriptionReq(event_id=e2, subscribe=True))
1855 with events_session(token1) as api:
1856 # test pagination with token first
1857 res = api.ListMyEvents(events_pb2.ListMyEventsReq(page_size=2))
1858 assert [event.event_id for event in res.events] == [e1, e2]
1859 res = api.ListMyEvents(events_pb2.ListMyEventsReq(page_size=2, page_token=res.next_page_token))
1860 assert [event.event_id for event in res.events] == [e3, e4]
1861 assert not res.next_page_token
1863 res = api.ListMyEvents(
1864 events_pb2.ListMyEventsReq(
1865 subscribed=True,
1866 attending=True,
1867 organizing=True,
1868 )
1869 )
1870 assert [event.event_id for event in res.events] == [e1, e2, e3, e4]
1872 res = api.ListMyEvents(events_pb2.ListMyEventsReq())
1873 assert [event.event_id for event in res.events] == [e1, e2, e3, e4]
1875 res = api.ListMyEvents(events_pb2.ListMyEventsReq(subscribed=True))
1876 assert [event.event_id for event in res.events] == [e2, e3, e4]
1878 res = api.ListMyEvents(events_pb2.ListMyEventsReq(attending=True))
1879 assert [event.event_id for event in res.events] == [e1, e2, e3]
1881 res = api.ListMyEvents(events_pb2.ListMyEventsReq(organizing=True))
1882 assert [event.event_id for event in res.events] == [e2, e3]
1884 with events_session(token1) as api:
1885 # Test pagination with page_number and verify total_items
1886 res = api.ListMyEvents(
1887 events_pb2.ListMyEventsReq(page_size=2, page_number=1, subscribed=True, attending=True, organizing=True)
1888 )
1889 assert [event.event_id for event in res.events] == [e1, e2]
1890 assert res.total_items == 4
1892 res = api.ListMyEvents(
1893 events_pb2.ListMyEventsReq(page_size=2, page_number=2, subscribed=True, attending=True, organizing=True)
1894 )
1895 assert [event.event_id for event in res.events] == [e3, e4]
1896 assert res.total_items == 4
1898 # Verify no more pages
1899 res = api.ListMyEvents(
1900 events_pb2.ListMyEventsReq(page_size=2, page_number=3, subscribed=True, attending=True, organizing=True)
1901 )
1902 assert not res.events
1903 assert res.total_items == 4
1905 with events_session(token2) as api:
1906 res = api.ListMyEvents(events_pb2.ListMyEventsReq())
1907 assert [event.event_id for event in res.events] == [e1, e3, e5]
1909 res = api.ListMyEvents(events_pb2.ListMyEventsReq(subscribed=True))
1910 assert [event.event_id for event in res.events] == [e1, e5]
1912 res = api.ListMyEvents(events_pb2.ListMyEventsReq(attending=True))
1913 assert [event.event_id for event in res.events] == [e1, e3, e5]
1915 res = api.ListMyEvents(events_pb2.ListMyEventsReq(organizing=True))
1916 assert [event.event_id for event in res.events] == [e1, e5]
1918 with events_session(token3) as api:
1919 res = api.ListMyEvents(events_pb2.ListMyEventsReq())
1920 assert [event.event_id for event in res.events] == [e1, e2, e3, e4, e5]
1922 res = api.ListMyEvents(events_pb2.ListMyEventsReq(subscribed=True))
1923 assert [event.event_id for event in res.events] == [e2, e4]
1925 res = api.ListMyEvents(events_pb2.ListMyEventsReq(attending=True))
1926 assert [event.event_id for event in res.events] == [e4]
1928 res = api.ListMyEvents(events_pb2.ListMyEventsReq(organizing=True))
1929 assert [event.event_id for event in res.events] == [e3, e4]
1931 res = api.ListMyEvents(events_pb2.ListMyEventsReq(my_communities=True))
1932 assert [event.event_id for event in res.events] == [e1, e2, e3, e4, e5]
1934 with events_session(token5) as api:
1935 res = api.ListAllEvents(events_pb2.ListAllEventsReq())
1936 assert [event.event_id for event in res.events] == [e1, e2, e3, e4, e5, e6]
1939def test_RemoveEventOrganizer(db):
1940 user1, token1 = generate_user()
1941 user2, token2 = generate_user()
1943 with session_scope() as session:
1944 c_id = create_community(session, 0, 2, "Community", [user1], [], None).id
1946 with events_session(token1) as api:
1947 event_id = api.CreateEvent(
1948 events_pb2.CreateEventReq(
1949 title="Dummy Title",
1950 content="Dummy content.",
1951 offline_information=events_pb2.OfflineEventInformation(
1952 address="Near Null Island",
1953 lat=0.1,
1954 lng=0.2,
1955 ),
1956 start_time=Timestamp_from_datetime(now() + timedelta(hours=2)),
1957 end_time=Timestamp_from_datetime(now() + timedelta(hours=5)),
1958 timezone="UTC",
1959 )
1960 ).event_id
1962 with events_session(token2) as api:
1963 assert not api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).organizer
1965 with pytest.raises(grpc.RpcError) as e:
1966 api.RemoveEventOrganizer(events_pb2.RemoveEventOrganizerReq(event_id=event_id))
1967 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1968 assert e.value.details() == errors.EVENT_NOT_AN_ORGANIZER
1970 assert not api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).organizer
1972 with events_session(token1) as api:
1973 api.InviteEventOrganizer(events_pb2.InviteEventOrganizerReq(event_id=event_id, user_id=user2.id))
1975 with pytest.raises(grpc.RpcError) as e:
1976 api.RemoveEventOrganizer(events_pb2.RemoveEventOrganizerReq(event_id=event_id))
1977 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1978 assert e.value.details() == errors.EVENT_CANT_REMOVE_OWNER_AS_ORGANIZER
1980 with events_session(token2) as api:
1981 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
1982 assert res.organizer
1983 assert res.organizer_count == 2
1984 api.RemoveEventOrganizer(events_pb2.RemoveEventOrganizerReq(event_id=event_id))
1985 assert not api.GetEvent(events_pb2.GetEventReq(event_id=event_id)).organizer
1987 with pytest.raises(grpc.RpcError) as e:
1988 api.RemoveEventOrganizer(events_pb2.RemoveEventOrganizerReq(event_id=event_id))
1989 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
1990 assert e.value.details() == errors.EVENT_NOT_AN_ORGANIZER
1992 res = api.GetEvent(events_pb2.GetEventReq(event_id=event_id))
1993 assert not res.organizer
1994 assert res.organizer_count == 1
1997def test_ListEventAttendees_regression(db):
1998 # see issue #1617:
1999 #
2000 # 1. Create an event
2001 # 2. Transfer the event to a community (although this step probably not necessarily, only needed for it to show up in UI/`ListEvents` from `communities.proto`
2002 # 3. Change the current user's attendance state to "not going" (with `SetEventAttendance`)
2003 # 4. Change the current user's attendance state to "going" again
2004 #
2005 # **Expected behaviour**
2006 # `ListEventAttendees` should return the current user's ID
2007 #
2008 # **Actual/current behaviour**
2009 # `ListEventAttendees` returns another user's ID. This ID seems to be determined from the row's auto increment ID in `event_occurrence_attendees` in the database
2011 user1, token1 = generate_user()
2012 user2, token2 = generate_user()
2013 user3, token3 = generate_user()
2014 user4, token4 = generate_user()
2015 user5, token5 = generate_user()
2017 with session_scope() as session:
2018 c_id = create_community(session, 0, 2, "Community", [user1], [], None).id
2020 start_time = now() + timedelta(hours=2)
2021 end_time = start_time + timedelta(hours=3)
2023 with events_session(token1) as api:
2024 res = api.CreateEvent(
2025 events_pb2.CreateEventReq(
2026 title="Dummy Title",
2027 content="Dummy content.",
2028 online_information=events_pb2.OnlineEventInformation(
2029 link="https://couchers.org",
2030 ),
2031 parent_community_id=c_id,
2032 start_time=Timestamp_from_datetime(start_time),
2033 end_time=Timestamp_from_datetime(end_time),
2034 timezone="UTC",
2035 )
2036 )
2038 res = api.TransferEvent(
2039 events_pb2.TransferEventReq(
2040 event_id=res.event_id,
2041 new_owner_community_id=c_id,
2042 )
2043 )
2045 event_id = res.event_id
2047 api.SetEventAttendance(
2048 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_NOT_GOING)
2049 )
2050 api.SetEventAttendance(
2051 events_pb2.SetEventAttendanceReq(event_id=event_id, attendance_state=events_pb2.ATTENDANCE_STATE_GOING)
2052 )
2054 res = api.ListEventAttendees(events_pb2.ListEventAttendeesReq(event_id=event_id))
2055 assert len(res.attendee_user_ids) == 1
2056 assert res.attendee_user_ids[0] == user1.id
2059def test_event_threads(db):
2060 user1, token1 = generate_user()
2061 user2, token2 = generate_user()
2062 user3, token3 = generate_user()
2063 user4, token4 = generate_user()
2065 with session_scope() as session:
2066 c = create_community(session, 0, 2, "Community", [user3], [], None)
2067 h = create_group(session, "Group", [user4], [], c)
2068 c_id = c.id
2069 h_id = h.id
2071 with events_session(token1) as api:
2072 event = api.CreateEvent(
2073 events_pb2.CreateEventReq(
2074 title="Dummy Title",
2075 content="Dummy content.",
2076 offline_information=events_pb2.OfflineEventInformation(
2077 address="Near Null Island",
2078 lat=0.1,
2079 lng=0.2,
2080 ),
2081 start_time=Timestamp_from_datetime(now() + timedelta(hours=2)),
2082 end_time=Timestamp_from_datetime(now() + timedelta(hours=5)),
2083 timezone="UTC",
2084 )
2085 )
2087 with threads_session(token2) as api:
2088 reply_id = api.PostReply(threads_pb2.PostReplyReq(thread_id=event.thread.thread_id, content="hi")).thread_id
2090 with events_session(token3) as api:
2091 res = api.GetEvent(events_pb2.GetEventReq(event_id=event.event_id))
2092 assert res.thread.num_responses == 1
2094 with threads_session(token3) as api:
2095 ret = api.GetThread(threads_pb2.GetThreadReq(thread_id=res.thread.thread_id))
2096 assert len(ret.replies) == 1
2097 assert not ret.next_page_token
2098 assert ret.replies[0].thread_id == reply_id
2099 assert ret.replies[0].content == "hi"
2100 assert ret.replies[0].author_user_id == user2.id
2101 assert ret.replies[0].num_replies == 0
2104def test_can_overlap_other_events_schedule_regression(db):
2105 # we had a bug where we were checking overlapping for *all* occurrences of *all* events, not just the ones for this event
2106 user, token = generate_user()
2108 with session_scope() as session:
2109 c_id = create_community(session, 0, 2, "Community", [user], [], None).id
2111 start = now()
2113 with events_session(token) as api:
2114 # create another event, should be able to overlap with this one
2115 api.CreateEvent(
2116 events_pb2.CreateEventReq(
2117 title="Dummy Title",
2118 content="Dummy content.",
2119 parent_community_id=c_id,
2120 online_information=events_pb2.OnlineEventInformation(
2121 link="https://couchers.org/meet/",
2122 ),
2123 start_time=Timestamp_from_datetime(start + timedelta(hours=1)),
2124 end_time=Timestamp_from_datetime(start + timedelta(hours=5)),
2125 timezone="UTC",
2126 )
2127 )
2129 # this event
2130 res = api.CreateEvent(
2131 events_pb2.CreateEventReq(
2132 title="Dummy Title",
2133 content="Dummy content.",
2134 parent_community_id=c_id,
2135 online_information=events_pb2.OnlineEventInformation(
2136 link="https://couchers.org/meet/",
2137 ),
2138 start_time=Timestamp_from_datetime(start + timedelta(hours=1)),
2139 end_time=Timestamp_from_datetime(start + timedelta(hours=2)),
2140 timezone="UTC",
2141 )
2142 )
2144 # this doesn't overlap with the just created event, but does overlap with the occurrence from earlier; which should be no problem
2145 api.ScheduleEvent(
2146 events_pb2.ScheduleEventReq(
2147 event_id=res.event_id,
2148 content="New event occurrence",
2149 offline_information=events_pb2.OfflineEventInformation(
2150 address="A bit further but still near Null Island",
2151 lat=0.3,
2152 lng=0.2,
2153 ),
2154 start_time=Timestamp_from_datetime(start + timedelta(hours=3)),
2155 end_time=Timestamp_from_datetime(start + timedelta(hours=6)),
2156 timezone="UTC",
2157 )
2158 )
2161def test_can_overlap_other_events_update_regression(db):
2162 user, token = generate_user()
2164 with session_scope() as session:
2165 c_id = create_community(session, 0, 2, "Community", [user], [], None).id
2167 start = now()
2169 with events_session(token) as api:
2170 # create another event, should be able to overlap with this one
2171 api.CreateEvent(
2172 events_pb2.CreateEventReq(
2173 title="Dummy Title",
2174 content="Dummy content.",
2175 parent_community_id=c_id,
2176 online_information=events_pb2.OnlineEventInformation(
2177 link="https://couchers.org/meet/",
2178 ),
2179 start_time=Timestamp_from_datetime(start + timedelta(hours=1)),
2180 end_time=Timestamp_from_datetime(start + timedelta(hours=3)),
2181 timezone="UTC",
2182 )
2183 )
2185 res = api.CreateEvent(
2186 events_pb2.CreateEventReq(
2187 title="Dummy Title",
2188 content="Dummy content.",
2189 parent_community_id=c_id,
2190 online_information=events_pb2.OnlineEventInformation(
2191 link="https://couchers.org/meet/",
2192 ),
2193 start_time=Timestamp_from_datetime(start + timedelta(hours=7)),
2194 end_time=Timestamp_from_datetime(start + timedelta(hours=8)),
2195 timezone="UTC",
2196 )
2197 )
2199 event_id = api.ScheduleEvent(
2200 events_pb2.ScheduleEventReq(
2201 event_id=res.event_id,
2202 content="New event occurrence",
2203 offline_information=events_pb2.OfflineEventInformation(
2204 address="A bit further but still near Null Island",
2205 lat=0.3,
2206 lng=0.2,
2207 ),
2208 start_time=Timestamp_from_datetime(start + timedelta(hours=4)),
2209 end_time=Timestamp_from_datetime(start + timedelta(hours=6)),
2210 timezone="UTC",
2211 )
2212 ).event_id
2214 # can overlap with this current existing occurrence
2215 api.UpdateEvent(
2216 events_pb2.UpdateEventReq(
2217 event_id=event_id,
2218 start_time=Timestamp_from_datetime(start + timedelta(hours=5)),
2219 end_time=Timestamp_from_datetime(start + timedelta(hours=6)),
2220 )
2221 )
2223 api.UpdateEvent(
2224 events_pb2.UpdateEventReq(
2225 event_id=event_id,
2226 start_time=Timestamp_from_datetime(start + timedelta(hours=2)),
2227 end_time=Timestamp_from_datetime(start + timedelta(hours=4)),
2228 )
2229 )
2232def test_list_past_events_regression(db):
2233 # test for a bug where listing past events didn't work if they didn't have a future occurrence
2234 user, token = generate_user()
2236 with session_scope() as session:
2237 c_id = create_community(session, 0, 2, "Community", [user], [], None).id
2239 start = now()
2241 with events_session(token) as api:
2242 api.CreateEvent(
2243 events_pb2.CreateEventReq(
2244 title="Dummy Title",
2245 content="Dummy content.",
2246 parent_community_id=c_id,
2247 online_information=events_pb2.OnlineEventInformation(
2248 link="https://couchers.org/meet/",
2249 ),
2250 start_time=Timestamp_from_datetime(start + timedelta(hours=3)),
2251 end_time=Timestamp_from_datetime(start + timedelta(hours=4)),
2252 timezone="UTC",
2253 )
2254 )
2256 with session_scope() as session:
2257 session.execute(
2258 update(EventOccurrence).values(
2259 during=DateTimeTZRange(start + timedelta(hours=-5), start + timedelta(hours=-4))
2260 )
2261 )
2263 with events_session(token) as api:
2264 res = api.ListAllEvents(events_pb2.ListAllEventsReq(past=True))
2265 assert len(res.events) == 1
2268def test_community_invite_requests(db):
2269 user1, token1 = generate_user(complete_profile=True)
2270 user2, token2 = generate_user()
2271 user3, token3 = generate_user()
2272 user4, token4 = generate_user()
2273 user5, token5 = generate_user(is_superuser=True)
2275 with session_scope() as session:
2276 w = create_community(session, 0, 2, "World Community", [user5], [], None)
2277 c_id = create_community(session, 0, 2, "Community", [user1, user3, user4], [], w).id
2279 enforce_community_memberships()
2281 with events_session(token1) as api:
2282 res = api.CreateEvent(
2283 events_pb2.CreateEventReq(
2284 title="Dummy Title",
2285 content="Dummy content.",
2286 parent_community_id=c_id,
2287 online_information=events_pb2.OnlineEventInformation(
2288 link="https://couchers.org/meet/",
2289 ),
2290 start_time=Timestamp_from_datetime(now() + timedelta(hours=3)),
2291 end_time=Timestamp_from_datetime(now() + timedelta(hours=4)),
2292 timezone="UTC",
2293 )
2294 )
2295 user_url = f"http://localhost:3000/user/{user1.username}"
2296 event_url = f"http://localhost:3000/event/{res.event_id}/{res.slug}"
2298 event_id = res.event_id
2300 with mock_notification_email() as mock:
2301 api.RequestCommunityInvite(events_pb2.RequestCommunityInviteReq(event_id=event_id))
2302 assert mock.call_count == 1
2303 e = email_fields(mock)
2304 assert e.recipient == "mods@couchers.org.invalid"
2306 assert user_url in e.plain
2307 assert event_url in e.plain
2309 # can't send another req
2310 with pytest.raises(grpc.RpcError) as e:
2311 api.RequestCommunityInvite(events_pb2.RequestCommunityInviteReq(event_id=event_id))
2312 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
2313 assert e.value.details() == errors.EVENT_COMMUNITY_INVITE_ALREADY_REQUESTED
2315 # another user can send one though
2316 with events_session(token3) as api:
2317 api.RequestCommunityInvite(events_pb2.RequestCommunityInviteReq(event_id=event_id))
2319 # but not a non-admin
2320 with events_session(token2) as api:
2321 with pytest.raises(grpc.RpcError) as e:
2322 api.RequestCommunityInvite(events_pb2.RequestCommunityInviteReq(event_id=event_id))
2323 assert e.value.code() == grpc.StatusCode.PERMISSION_DENIED
2324 assert e.value.details() == errors.EVENT_EDIT_PERMISSION_DENIED
2326 with real_admin_session(token5) as admin:
2327 res = admin.ListEventCommunityInviteRequests(admin_pb2.ListEventCommunityInviteRequestsReq())
2328 assert len(res.requests) == 2
2329 assert res.requests[0].user_id == user1.id
2330 assert res.requests[0].approx_users_to_notify == 3
2331 assert res.requests[1].user_id == user3.id
2332 assert res.requests[1].approx_users_to_notify == 3
2334 admin.DecideEventCommunityInviteRequest(
2335 admin_pb2.DecideEventCommunityInviteRequestReq(
2336 event_community_invite_request_id=res.requests[0].event_community_invite_request_id,
2337 approve=False,
2338 )
2339 )
2341 admin.DecideEventCommunityInviteRequest(
2342 admin_pb2.DecideEventCommunityInviteRequestReq(
2343 event_community_invite_request_id=res.requests[1].event_community_invite_request_id,
2344 approve=True,
2345 )
2346 )
2348 # not after approve
2349 with events_session(token4) as api:
2350 with pytest.raises(grpc.RpcError) as e:
2351 api.RequestCommunityInvite(events_pb2.RequestCommunityInviteReq(event_id=event_id))
2352 assert e.value.code() == grpc.StatusCode.FAILED_PRECONDITION
2353 assert e.value.details() == errors.EVENT_COMMUNITY_INVITE_ALREADY_APPROVED