#!/usr/bin/env python from unittest import TestCase import vobject import icalendar import uuid from caldav.lib.vcal import fix, create_ical #from datetime import timezone import pytz from datetime import datetime, timedelta from caldav.lib.python_utilities import to_normal_str, to_wire #utc = timezone.utc import pytz utc = pytz.utc # example from http://www.rfc-editor.org/rfc/rfc5545.txt ev = """BEGIN:VCALENDAR VERSION:2.0 PRODID:-//Example Corp.//CalDAV Client//EN BEGIN:VEVENT UID:19970901T130000Z-123403@example.com DTSTAMP:19970901T130000Z DTSTART;VALUE=DATE:19971102 SUMMARY:Our Blissful Anniversary TRANSP:TRANSPARENT CLASS:CONFIDENTIAL CATEGORIES:ANNIVERSARY,PERSONAL,SPECIAL OCCASION RRULE:FREQ=YEARLY END:VEVENT END:VCALENDAR""" class TestVcal(TestCase): def assertSameICal(self, ical1, ical2, ignore_uid=False): """helper method""" def normalize(s, ignore_uid): s = to_wire(s).replace(b'\r\n',b'\n').strip().split(b'\n') s.sort() if ignore_uid: s = [x for x in s if not x.startswith(b'UID:')] return b"\n".join(s) self.assertEqual(normalize(ical1, ignore_uid), normalize(ical2, ignore_uid)) return ical2 def verifyICal(self, ical): """ Does a best effort on verifying that the ical is correct, by pushing it through the vobject and icalendar library """ vobj = vobject.readOne(to_normal_str(ical)) icalobj = icalendar.Calendar.from_ical(ical) self.assertSameICal(icalobj.to_ical(), ical) self.assertSameICal(vobj.serialize(), ical) return icalobj.to_ical() ## TODO: create a test_fix, should be fairly simple - for each ## "fix" that's done in the code, make up some broken ical data ## that demonstrates the brokenness we're dealing with (preferably ## real-world examples). Then ... #for bical in broken_ical: # verifyICal(vcal.fix(bical)) def test_create_ical(self): def create_and_validate(**args): return self.verifyICal(create_ical(**args)) ## First, a fully valid ical_fragment should go through as is self.assertSameICal(create_and_validate(ical_fragment=ev), ev) ## One may add stuff to a fully valid ical_fragment self.assertSameICal(create_and_validate(ical_fragment=ev, priority=3), ev+"\nPRIORITY:3\n") ## binary string or unicode string ... shouldn't matter self.assertSameICal(create_and_validate(ical_fragment=ev.encode('utf-8'), priority=3), ev+"\nPRIORITY:3\n") ## The returned ical_fragment should always contain BEGIN:VCALENDAR and END:VCALENDAR ical_fragment = ev.replace('BEGIN:VCALENDAR', '').replace('END:VCALENDAR', '') self.assertSameICal(create_and_validate(ical_fragment=ical_fragment), ev) ## Create something with a dtstart and verify that we get it back in the ical some_ical0 = create_and_validate(summary="gobledok", dtstart=datetime(2032,10,10,10,10,10, tzinfo=utc), duration=timedelta(hours=5)) some_ical1 = create_and_validate(summary=b"gobledok", dtstart=datetime(2032,10,10,10,10,10, tzinfo=utc), duration=timedelta(hours=5)) self.assertTrue(b'DTSTART;VALUE=DATE-TIME:20321010T101010Z' in some_ical0) self.assertSameICal(some_ical0, some_ical1, ignore_uid=True) ## Verify that ical_fragment works as intended some_ical = create_and_validate(summary="gobledok", ical_fragment="PRIORITY:3", dtstart=datetime(2032,10,10,10,10,10, tzinfo=utc), duration=timedelta(hours=5)) self.assertTrue(b'DTSTART;VALUE=DATE-TIME:20321010T101010Z' in some_ical) some_ical = create_and_validate(summary="gobledok", ical_fragment=b"PRIORITY:3", dtstart=datetime(2032,10,10,10,10,10, tzinfo=utc), duration=timedelta(hours=5)) self.assertTrue(b'DTSTART;VALUE=DATE-TIME:20321010T101010Z' in some_ical) some_ical = create_and_validate(summary=b"gobledok", ical_fragment="", dtstart=datetime(2032,10,10,10,10,10, tzinfo=utc), duration=timedelta(hours=5)) self.assertTrue(b'DTSTART;VALUE=DATE-TIME:20321010T101010Z' in some_ical)