summaryrefslogtreecommitdiffstats
path: root/tests/unit
diff options
context:
space:
mode:
authorJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2012-07-20 10:34:05 +0100
committerJeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>2012-07-20 10:34:05 +0100
commitefaef7e429879c34d30c12c4561ab201f2dec27e (patch)
tree44de15339b707afc13f75d36e9c6575d8c6c8dfe /tests/unit
parentc3cb7ec328dfac4579a246753455fa592e0dcd46 (diff)
parentbde1f6b4d468c6f9e9f7586280c79736ca07ca91 (diff)
downloadpykolab-efaef7e429879c34d30c12c4561ab201f2dec27e.tar.gz
Merge branch 'master' of ssh://git.kolabsys.com/git/pykolab
Diffstat (limited to 'tests/unit')
-rw-r--r--tests/unit/__init__.py4
-rw-r--r--tests/unit/test-000-imports.py23
-rw-r--r--tests/unit/test-001-contact_reference.py30
-rw-r--r--tests/unit/test-002-attendee.py105
-rw-r--r--tests/unit/test-003-event.py108
-rw-r--r--tests/unit/test-004-icalendar.py220
-rw-r--r--tests/unit/test-005-timezone.py73
7 files changed, 563 insertions, 0 deletions
diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py
new file mode 100644
index 0000000..b5e7094
--- /dev/null
+++ b/tests/unit/__init__.py
@@ -0,0 +1,4 @@
+import sys
+
+sys.path = [ '.', '..' ] + sys.path
+
diff --git a/tests/unit/test-000-imports.py b/tests/unit/test-000-imports.py
new file mode 100644
index 0000000..17e1c57
--- /dev/null
+++ b/tests/unit/test-000-imports.py
@@ -0,0 +1,23 @@
+import unittest
+
+class TestImports(unittest.TestCase):
+ def test_pykolab(self):
+ import pykolab
+
+ def test_pykolab_xml(self):
+ import pykolab.xml
+
+ def test_pykolab_xml_attendee(self):
+ from pykolab.xml import Attendee
+
+ def test_pykolab_xml_contact(self):
+ from pykolab.xml import Contact
+
+ def test_pykolab_xml_contactReference(self):
+ from pykolab.xml import ContactReference
+
+ def test_pykolab_xml_event(self):
+ from pykolab.xml import Event
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/unit/test-001-contact_reference.py b/tests/unit/test-001-contact_reference.py
new file mode 100644
index 0000000..7c8f128
--- /dev/null
+++ b/tests/unit/test-001-contact_reference.py
@@ -0,0 +1,30 @@
+import datetime
+import unittest
+
+from pykolab.xml import ContactReference
+
+class TestEventXML(unittest.TestCase):
+ contact_reference = ContactReference("jane@doe.org")
+
+ def assertIsInstance(self, _value, _type):
+ if hasattr(unittest.TestCase, 'assertIsInstance'):
+ return unittest.TestCase.assertIsInstance(self, _value, _type)
+ else:
+ if (type(_value)) == _type:
+ return True
+ else:
+ raise AssertionError, "%s != %s" % (type(_value), _type)
+
+ def test_001_minimal(self):
+ self.assertIsInstance(self.contact_reference.__str__(), str)
+
+ def test_002_empty_name(self):
+ self.assertEqual(self.contact_reference.get_name(), "")
+
+ def test_003_set_name(self):
+ name = "Doe, Jane"
+ self.contact_reference.set_name(name)
+ self.assertEqual(self.contact_reference.get_name(), name)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/unit/test-002-attendee.py b/tests/unit/test-002-attendee.py
new file mode 100644
index 0000000..4298761
--- /dev/null
+++ b/tests/unit/test-002-attendee.py
@@ -0,0 +1,105 @@
+import datetime
+import unittest
+
+from pykolab.xml import Attendee
+
+class TestEventXML(unittest.TestCase):
+ attendee = Attendee("jane@doe.org")
+
+ def assertIsInstance(self, _value, _type):
+ if hasattr(unittest.TestCase, 'assertIsInstance'):
+ return unittest.TestCase.assertIsInstance(self, _value, _type)
+ else:
+ if (type(_value)) == _type:
+ return True
+ else:
+ raise AssertionError, "%s != %s" % (type(_value), _type)
+
+ def test_001_minimal(self):
+ self.assertIsInstance(self.attendee.__str__(), str)
+
+ def test_002_empty_name(self):
+ self.assertEqual(self.attendee.get_name(), "")
+
+ def test_003_set_name(self):
+ name = "Doe, Jane"
+ self.attendee.set_name(name)
+ self.assertEqual(self.attendee.get_name(), name)
+
+ def test_004_default_participant_status(self):
+ self.assertEqual(self.attendee.get_participant_status(), 0)
+
+ def test_005_participant_status_map_length(self):
+ self.assertEqual(len(self.attendee.participant_status_map.keys()), 5)
+
+ def test_006_participant_status_map_forward_lookup(self):
+ # Forward lookups
+ self.assertEqual(self.attendee.participant_status_map["NEEDS-ACTION"], 0)
+ self.assertEqual(self.attendee.participant_status_map["ACCEPTED"], 1)
+ self.assertEqual(self.attendee.participant_status_map["DECLINED"], 2)
+ self.assertEqual(self.attendee.participant_status_map["TENTATIVE"], 3)
+ self.assertEqual(self.attendee.participant_status_map["DELEGATED"], 4)
+
+ def test_007_participant_status_map_reverse_lookup(self):
+ # Reverse lookups
+ self.assertEqual([k for k,v in self.attendee.participant_status_map.iteritems() if v == 0][0], "NEEDS-ACTION")
+ self.assertEqual([k for k,v in self.attendee.participant_status_map.iteritems() if v == 1][0], "ACCEPTED")
+ self.assertEqual([k for k,v in self.attendee.participant_status_map.iteritems() if v == 2][0], "DECLINED")
+ self.assertEqual([k for k,v in self.attendee.participant_status_map.iteritems() if v == 3][0], "TENTATIVE")
+ self.assertEqual([k for k,v in self.attendee.participant_status_map.iteritems() if v == 4][0], "DELEGATED")
+
+ def test_008_default_rsvp(self):
+ self.assertEqual(self.attendee.get_rsvp(), 0)
+
+ def test_009_rsvp_map_length(self):
+ self.assertEqual(len(self.attendee.rsvp_map.keys()), 2)
+
+ def test_010_rsvp_map_forward_lookup_boolean(self):
+ self.assertEqual(self.attendee.rsvp_map["TRUE"], True)
+ self.assertEqual(self.attendee.rsvp_map["FALSE"], False)
+
+ def test_011_rsvp_map_forward_lookup_integer(self):
+ self.assertEqual(self.attendee.rsvp_map["TRUE"], 1)
+ self.assertEqual(self.attendee.rsvp_map["FALSE"], 0)
+
+ def test_012_rsvp_map_reverse_lookup_boolean(self):
+ self.assertEqual([k for k,v in self.attendee.rsvp_map.iteritems() if v == True][0], "TRUE")
+ self.assertEqual([k for k,v in self.attendee.rsvp_map.iteritems() if v == False][0], "FALSE")
+
+ def test_013_rsvp_map_reverse_lookup_integer(self):
+ self.assertEqual([k for k,v in self.attendee.rsvp_map.iteritems() if v == 1][0], "TRUE")
+ self.assertEqual([k for k,v in self.attendee.rsvp_map.iteritems() if v == 0][0], "FALSE")
+
+ def test_014_default_role(self):
+ self.assertEqual(self.attendee.get_role(), 0)
+
+ def test_015_role_map_length(self):
+ self.assertEqual(len(self.attendee.role_map.keys()), 4)
+
+ def test_016_role_map_forward_lookup(self):
+ self.assertEqual(self.attendee.role_map["REQ-PARTICIPANT"], 0)
+ self.assertEqual(self.attendee.role_map["CHAIR"], 1)
+ self.assertEqual(self.attendee.role_map["OPTIONAL"], 2)
+ self.assertEqual(self.attendee.role_map["NONPARTICIPANT"], 3)
+
+ def test_017_role_map_reverse_lookup(self):
+ self.assertEqual([k for k,v in self.attendee.role_map.iteritems() if v == 0][0], "REQ-PARTICIPANT")
+ self.assertEqual([k for k,v in self.attendee.role_map.iteritems() if v == 1][0], "CHAIR")
+ self.assertEqual([k for k,v in self.attendee.role_map.iteritems() if v == 2][0], "OPTIONAL")
+ self.assertEqual([k for k,v in self.attendee.role_map.iteritems() if v == 3][0], "NONPARTICIPANT")
+
+ def test_015_cutype_map_length(self):
+ self.assertEqual(len(self.attendee.cutype_map.keys()), 3)
+
+ def test_016_cutype_map_forward_lookup(self):
+ self.assertEqual(self.attendee.cutype_map["GROUP"], 1)
+ self.assertEqual(self.attendee.cutype_map["INDIVIDUAL"], 2)
+ self.assertEqual(self.attendee.cutype_map["RESOURCE"], 3)
+
+ def test_017_cutype_map_reverse_lookup(self):
+ self.assertEqual([k for k,v in self.attendee.cutype_map.iteritems() if v == 1][0], "GROUP")
+ self.assertEqual([k for k,v in self.attendee.cutype_map.iteritems() if v == 2][0], "INDIVIDUAL")
+ self.assertEqual([k for k,v in self.attendee.cutype_map.iteritems() if v == 3][0], "RESOURCE")
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/unit/test-003-event.py b/tests/unit/test-003-event.py
new file mode 100644
index 0000000..8f76397
--- /dev/null
+++ b/tests/unit/test-003-event.py
@@ -0,0 +1,108 @@
+import datetime
+import pytz
+import sys
+import unittest
+
+from pykolab.xml import Attendee
+from pykolab.xml import Event
+from pykolab.xml import EventIntegrityError
+from pykolab.xml import InvalidAttendeeParticipantStatusError
+from pykolab.xml import InvalidEventDateError
+
+class TestEventXML(unittest.TestCase):
+ event = Event()
+
+ def assertIsInstance(self, _value, _type):
+ if hasattr(unittest.TestCase, 'assertIsInstance'):
+ return unittest.TestCase.assertIsInstance(self, _value, _type)
+ else:
+ if (type(_value)) == _type:
+ return True
+ else:
+ raise AssertionError, "%s != %s" % (type(_value), _type)
+
+ def test_000_no_start_date(self):
+ self.assertRaises(EventIntegrityError, self.event.__str__)
+
+ def test_001_minimal(self):
+ self.event.set_start(datetime.datetime.now(pytz.timezone("Europe/London")))
+ self.assertIsInstance(self.event.get_start(), datetime.datetime)
+ self.assertIsInstance(self.event.__str__(), str)
+
+ def test_002_attendees_list(self):
+ self.assertIsInstance(self.event.get_attendees(), list)
+
+ def test_003_attendees_no_default(self):
+ self.assertEqual(len(self.event.get_attendees()), 0)
+
+ def test_004_attendee_add(self):
+ self.event.add_attendee("john@doe.org")
+ self.assertIsInstance(self.event.get_attendees(), list)
+ self.assertEqual(len(self.event.get_attendees()), 1)
+
+ def test_005_attendee_add_name(self):
+ self.event.add_attendee("jane@doe.org", "Doe, Jane")
+ self.assertIsInstance(self.event.get_attendees(), list)
+ self.assertEqual(len(self.event.get_attendees()), 2)
+
+ def test_006_get_attendees(self):
+ self.assertEqual([x.get_email() for x in self.event.get_attendees()], ["john@doe.org", "jane@doe.org"])
+
+ def test_007_get_attendee_by_email(self):
+ self.assertIsInstance(self.event.get_attendee_by_email("jane@doe.org"), Attendee)
+ self.assertIsInstance(self.event.get_attendee("jane@doe.org"), Attendee)
+
+ def test_007_get_nonexistent_attendee_by_email(self):
+ self.assertRaises(ValueError, self.event.get_attendee_by_email, "nosuchattendee@invalid.domain")
+ self.assertRaises(ValueError, self.event.get_attendee, "nosuchattendee@invalid.domain")
+
+ def test_008_get_attendee_by_name(self):
+ self.assertIsInstance(self.event.get_attendee_by_name("Doe, Jane"), Attendee)
+ self.assertIsInstance(self.event.get_attendee("Doe, Jane"), Attendee)
+
+ def test_008_get_nonexistent_attendee_by_name(self):
+ self.assertRaises(ValueError, self.event.get_attendee_by_name, "Houdini, Harry")
+ self.assertRaises(ValueError, self.event.get_attendee, "Houdini, Harry")
+
+ def test_009_invalid_participant_status(self):
+ self.assertRaises(InvalidAttendeeParticipantStatusError, self.event.set_attendee_participant_status, "jane@doe.org", "INVALID")
+
+ def test_010_datetime_from_string(self):
+ self.assertRaises(InvalidEventDateError, self.event.set_start, "2012-05-23 11:58:00")
+
+ def test_011_attendee_equality(self):
+ self.assertEqual(self.event.get_attendee("jane@doe.org").get_email(), "jane@doe.org")
+
+ def test_012_delegate_new_attendee(self):
+ self.event.delegate("jane@doe.org", "max@imum.com")
+
+ def test_013_delegatee_is_now_attendee(self):
+ self.assertIsInstance(self.event.get_attendee("max@imum.com"), Attendee)
+
+ def test_014_delegate_attendee_adds(self):
+ self.assertEqual(len(self.event.get_attendee("jane@doe.org").get_delegated_to()), 1)
+ self.event.delegate("jane@doe.org", "john@doe.org")
+ self.assertEqual(len(self.event.get_attendee("jane@doe.org").get_delegated_to()), 2)
+
+ def test_015_timezone(self):
+ _tz = self.event.get_start()
+ self.assertIsInstance(_tz.tzinfo, datetime.tzinfo)
+
+ def test_016_start_with_timezone(self):
+ _start = datetime.datetime(2012, 05, 23, 11, 58, 00, tzinfo=pytz.timezone("Europe/Zurich"))
+ _start_utc = _start.astimezone(pytz.utc)
+ self.assertEqual(_start.__str__(), "2012-05-23 11:58:00+01:00")
+ self.assertEqual(_start_utc.__str__(), "2012-05-23 10:58:00+00:00")
+ self.event.set_start(_start)
+ self.assertIsInstance(_start.tzinfo, datetime.tzinfo)
+ self.assertEqual(_start.tzinfo, pytz.timezone("Europe/Zurich"))
+
+ def test_017_allday_without_timezone(self):
+ _start = datetime.date(2012, 05, 23)
+ self.assertEqual(_start.__str__(), "2012-05-23")
+ self.event.set_start(_start)
+ self.assertEqual(hasattr(_start,'tzinfo'), False)
+ self.assertEqual(self.event.get_start().__str__(), "2012-05-23")
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/unit/test-004-icalendar.py b/tests/unit/test-004-icalendar.py
new file mode 100644
index 0000000..6033a33
--- /dev/null
+++ b/tests/unit/test-004-icalendar.py
@@ -0,0 +1,220 @@
+from email import message_from_string
+import icalendar
+import unittest
+
+class TestICalendar(unittest.TestCase):
+
+ def test_001_from_message_recurrence(self):
+ message = message_from_string("""Received: from localhost (localhost [127.0.0.1])
+ by kolab.example.org (Postfix) with ESMTP id 513B942E10
+ for <resource-collection-car@example.org>; Fri, 13 Jul 2012 14:54:16 +0200 (CEST)
+X-Virus-Scanned: amavisd-new at example.org
+X-Spam-Flag: NO
+X-Spam-Score: 0.551
+X-Spam-Level:
+X-Spam-Status: No, score=0.551 tagged_above=-10 required=6.2
+ tests=[ALL_TRUSTED=-1, DNS_FROM_RFC_DSN=0.001,
+ NORMAL_HTTP_TO_IP=0.001, TVD_RCVD_IP=0.054, TVD_RCVD_IP4=1.495]
+ autolearn=no
+Received: from kolab.example.org ([127.0.0.1])
+ by localhost (kolab.example.org [127.0.0.1]) (amavisd-new, port 10024)
+ with ESMTP id KNJgv841fj-1 for <resource-collection-car@example.org>;
+ Fri, 13 Jul 2012 14:54:15 +0200 (CEST)
+Received: from 192.168.122.228 (localhost [127.0.0.1])
+ (Authenticated sender: john.doe@example.org)
+ by kolab.example.org (Postfix) with ESMTPSA id 0EBDA42E39
+ for <resource-collection-car@example.org>; Fri, 13 Jul 2012 14:54:14 +0200 (CEST)
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="=_c8894dbdb8baeedacae836230e3436fd"
+From: "Doe, John" <john.doe@example.org>
+Date: Fri, 13 Jul 2012 13:54:14 +0100
+Message-ID: <240fe7ae7e139129e9eb95213c1016d7@example.org>
+X-Sender: john.doe@example.org
+User-Agent: Roundcube Webmail/0.9-0.3.el6.kolab_3.0
+To: resource-collection-car@example.org
+Subject: "test" has been updated
+
+--=_c8894dbdb8baeedacae836230e3436fd
+Content-Transfer-Encoding: quoted-printable
+Content-Type: text/plain; charset=UTF-8;
+ format=flowed
+
+*test*
+
+When: 2012-07-13 10:00 - 11:00 (Europe/London)
+
+Invitees: Doe, John <john.doe@example.org>,=20
+resource-collection-car@example.org
+
+Please find attached an iCalendar file with the updated event details which=
+=20
+you can import to your calendar application.
+
+In case your email client doesn't support iTip requests you can use the=20
+following link to either accept or decline this invitation:
+http://192.168.122.228/roundcubemail/?_task=3Dcalendar&_t=3D9febd7562df0f5b=
+ca7646a7bf6696801a394dd5a.cmVzb3VyY2UtY29sbGVjdGlvbi1jYXJAZXhhbXBsZS5vcmc%3=
+D.726d2f&_action=3Dattend
+--=_c8894dbdb8baeedacae836230e3436fd
+Content-Type: text/calendar; charset=UTF-8; method=REQUEST;
+ name=event.ics
+Content-Disposition: attachment;
+ filename=event.ics
+Content-Transfer-Encoding: quoted-printable
+
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Roundcube Webmail 0.9-0.3.el6.kolab_3.0//NONSGML Calendar//EN
+CALSCALE:GREGORIAN
+METHOD:REQUEST
+BEGIN:VEVENT
+UID:626421779C777FBE9C9B85A80D04DDFA-A4BF5BBB9FEAA271
+DTSTAMP:20120713T1254140
+DTSTART;TZID=3DEurope/London:20120713T100000
+DTEND;TZID=3DEurope/London:20120713T110000
+SUMMARY:test
+DESCRIPTION:test
+ORGANIZER;CN=3D"Doe, John":mailto:john.doe@example.org
+ATTENDEE;ROLE=3DREQ-PARTICIPANT;PARTSTAT=3DNEEDS-ACTION;RSVP=3DTRUE:mailt=
+o:resourc
+ e-collection-car@example.org
+RRULE:FREQ=3DWEEKLY;INTERVAL=3D1;BYDAY=3DFR
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+
+--=_c8894dbdb8baeedacae836230e3436fd--
+""")
+
+ self.assertTrue(message.is_multipart())
+
+ itip_methods = [ "REQUEST" ]
+
+ # Check each part
+ for part in message.walk():
+
+ # The iTip part MUST be Content-Type: text/calendar (RFC 6047,
+ # section 2.4)
+ if part.get_content_type() == "text/calendar":
+ if not part.get_param('method') in itip_methods:
+ raise Exception, "method not interesting"
+
+ # Get the itip_payload
+ itip_payload = part.get_payload(decode=True)
+
+ # Python iCalendar prior to 3.0 uses "from_string".
+ if hasattr(icalendar.Calendar, 'from_ical'):
+ cal = icalendar.Calendar.from_ical(itip_payload)
+ elif hasattr(icalendar.Calendar, 'from_string'):
+ cal = icalendar.Calendar.from_string(itip_payload)
+ # If we can't read it, we're out
+ else:
+ return []
+
+ def test_002_from_message(self):
+ message = message_from_string("""Received: from localhost (localhost [127.0.0.1])
+ by kolab.example.org (Postfix) with ESMTP id 513B942E10
+ for <resource-collection-car@example.org>; Fri, 13 Jul 2012 14:54:16 +0200 (CEST)
+X-Virus-Scanned: amavisd-new at example.org
+X-Spam-Flag: NO
+X-Spam-Score: 0.551
+X-Spam-Level:
+X-Spam-Status: No, score=0.551 tagged_above=-10 required=6.2
+ tests=[ALL_TRUSTED=-1, DNS_FROM_RFC_DSN=0.001,
+ NORMAL_HTTP_TO_IP=0.001, TVD_RCVD_IP=0.054, TVD_RCVD_IP4=1.495]
+ autolearn=no
+Received: from kolab.example.org ([127.0.0.1])
+ by localhost (kolab.example.org [127.0.0.1]) (amavisd-new, port 10024)
+ with ESMTP id KNJgv841fj-1 for <resource-collection-car@example.org>;
+ Fri, 13 Jul 2012 14:54:15 +0200 (CEST)
+Received: from 192.168.122.228 (localhost [127.0.0.1])
+ (Authenticated sender: john.doe@example.org)
+ by kolab.example.org (Postfix) with ESMTPSA id 0EBDA42E39
+ for <resource-collection-car@example.org>; Fri, 13 Jul 2012 14:54:14 +0200 (CEST)
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="=_c8894dbdb8baeedacae836230e3436fd"
+From: "Doe, John" <john.doe@example.org>
+Date: Fri, 13 Jul 2012 13:54:14 +0100
+Message-ID: <240fe7ae7e139129e9eb95213c1016d7@example.org>
+X-Sender: john.doe@example.org
+User-Agent: Roundcube Webmail/0.9-0.3.el6.kolab_3.0
+To: resource-collection-car@example.org
+Subject: "test" has been updated
+
+--=_c8894dbdb8baeedacae836230e3436fd
+Content-Transfer-Encoding: quoted-printable
+Content-Type: text/plain; charset=UTF-8;
+ format=flowed
+
+*test*
+
+When: 2012-07-13 10:00 - 11:00 (Europe/London)
+
+Invitees: Doe, John <john.doe@example.org>,=20
+resource-collection-car@example.org
+
+Please find attached an iCalendar file with the updated event details which=
+=20
+you can import to your calendar application.
+
+In case your email client doesn't support iTip requests you can use the=20
+following link to either accept or decline this invitation:
+http://192.168.122.228/roundcubemail/?_task=3Dcalendar&_t=3D9febd7562df0f5b=
+ca7646a7bf6696801a394dd5a.cmVzb3VyY2UtY29sbGVjdGlvbi1jYXJAZXhhbXBsZS5vcmc%3=
+D.726d2f&_action=3Dattend
+--=_c8894dbdb8baeedacae836230e3436fd
+Content-Type: text/calendar; charset=UTF-8; method=REQUEST;
+ name=event.ics
+Content-Disposition: attachment;
+ filename=event.ics
+Content-Transfer-Encoding: quoted-printable
+
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//Roundcube Webmail 0.9-0.3.el6.kolab_3.0//NONSGML Calendar//EN
+CALSCALE:GREGORIAN
+METHOD:REQUEST
+BEGIN:VEVENT
+UID:626421779C777FBE9C9B85A80D04DDFA-A4BF5BBB9FEAA271
+DTSTAMP:20120713T1254140
+DTSTART;TZID=3DEurope/London:20120713T100000
+DTEND;TZID=3DEurope/London:20120713T110000
+SUMMARY:test
+DESCRIPTION:test
+ORGANIZER;CN=3D"Doe, John":mailto:john.doe@example.org
+ATTENDEE;ROLE=3DREQ-PARTICIPANT;PARTSTAT=3DNEEDS-ACTION;RSVP=3DTRUE:mailt=
+o:resourc
+ e-collection-car@example.org
+TRANSP:OPAQUE
+END:VEVENT
+END:VCALENDAR
+
+--=_c8894dbdb8baeedacae836230e3436fd--
+""")
+
+ self.assertTrue(message.is_multipart())
+
+ itip_methods = [ "REQUEST" ]
+
+ # Check each part
+ for part in message.walk():
+
+ # The iTip part MUST be Content-Type: text/calendar (RFC 6047,
+ # section 2.4)
+ if part.get_content_type() == "text/calendar":
+ if not part.get_param('method') in itip_methods:
+ raise Exception, "method not interesting"
+
+ # Get the itip_payload
+ itip_payload = part.get_payload(decode=True)
+
+ # Python iCalendar prior to 3.0 uses "from_string".
+ if hasattr(icalendar.Calendar, 'from_ical'):
+ cal = icalendar.Calendar.from_ical(itip_payload)
+ elif hasattr(icalendar.Calendar, 'from_string'):
+ cal = icalendar.Calendar.from_string(itip_payload)
+ # If we can't read it, we're out
+ else:
+ return []
diff --git a/tests/unit/test-005-timezone.py b/tests/unit/test-005-timezone.py
new file mode 100644
index 0000000..8110e30
--- /dev/null
+++ b/tests/unit/test-005-timezone.py
@@ -0,0 +1,73 @@
+import datetime
+import icalendar
+import os
+import pytz
+import unittest
+
+from pykolab.xml import Attendee
+from pykolab.xml import Event
+from pykolab.xml import EventIntegrityError
+from pykolab.xml import InvalidAttendeeParticipantStatusError
+from pykolab.xml import InvalidEventDateError
+from pykolab.xml import event_from_ical
+
+class TestTimezone(unittest.TestCase):
+
+ def test_001_timezone_conflict(self):
+ #class datetime.timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])
+ tdelta = datetime.timedelta(0, 0, 0, 0, 0, 1)
+
+ event_start = datetime.datetime.now(pytz.timezone("UTC"))
+ event_end = datetime.datetime.now(pytz.timezone("UTC")) + tdelta
+
+ london = Event()
+ london.set_organizer("john.doe@example.org", "Doe, John")
+ london.add_attendee("resource-car-vw@example.org", cutype="RESOURCE")
+ london.set_start(event_start.replace(tzinfo=pytz.timezone("Europe/London")))
+ london.set_end(event_end.replace(tzinfo=pytz.timezone("Europe/London")))
+
+ zurich = Event()
+ zurich.set_organizer("john.doe@example.org", "Doe, John")
+ zurich.add_attendee("resource-car-vw@example.org", cutype="RESOURCE")
+ zurich.set_start(event_start.replace(tzinfo=pytz.timezone("Europe/Zurich")))
+ zurich.set_end(event_end.replace(tzinfo=pytz.timezone("Europe/Zurich")))
+
+ london_xml = london.__str__()
+ zurich_xml = zurich.__str__()
+
+ #print london_xml
+ #print zurich_xml
+
+ london_itip = london.as_string_itip()
+ zurich_itip = zurich.as_string_itip()
+
+ del london, zurich
+
+ #print london_itip
+ #print zurich_itip
+
+ london_cal = icalendar.Calendar.from_ical(london_itip)
+ london = event_from_ical(london_cal.walk('VEVENT')[0].to_ical())
+
+ zurich_cal = icalendar.Calendar.from_ical(zurich_itip)
+ zurich = event_from_ical(zurich_cal.walk('VEVENT')[0].to_ical())
+
+ #fp = open(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'event-london1')), 'w')
+ #fp.write(london_xml)
+ #fp.close()
+
+ #fp = open(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'event-london2')), 'w')
+ #fp.write(london.__str__())
+ #fp.close()
+
+ #fp = open(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'event-zurich1')), 'w')
+ #fp.write(zurich_xml)
+ #fp.close()
+
+ #fp = open(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'event-zurich2')), 'w')
+ #fp.write(zurich.__str__())
+ #fp.close()
+
+ self.assertEqual(london_xml, london.__str__())
+ self.assertEqual(zurich_xml, zurich.__str__())
+