11import datetime
2+ from xml .etree import ElementTree
23
34import icalendar
4- import pytz
55from django .contrib .auth .models import User
6- from django .test import TestCase
6+ from django .contrib .sites .models import Site
7+ from django .test import TestCase , override_settings
78from django .urls import reverse
89
910from schedule .models import Calendar , Event , Occurrence , Rule
1011
1112
13+ @override_settings (SITE_ID = 1 )
14+ class TestUpcomingEventsFeed (TestCase ):
15+ def setUp (self ):
16+ Site .objects .update_or_create (
17+ id = 1 , defaults = {"domain" : "example.com" , "name" : "example.com" }
18+ )
19+ self .user = User .objects .create_user ("alice" , "alice@example.com" , "password" )
20+ self .calendar = Calendar .objects .create (name = "MyCal" , slug = "mycal" )
21+ self .rule = Rule .objects .create (
22+ frequency = "DAILY" , name = "daily" , description = "Daily"
23+ )
24+ self .event = Event .objects .create (
25+ title = "Recurring Event" ,
26+ description = "A test event" ,
27+ start = datetime .datetime (2008 , 1 , 5 , 8 , 0 , tzinfo = datetime .timezone .utc ),
28+ end = datetime .datetime (2008 , 1 , 5 , 9 , 0 , tzinfo = datetime .timezone .utc ),
29+ end_recurring_period = datetime .datetime (
30+ 2100 , 1 , 1 , 0 , 0 , tzinfo = datetime .timezone .utc
31+ ),
32+ rule = self .rule ,
33+ calendar = self .calendar ,
34+ creator = self .user ,
35+ )
36+
37+ def _get_feed (self ):
38+ return self .client .get (f"/feed/calendar/upcoming/{ self .calendar .pk } /" )
39+
40+ def test_feed_returns_200 (self ):
41+ response = self ._get_feed ()
42+ self .assertEqual (response .status_code , 200 )
43+ self .assertIn ("xml" , response ["Content-Type" ])
44+
45+ def test_feed_contains_item_title (self ):
46+ response = self ._get_feed ()
47+ content = response .content .decode ()
48+ self .assertIn ("Recurring Event" , content )
49+
50+ def test_feed_contains_item_description (self ):
51+ response = self ._get_feed ()
52+ content = response .content .decode ()
53+ self .assertIn ("A test event" , content )
54+
55+ def test_feed_contains_author (self ):
56+ response = self ._get_feed ()
57+ content = response .content .decode ()
58+ self .assertIn ("alice" , content )
59+
60+ def test_feed_no_creator (self ):
61+ self .event .creator = None
62+ self .event .save ()
63+ response = self ._get_feed ()
64+ self .assertEqual (response .status_code , 200 )
65+
66+ def test_feed_item_has_guid (self ):
67+ response = self ._get_feed ()
68+ root = ElementTree .fromstring (response .content )
69+ guids = root .findall (".//guid" )
70+ self .assertTrue (len (guids ) > 0 )
71+ for guid in guids :
72+ self .assertNotEqual (guid .text , "None" )
73+
74+ def test_feed_item_has_pubdate (self ):
75+ response = self ._get_feed ()
76+ root = ElementTree .fromstring (response .content )
77+ pubdates = root .findall (".//item/pubDate" )
78+ self .assertTrue (len (pubdates ) > 0 )
79+ self .assertTrue (pubdates [0 ].text ) # not empty
80+
81+ def test_feed_404_for_nonexistent_calendar (self ):
82+ response = self .client .get ("/feed/calendar/upcoming/99999/" )
83+ self .assertEqual (response .status_code , 404 )
84+
85+ @override_settings (FEED_LIST_LENGTH = 2 )
86+ def test_feed_respects_list_length (self ):
87+ response = self ._get_feed ()
88+ root = ElementTree .fromstring (response .content )
89+ items = root .findall (".//item" )
90+ self .assertLessEqual (len (items ), 2 )
91+
92+
1293class TestICalendarFeed (TestCase ):
1394 """Test iCalendar feed export functionality"""
1495
@@ -19,8 +100,8 @@ def setUp(self):
19100 # Create a simple event
20101 self .simple_event = Event .objects .create (
21102 title = "Simple Event" ,
22- start = datetime .datetime (2024 , 1 , 15 , 10 , 0 , tzinfo = pytz .utc ),
23- end = datetime .datetime (2024 , 1 , 15 , 11 , 0 , tzinfo = pytz .utc ),
103+ start = datetime .datetime (2024 , 1 , 15 , 10 , 0 , tzinfo = datetime . timezone .utc ),
104+ end = datetime .datetime (2024 , 1 , 15 , 11 , 0 , tzinfo = datetime . timezone .utc ),
24105 description = "A simple test event" ,
25106 calendar = self .calendar ,
26107 )
@@ -29,9 +110,11 @@ def setUp(self):
29110 self .rule = Rule .objects .create (frequency = "WEEKLY" )
30111 self .recurring_event = Event .objects .create (
31112 title = "Weekly Meeting" ,
32- start = datetime .datetime (2024 , 1 , 1 , 14 , 0 , tzinfo = pytz .utc ),
33- end = datetime .datetime (2024 , 1 , 1 , 15 , 0 , tzinfo = pytz .utc ),
34- end_recurring_period = datetime .datetime (2024 , 3 , 1 , 0 , 0 , tzinfo = pytz .utc ),
113+ start = datetime .datetime (2024 , 1 , 1 , 14 , 0 , tzinfo = datetime .timezone .utc ),
114+ end = datetime .datetime (2024 , 1 , 1 , 15 , 0 , tzinfo = datetime .timezone .utc ),
115+ end_recurring_period = datetime .datetime (
116+ 2024 , 3 , 1 , 0 , 0 , tzinfo = datetime .timezone .utc
117+ ),
35118 description = "Recurring weekly meeting" ,
36119 rule = self .rule ,
37120 calendar = self .calendar ,
@@ -113,8 +196,8 @@ def test_icalendar_feed_with_occurrence(self):
113196 # Create a modified occurrence
114197 Occurrence .objects .create (
115198 event = self .simple_event ,
116- start = datetime .datetime (2024 , 1 , 16 , 11 , 0 , tzinfo = pytz .utc ),
117- end = datetime .datetime (2024 , 1 , 16 , 12 , 0 , tzinfo = pytz .utc ),
199+ start = datetime .datetime (2024 , 1 , 16 , 11 , 0 , tzinfo = datetime . timezone .utc ),
200+ end = datetime .datetime (2024 , 1 , 16 , 12 , 0 , tzinfo = datetime . timezone .utc ),
118201 original_start = self .simple_event .start ,
119202 original_end = self .simple_event .end ,
120203 title = "Modified Simple Event" ,
0 commit comments