class TestSimpleVEvent(TestCase): def setUp(self): site = Site.objects.get(is_default_site=True) site.hostname = "joy.test" site.save() self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() def testFromPage(self): page = SimpleEventPage(owner=self.user, slug="pet-show", title="Pet Show", date=dt.date(1987, 6, 5), time_from=dt.time(11), time_to=dt.time(17, 30), tz=pytz.timezone("Australia/Sydney")) self.calendar.add_child(instance=page) page.save_revision().publish() vev = SimpleVEvent.fromPage(page) tz = pytz.timezone("Australia/Sydney") self.assertEqual(vev['dtstart'].dt, tz.localize(dt.datetime(1987, 6, 5, 11, 0)))
def testSubSiteAnotherCalendar(self): calendar = CalendarPage(owner = self.user, slug = "events", title = "Events") self.main.add_child(instance=calendar) calendar.save_revision().publish() self.assertTrue(CalendarPage.can_create_at(self.sub))
class TestMultidayVEvent(TestCase): def setUp(self): site = Site.objects.get(is_default_site=True) site.hostname = "joy.test" site.save() self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() def testFromPage(self): page = MultidayEventPage(owner=self.user, slug="niuekulele2018", title="Niuekulele Ukulele Music Festival", date_from=dt.date(2018, 3, 16), date_to=dt.date(2018, 3, 20), tz=pytz.timezone("Pacific/Niue")) self.calendar.add_child(instance=page) page.save_revision().publish() vev = MultidayVEvent.fromPage(page) tz = pytz.timezone("Pacific/Niue") self.assertEqual(vev['dtstart'].dt, tz.localize(dt.datetime(2018, 3, 16, 0, 0))) self.assertEqual( vev['dtend'].dt, tz.localize(dt.datetime(2018, 3, 20, 23, 59, 59, 999999)))
class TestMultiday(TestCase): def setUp(self): site = Site.objects.get(is_default_site=True) site.hostname = "joy.test" site.save() self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() def testFromPage(self): page = MultidayEventPage(owner=self.user, slug="kainiue-food-festival", title="KaiNiue Food Festival", date_from=dt.date(2018, 11, 2), date_to=dt.date(2018, 11, 5), tz=pytz.timezone("Pacific/Niue")) self.calendar.add_child(instance=page) page.save_revision().publish() gev = MultidayGEvent.fromPage(page) self.assertEqual(gev['dates'], "20181102T000000/20181105T235959") self.assertEqual(gev['ctz'], "Pacific/Niue")
class TestTZ(TestCase): def setUp(self): self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3(r3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.event = RecurringEventPage(slug="test-meeting", title="Test Meeting", repeat=Recurrence( dtstart=dt.date(1989, 1, 1), freq=WEEKLY, byweekday=[MO, WE, FR]), time_from=dt.time(13, 30), time_to=dt.time(16), tz=pytz.timezone("US/Eastern")) self.calendar.add_child(instance=self.event) self.cancellation = CancellationPage( owner=self.user, overrides=self.event, except_date=dt.date(1989, 2, 1), cancellation_title="Meeting Cancelled", cancellation_details="Cancelled due to lack of interest") self.event.add_child(instance=self.cancellation) self.cancellation.save_revision().publish() @timezone.override("Australia/Sydney") @freeze_timetz("1989-02-02T06:00:00+11:00") def testCurrentLocalDt(self): when = self.cancellation._current_datetime_from self.assertEqual(when.tzinfo.zone, "Australia/Sydney") self.assertEqual(when.time(), dt.time(5, 30)) self.assertEqual(when.date(), dt.date(1989, 2, 2)) @timezone.override("Australia/Sydney") @freeze_timetz("1989-02-02T06:00:00+11:00") def testFutureLocalDt(self): when = self.cancellation._future_datetime_from self.assertIsNone(when) @timezone.override("Australia/Sydney") def testPastLocalDt(self): when = self.cancellation._past_datetime_from self.assertEqual(when.tzinfo.zone, "Australia/Sydney") self.assertEqual(when.time(), dt.time(5, 30)) self.assertEqual(when.date(), dt.date(1989, 2, 2)) @timezone.override("Australia/Sydney") @freeze_timetz("1989-10-01T21:00:00+11:00") def testCopyFieldsFromParent(self): self.assertEqual(self.event.next_date, dt.date(1989, 10, 3)) cancellation = CancellationPage(owner=self.user) cancellation._copyFieldsFromParent(self.event) self.assertEqual(cancellation.overrides, self.event) self.assertEqual(cancellation.except_date, dt.date(1989, 10, 2))
class Test40Day(TestCase): def setUp(self): self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") Page.objects.get(slug='home').add_child(instance=self.calendar) self.calendar.save() self.calendar.save_revision().publish() self.event = MultidayRecurringEventPage( owner=self.user, slug="ice-festival", title="Ice Festival", repeat=Recurrence(dtstart=dt.date(2000, 12, 25), until=dt.date(2020, 1, 31), freq=YEARLY, bymonth=12, byweekday=MO(4)), num_days=40) self.calendar.add_child(instance=self.event) self.event.save_revision().publish() def testGetEventsByDay(self): events = MultidayRecurringEventPage.events.byDay( dt.date(2020, 1, 1), dt.date(2020, 1, 31)) self.assertEqual(len(events), 31) evod = events[0] self.assertEqual(evod.date, dt.date(2020, 1, 1)) self.assertEqual(len(evod.days_events), 0) self.assertEqual(len(evod.continuing_events), 1) thisEvent = evod.continuing_events[0] self.assertEqual(thisEvent.title, "Ice Festival") evod = events[10] self.assertEqual(evod.date, dt.date(2020, 1, 11)) self.assertEqual(len(evod.continuing_events), 1) thisEvent = evod.continuing_events[0] self.assertEqual(thisEvent.title, "Ice Festival") def testStatus(self): with freeze_timetz("2019-12-20 13:00:00"): self.assertEqual(self.event.status_text, "") with freeze_timetz("2020-01-02 13:00:00"): self.assertEqual(self.event.status_text, "This event has started.") with freeze_timetz("2020-02-03 17:00:00"): self.assertEqual(self.event.status_text, "These events have finished.") def testAt(self): self.assertEqual(self.event.at.strip(), "") @freeze_timetz("2035-04-03 10:00:00") def testNextDate(self): self.assertEqual(self.event.next_date, None) @freeze_timetz("2035-04-03 10:00:00") def testPrevDate(self): self.assertEqual(self.event.prev_date, dt.date(2019, 12, 23))
class TestTZ(TestCase): def setUp(self): self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.event = MultidayEventPage( owner=self.user, slug="niuekulele2018", title="Niuekulele Ukulele Music Festival", date_from=dt.date(2018, 3, 16), date_to=dt.date(2018, 3, 20), tz=pytz.timezone("Pacific/Niue")) self.calendar.add_child(instance=self.event) self.event.save_revision().publish() def testGetEventsByLocalDay(self): events = MultidayEventPage.events.byDay(dt.date(2018, 3, 1), dt.date(2018, 3, 31)) self.assertEqual(len(events), 31) evod1 = events[16] self.assertEqual(evod1.date, dt.date(2018, 3, 17)) self.assertEqual(len(evod1.days_events), 1) self.assertEqual(len(evod1.continuing_events), 0) evod5 = events[20] self.assertEqual(evod5.date, dt.date(2018, 3, 21)) self.assertEqual(len(evod5.days_events), 0) self.assertEqual(len(evod5.continuing_events), 1) self.assertEqual(evod1.all_events[0], evod5.all_events[0]) self.assertEqual(evod1.all_events[0].page, evod5.all_events[0].page) @freeze_time("2018-04-01") def testLocalWhen(self): self.assertEqual(self.event.when, "Friday 16th of March to Wednesday 21st of March") def testLocalAt(self): self.assertEqual(self.event.at, "") @timezone.override("America/Los_Angeles") def testCurrentLocalDt(self): self.assertIsNone(self.event._current_datetime_from) @timezone.override("America/Los_Angeles") def testFutureLocalDt(self): self.assertIsNone(self.event._future_datetime_from) @timezone.override("Pacific/Auckland") def testPastLocalDt(self): when = self.event._past_datetime_from self.assertEqual(when.tzinfo.zone, "Pacific/Auckland") self.assertEqual(when.time(), dt.time.max) self.assertEqual(when.date(), dt.date(2018, 3, 17))
def setUp(self): self.user = User.objects.create_user('i', '*****@*****.**', 's3(r3t') calendar = CalendarPage(owner = self.user, slug = "events", title = "Events") Page.objects.get(slug='home').add_child(instance=calendar) calendar.save_revision().publish() event = SimpleEventPage(owner = self.user, slug = "tree-planting", title = "Tree Planting", date = dt.date(2011,6,5), time_from = dt.time(9,30), time_to = dt.time(11,0)) calendar.add_child(instance=event) event.save_revision().publish()
def setUp(self): translation.activate('fr') self.user = User.objects.create_superuser('i', '*****@*****.**', 's3(r3t') calendar = CalendarPage(owner=self.user, slug="calendrier", title="Calendrier") Page.objects.get(slug='home').add_child(instance=calendar) calendar.save_revision().publish() event = SimpleEventPage(owner=self.user, slug="plantation-d-arbres", title="Plantation d'arbres", date=dt.date(2011, 6, 5), time_from=dt.time(9, 30), time_to=dt.time(11, 0)) calendar.add_child(instance=event) event.save_revision().publish()
class TestRecurring(TestCase): def setUp(self): site = Site.objects.get(is_default_site=True) site.hostname = "joy.test" site.save() self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() def testFromPage(self): page = RecurringEventPage(owner=self.user, slug="lunch-and-code", title="Lunch and Code", details="What we'll do really depends on " "what the group feels is useful, " "some ideas are:\n" "- Providing feedback on past, or " "in progress, projects\n" "- Pair programming\n" "- Coding\n", repeat=Recurrence(dtstart=dt.date( 2017, 3, 15), freq=MONTHLY, byweekday=[FR(-1)]), time_from=dt.time(12), time_to=dt.time(13), tz=pytz.timezone("Pacific/Auckland"), location="70 Molesworth Street, Wellington") self.calendar.add_child(instance=page) page.save_revision().publish() gev = RecurringGEvent.fromPage(page) self.assertEqual( gev.url, "http://www.google.com/calendar/event?" "action=TEMPLATE&" "text=Lunch+and+Code&" "details=What+we%27ll+do+really+depends+on+what+the+" "group+feels+is+useful%2C+some+ideas+are%3A%0A" "-+Providing+feedback+on+past%2C+or+in+progress%2C+projects%0A" "-+Pair+programming%0A-+Coding%0A&" "location=70+Molesworth+Street%2C+Wellington&" "dates=20170331T120000%2F20170331T130000&" "ctz=Pacific%2FAuckland&" "recur=RRULE%3AFREQ%3DMONTHLY%3BWKST%3DSU%3BBYDAY%3D-1FR")
def testCalendarMixture(self): general = GeneralCalendarPage(owner=self.user, slug="events1", title="Events") self.main.add_child(instance=general) general.save_revision().publish() self.assertTrue(CalendarPage.can_create_at(self.main)) calendar = CalendarPage(owner=self.user, slug="events2", title="Events") self.main.add_child(instance=calendar) calendar.save_revision().publish() self.assertTrue(SpecificCalendarPage.can_create_at(self.main)) specific = SpecificCalendarPage(owner=self.user, slug="events3", title="Events") self.main.add_child(instance=specific) specific.save_revision().publish()
class TestWagtailHooks(TestCase): def setUp(self): self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3(r3t') self.page = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.page) self.page.save_revision().publish() @patch("ls.joyous.wagtail_hooks.ICalHandler") def testICalExport(self, Handler): request = RequestFactory().get("/test?format=ical") handlePageExport(self.page, request, [], {}) Handler.assert_called_with() Handler().serve.assert_called_with(self.page, request, [], {}) @patch("ls.joyous.wagtail_hooks.GoogleCalendarHandler") def testGoogleExport(self, Handler): request = RequestFactory().get("/test?format=google") handlePageExport(self.page, request, [], {}) Handler.assert_called_with() Handler().serve.assert_called_with(self.page, request, [], {}) @patch("ls.joyous.wagtail_hooks.RssHandler") def testRssExport(self, Handler): request = RequestFactory().get("/test?format=rss") handlePageExport(self.page, request, [], {}) Handler.assert_called_with() Handler().serve.assert_called_with(self.page, request, [], {}) @patch("ls.joyous.wagtail_hooks.NullHandler") def testNullExport(self, Handler): request = RequestFactory().get("/test") handlePageExport(self.page, request, [], {}) Handler.assert_called_with() Handler().serve.assert_called_with(self.page, request, [], {}) def testStashRequest(self): request = RequestFactory().get("/test") stashRequest(request, self.page) self.assertEqual(getattr(self.page, '__joyous_edit_request'), request) delattr(self.page, '__joyous_edit_request')
class TestExport(TestCase): def setUp(self): Site.objects.update(hostname="joy.test") self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3(R3t') self.requestFactory = RequestFactory() self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.dicerun = SimpleEventPage(owner=self.user, slug="mercy-dice-run", title="Mercy Dice Run", date=dt.date(2020, 3, 16), location="Newtown") self.calendar.add_child(instance=self.dicerun) self.dicerun.save_revision().publish() event = SimpleEventPage(owner=self.user, slug="workshop", title="Workshop", date=dt.date(2020, 3, 22)) self.calendar.add_child(instance=event) event.save_revision().publish() self.handler = RssHandler() def _getRequest(self, path="/"): request = self.requestFactory.get(path) request.user = self.user request.site = self.home.get_site() request.session = {} request._messages = FallbackStorage(request) request.POST = request.POST.copy() request.POST['action-publish'] = "action-publish" return request def testServeCalendar(self): response = self.handler.serve(self.calendar, self._getRequest("/events/")) self.assertEqual(response.status_code, 200) self.assertEqual(response.get('Content-Type'), "application/xml; charset=utf-8")
class TestPageFormDeutsche(TestCase): Form = ExtraInfoPage.get_edit_handler().get_form_class() def setUp(self): translation.activate('de') self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3(r3t') self.calendar = CalendarPage(owner = self.user, slug = "ereignisse", title = "Ereignisse") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.event = RecurringEventPage(slug = "meeting", title = "Testen Sie Meeting", repeat = Recurrence(dtstart=dt.date(1988,1,1), freq=WEEKLY, byweekday=[MO,WE,FR]), time_from = dt.time(13), time_to = dt.time(15,30)) self.calendar.add_child(instance=self.event) self.info = ExtraInfoPage(owner = self.user, overrides = self.event, except_date = dt.date(1999,1,5), extra_title = "Freitag", extra_information = "Besonderer Freitag") self.event.add_child(instance=self.info) self.info.save_revision().publish() def tearDown(self): translation.deactivate() def testExceptionAlreadyExists(self): page = ExtraInfoPage(owner=self.user) form = self.Form({'overrides': self.event, 'except_date': "1999-01-05", 'extra_title': "Es ist Freitag", 'extra_information': rich_text("Besonderer spezieller Freitag")}, instance=page, parent_page=self.event) self.assertFalse(form.is_valid()) self.assertDictEqual(form.errors, {'except_date': ['Dieses Datum enthält bereits zusätzliche information']})
class TestPageForm(TestCase): Form = ExtraInfoPage.get_edit_handler().get_form_class() def setUp(self): self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3(r3t') self.calendar = CalendarPage(owner = self.user, slug = "events", title = "Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.event = RecurringEventPage(slug = "test-meeting", title = "Test Meeting", repeat = Recurrence(dtstart=dt.date(1988,1,1), freq=WEEKLY, byweekday=[MO,WE,FR]), time_from = dt.time(13), time_to = dt.time(15,30)) self.calendar.add_child(instance=self.event) self.info = ExtraInfoPage(owner = self.user, overrides = self.event, except_date = dt.date(1999,1,5), extra_title = "Fri-day", extra_information = "Special Friday") self.event.add_child(instance=self.info) self.info.save_revision().publish() def testExceptionAlreadyExists(self): page = ExtraInfoPage(owner=self.user) form = self.Form({'overrides': self.event, 'except_date': "1999-01-05", 'extra_title': "It's Friday", 'extra_information': rich_text("Special Special Friday")}, instance=page, parent_page=self.event) self.assertFalse(form.is_valid()) self.assertDictEqual(form.errors, {'except_date': ['That date already has extra information']})
class TestSimple(TestCase): def setUp(self): self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() def testFromPage(self): page = SimpleEventPage(owner=self.user, slug="baseball-game", title="Baseball Game", date=dt.date(2014, 7, 30), time_from=dt.time(13), time_to=dt.time(16), tz=pytz.timezone("America/Los_Angeles")) self.calendar.add_child(instance=page) page.save_revision().publish() gev = SimpleGEvent.fromPage(page) self.assertEqual(gev['dates'], "20140730T130000/20140730T160000") self.assertEqual(gev['ctz'], "America/Los_Angeles")
class TestMultidayRecurring(TestCase): def setUp(self): site = Site.objects.get(is_default_site=True) site.hostname = "joy.test" site.save() self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() @freeze_time("2017-08-15") def testFromPage(self): page = MultidayRecurringEventPage(owner=self.user, slug="bought-from-rubber-man", title="Bought from a Rubber Man", repeat=Recurrence(dtstart=dt.date( 2019, 4, 2), freq=WEEKLY, byweekday=[TU]), num_days=3, time_from=dt.time(16), time_to=dt.time(18), tz=pytz.timezone("Pacific/Auckland")) self.calendar.add_child(instance=page) page.save_revision().publish() vev = VEventFactory().makeFromPage(page) self.assertIs(type(vev), MultidayRecurringVEvent) tz = pytz.timezone("Pacific/Auckland") self.assertEqual(vev['DTSTART'].dt, tz.localize(dt.datetime(2019, 4, 2, 16, 0))) self.assertEqual(vev['DTEND'].dt, tz.localize(dt.datetime(2019, 4, 4, 18, 0))) self.assertEqual(vev['RRULE']['FREQ'], ["WEEKLY"]) self.assertEqual(vev['RRULE']['BYDAY'], ["TU"])
class TestCalendarPageForm(TestCase): def setUp(self): self.user = User.objects.create_superuser('i', '*****@*****.**', 's3(r3t') self.request = RequestFactory().get("/test") self.request.user = self.user self.request.session = {} self.home = Page.objects.get(slug='home') self.page = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.page) self.page.save_revision().publish() def testImportPanel(self): CalendarPageForm.registerImportHandler(Mock()) panel = CalendarPage.settings_panels[-1] self.assertFalse(panel._show()) panel.instance = self.page panel.request = self.request self.assertFalse(panel._show()) setattr(self.page, '__joyous_edit_request', self.request) self.assertTrue(panel._show()) delattr(self.page, '__joyous_edit_request') def testSave(self): Form = get_form_for_model(CalendarPage, form_class=CalendarPageForm) setattr(self.page, '__joyous_edit_request', self.request) form = Form(instance=self.page, parent_page=self.home) handler = Mock() CalendarPageForm.registerImportHandler(handler) form.cleaned_data = {'utc2local': True, 'upload': "FILE"} form.save() handler.load.assert_called_with(self.page, self.request, "FILE", utc2local=True)
class TestImport(TestCase): def setUp(self): Site.objects.update(hostname="joy.test") self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.requestFactory = RequestFactory() self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.handler = ICalHandler() def _getRequest(self, path="/"): request = self.requestFactory.get(path) request.user = self.user request.site = self.home.get_site() request.session = {} request._messages = FallbackStorage(request) request.POST = request.POST.copy() request.POST['action-publish'] = "action-publish" return request @freeze_time("2018-07-24 19:00:00") def testMeetup(self): stream = BytesIO(b"""\ BEGIN:VCALENDAR\r VERSION:2.0\r PRODID:-//Meetup//RemoteApi//EN\r CALSCALE:GREGORIAN\r METHOD:PUBLISH\r X-ORIGINAL-URL:https://www.meetup.com/Code-for-Boston/events/249894034/ic\r al/Weekly+Hack+Night.ics\r X-WR-CALNAME:Events - Weekly Hack Night.ics\r X-MS-OLK-FORCEINSPECTOROPEN:TRUE\r BEGIN:VTIMEZONE\r TZID:America/New_York\r X-LIC-LOCATION:America/New_York\r BEGIN:DAYLIGHT\r TZOFFSETFROM:-0500\r TZOFFSETTO:-0400\r TZNAME:EDT\r DTSTART:19700308T020000\r RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU\r END:DAYLIGHT\r BEGIN:STANDARD\r TZOFFSETFROM:-0400\r TZOFFSETTO:-0500\r TZNAME:EST\r DTSTART:19701101T020000\r RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU\r END:STANDARD\r END:VTIMEZONE\r BEGIN:VEVENT\r DTSTAMP:20180721T015100Z\r DTSTART;TZID=America/New_York:20180724T190000\r DTEND;TZID=America/New_York:20180724T213000\r STATUS:CONFIRMED\r SUMMARY:Weekly Hack Night\r DESCRIPTION:Code for Boston\\nTuesday\\, July 24 at 7:00 PM\\n\\nOur weekly w\r ork session will be at the Cambridge Innovation Center in Kendall Square\r \\, on the FOURTH FLOOR\\, in the CAFE. These Hack Nights are our time...\\\r n\\nhttps://www.meetup.com/Code-for-Boston/events/249894034/\r CLASS:PUBLIC\r CREATED:20180404T010420Z\r GEO:42.36;-71.09\r LOCATION:Cambridge Innovation Center\\, 4th Floor Cafe (1 Broadway\\, Cambr\r idge\\, MA)\r URL:https://www.meetup.com/Code-for-Boston/events/249894034/\r LAST-MODIFIED:20180404T010420Z\r UID:[email protected]\r END:VEVENT\r END:VCALENDAR""") self.handler.load(self.calendar, self._getRequest(), stream) events = SimpleEventPage.events.child_of(self.calendar).all() self.assertEqual(len(events), 1) event = events[0] self.assertEqual(event.owner, self.user) self.assertEqual(event.slug, "weekly-hack-night") self.assertEqual(event.title, "Weekly Hack Night") self.assertEqual( event.details, "\n".join([ "Code for Boston", "Tuesday, July 24 at 7:00 PM", "", "Our weekly work session will be at the Cambridge Innovation Center in Kendall Square" ", on the FOURTH FLOOR, in the CAFE. These Hack Nights are our time...", "", "https://www.meetup.com/Code-for-Boston/events/249894034/" ])) self.assertEqual(event.date, dt.date(2018, 7, 24)) self.assertEqual(event.time_from, dt.time(19)) self.assertEqual(event.time_to, dt.time(21, 30)) self.assertEqual(event.tz.zone, "America/New_York") @freeze_time("2018-02-01") @timezone.override("Pacific/Auckland") def testGoogleCalendar(self): stream = BytesIO(rb""" BEGIN:VCALENDAR PRODID:-//Google Inc//Google Calendar 70.9054//EN VERSION:2.0 CALSCALE:GREGORIAN METHOD:PUBLISH X-WR-CALNAME:Test Data X-WR-TIMEZONE:Pacific/Auckland X-WR-CALDESC:Sample data for Joyous test_ical unittest BEGIN:VTIMEZONE TZID:Pacific/Auckland X-LIC-LOCATION:Pacific/Auckland BEGIN:DAYLIGHT TZOFFSETFROM:+1200 TZOFFSETTO:+1300 TZNAME:NZDT DTSTART:19700927T020000 RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:+1300 TZOFFSETTO:+1200 TZNAME:NZST DTSTART:19700405T030000 RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTART:20180725T210000Z DTEND:20180726T083000Z DTSTAMP:20180722T060025Z UID:[email protected] CREATED:20180722T035919Z DESCRIPTION:Hounit <b>catlike</b> at ethatial to thin a usistiques onshiend alits mily tente duse prommuniss ind sedships itommunte of perpollood. LAST-MODIFIED:20180722T035919Z LOCATION: SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Big Thursday TRANSP:OPAQUE END:VEVENT BEGIN:VEVENT DTSTART;TZID=Pacific/Auckland:20180703T093000 DTEND;TZID=Pacific/Auckland:20180703T113000 RRULE:FREQ=WEEKLY;UNTIL=20180828T115959Z;BYDAY=TU EXDATE;TZID=Pacific/Auckland:20180814T093000 DTSTAMP:20180722T060025Z UID:[email protected] CREATED:20180722T035429Z DESCRIPTION:\nFammulturacha matent theaminerviencess atinjuse it shin sue o f Aothips to ming an sed prage thnisithass invernships oftegruct and encome . Taimen in grose to to ner grough ingin orgagences' of Fries seed\n\nFrith erovere Houps of custims analienessuppol. Tiriendindnew\, vality a gruccous er to be the juse Truch ince lity Te therneramparcialues the the neshipland s tortandamength\, Comene ups a mitioney dend peachassfy de are to entices meand evelas of Friscerple th iseek arces a wind. LAST-MODIFIED:20180722T035937Z LOCATION:Coast Rd\, Barrytown\, New Zealand SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Tuesday Mornings TRANSP:OPAQUE END:VEVENT BEGIN:VEVENT DTSTART;VALUE=DATE:20180713 DTEND;VALUE=DATE:20180716 DTSTAMP:20180722T060025Z UID:[email protected] CREATED:20180722T040054Z DESCRIPTION: LAST-MODIFIED:20180722T040054Z LOCATION:Home SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Three days off TRANSP:TRANSPARENT END:VEVENT BEGIN:VEVENT DTSTART;TZID=Pacific/Auckland:20180725T093000 DTEND;TZID=Pacific/Auckland:20180725T113000 DTSTAMP:20180722T060025Z UID:[email protected] RECURRENCE-ID;TZID=Pacific/Auckland:20180724T093000 CREATED:20180722T035429Z DESCRIPTION:\nFammulturacha matent theaminerviencess atinjuse it shin sue o f Aothips to ming an sed prage thnisithass invernships oftegruct and encome . Taimen in grose to to ner grough ingin orgagences' of Fries seed\n\nFrith erovere Houps of custims analienessuppol. Tiriendindnew\, vality a gruccous er to be the juse Truch ince lity Te therneramparcialues the the neshipland s tortandamength\, Comene ups a mitioney dend peachassfy de are to entices meand evelas of Friscerple th iseek arces a wind. LAST-MODIFIED:20180722T051000Z LOCATION:Coast Rd\, Barrytown\, New Zealand SEQUENCE:1 STATUS:CONFIRMED SUMMARY:Tuesday Mornings Postponed TRANSP:OPAQUE END:VEVENT BEGIN:VEVENT DTSTART;TZID=Pacific/Auckland:20180731T093000 DTEND;TZID=Pacific/Auckland:20180731T113000 DTSTAMP:20180722T060025Z UID:[email protected] RECURRENCE-ID;TZID=Pacific/Auckland:20180731T093000 CREATED:20180722T035429Z DESCRIPTION:\nExtra Famin fork\, andivery\, Hough in the re of re whels ot edshiplue porturat inve in nurectic. LAST-MODIFIED:20180722T051201Z LOCATION:Coast Rd\, Barrytown\, New Zealand SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Tuesday Morning Extra Info TRANSP:OPAQUE END:VEVENT BEGIN:VEVENT DTSTART:20180717T220000Z DTEND:20180717T223000Z DTSTAMP:20180722T060025Z UID:[email protected] CREATED:20180722T050847Z DESCRIPTION: LAST-MODIFIED:20180722T055756Z LOCATION:Pariroa Beach SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Little Wednesday TRANSP:OPAQUE END:VEVENT BEGIN:VEVENT DTSTART:20180723T190000Z DTEND:20180723T200000Z DTSTAMP:20180722T060025Z UID:[email protected] CREATED:20180722T055954Z DESCRIPTION: LAST-MODIFIED:20180722T055954Z LOCATION: SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Conference Call TRANSP:OPAQUE END:VEVENT END:VCALENDAR """) request = self._getRequest() self.handler.load(self.calendar, request, stream) events = getAllEvents(request, home=self.calendar) self.assertEqual(len(events), 5) tueMorn, daysOff, lilWeds, cnfCall, bigThur = events self.assertEqual(tueMorn.owner, self.user) self.assertEqual(tueMorn.slug, "tuesday-mornings") self.assertEqual(tueMorn.title, "Tuesday Mornings") self.assertEqual( tueMorn.details, "\n".join([ "", "Fammulturacha matent theaminerviencess atinjuse it shin sue of " "Aothips to ming an sed prage thnisithass invernships oftegruct " "and encome. Taimen in grose to to ner grough ingin orgagences' " "of Fries seed", "", "Fritherovere Houps of custims analienessuppol. Tiriendindnew, " "vality a gruccouser to be the juse Truch ince lity Te " "therneramparcialues the the neshiplands tortandamength, " "Comene ups a mitioney dend peachassfy de are to entices meand " "evelas of Friscerple th iseek arces a wind." ])) self.assertEqual(tueMorn.tz.zone, "Pacific/Auckland") self.assertEqual(tueMorn.time_from, dt.time(9, 30)) self.assertEqual(tueMorn.time_to, dt.time(11, 30)) self.assertEqual(tueMorn.location, "Coast Rd, Barrytown, New Zealand") self.assertEqual( tueMorn.when, "Tuesdays (until 28 August 2018) at 9:30am to 11:30am") tueExceptions = tueMorn.get_children() self.assertEqual(len(tueExceptions), 3) tue24th, tue31st, tue14th = [page.specific for page in tueExceptions] self.assertEqual(tue24th.owner, self.user) self.assertEqual(tue24th.overrides, tueMorn) self.assertEqual(tue24th.slug, "2018-07-24-postponement") self.assertEqual(tue24th.title, "Postponement for Tuesday 24th of July") self.assertEqual(tue24th.details, tueMorn.details) self.assertEqual(tue24th.tz.zone, "Pacific/Auckland") self.assertEqual(tue24th.except_date, dt.date(2018, 7, 24)) self.assertEqual(tue24th.date, dt.date(2018, 7, 25)) self.assertEqual(tue24th.time_from, dt.time(9, 30)) self.assertEqual(tue24th.time_to, dt.time(11, 30)) self.assertEqual(tue24th.location, "Coast Rd, Barrytown, New Zealand") self.assertEqual(tue31st.owner, self.user) self.assertEqual(tue31st.overrides, tueMorn) self.assertEqual(tue31st.slug, "2018-07-31-extra-info") self.assertEqual(tue31st.title, "Extra-Info for Tuesday 31st of July") self.assertEqual(tue31st.extra_title, "Tuesday Morning Extra Info") self.assertEqual( tue31st.extra_information, "\n".join([ "", "Extra Famin fork, andivery, Hough in the re of re whels " "otedshiplue porturat inve in nurectic." ])) self.assertEqual(tue31st.tz.zone, "Pacific/Auckland") self.assertEqual(tue31st.except_date, dt.date(2018, 7, 31)) self.assertEqual(tue14th.owner, self.user) self.assertEqual(tue14th.overrides, tueMorn) self.assertEqual(tue14th.slug, "2018-08-14-cancellation") self.assertEqual(tue14th.title, "Cancellation for Tuesday 14th of August") self.assertEqual(tue14th.cancellation_title, "") self.assertEqual(tue14th.cancellation_details, "") self.assertEqual(tue14th.tz.zone, "Pacific/Auckland") self.assertEqual(tue14th.except_date, dt.date(2018, 8, 14)) self.assertEqual(daysOff.owner, self.user) self.assertEqual(daysOff.slug, "three-days-off") self.assertEqual(daysOff.title, "Three days off") self.assertEqual(daysOff.details, "") self.assertEqual(daysOff.tz.zone, "Pacific/Auckland") self.assertEqual(daysOff.date_from, dt.date(2018, 7, 13)) self.assertEqual(daysOff.time_from, None) self.assertEqual(daysOff.date_to, dt.date(2018, 7, 15)) self.assertEqual(daysOff.time_to, None) self.assertEqual(daysOff.location, "Home") self.assertEqual(lilWeds.owner, self.user) self.assertEqual(lilWeds.slug, "little-wednesday") self.assertEqual(lilWeds.title, "Little Wednesday") self.assertEqual(lilWeds.details, "") self.assertEqual(lilWeds.tz, pytz.utc) self.assertEqual(lilWeds.date, dt.date(2018, 7, 17)) self.assertEqual(lilWeds.time_from, dt.time(22)) self.assertEqual(lilWeds.time_to, dt.time(22, 30)) self.assertEqual(lilWeds.location, "Pariroa Beach") self.assertEqual(lilWeds.when, "Wednesday 18th of July at 10am to 10:30am") self.assertEqual(cnfCall.owner, self.user) self.assertEqual(cnfCall.slug, "conference-call") self.assertEqual(cnfCall.title, "Conference Call") self.assertEqual(cnfCall.details, "") self.assertEqual(cnfCall.tz, pytz.utc) self.assertEqual(cnfCall.date, dt.date(2018, 7, 23)) self.assertEqual(cnfCall.time_from, dt.time(19)) self.assertEqual(cnfCall.time_to, dt.time(20)) self.assertEqual(bigThur.owner, self.user) self.assertEqual(bigThur.slug, "big-thursday") self.assertEqual(bigThur.title, "Big Thursday") self.assertEqual( bigThur.details, "Hounit <b>catlike</b> at ethatial to thin a usistiques onshiend " "alits mily tente duse prommuniss ind sedships itommunte of perpollood." ) self.assertEqual(bigThur.tz, pytz.utc) self.assertEqual(bigThur.date_from, dt.date(2018, 7, 25)) self.assertEqual(bigThur.time_from, dt.time(21)) self.assertEqual(bigThur.date_to, dt.date(2018, 7, 26)) self.assertEqual(bigThur.time_to, dt.time(8, 30)) self.assertEqual(bigThur.when, "Thursday 26th of July at 9am to 8:30pm") @freeze_time("2018-02-01") @timezone.override("Pacific/Auckland") def testUtc2Local(self): stream = BytesIO(rb""" BEGIN:VCALENDAR PRODID:-//Google Inc//Google Calendar 70.9054//EN VERSION:2.0 CALSCALE:GREGORIAN METHOD:PUBLISH X-WR-CALNAME:Test Data X-WR-TIMEZONE:Australia/Sydney X-WR-CALDESC:Sample data for Joyous test_ical unittest BEGIN:VEVENT DTSTART:20180725T210000Z DTEND:20180726T083000Z DTSTAMP:20180722T060025Z UID:[email protected] CREATED:20180722T035919Z DESCRIPTION:Hounit <b>catlike</b> at ethatial to thin a usistiques onshiend alits mily tente duse prommuniss ind sedships itommunte of perpollood. LAST-MODIFIED:20180722T035919Z LOCATION: SEQUENCE:0 STATUS:CONFIRMED SUMMARY:Big Thursday TRANSP:OPAQUE END:VEVENT END:VCALENDAR """) request = self._getRequest() self.handler.load(self.calendar, request, stream, utc2local=True) events = getAllEvents(request, home=self.calendar) self.assertEqual(len(events), 1) bigThur = events[0] self.assertEqual(bigThur.owner, self.user) self.assertEqual(bigThur.slug, "big-thursday") self.assertEqual(bigThur.title, "Big Thursday") self.assertEqual( bigThur.details, "Hounit <b>catlike</b> at ethatial to thin a usistiques onshiend " "alits mily tente duse prommuniss ind sedships itommunte of perpollood." ) self.assertEqual(bigThur.tz.zone, "Australia/Sydney") self.assertEqual(bigThur.date_from, dt.date(2018, 7, 26)) self.assertEqual(bigThur.time_from, dt.time(7)) self.assertEqual(bigThur.date_to, dt.date(2018, 7, 26)) self.assertEqual(bigThur.time_to, dt.time(18, 30)) self.assertEqual(bigThur.when, "Thursday 26th of July at 9am to 8:30pm") def testOutlook(self): stream = BytesIO(rb""" BEGIN:VCALENDAR PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN VERSION:2.0 METHOD:PUBLISH BEGIN:VEVENT DTSTART:20180730T092500 DTEND:20180730T101500 UID:7N7Y7V6J4N2U4I3U7H0N7W5O4V2U0K3H2E4Q4O7A2H0W1A5M6N DTSTAMP:20180728T035656 DESCRIPTION;ENCODING=QUOTED-PRINTABLE:Booking number 9876543=0D=0A=0D=0AYour outgoing route is Westport > Wellington.=0D=0AThis route departs Westport on 30/Jul/2018 09:25 and arrives at Wellington at 10:15. The check-in time is 08:55.=0A SUMMARY;ENCODING=QUOTED-PRINTABLE:Sounds Air - Flight Reminder PRIORITY:3 BEGIN:VALARM TRIGGER:-PT24H ACTION:DISPLAY DESCRIPTION:Reminder END:VALARM END:VEVENT END:VCALENDAR BEGIN:VCALENDAR PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN VERSION:2.0 METHOD:PUBLISH BEGIN:VEVENT DTSTART:20180731T081500 DTEND:20180731T090000 UID:1G0K0V7K4L0H4Q4T5F4R8U2E0D0S4H2M6O1J6M5C5S2R4D0S2Q DTSTAMP:20180728T035656 DESCRIPTION;ENCODING=QUOTED-PRINTABLE:Booking number 9876543=0D=0A=0D=0A=0D=0AYour return route is Wellington > Westport.=0D=0AThis route departs Wellington on 31/Jul/2018 08:15 and arrives at Westport at 09:00. The check-in time is 07:45.=0A SUMMARY;ENCODING=QUOTED-PRINTABLE:Sounds Air - Flight Reminder PRIORITY:3 BEGIN:VALARM TRIGGER:-PT24H ACTION:DISPLAY DESCRIPTION:Reminder END:VALARM END:VEVENT END:VCALENDAR """) request = self._getRequest() self.handler.load(self.calendar, request, stream) events = [page.specific for page in self.calendar.get_children()] self.assertEqual(len(events), 2) flight1, flight2 = events self.assertEqual(flight1.slug, "sounds-air-flight-reminder") self.assertEqual(flight1.title, "Sounds Air - Flight Reminder") self.assertEqual( flight1.details, "\r\n".join([ "Booking number 9876543", "", "Your outgoing route is Westport > Wellington.", "This route departs Westport on 30/Jul/2018 09:25 and arrives at " "Wellington at 10:15. The check-in time is 08:55.\n" ])) self.assertEqual(flight1.tz.zone, "Asia/Tokyo") self.assertEqual(flight1.date, dt.date(2018, 7, 30)) self.assertEqual(flight1.time_from, dt.time(9, 25)) self.assertEqual(flight1.time_to, dt.time(10, 15)) self.assertEqual(flight2.slug, "sounds-air-flight-reminder-2") self.assertEqual(flight2.title, "Sounds Air - Flight Reminder") self.assertEqual( flight2.details, "\r\n".join([ "Booking number 9876543", "", "", "Your return route is Wellington > Westport.", "This route departs Wellington on 31/Jul/2018 08:15 and arrives at " "Westport at 09:00. The check-in time is 07:45.\n" ])) self.assertEqual(flight2.tz.zone, "Asia/Tokyo") self.assertEqual(flight2.date, dt.date(2018, 7, 31)) self.assertEqual(flight2.time_from, dt.time(8, 15)) self.assertEqual(flight2.time_to, dt.time(9)) def testFacebook(self): stream = BytesIO(rb""" BEGIN:VCALENDAR PRODID:-//Facebook//NONSGML Facebook Events V1.0//EN X-PUBLISHED-TTL:PT12H X-ORIGINAL-URL:https://www.facebook.com/events/501511573641525/ VERSION:2.0 CALSCALE:GREGORIAN METHOD:PUBLISH BEGIN:VEVENT DTSTAMP:20180729T102010Z LAST-MODIFIED:20180729T102010Z CREATED:20180729T102010Z SEQUENCE:0 ORGANIZER;CN=Jjjj Bbbbb:MAILTO:[email protected] ATTENDEE;CN=Bbbbb Wwwwww;PARTSTAT=ACCEPTED:https://www.facebook.com/bbwwwwww ATTENDEE;CN=Jjjj Bbbbb;PARTSTAT=ACCEPTED:https://www.facebook.com/jjjj.bbbbb ATTENDEE;CN=Pppp Tttttt;PARTSTAT=TENTATIVE:https://www.facebook.com/pppp.tttttt.123 DTSTART:20180831T070000Z DTEND:20180831T100000Z UID:[email protected] SUMMARY:Photo Comp - Prize Giving LOCATION:TBC URL:https://www.facebook.com/events/501511573641525/ DESCRIPTION:The much anticipated 2018 West Coa st Alpine Club is open!\nEntries cl ose midnight Friday 24th August. F ull details and entry form in the linked PDF: https://www.dropbox.co m/s/5vxnep33ccxok9z/PhotoCompDetai ls.pdf?dl=0\nDetails of the prize g iving will be added here in due co urse\, but save the date in the mea n time.\n\nhttps://www.facebook.com/ events/501511573641525/ CLASS:PUBLIC STATUS:CONFIRMED PARTSTAT:NEEDS-ACTION END:VEVENT END:VCALENDAR """) request = self._getRequest() self.handler.load(self.calendar, request, stream) events = self.calendar.get_children() self.assertEqual(len(events), 1) event = events[0].specific self.assertEqual(event.slug, "photo-comp-prize-giving") self.assertEqual(event.title, "Photo Comp - Prize Giving") self.assertEqual( event.details, "\n".join([ "The much anticipated 2018 West Coast Alpine Club is open!", "Entries close midnight Friday 24th August. Full details and " "entry form in the linked PDF: https://www.dropbox.com/s/" "5vxnep33ccxok9z/PhotoCompDetails.pdf?dl=0", "Details of the prize giving will be added here in due course, " "but save the date in the mean time.", "", "https://www.facebook.com/events/501511573641525/" ])) self.assertEqual(event.tz.zone, "UTC") self.assertEqual(event.date, dt.date(2018, 8, 31)) self.assertEqual(event.time_from, dt.time(7)) self.assertEqual(event.time_to, dt.time(10)) def testUntilTZ(self): stream = BytesIO(rb""" BEGIN:VCALENDAR PRODID:-//Google Inc//Google Calendar 70.9054//EN VERSION:2.0 CALSCALE:GREGORIAN METHOD:PUBLISH X-WR-CALNAME:[email protected] X-WR-TIMEZONE:Pacific/Auckland BEGIN:VTIMEZONE TZID:America/New_York X-LIC-LOCATION:America/New_York BEGIN:DAYLIGHT TZOFFSETFROM:-0500 TZOFFSETTO:-0400 TZNAME:EDT DTSTART:19700308T020000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:-0400 TZOFFSETTO:-0500 TZNAME:EST DTSTART:19701101T020000 RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTART;TZID=America/New_York:20310101T050000 DTEND;TZID=America/New_York:20310101T070000 RRULE:FREQ=DAILY;UNTIL=20310108T045959Z DTSTAMP:20190331T203301Z UID:[email protected] CREATED:20190331T200304Z DESCRIPTION:New Year resolution LAST-MODIFIED:20190331T203219Z LOCATION:New York\, NY\, USA SEQUENCE:5 STATUS:CONFIRMED SUMMARY:Exercise TRANSP:OPAQUE END:VEVENT END:VCALENDAR""") request = self._getRequest() self.handler.load(self.calendar, request, stream) events = self.calendar.get_children() self.assertEqual(len(events), 1) event = events[0].specific self.assertIs(type(event), RecurringEventPage) self.assertEqual(event.slug, "exercise") self.assertEqual(event.tz.zone, "America/New_York") self.assertEqual(event.time_from, dt.time(5)) self.assertEqual(event.time_to, dt.time(7)) self.assertEqual(event.repeat.getCount(), 7) self.assertTrue(event._occursOn(dt.date(2031, 1, 1))) self.assertFalse(event._occursOn(dt.date(2031, 1, 8))) def testMultidayRecurringEvent(self): stream = BytesIO(rb""" BEGIN:VCALENDAR VERSION:2.0 PRODID:-//linuxsoftware.nz//NONSGML Joyous v0.8//EN BEGIN:VEVENT SUMMARY:Bought from a Rubber Man DTSTART;TZID=Pacific/Auckland:20190402T160000 DTEND;TZID=Pacific/Auckland:20190404T180000 DTSTAMP:20190405T054311Z UID:e6936872-f15c-4c47-92f2-3559a6610c78 SEQUENCE:1 RRULE:FREQ=WEEKLY;BYDAY=TU;WKST=SU CREATED:20190405T054255Z DESCRIPTION:<p></p> LAST-MODIFIED:20190405T054255Z LOCATION: URL:http://localhost/calendar/bought-rubber-man/ END:VEVENT BEGIN:VTIMEZONE TZID:Pacific/Auckland BEGIN:DAYLIGHT DTSTART;VALUE=DATE-TIME:20180930T030000 RDATE:20190929T030000,20200927T030000,20210926T030000,20220925T030000,2023 0924T030000,20240929T030000,20250928T030000,20260927T030000,20270926T03000 0,20280924T030000,20290930T030000,20300929T030000,20310928T030000,20320926 T030000,20330925T030000,20340924T030000,20350930T030000,20360928T030000,20 370927T030000 TZNAME:NZDT TZOFFSETFROM:+1200 TZOFFSETTO:+1300 END:DAYLIGHT BEGIN:STANDARD DTSTART;VALUE=DATE-TIME:20190407T020000 RDATE:20200405T020000,20210404T020000,20220403T020000,20230402T020000,2024 0407T020000,20250406T020000,20260405T020000,20270404T020000,20280402T02000 0,20290401T020000,20300407T020000,20310406T020000,20320404T020000,20330403 T020000,20340402T020000,20350401T020000,20360406T020000,20370405T020000 TZNAME:NZST TZOFFSETFROM:+1300 TZOFFSETTO:+1200 END:STANDARD END:VTIMEZONE END:VCALENDAR""") request = self._getRequest() self.handler.load(self.calendar, request, stream) events = self.calendar.get_children() self.assertEqual(len(events), 1) event = events[0].specific self.assertIs(type(event), MultidayRecurringEventPage) self.assertEqual(event.title, "Bought from a Rubber Man") self.assertEqual(event.tz.zone, "Pacific/Auckland") self.assertEqual(event.num_days, 3) self.assertEqual(event.time_from, dt.time(16)) self.assertEqual(event.time_to, dt.time(18))
class Test(TestCase): def setUp(self): Site.objects.update(hostname="joy.test") self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3(R3t') self.requestFactory = RequestFactory() self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.handler = GoogleCalendarHandler() def _getRequest(self, path="/"): request = self.requestFactory.get(path) request.user = self.user request.site = self.home.get_site() request.session = {} request._messages = FallbackStorage(request) request.POST = request.POST.copy() request.POST['action-publish'] = "action-publish" return request def testServeSimple(self): page = SimpleEventPage(owner=self.user, slug="baseball-game", title="Baseball Game", date=dt.date(2014, 7, 30), time_from=dt.time(13), time_to=dt.time(16), tz=pytz.timezone("America/Los_Angeles")) self.calendar.add_child(instance=page) page.save_revision().publish() response = self.handler.serve( page, self._getRequest("/events/baseball-game/" "?format=google")) self.assertEqual(response.status_code, 302) self.assertEqual( response.url, "http://www.google.com/calendar/event?action=TEMPLATE&" "text=Baseball+Game&dates=20140730T130000%2F20140730T160000&" "ctz=America%2FLos_Angeles") def testServeMultiday(self): page = MultidayEventPage(owner=self.user, slug="food-festival", title="Food Festival", date_from=dt.date(2018, 11, 2), date_to=dt.date(2018, 11, 5), tz=pytz.timezone("Pacific/Niue")) self.calendar.add_child(instance=page) page.save_revision().publish() response = self.handler.serve( page, self._getRequest("/events/food-festival/" "?format=google")) self.assertEqual(response.status_code, 302) self.assertEqual( response.url, "http://www.google.com/calendar/event?action=TEMPLATE&" "text=Food+Festival&dates=20181102T000000%2F20181105T235959&" "ctz=Pacific%2FNiue") def testServeRecurring(self): page = RecurringEventPage(owner=self.user, slug="lunch-and-code", title="Lunch and Code", repeat=Recurrence(dtstart=dt.date( 2017, 3, 15), freq=MONTHLY, byweekday=[FR(-1)]), time_from=dt.time(12), time_to=dt.time(13), tz=pytz.timezone("Pacific/Auckland"), location="70 Molesworth Street, Wellington") self.calendar.add_child(instance=page) page.save_revision().publish() response = self.handler.serve( page, self._getRequest("/events/lunch-and-code/" "?format=google")) self.assertEqual(response.status_code, 302) self.assertEqual( response.url, "http://www.google.com/calendar/event?action=TEMPLATE&" "text=Lunch+and+Code&" "location=70+Molesworth+Street%2C+Wellington&" "dates=20170331T120000%2F20170331T130000&" "ctz=Pacific%2FAuckland&" "recur=RRULE%3AFREQ%3DMONTHLY%3BWKST%3DSU%3BBYDAY%3D-1FR") def testServeException(self): event = RecurringEventPage(slug="test-meeting", title="Test Meeting", repeat=Recurrence(dtstart=dt.date( 1988, 1, 1), freq=WEEKLY, byweekday=[MO, WE, FR]), time_from=dt.time(13), time_to=dt.time(15, 30)) self.calendar.add_child(instance=event) event.save_revision().publish() info = ExtraInfoPage(owner=self.user, overrides=event, except_date=dt.date(1988, 11, 11), extra_title="System Demo", extra_information="<h3>System Demo</h3>") event.add_child(instance=info) info.save_revision().publish() response = self.handler.serve( info, self._getRequest("/events/test-meeting/1998-11-11/extra-info/" "?format=google")) self.assertEqual(response.status_code, 302) self.assertEqual( response.url, "http://www.google.com/calendar/event?action=TEMPLATE&" "text=Test+Meeting&" "dates=19880101T130000%2F19880101T153000&" "ctz=Asia%2FTokyo&" "recur=RRULE%3AFREQ%3DWEEKLY%3BWKST%3DSU%3BBYDAY%3DMO%2CWE%2CFR") def testServeUnsupported(self): response = self.handler.serve(self.home, self._getRequest("/")) self.assertIsNone(response)
class Test(TestCase): def setUp(self): self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3(r3t') self.calendar = CalendarPage(owner = self.user, slug = "events", title = "Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.event = RecurringEventPage(slug = "test-meeting", title = "Test Meeting", repeat = Recurrence(dtstart=dt.date(1988,1,1), freq=WEEKLY, byweekday=[MO,WE,FR]), time_from = dt.time(13), time_to = dt.time(15,30)) self.calendar.add_child(instance=self.event) self.info = ExtraInfoPage(owner = self.user, overrides = self.event, except_date = dt.date(1988,11,11), extra_title = "System Demo", extra_information = "<h3>System Demo</h3>") self.event.add_child(instance=self.info) self.info.save_revision().publish() def testGetEventsByDay(self): events = RecurringEventPage.events.byDay(dt.date(1988,11,1), dt.date(1988,11,30)) self.assertEqual(len(events), 30) evod = events[10] self.assertEqual(evod.date, dt.date(1988,11,11)) self.assertEqual(len(evod.all_events), 1) self.assertEqual(len(evod.days_events), 1) self.assertEqual(len(evod.continuing_events), 0) title, page, url = evod.days_events[0] self.assertEqual(title, "System Demo") self.assertIs(type(page), ExtraInfoPage) def testStatus(self): self.assertEqual(self.info.status, "finished") self.assertEqual(self.info.status_text, "This event has finished.") now = timezone.localtime() myday = now.date() + dt.timedelta(days=1) friday = myday + dt.timedelta(days=(4-myday.weekday())%7) futureInfo = ExtraInfoPage(owner = self.user, overrides = self.event, except_date = friday, extra_title = "It's Friday", extra_information = "Special") self.event.add_child(instance=futureInfo) self.assertIsNone(futureInfo.status) self.assertEqual(futureInfo.status_text, "") @freeze_timetz("1988-11-11 14:00:00") def testStatusStarted(self): self.assertEqual(self.info.status, "started") self.assertEqual(self.info.status_text, "This event has started.") def testWhen(self): self.assertEqual(self.info.when, "Friday 11th of November 1988 at 1pm to 3:30pm") def testAt(self): self.assertEqual(self.info.at.strip(), "1pm") def testCurrentDt(self): self.assertIsNone(self.info._current_datetime_from) def testFutureDt(self): self.assertIsNone(self.info._future_datetime_from) def testPastDt(self): self.assertEqual(self.info._past_datetime_from, datetimetz(1988,11,11,13,0)) def testNeverOccursOn(self): info = ExtraInfoPage(owner = self.user, overrides = self.event, except_date = dt.date(1988,3,1), extra_title = "Tuesday", extra_information = "Standard") self.event.add_child(instance=info) self.assertIsNone(info._current_datetime_from) self.assertIsNone(info._future_datetime_from) self.assertIsNone(info._past_datetime_from) def testGroup(self): self.assertIsNone(self.info.group) def testOverridesRepeat(self): self.assertEqual(self.info.overrides_repeat, self.event.repeat)
class Test(TestCase): def setUp(self): self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3(r3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.event = RecurringEventPage(slug="test-meeting", title="Test Meeting", repeat=Recurrence( dtstart=dt.date(1989, 1, 1), freq=WEEKLY, byweekday=[MO, WE, FR]), time_from=dt.time(13), time_to=dt.time(15, 30)) self.calendar.add_child(instance=self.event) self.cancellation = CancellationPage( owner=self.user, overrides=self.event, except_date=dt.date(1989, 2, 1), cancellation_title="Meeting Cancelled", cancellation_details="Cancelled due to lack of interest") self.event.add_child(instance=self.cancellation) self.cancellation.save_revision().publish() def testGetEventsByDay(self): hiddenCancellation = CancellationPage(owner=self.user, overrides=self.event, except_date=dt.date(1989, 2, 13)) self.event.add_child(instance=hiddenCancellation) events = RecurringEventPage.events.byDay(dt.date(1989, 2, 1), dt.date(1989, 2, 28)) self.assertEqual(len(events), 28) evod1 = events[0] self.assertEqual(evod1.date, dt.date(1989, 2, 1)) self.assertEqual(len(evod1.days_events), 1) self.assertEqual(len(evod1.continuing_events), 0) title, page, url = evod1.days_events[0] self.assertEqual(title, "Meeting Cancelled") self.assertIs(type(page), CancellationPage) evod2 = events[12] self.assertEqual(evod2.date, dt.date(1989, 2, 13)) self.assertEqual(len(evod2.days_events), 0) self.assertEqual(len(evod2.continuing_events), 0) def testOccursOn(self): self.assertIs(self.event._occursOn(dt.date(1989, 2, 1)), False) self.assertIs(self.event._occursOn(dt.date(1989, 2, 3)), True) def testUnexplainedCancellation(self): self._cancel_1999_02_08() events = RecurringEventPage.events.byDay(dt.date(1999, 2, 1), dt.date(1999, 2, 28)) self.assertEqual(len(events), 28) evod = events[7] self.assertEqual(evod.date, dt.date(1999, 2, 8)) self.assertEqual(len(evod.days_events), 0) self.assertEqual(len(evod.continuing_events), 0) def testUnexplainedCancellationExplained(self): restriction = self._cancel_1999_02_08() request = RequestFactory().get("/test") request.user = self.user KEY = PageViewRestriction.passed_view_restrictions_session_key request.session = {KEY: [restriction.id]} events = RecurringEventPage.events(request).byDay( dt.date(1999, 2, 1), dt.date(1999, 2, 28)) self.assertEqual(len(events), 28) evod = events[7] self.assertEqual(evod.date, dt.date(1999, 2, 8)) self.assertEqual(len(evod.days_events), 1) self.assertEqual(len(evod.continuing_events), 0) title, page, url = evod.days_events[0] self.assertEqual(title, "Restructure Pending") self.assertIs(type(page), CancellationPage) def _cancel_1999_02_08(self): cancellation = CancellationPage( owner=self.user, overrides=self.event, except_date=dt.date(1999, 2, 8), cancellation_title="Restructure Pending", cancellation_details="Keep it quiet") self.event.add_child(instance=cancellation) PASSWORD = PageViewRestriction.PASSWORD restriction = PageViewRestriction.objects.create( restriction_type=PASSWORD, password="******", page=cancellation) restriction.save() return restriction def testStatus(self): self.assertEqual(self.cancellation.status, "cancelled") self.assertEqual(self.cancellation.status_text, "This event has been cancelled.") now = dt.datetime.now() myday = now.date() + dt.timedelta(1) friday = myday + dt.timedelta(days=(4 - myday.weekday()) % 7) futureCan = CancellationPage(owner=self.user, overrides=self.event, except_date=friday, cancellation_title="", cancellation_details="") self.event.add_child(instance=futureCan) self.assertEqual(futureCan.status, "cancelled") self.assertEqual(futureCan.status_text, "This event has been cancelled.") def testWhen(self): self.assertEqual(self.cancellation.when, "Wednesday 1st of February 1989 at 1pm to 3:30pm") def testWhenEver(self): event = RecurringEventPage(slug="XYZ", title="Xylophone yacht zombies", repeat=Recurrence(dtstart=dt.date( 1989, 1, 1), freq=WEEKLY, byweekday=[FR]), time_from=dt.time(19)) self.calendar.add_child(instance=event) cancellation = CancellationPage(owner=self.user, overrides=event, except_date=dt.date(1989, 3, 10), cancellation_title="Cancelled") event.add_child(instance=cancellation) cancellation.save_revision().publish() self.assertEqual(cancellation.when, "Friday 10th of March 1989 at 7pm") def testAt(self): self.assertEqual(self.cancellation.at.strip(), "1pm") def testCurrentDt(self): self.assertIsNone(self.cancellation._current_datetime_from) def testFutureDt(self): self.assertIsNone(self.cancellation._future_datetime_from) def testPastDt(self): self.assertEqual(self.cancellation._past_datetime_from, datetimetz(1989, 2, 1, 13, 0)) def testNeverOccursOn(self): cancellation = CancellationPage(owner=self.user, overrides=self.event, except_date=dt.date(1989, 2, 7), cancellation_title="Tuesday", cancellation_details="Banner") self.event.add_child(instance=cancellation) self.assertIsNone(cancellation._current_datetime_from) self.assertIsNone(cancellation._future_datetime_from) self.assertIsNone(cancellation._past_datetime_from) def testGroup(self): self.assertIsNone(self.cancellation.group) def testOverridesRepeat(self): self.assertEqual(self.cancellation.overrides_repeat, self.event.repeat) def testGetContext(self): request = RequestFactory().get("/test") context = self.cancellation.get_context(request) self.assertIn('overrides', context)
class TestRecurringEvent(TestCase): def setUp(self): self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner = self.user, slug = "events", title = "Events") Page.objects.get(slug='home').add_child(instance=self.calendar) self.calendar.save() self.calendar.save_revision().publish() self.event = RecurringEventPage(owner = self.user, slug = "lug-meetup", title = "Linux Users Group Meetup", repeat = Recurrence(dtstart=dt.date(2017,8,5), freq=MONTHLY, byweekday=[TU(1)]), time_from = dt.time(18,30), time_to = dt.time(20), location = "6 Mackay St, Greymouth (upstairs)") self.calendar.add_child(instance=self.event) self.event.save_revision().publish() def testGetEventsByDay(self): events = RecurringEventPage.events.byDay(dt.date(2017,8,1), dt.date(2017,10,31)) self.assertEqual(len(events), 92) evod = events[35] self.assertEqual(evod.date, dt.date(2017,9,5)) self.assertEqual(len(evod.all_events), 1) self.assertEqual(len(evod.days_events), 1) self.assertEqual(len(evod.continuing_events), 0) def testStatus(self): pastEvent = RecurringEventPage(owner = self.user, slug = "past", title = "Past Event", repeat = Recurrence(dtstart=dt.date(2008,2,1), until=dt.date(2008,5,4), freq=WEEKLY, byweekday=WEEKEND)) self.calendar.add_child(instance=pastEvent) self.assertEqual(pastEvent.status, "finished") self.assertEqual(pastEvent.status_text, "These events have finished.") now = timezone.localtime() earlier = now - dt.timedelta(hours=1) if earlier.date() != now.date(): earlier = datetimetz(now.date(), dt.time.min) nowEvent = RecurringEventPage(owner = self.user, slug = "now", title = "Now Event", repeat = Recurrence(dtstart=dt.date(2010,1,1), freq=DAILY), time_from = earlier.time(), time_to = dt.time.max) self.calendar.add_child(instance=nowEvent) self.assertEqual(nowEvent.status, "started") self.assertEqual(nowEvent.status_text, "This event has started.") today = timezone.localdate() notToday = [weekday for weekday in EVERYDAY if weekday.weekday != today.weekday()] pastAndFutureEvent = RecurringEventPage(owner = self.user, slug = "not-today", title = "Any day but today", repeat = Recurrence(dtstart=dt.date(2009,8,7), freq=WEEKLY, byweekday=notToday)) self.calendar.add_child(instance=pastAndFutureEvent) self.assertIsNone(pastAndFutureEvent.status) self.assertEqual(pastAndFutureEvent.status_text, "") def testWhen(self): self.assertEqual(self.event.when, "The first Tuesday of the month at 6:30pm to 8pm") def testAt(self): self.assertEqual(self.event.at.strip(), "6:30pm") def testUpcomingDt(self): lugDt = self.event._upcoming_datetime_from self.assertEqual(lugDt.time(), dt.time(18,30)) self.assertEqual(lugDt.date().weekday(), 1) self.assertLess(lugDt.date().day, 8) movieNight = RecurringEventPage(owner = self.user, slug = "movies", title = "Movies", repeat = Recurrence(dtstart=dt.date(2005,2,1), freq=WEEKLY, byweekday=[TH,]), time_from = dt.time(20,15), time_to = dt.time(21,30)) self.calendar.add_child(instance=movieNight) now = timezone.localtime() myday = now.date() startTime = dt.time(20,15) if now.time() > startTime: myday += dt.timedelta(days=1) thursday = myday + dt.timedelta(days=(3-myday.weekday())%7) self.assertEqual(movieNight._upcoming_datetime_from, datetimetz(thursday, startTime)) def testPastDt(self): lugDt = self.event._past_datetime_from self.assertEqual(lugDt.time(), dt.time(18,30)) self.assertEqual(lugDt.date().weekday(), 1) self.assertLess(lugDt.date().day, 8) movieNight = RecurringEventPage(owner = self.user, slug = "movies", title = "Movies", repeat = Recurrence(dtstart=dt.date(2005,2,1), freq=WEEKLY, byweekday=[TH,]), time_from = dt.time(20,15), time_to = dt.time(21,30)) self.calendar.add_child(instance=movieNight) now = timezone.localtime() myday = now.date() startTime = dt.time(20,15) if now.time() < startTime: myday -= dt.timedelta(days=1) thursday = myday - dt.timedelta(days=(myday.weekday()-3)%7) self.assertEqual(movieNight._past_datetime_from, datetimetz(thursday, startTime)) def testGroup(self): self.assertIsNone(self.event.group) def testOccursOn(self): self.assertIs(self.event._occursOn(dt.date(2018,3,6)), True) self.assertIs(self.event._occursOn(dt.date(2018,3,13)), False)
class Test(TestCase): def setUp(self): self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3(r3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.event = RecurringEventPage(slug="test-meeting", title="Test Meeting", repeat=Recurrence( dtstart=dt.date(1989, 1, 1), freq=WEEKLY, byweekday=[MO, WE, FR]), time_from=dt.time(13), time_to=dt.time(15, 30)) self.calendar.add_child(instance=self.event) self.cancellation = CancellationPage( owner=self.user, slug="1989-02-01-cancellation", title="Cancellation for Wednesday 1st of February", overrides=self.event, except_date=dt.date(1989, 2, 1), cancellation_title="Meeting Cancelled", cancellation_details="Cancelled due to lack of interest") self.event.add_child(instance=self.cancellation) self.cancellation.save_revision().publish() def testGetEventsByDay(self): hiddenCancellation = CancellationPage( owner=self.user, slug="1989-02-13-cancellation", title="Cancellation for Monday 13th of February", overrides=self.event, except_date=dt.date(1989, 2, 13)) self.event.add_child(instance=hiddenCancellation) events = RecurringEventPage.events.byDay(dt.date(1989, 2, 1), dt.date(1989, 2, 28)) self.assertEqual(len(events), 28) evod1 = events[0] self.assertEqual(evod1.date, dt.date(1989, 2, 1)) self.assertEqual(len(evod1.days_events), 1) self.assertEqual(len(evod1.continuing_events), 0) title, page, url = evod1.days_events[0] self.assertEqual(title, "Meeting Cancelled") self.assertIs(type(page), CancellationPage) evod2 = events[12] self.assertEqual(evod2.date, dt.date(1989, 2, 13)) self.assertEqual(len(evod2.days_events), 0) self.assertEqual(len(evod2.continuing_events), 0) def testUnexplainedCancellation(self): self._cancel_1999_02_08() events = RecurringEventPage.events.byDay(dt.date(1999, 2, 1), dt.date(1999, 2, 28)) self.assertEqual(len(events), 28) evod = events[7] self.assertEqual(evod.date, dt.date(1999, 2, 8)) self.assertEqual(len(evod.days_events), 0) self.assertEqual(len(evod.continuing_events), 0) def testUnexplainedCancellationExplained(self): restriction = self._cancel_1999_02_08() request = RequestFactory().get("/test") request.user = self.user KEY = PageViewRestriction.passed_view_restrictions_session_key request.session = {KEY: [restriction.id]} events = RecurringEventPage.events(request).byDay( dt.date(1999, 2, 1), dt.date(1999, 2, 28)) self.assertEqual(len(events), 28) evod = events[7] self.assertEqual(evod.date, dt.date(1999, 2, 8)) self.assertEqual(len(evod.days_events), 1) self.assertEqual(len(evod.continuing_events), 0) title, page, url = evod.days_events[0] self.assertEqual(title, "Restructure Pending") self.assertIs(type(page), CancellationPage) def _cancel_1999_02_08(self): cancellation = CancellationPage( owner=self.user, slug="1999-02-08-cancellation", title="Cancellation for Monday 8th of February", overrides=self.event, except_date=dt.date(1999, 2, 8), cancellation_title="Restructure Pending", cancellation_details="Keep it quiet") self.event.add_child(instance=cancellation) PASSWORD = PageViewRestriction.PASSWORD restriction = PageViewRestriction.objects.create( restriction_type=PASSWORD, password="******", page=cancellation) restriction.save() return restriction def testStatus(self): self.assertEqual(self.cancellation.status, "cancelled") self.assertEqual(self.cancellation.status_text, "This event has been cancelled.") now = dt.datetime.now() myday = now.date() + dt.timedelta(1) friday = myday + dt.timedelta(days=(4 - myday.weekday()) % 7) futureCan = CancellationPage(owner=self.user, slug="fri-cancellation", title="Cancellation for Friday", overrides=self.event, except_date=friday, cancellation_title="", cancellation_details="") self.event.add_child(instance=futureCan) self.assertEqual(futureCan.status, "cancelled") self.assertEqual(futureCan.status_text, "This event has been cancelled.") def testWhen(self): self.assertEqual(self.cancellation.when, "Wednesday 1st of February 1989 at 1pm to 3:30pm") def testAt(self): self.assertEqual(self.cancellation.at.strip(), "1pm")
class TestTZ(TestCase): def setUp(self): self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.event = RecurringEventPage( owner=self.user, slug="code-for-boston", title="Code for Boston", repeat=Recurrence(dtstart=dt.date(2017, 1, 1), freq=WEEKLY, byweekday=[TU]), time_from=dt.time(19), time_to=dt.time(21, 30), tz=pytz.timezone("US/Eastern"), location="4th Floor, 1 Broadway, Cambridge, MA") self.calendar.add_child(instance=self.event) self.event.save_revision().publish() def testGetEventsByLocalDay(self): events = RecurringEventPage.events.byDay(dt.date(2018, 4, 1), dt.date(2018, 4, 30)) self.assertEqual(len(events), 30) evod1 = events[3] self.assertEqual(evod1.date, dt.date(2018, 4, 4)) self.assertEqual(len(evod1.days_events), 1) self.assertEqual(len(evod1.continuing_events), 0) @freeze_timetz("2017-05-31") def testLocalWhen(self): with timezone.override("America/Los_Angeles"): self.assertEqual(self.event.when, "Tuesdays at 4pm to 6:30pm") with timezone.override("Australia/Perth"): self.assertEqual(self.event.when, "Wednesdays at 7am to 9:30am") @timezone.override("America/Los_Angeles") def testLocalAt(self): self.assertEqual(self.event.at, "4pm") @timezone.override("America/Los_Angeles") def testUpcomingLocalDt(self): when = self.event._upcoming_datetime_from self.assertEqual(when.tzinfo.zone, "America/Los_Angeles") self.assertEqual(when.weekday(), calendar.TUESDAY) @timezone.override("Pacific/Auckland") def testPastLocalDt(self): when = self.event._past_datetime_from self.assertEqual(when.tzinfo.zone, "Pacific/Auckland") self.assertEqual(when.weekday(), calendar.WEDNESDAY) @timezone.override("Pacific/Kiritimati") def testExtremeTimeZones(self): lions = RecurringEventPage(owner=self.user, slug="pago-pago-lions", title="Pago Pago Lions Club", repeat=Recurrence(dtstart=dt.date( 2015, 2, 1), freq=MONTHLY, byweekday=[TH(1), TH(3)]), time_from=dt.time(23, 0), tz=pytz.timezone("Pacific/Pago_Pago"), location="Lions Den, Tafuna, PagoPago", website="http://www.lionsclubs.org.nz") self.calendar.add_child(instance=lions) self.assertEqual( lions.when, "The Saturday after the first Thursday and " "Saturday after the third Thursday of the month at 12am")
class Test(TestCase): def setUp(self): self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner = self.user, slug = "events", title = "Events") Page.objects.get(slug='home').add_child(instance=self.calendar) self.calendar.save() self.calendar.save_revision().publish() self.event = MultidayRecurringEventPage( owner = self.user, slug = "team-retreat", title = "Team Retreat", repeat = Recurrence(dtstart=dt.date(2000,1,1), freq=YEARLY, bymonth=8, byweekday=FR(1)), num_days = 3, time_from = dt.time(18), time_to = dt.time(16,30)) self.calendar.add_child(instance=self.event) self.event.save_revision().publish() def testGetEventsByDay(self): events = MultidayRecurringEventPage.events.byDay(dt.date(2017,8,1), dt.date(2017,8,31)) self.assertEqual(len(events), 31) evod = events[3] self.assertEqual(evod.date, dt.date(2017,8,4)) self.assertEqual(len(evod.days_events), 1) self.assertEqual(len(evod.continuing_events), 0) evod = events[4] self.assertEqual(evod.date, dt.date(2017,8,5)) self.assertEqual(len(evod.days_events), 0) self.assertEqual(len(evod.continuing_events), 1) evod = events[5] self.assertEqual(evod.date, dt.date(2017,8,6)) self.assertEqual(len(evod.days_events), 0) self.assertEqual(len(evod.continuing_events), 1) def testStatus(self): with freeze_timetz("2014-08-01 17:00:00"): self.assertEqual(self.event.status_text, "") with freeze_timetz("2014-08-02 13:00:00"): self.assertEqual(self.event.status_text, "This event has started.") with freeze_timetz("2014-08-03 15:00:00"): self.assertEqual(self.event.status_text, "This event has started.") with freeze_timetz("2014-08-03 17:00:00"): self.assertEqual(self.event.status_text, "") def testNextOn(self): request = RequestFactory().get("/test") request.user = self.user request.session = {} oldEvent = MultidayRecurringEventPage( owner = self.user, slug = "same-old-thing", title = "Same Ol'", repeat = Recurrence(dtstart=dt.date(1971,1,1), until=dt.date(1982,1,1), freq=WEEKLY, byweekday=SA(1)), num_days = 2) self.calendar.add_child(instance=oldEvent) oldEvent.save_revision().publish() with freeze_timetz("1974-08-01 17:00:00"): self.assertEqual(oldEvent.next_date, dt.date(1974, 8, 3)) self.assertEqual(oldEvent._nextOn(request), "Saturday 3rd of August ") with freeze_timetz("1982-01-01 17:00:00"): self.assertIsNone(oldEvent.next_date) self.assertEqual(oldEvent._nextOn(request), None) def testWhen(self): self.assertEqual(self.event.when, "The first Friday of August for 3 days " "starting at 6pm finishing at 4:30pm") def testAt(self): self.assertEqual(self.event.at.strip(), "6pm") @freeze_timetz("2035-04-03 10:00:00") def testPrevDate(self): self.assertEqual(self.event.prev_date, dt.date(2034, 8, 4)) @freeze_timetz("2018-04-03 10:00:00") def testFutureExceptions(self): request = RequestFactory().get("/test") request.user = self.user request.session = {} info2018 = ExtraInfoPage(owner = self.user, overrides = self.event, except_date = dt.date(2018, 8, 3), extra_title = "Team Retreat 2018", extra_information = "Weekend at Bernie's") self.event.add_child(instance=info2018) exceptions = self.event._futureExceptions(request) self.assertEqual(len(exceptions), 1) info = exceptions[0] self.assertEqual(info.slug, "2018-08-03-extra-info") self.assertEqual(info.extra_title, "Team Retreat 2018") @freeze_timetz("2018-08-04 02:00:00") def testPastExcludeExtraInfo(self): info2018 = ExtraInfoPage(owner = self.user, overrides = self.event, except_date = dt.date(2018, 8, 3), extra_title = "Team Retreat 2018", extra_information = "Weekend at Bernie's") self.event.add_child(instance=info2018) before = self.event._past_datetime_from self.assertEqual(before, datetimetz(2017, 8, 4, 18))
class TestFeed(TestCase): @freeze_time("2016-03-24") def setUp(self): imgFile = get_test_image_file() imgFile.name = "logo.png" self.img = Image.objects.create(title="Logo", file=imgFile) imgName = os.path.splitext(os.path.basename(self.img.file.name))[0] self.rendName = "{}.width-350.format-png.png".format(imgName) Site.objects.update(hostname="joy.test") self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3(R3t') self.requestFactory = RequestFactory() self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.event = RecurringEventPage(owner=self.user, slug="workshop", title="Workshop", image=self.img, repeat=Recurrence( dtstart=dt.date(2017, 1, 1), freq=MONTHLY, byweekday=[TU(1)], until=dt.date(2017, 12, 26))) self.calendar.add_child(instance=self.event) self.event.save_revision().publish() self.handler = RssHandler() def tearDown(self): self.img.file.delete(False) for rend in self.img.renditions.all(): rend.file.delete(False) def _getRequest(self, path="/"): request = self.requestFactory.get(path) request.user = self.user request.site = self.home.get_site() request.session = {} request._messages = FallbackStorage(request) request.POST = request.POST.copy() request.POST['action-publish'] = "action-publish" return request @freeze_time("2016-12-02") def testServe(self): response = self.handler.serve(self.calendar, self._getRequest("/events/")) self.assertEqual(response.status_code, 200) self.assertEqual(response.get('Content-Type'), "application/xml; charset=utf-8") self.assertIn(b'<?xml version=\'1.0\' encoding=\'UTF-8\'?>', response.content) soup = BeautifulSoup(response.content, "xml") channel = soup.channel self.assertEqual(channel.title.string, "Events") self.assertEqual(channel.description.string, "Events") self.assertEqual(channel.link.string, "http://joy.test/events/") self.assertEqual(channel.generator.string, "ls.joyous") self.assertEqual(len(channel("image")), 1) image = channel.image self.assertEqual(image.url.string, "http://joy.test/static/joyous/img/logo.png") self.assertEqual(image.title.string, "Events") self.assertEqual(image.link.string, "http://joy.test/events/") self.assertEqual(channel.lastBuildDate.string, "Fri, 02 Dec 2016 00:00:00 +0000") self.assertEqual(len(channel("item")), 1) item = channel.item self.assertEqual(item.title.string, "Workshop") self.assertEqual(item.link.string, "http://joy.test/events/workshop/") self.assertEqual( item.enclosure.decode(), '<enclosure length="773" type="image/png" ' 'url="http://joy.test/media/images/{}"/>'.format(self.rendName)) self.assertEqual( item.description.decode(), """<description>\n\n\n <div class="joy-ev-when joy-field"> The first Tuesday of the month (until 26 December 2017) </div>\n <div class="joy-ev-next-on joy-field"> Next on Tuesday 3rd of January 2017 </div>\n\n\n\n <div class="rich-text"></div>\n</description>""") self.assertEqual(item.guid.get("isPermaLink"), "true") self.assertEqual(item.guid.string, "http://joy.test/events/workshop/") self.assertEqual(item.pubDate.string, "Thu, 24 Mar 2016 00:00:00 +0000") def testServeUnsupported(self): response = self.handler.serve(self.event, self._getRequest("/events/workshop")) self.assertIsNone(response) @freeze_time("2016-03-25") def testServeExtraInfo(self): info = ExtraInfoPage(owner=self.user, overrides=self.event, except_date=dt.date(2017, 2, 7), extra_title="System Demo", extra_information="<h3>System Demo</h3>") self.event.add_child(instance=info) info.save_revision().publish() response = self.handler.serve(self.calendar, self._getRequest("/events/")) self.assertEqual(response.status_code, 200) self.assertEqual(response.get('Content-Type'), "application/xml; charset=utf-8") soup = BeautifulSoup(response.content, "xml") channel = soup.channel self.assertEqual(channel.title.string, "Events") self.assertEqual(len(channel("item")), 2) item = channel("item")[1] self.assertEqual(item.title.string, "System Demo") self.assertEqual( item.link.string, "http://joy.test/events/workshop/2017-02-07-extra-info/") self.assertEqual( item.enclosure.decode(), '<enclosure length="773" type="image/png" ' 'url="http://joy.test/media/images/{}"/>'.format(self.rendName)) self.assertEqual( item.description.decode(), """<description>\n\n\n <div class="joy-ev-when joy-field"> Tuesday 7th of February 2017 </div>\n\n\n\n <div class="rich-text"><h3>System Demo</h3></div> <div class="rich-text"></div>\n</description>""") self.assertEqual(item.guid.get("isPermaLink"), "true") self.assertEqual( item.guid.string, "http://joy.test/events/workshop/2017-02-07-extra-info/") self.assertEqual(item.pubDate.string, "Fri, 25 Mar 2016 00:00:00 +0000") @freeze_time("2016-03-26") def testServePostponement(self): postponement = PostponementPage( owner=self.user, overrides=self.event, except_date=dt.date(2017, 4, 4), image=self.img, cancellation_title="Workshop Postponed", cancellation_details="Workshop will take place next week", postponement_title="Workshop", date=dt.date(2017, 4, 11), details="Interesting stuff") self.event.add_child(instance=postponement) postponement.save_revision().publish() response = self.handler.serve(self.calendar, self._getRequest("/events/")) self.assertEqual(response.status_code, 200) soup = BeautifulSoup(response.content, "xml") channel = soup.channel self.assertEqual(channel.title.string, "Events") self.assertEqual(len(channel("item")), 2) item = channel("item")[1] self.assertEqual(item.title.string, "Workshop") self.assertEqual( item.link.string, "http://joy.test/events/workshop/2017-04-04-postponement/") self.assertEqual( item.enclosure.decode(), '<enclosure length="773" type="image/png" ' 'url="http://joy.test/media/images/{}"/>'.format(self.rendName)) self.assertEqual( item.description.decode(), """<description>\n\n\n <div class="joy-ev-when joy-field"> Tuesday 11th of April 2017 </div>\n <div class="joy-ev-from-when joy-field"> Postponed from Tuesday 4th of April 2017 </div>\n\n\n\n <div class="rich-text">Interesting stuff</div>\n</description>""") self.assertEqual(item.guid.get("isPermaLink"), "true") self.assertEqual( item.guid.string, "http://joy.test/events/workshop/2017-04-04-postponement/") self.assertEqual(item.pubDate.string, "Sat, 26 Mar 2016 00:00:00 +0000")
class TestExport(TestCase): def setUp(self): Site.objects.update(hostname="joy.test") self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3(R3t') self.requestFactory = RequestFactory() self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() self.dicerun = SimpleEventPage(owner=self.user, slug="mercy-dice-run", title="Mercy Dice Run", date=dt.date(2020, 3, 16), location="Newtown") self.calendar.add_child(instance=self.dicerun) self.dicerun.save_revision().publish() event = SimpleEventPage(owner=self.user, slug="workshop", title="Workshop", date=dt.date(2020, 3, 22)) self.calendar.add_child(instance=event) event.save_revision().publish() self.handler = ICalHandler() def _getRequest(self, path="/"): request = self.requestFactory.get(path) request.user = self.user request.site = self.home.get_site() request.session = {} request._messages = FallbackStorage(request) request.POST = request.POST.copy() request.POST['action-publish'] = "action-publish" return request def testServeCalendar(self): response = self.handler.serve(self.calendar, self._getRequest("/events/")) self.assertEqual(response.status_code, 200) self.assertEqual(response.get('Content-Type'), "text/calendar") self.assertEqual(response.get('Content-Disposition'), "attachment; filename=events.ics") self.assertEqual(response.content.count(b"BEGIN:VEVENT"), 2) def testServeEvent(self): response = self.handler.serve( self.dicerun, self._getRequest("/events/mercy-dice-run/")) self.assertEqual(response.status_code, 200) self.assertEqual(response.get('Content-Type'), "text/calendar") self.assertEqual(response.get('Content-Disposition'), "attachment; filename=mercy-dice-run.ics") self.assertEqual(response.content.count(b"BEGIN:VEVENT"), 1) self.assertIn(b"SUMMARY:Mercy Dice Run", response.content) self.assertIn(b"DTSTART;TZID=Asia/Tokyo:20200316T000000", response.content) self.assertIn(b"DTEND;TZID=Asia/Tokyo:20200316T235959", response.content) self.assertIn(b"LOCATION:Newtown", response.content) self.assertIn(b"URL:http://joy.test/events/mercy-dice-run", response.content) def testServePage(self): response = self.handler.serve(self.home, self._getRequest("/")) self.assertIsNone(response)
class Test(TestCase): def setUp(self): Site.objects.update(hostname="joy.test") self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") Page.objects.get(slug='home').add_child(instance=self.calendar) self.calendar.save() self.calendar.save_revision().publish() self.event = RecurringEventPage( owner=self.user, slug="lug-meetup", title="Linux Users Group Meetup", repeat=Recurrence(dtstart=dt.date(2017, 8, 5), freq=MONTHLY, byweekday=[TU(1)]), time_from=dt.time(18, 30), time_to=dt.time(20), location="6 Mackay St, Greymouth (upstairs)") self.calendar.add_child(instance=self.event) self.event.save_revision().publish() def testGetEventsByDay(self): events = RecurringEventPage.events.byDay(dt.date(2017, 8, 1), dt.date(2017, 10, 31)) self.assertEqual(len(events), 92) evod = events[35] self.assertEqual(evod.date, dt.date(2017, 9, 5)) self.assertEqual(len(evod.all_events), 1) self.assertEqual(len(evod.days_events), 1) self.assertEqual(len(evod.continuing_events), 0) def testStatus(self): pastEvent = RecurringEventPage(owner=self.user, slug="past", title="Past Event", repeat=Recurrence( dtstart=dt.date(2008, 2, 1), until=dt.date(2008, 5, 4), freq=WEEKLY, byweekday=[SA, SU])) self.calendar.add_child(instance=pastEvent) self.assertEqual(pastEvent.status, "finished") self.assertEqual(pastEvent.status_text, "These events have finished.") now = timezone.localtime() earlier = now - dt.timedelta(hours=1) if earlier.date() != now.date(): earlier = datetimetz(now.date(), dt.time.min) nowEvent = RecurringEventPage(owner=self.user, slug="now", title="Now Event", repeat=Recurrence(dtstart=dt.date( 2010, 1, 1), freq=DAILY), time_from=earlier.time(), time_to=dt.time.max) self.calendar.add_child(instance=nowEvent) self.assertEqual(nowEvent.status, "started") self.assertEqual(nowEvent.status_text, "This event has started.") today = timezone.localdate() notToday = [ weekday for weekday in EVERYWEEKDAY if weekday.weekday != today.weekday() ] pastAndFutureEvent = RecurringEventPage( owner=self.user, slug="not-today", title="Any day but today", repeat=Recurrence(dtstart=dt.date(2009, 8, 7), freq=WEEKLY, byweekday=notToday)) self.calendar.add_child(instance=pastAndFutureEvent) self.assertIsNone(pastAndFutureEvent.status) self.assertEqual(pastAndFutureEvent.status_text, "") @freeze_timetz("2008-05-04 09:01") def testJustFinishedStatus(self): event = RecurringEventPage(owner=self.user, slug="breakfast1", title="Breakfast-in-bed", repeat=Recurrence(dtstart=dt.date( 2008, 2, 1), until=dt.date(2008, 5, 9), freq=WEEKLY, byweekday=[SA, SU]), time_from=dt.time(8), time_to=dt.time(9)) self.calendar.add_child(instance=event) self.assertEqual(event.status, "finished") @freeze_timetz("2008-05-04 07:00") def testLastOccurenceCancelledStatus(self): event = RecurringEventPage(owner=self.user, slug="breakfast2", title="Breakfast-in-bed", repeat=Recurrence(dtstart=dt.date( 2008, 2, 1), until=dt.date(2008, 5, 9), freq=WEEKLY, byweekday=[SA, SU]), time_from=dt.time(8), time_to=dt.time(9)) self.calendar.add_child(instance=event) cancellation = CancellationPage( owner=self.user, overrides=event, except_date=dt.date(2008, 5, 4), cancellation_title="Fire in the kitchen", cancellation_details="The bacon fat is burning") event.add_child(instance=cancellation) self.assertEqual(event.status, "finished") @freeze_timetz("2008-05-04 12:00") def testPostponementOccurenceLast(self): request = RequestFactory().get("/test") request.user = self.user request.session = {} event = RecurringEventPage(owner=self.user, slug="breakfast3", title="Breakfast-in-bed", repeat=Recurrence(dtstart=dt.date( 2008, 2, 1), until=dt.date(2008, 5, 9), freq=WEEKLY, byweekday=[SA, SU]), time_from=dt.time(8), time_to=dt.time(9)) self.calendar.add_child(instance=event) postponement = PostponementPage( owner=self.user, overrides=event, except_date=dt.date(2008, 5, 3), postponement_title="Breakfast in Bed owed from May", date=dt.date(2008, 5, 24), time_from=dt.time(8), time_to=dt.time(9)) event.add_child(instance=postponement) self.assertIsNone(event.status) self.assertEqual( event._nextOn(request), '<a class="inline-link" href="/events/breakfast3/2008-05-03-postponement/">Saturday 24th of May at 8am</a>' ) def testWhen(self): self.assertEqual(self.event.when, "The first Tuesday of the month at 6:30pm to 8pm") def testAt(self): self.assertEqual(self.event.at.strip(), "6:30pm") def testUpcomingDt(self): lugDt = self.event._upcoming_datetime_from self.assertEqual(lugDt.time(), dt.time(18, 30)) self.assertEqual(lugDt.date().weekday(), 1) self.assertLess(lugDt.date().day, 8) movieNight = RecurringEventPage(owner=self.user, slug="movies", title="Movies", repeat=Recurrence(dtstart=dt.date( 2005, 2, 1), freq=WEEKLY, byweekday=[ TH, ]), time_from=dt.time(20, 15), time_to=dt.time(21, 30)) self.calendar.add_child(instance=movieNight) now = timezone.localtime() myday = now.date() startTime = dt.time(20, 15) if now.time() > startTime: myday += dt.timedelta(days=1) thursday = myday + dt.timedelta(days=(3 - myday.weekday()) % 7) self.assertEqual(movieNight._upcoming_datetime_from, datetimetz(thursday, startTime)) def testPastDt(self): lugDt = self.event._past_datetime_from self.assertEqual(lugDt.time(), dt.time(18, 30)) self.assertEqual(lugDt.date().weekday(), 1) self.assertLess(lugDt.date().day, 8) movieNight = RecurringEventPage(owner=self.user, slug="movies", title="Movies", repeat=Recurrence(dtstart=dt.date( 2005, 2, 1), freq=WEEKLY, byweekday=[ TH, ]), time_from=dt.time(20, 15), time_to=dt.time(21, 30)) self.calendar.add_child(instance=movieNight) now = timezone.localtime() myday = now.date() startTime = dt.time(20, 15) if now.time() < startTime: myday -= dt.timedelta(days=1) thursday = myday - dt.timedelta(days=(myday.weekday() - 3) % 7) self.assertEqual(movieNight._past_datetime_from, datetimetz(thursday, startTime)) def testGroup(self): self.assertIsNone(self.event.group) def testOccursOn(self): self.assertIs(self.event._occursOn(dt.date(2018, 3, 6)), True) self.assertIs(self.event._occursOn(dt.date(2018, 3, 13)), False)
class TestRecurringVEvent(TestCase): def setUp(self): site = Site.objects.get(is_default_site=True) site.hostname = "joy.test" site.save() self.home = Page.objects.get(slug='home') self.user = User.objects.create_user('i', '*****@*****.**', 's3cr3t') self.calendar = CalendarPage(owner=self.user, slug="events", title="Events") self.home.add_child(instance=self.calendar) self.calendar.save_revision().publish() @freeze_time("2017-08-15") def testFromPage(self): page = RecurringEventPage( owner=self.user, slug="code-for-boston", title="Code for Boston", repeat=Recurrence(dtstart=dt.date(2017, 1, 1), freq=WEEKLY, byweekday=[TU]), time_from=dt.time(19), time_to=dt.time(21, 30), tz=pytz.timezone("US/Eastern"), location="4th Floor, 1 Broadway, Cambridge, MA") self.calendar.add_child(instance=page) page.save_revision().publish() vev = RecurringVEvent.fromPage(page) vev.set('UID', "this-is-not-a-unique-identifier") codeForBoston = b"\r\n".join([ b"BEGIN:VEVENT", b"SUMMARY:Code for Boston", b"DTSTART;TZID=US/Eastern:20170103T190000", b"DTEND;TZID=US/Eastern:20170103T213000", b"DTSTAMP:20170815T000000Z", b"UID:this-is-not-a-unique-identifier", b"SEQUENCE:1", b"RRULE:FREQ=WEEKLY;BYDAY=TU;WKST=SU", b"CREATED:20170815T000000Z", b"DESCRIPTION:", b"LAST-MODIFIED:20170815T000000Z", b"LOCATION:4th Floor\\, 1 Broadway\\, Cambridge\\, MA", b"URL:http://joy.test/events/code-for-boston/", b"END:VEVENT", b"" ]) self.assertEqual(vev.to_ical(), codeForBoston) @freeze_time("2018-05-10") def testExdate(self): page = RecurringEventPage(owner=self.user, slug="sleep", title="Sleep In", repeat=Recurrence(dtstart=dt.date( 2018, 5, 1), freq=MONTHLY, byweekday=[SA(+2)]), time_from=dt.time(7), time_to=dt.time(10, 30), tz=pytz.timezone("Pacific/Auckland"), details="<p>zzzZZZZZZZZZ</p>", location="Bed") self.calendar.add_child(instance=page) page.save_revision().publish() except1 = CancellationPage( owner=self.user, slug="2018-06-09-cancellation", title="Cancellation for Saturday 9th of June", overrides=page, except_date=dt.date(2018, 6, 9)) page.add_child(instance=except1) except1.save_revision().publish() except2 = CancellationPage( owner=self.user, slug="2018-07-14-cancellation", title="Cancellation for Saturday 14th of July", overrides=page, except_date=dt.date(2018, 7, 14)) page.add_child(instance=except2) except2.save_revision().publish() vev = RecurringVEvent.fromPage(page) vev.set('UID', "this-is-not-a-unique-identifier") tz = pytz.timezone("Pacific/Auckland") exDates = [exDate.dt for exDate in vev['EXDATE'].dts] self.assertEqual(exDates, [ tz.localize(dt.datetime(2018, 6, 9, 7)), tz.localize(dt.datetime(2018, 7, 14, 7)) ]) sleepIn = b"\r\n".join([ b"BEGIN:VEVENT", b"SUMMARY:Sleep In", b"DTSTART;TZID=Pacific/Auckland:20180512T070000", b"DTEND;TZID=Pacific/Auckland:20180512T103000", b"DTSTAMP:20180510T000000Z", b"UID:this-is-not-a-unique-identifier", b"SEQUENCE:1", b"RRULE:FREQ=MONTHLY;BYDAY=+2SA;WKST=SU", b"EXDATE;TZID=Pacific/Auckland:20180609T070000,20180714T070000", b"CREATED:20180510T000000Z", b"DESCRIPTION:<p>zzzZZZZZZZZZ</p>", b"LAST-MODIFIED:20180510T000000Z", b"LOCATION:Bed", b"URL:http://joy.test/events/sleep/", b"END:VEVENT", b"" ]) self.assertEqual(vev.to_ical(), sleepIn)