def test_api_override_serialization(db, api_client, default_namespace, recurring_event): event = recurring_event override = Event.create( original_start_time=event.start, master_event_uid=event.uid, namespace_id=default_namespace.id, calendar_id=event.calendar_id, ) override.update(event) override.uid = event.uid + "_" + event.start.strftime("%Y%m%dT%H%M%SZ") override.master = event override.master_event_uid = event.uid override.cancelled = True db.session.add(override) db.session.commit() filter = "starts_after={}&ends_before={}".format( urlsafe(event.start.shift(hours=-1)), urlsafe(event.start.shift(weeks=+1)) ) events = api_client.get_data("/events?" + filter) # We should have the base event and the override back, but no extras; # this allows clients to do their own expansion, should they ever desire # to experience the joy that is RFC 2445 section 4.8.5.4. assert len(events) == 2 assert events[0].get("object") == "event" assert events[0].get("recurrence") is not None assert events[1].get("object") == "event" assert events[1].get("status") == "cancelled"
def event_response_with_update(calendar_uid, sync_from_time): if calendar_uid == "first_calendar_uid": return [ Event.create(uid="first_event_uid", title="Top Secret Plotting Meeting", **default_params) ]
def event_response_with_delete(calendar_uid, sync_from_time): if calendar_uid == "first_calendar_uid": return [ Event.create(uid="first_event_uid", status="cancelled", **default_params) ]
def event_response_with_participants_update(calendar_uid, sync_from_time): if calendar_uid == "first_calendar_uid": new_events = [Event.create(uid="first_event_uid", **default_params)] new_events[0].participants = [{ "name": "Johnny Thunders", "email": "*****@*****.**" }] return new_events
def event_response(calendar_uid, sync_from_time): if calendar_uid == "first_calendar_uid": return [ Event.create(uid="first_event_uid", title="Plotting Meeting", **default_params), Event.create(uid="second_event_uid", title="Scheming meeting", **default_params), Event.create(uid="third_event_uid", title="Innocent Meeting", **default_params), ] else: return [ Event.create(uid="second_event_uid", title="Plotting Meeting", **default_params), Event.create(uid="third_event_uid", title="Scheming meeting", **default_params), ]
def noop_event_update(event, data): # Check whether the update is actually updating fields. # We do this by cloning the event, updating the fields and # comparing them. This is less cumbersome than having to think # about the multiple values of the `when` field. e = Event.create() e.update(event) e.namespace = event.namespace for attr in Event.API_MODIFIABLE_FIELDS: if attr in data: setattr(e, attr, data[attr]) e1 = encode(event) e2 = encode(e) for attr in Event.API_MODIFIABLE_FIELDS: # We have to handle participants a bit differently because # it's a list which can be permuted. if attr == "participants": continue event_value = e1.get(attr) e_value = e2.get(attr) if event_value != e_value: return False e_participants = {p["email"]: p for p in e.participants} event_participants = {p["email"]: p for p in event.participants} if len(e_participants.keys()) != len(event_participants.keys()): return False for email in e_participants: if email not in event_participants: return False p1 = e_participants[email] p2 = event_participants[email] p1_status = p1.get("status") p2_status = p2.get("status") if p1_status != p2_status: return False p1_comment = p1.get("comment") p2_comment = p2.get("comment") if p1_comment != p2_comment: return False return True
def add_fake_event( db_session, namespace_id, calendar=None, title="title", description="", location="", busy=False, read_only=False, reminders="", recurrence="", start=None, end=None, all_day=False, ): from inbox.models import Event start = start or datetime.utcnow() end = end or (datetime.utcnow() + timedelta(seconds=1)) calendar = calendar or add_fake_calendar(db_session, namespace_id) event = Event.create( namespace_id=namespace_id, calendar=calendar, title=title, description=description, location=location, busy=busy, read_only=read_only, reminders=reminders, recurrence=recurrence, start=start, end=end, all_day=all_day, raw_data="", uid=str(uuid.uuid4()), ) event.sequence_number = 0 db_session.add(event) db_session.commit() return event
def test_handle_offset_all_day_events(): raw_event = { "created": "2014-01-09T03:33:02.000Z", "creator": { "displayName": "Ben Bitdiddle", "email": "*****@*****.**", "self": True, }, "etag": '"2778476764000000"', "htmlLink": "https://www.google.com/calendar/event?eid=BAR", "iCalUID": "*****@*****.**", "id": "20140615_60o30dr564o30c1g60o30dr4ck", "kind": "calendar#event", "organizer": { "displayName": "Ben Bitdiddle", "email": "*****@*****.**", "self": True, }, "sequence": 0, "start": {"date": "2014-03-15"}, "end": {u"date": "2014-03-15"}, "status": "confirmed", "summary": "Ides of March", "transparency": "transparent", "updated": "2014-01-09T03:33:02.000Z", "visibility": "public", } expected = Event.create( uid="20140615_60o30dr564o30c1g60o30dr4ck", title="Ides of March", description=None, read_only=False, busy=False, start=arrow.get(2014, 3, 15), end=arrow.get(2014, 3, 15), all_day=True, owner="Ben Bitdiddle <*****@*****.**>", participants=[], ) assert cmp_event_attrs(expected, parse_event_response(raw_event, False))
def _make_recurring_event(**kwargs): default_kwargs = { "namespace_id": default_namespace.id, "title": "recurring-weekly", "description": "", "uid": "recurapitest", "location": "", "busy": False, "read_only": False, "reminders": "", "recurrence": [ "RRULE:FREQ=WEEKLY", "EXDATE:20150324T013000,20150331T013000Z", ], "start": arrow.get(2015, 3, 17, 1, 30, 0), "end": arrow.get(2015, 3, 17, 1, 45, 0), "all_day": False, "is_owner": True, "participants": [], "provider_name": "inbox", "raw_data": "", "original_start_tz": "America/Los_Angeles", "original_start_time": None, "master_event_uid": None, "source": "local", } if "calendar" not in kwargs: default_kwargs["calendar"] = ( db.session.query(Calendar) .filter_by(namespace_id=default_namespace.id) .order_by("id") .first() ) default_kwargs.update(kwargs) ev = Event.create(**default_kwargs) db.session.add(ev) db.session.commit() return ev
def test_event_parsing(): raw_response = [ { "created": "2012-10-09T22:35:50.000Z", "creator": { "displayName": "Eben Freeman", "email": "*****@*****.**", "self": True, }, "end": {"dateTime": "2012-10-15T18:00:00-07:00"}, "etag": '"2806773858144000"', "htmlLink": "https://www.google.com/calendar/event?eid=FOO", "iCalUID": "*****@*****.**", "id": "tn7krk4cekt8ag3pk6gapqqbro", "kind": "calendar#event", "organizer": { "displayName": "Eben Freeman", "email": "*****@*****.**", "self": True, }, "attendees": [ { "displayName": "MITOC BOD", "email": "*****@*****.**", "responseStatus": "accepted", }, { "displayName": "Eben Freeman", "email": "*****@*****.**", "responseStatus": "accepted", }, ], "reminders": {"useDefault": True}, "recurrence": ["RRULE:FREQ=WEEKLY;UNTIL=20150209T075959Z;BYDAY=MO"], "sequence": 0, "start": {"dateTime": "2012-10-15T17:00:00-07:00"}, "status": "confirmed", "summary": "BOD Meeting", "updated": "2014-06-21T21:42:09.072Z", }, { "created": "2014-01-09T03:33:02.000Z", "creator": { "displayName": "Holidays in United States", "email": "en.usa#[email protected]", "self": True, }, "end": {u"date": "2014-06-16"}, "etag": '"2778476764000000"', "htmlLink": "https://www.google.com/calendar/event?eid=BAR", "iCalUID": "*****@*****.**", "id": "20140615_60o30dr564o30c1g60o30dr4ck", "kind": "calendar#event", "organizer": { "displayName": "Holidays in United States", "email": "en.usa#[email protected]", "self": True, }, "sequence": 0, "start": {"date": "2014-06-15"}, "status": "confirmed", "summary": "Fathers' Day", "transparency": "transparent", "updated": "2014-01-09T03:33:02.000Z", "visibility": "public", }, { "created": "2015-03-10T01:19:59.000Z", "creator": { "displayName": "Ben Bitdiddle", "email": "*****@*****.**", "self": True, }, "end": {u"date": "2015-03-11"}, "etag": '"2851906839480000"', "htmlLink": "https://www.google.com/calendar/event?eid=BAZ", "iCalUID": "*****@*****.**", "id": "3uisajkmdjqo43tfc3ig1l5hek", "kind": "calendar#event", "organizer": { "displayName": "Ben Bitdiddle", "email": "*****@*****.**", "self": True, }, "reminders": {u"useDefault": False}, "sequence": 1, "start": {u"date": "2015-03-10"}, "status": "cancelled", "summary": "TUESDAY", "transparency": "transparent", "updated": "2015-03-10T02:10:19.740Z", }, ] expected_deletes = ["3uisajkmdjqo43tfc3ig1l5hek"] expected_updates = [ Event.create( uid="tn7krk4cekt8ag3pk6gapqqbro", title="BOD Meeting", description=None, read_only=False, start=arrow.get(2012, 10, 16, 0, 0, 0), end=arrow.get(2012, 10, 16, 1, 0, 0), all_day=False, busy=True, owner="Eben Freeman <*****@*****.**>", recurrence=["RRULE:FREQ=WEEKLY;UNTIL=20150209T075959Z;BYDAY=MO"], participants=[ { "email": "*****@*****.**", "name": "MITOC BOD", "status": "yes", "notes": None, }, { "email": "*****@*****.**", "name": "Eben Freeman", "status": "yes", "notes": None, }, ], ), Event.create( uid="20140615_60o30dr564o30c1g60o30dr4ck", title="Fathers' Day", description=None, read_only=False, busy=False, start=arrow.get(2014, 6, 15), end=arrow.get(2014, 6, 15), all_day=True, owner="Holidays in United States <en.usa#[email protected]>", participants=[], ), ] provider = GoogleEventsProvider(1, 1) provider.calendars_table = {"uid": False} provider._get_raw_events = mock.MagicMock(return_value=raw_response) updates = provider.sync_events("uid", 1) # deleted events are actually only marked as # cancelled. Look for them in the updates stream. found_cancelled_event = False for event in updates: if event.uid in expected_deletes and event.status == "cancelled": found_cancelled_event = True break assert found_cancelled_event for obtained, expected in zip(updates, expected_updates): print(obtained, expected) assert cmp_event_attrs(obtained, expected) # Test read-only support raw_response = [ { "created": "2014-01-09T03:33:02.000Z", "creator": { "displayName": "Holidays in United States", "email": "en.usa#[email protected]", "self": True, }, "end": {u"date": "2014-06-16"}, "etag": '"2778476764000000"', "htmlLink": "https://www.google.com/calendar/event?eid=BAR", "iCalUID": "*****@*****.**", "id": "20140615_60o30dr564o30c1g60o30dr4ck", "kind": "calendar#event", "organizer": { "displayName": "Holidays in United States", "email": "en.usa#[email protected]", "self": True, }, "sequence": 0, "start": {"date": "2014-06-15"}, "status": "confirmed", "summary": "Fathers' Day", "transparency": "transparent", "updated": "2014-01-09T03:33:02.000Z", "visibility": "public", "guestCanModify": True, } ] provider = GoogleEventsProvider(1, 1) # This is a read-only calendar provider.calendars_table = {"uid": True} provider._get_raw_events = mock.MagicMock(return_value=raw_response) updates = provider.sync_events("uid", 1) assert len(updates) == 1 assert updates[0].read_only is True