Skip to content

Commit c33a664

Browse files
fix(#1701): Events page displays year for events scheduled to start or end at a future year (#2500)
* Add Methods To Check If Event Starts And Ends This Year * Set Up Templates For Querying Start And End Years Passed variables to the time_tag template [time_tag.html] that checks if an event was scheduled to start or end with the current year. * Insert New Test Data And Update test_views.py More events are created to test particular scenarios of events especially events set to start or end at a future year. * Time Tag Now Shows Year For Events With Details Not Within The Current Year The time tag now displays the year when an event will occur. This is only for events that have been scheduled to start or end in at a future year. The accompanying functional tests have also been included. * Move All Test Data To Functional Test All test data concerning the provision of data to serve the functional tests have been moved to the functional test. As it improves readability. All other test data at test_views.py was reset to accommodate for the reduction in number of test data instances. * Functional Test For Displaying Year Of Event For Future Events Now Implemented With Unit Tests * Remove Functional Test For Displaying Year Of Future Event Since the current CI at the main branch does not support selenium [web driver] operations, the functional test which depends on selenium to run has been removed. * Handle Case When Call To Next Event Returns None * Fix Erroneous Addition To Dev Requirements This error was introduced in 115af08 * Refactor Tests For Relevant Year String Rendering At Events Page - Updated the test methods `test_scheduled_to_start_this_year_method` and `test_scheduled_to_end_this_year_method` to better reflect event scheduling edge cases. - Added assertions to verify when events are not scheduled to start or end within the current year. - Utilize `unittest.mock` to clamp down datetime-sensitive tests. --------- Co-authored-by: Jacob Coffee <jacob@z7x.org>
1 parent 691c713 commit c33a664

File tree

5 files changed

+167
-11
lines changed

5 files changed

+167
-11
lines changed

events/models.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,20 @@ def next_time(self):
181181
except IndexError:
182182
return None
183183

184+
def is_scheduled_to_start_this_year(self) -> bool:
185+
if self.next_time:
186+
current_year: int = timezone.now().year
187+
if self.next_time.dt_start.year == current_year:
188+
return True
189+
return False
190+
191+
def is_scheduled_to_end_this_year(self) -> bool:
192+
if self.next_time:
193+
current_year: int = timezone.now().year
194+
if self.next_time.dt_end.year == current_year:
195+
return True
196+
return False
197+
184198
@property
185199
def previous_time(self):
186200
now = timezone.now()

events/tests/test_models.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import datetime
2+
from types import SimpleNamespace
3+
from unittest.mock import patch
24

35
from django.contrib.auth import get_user_model
46
from django.test import TestCase
@@ -62,7 +64,6 @@ def test_recurring_event(self):
6264
self.assertEqual(self.event.next_time.dt_start, recurring_time_dtstart)
6365
self.assertTrue(rt.valid_dt_end())
6466

65-
6667
rt.begin = now - datetime.timedelta(days=5)
6768
rt.finish = now - datetime.timedelta(days=3)
6869
rt.save()
@@ -186,3 +187,61 @@ def test_event_previous_event(self):
186187
# 'Event.previous_event' can return None if there is no
187188
# OccurringRule or RecurringRule found.
188189
self.assertIsNone(self.event.previous_event)
190+
191+
def test_scheduled_to_start_this_year_method(self):
192+
test_datetime = SimpleNamespace(
193+
now=lambda: timezone.datetime(timezone.now().year,
194+
6, 1, tzinfo=timezone.now().tzinfo)
195+
)
196+
197+
with patch("django.utils.timezone", new=test_datetime) as mock_timezone:
198+
with patch("events.models.timezone", new=test_datetime):
199+
now = seconds_resolution(mock_timezone.now())
200+
201+
occurring_time_dtstart = now + datetime.timedelta(days=1)
202+
OccurringRule.objects.create(
203+
event=self.event,
204+
dt_start=occurring_time_dtstart,
205+
dt_end=occurring_time_dtstart + datetime.timedelta(days=3)
206+
)
207+
self.assertTrue(self.event.is_scheduled_to_start_this_year())
208+
209+
OccurringRule.objects.get(event=self.event).delete()
210+
211+
event_not_scheduled_to_start_this_year_occurring_time_dtstart = now + datetime.timedelta(days=365)
212+
OccurringRule.objects.create(
213+
event=self.event,
214+
dt_start=event_not_scheduled_to_start_this_year_occurring_time_dtstart,
215+
dt_end=event_not_scheduled_to_start_this_year_occurring_time_dtstart + datetime.timedelta(days=3)
216+
)
217+
218+
self.assertFalse(self.event.is_scheduled_to_start_this_year())
219+
220+
def test_scheduled_to_end_this_year_method(self):
221+
test_datetime = SimpleNamespace(
222+
now=lambda: timezone.datetime(timezone.now().year,
223+
6, 1, tzinfo=timezone.now().tzinfo)
224+
)
225+
226+
with patch("django.utils.timezone", new=test_datetime) as mock_timezone:
227+
with patch("events.models.timezone", new=test_datetime):
228+
now = seconds_resolution(mock_timezone.now())
229+
occurring_time_dtstart = now + datetime.timedelta(days=1)
230+
231+
OccurringRule.objects.create(
232+
event=self.event,
233+
dt_start=occurring_time_dtstart,
234+
dt_end=occurring_time_dtstart
235+
)
236+
237+
self.assertTrue(self.event.is_scheduled_to_end_this_year())
238+
239+
OccurringRule.objects.get(event=self.event).delete()
240+
241+
OccurringRule.objects.create(
242+
event=self.event,
243+
dt_start=now,
244+
dt_end=now + datetime.timedelta(days=365)
245+
)
246+
247+
self.assertFalse(self.event.is_scheduled_to_end_this_year())

events/tests/test_views.py

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from django.test import TestCase
77
from django.utils import timezone
88

9-
from ..models import Calendar, Event, EventCategory, EventLocation, RecurringRule
9+
from ..models import Calendar, Event, EventCategory, EventLocation, RecurringRule, OccurringRule
1010
from ..templatetags.events import get_events_upcoming
1111
from users.factories import UserFactory
1212

@@ -18,6 +18,11 @@ def setUpTestData(cls):
1818
cls.calendar = Calendar.objects.create(creator=cls.user, slug="test-calendar")
1919
cls.event = Event.objects.create(creator=cls.user, calendar=cls.calendar)
2020
cls.event_past = Event.objects.create(title='Past Event', creator=cls.user, calendar=cls.calendar)
21+
cls.event_single_day = Event.objects.create(title="Single Day Event", creator=cls.user, calendar=cls.calendar)
22+
cls.event_starts_at_future_year = Event.objects.create(title='Event Starting Following Year',
23+
creator=cls.user, calendar=cls.calendar)
24+
cls.event_ends_at_future_year = Event.objects.create(title='Event Ending Following Year',
25+
creator=cls.user, calendar=cls.calendar)
2126

2227
cls.now = timezone.now()
2328

@@ -34,7 +39,6 @@ def setUpTestData(cls):
3439
begin=cls.now - datetime.timedelta(days=2),
3540
finish=cls.now - datetime.timedelta(days=1),
3641
)
37-
3842
# Future event
3943
cls.future_event = Event.objects.create(title='Future Event', creator=cls.user, calendar=cls.calendar, featured=True)
4044
RecurringRule.objects.create(
@@ -67,18 +71,36 @@ def setUpTestData(cls):
6771
finish=cls.now - datetime.timedelta(days=1),
6872
)
6973

74+
cls.rule_single_day = OccurringRule.objects.create(
75+
event=cls.event_single_day,
76+
dt_start=recurring_time_dtstart,
77+
dt_end=recurring_time_dtstart
78+
)
79+
cls.rule_future_start_year = OccurringRule.objects.create(
80+
event=cls.event_starts_at_future_year,
81+
dt_start=recurring_time_dtstart + datetime.timedelta(weeks=52),
82+
dt_end=recurring_time_dtstart + datetime.timedelta(weeks=53),
83+
)
84+
cls.rule_future_end_year = OccurringRule.objects.create(
85+
event=cls.event_ends_at_future_year,
86+
dt_start=recurring_time_dtstart,
87+
dt_end=recurring_time_dtend + datetime.timedelta(weeks=52)
88+
)
89+
7090
def test_events_homepage(self):
7191
url = reverse('events:events')
7292
response = self.client.get(url)
7393
events = response.context['object_list']
7494
event_titles = [event.title for event in events]
7595

7696
self.assertEqual(response.status_code, 200)
77-
self.assertEqual(len(events), 6)
97+
self.assertEqual(len(events), 9)
7898

7999
self.assertIn('Future Event', event_titles)
80100
self.assertIn('Current Event', event_titles)
81101
self.assertIn('Past Event', event_titles)
102+
self.assertIn('Event Starting Following Year', event_titles)
103+
self.assertIn('Event Ending Following Year', event_titles)
82104

83105
def test_calendar_list(self):
84106
calendars_count = Calendar.objects.count()
@@ -93,7 +115,7 @@ def test_event_list(self):
93115
response = self.client.get(url)
94116

95117
self.assertEqual(response.status_code, 200)
96-
self.assertEqual(len(response.context['object_list']), 3)
118+
self.assertEqual(len(response.context['object_list']), 6)
97119

98120
url = reverse('events:event_list_past', kwargs={"calendar_slug": 'unexisting'})
99121
response = self.client.get(url)
@@ -189,12 +211,21 @@ def test_event_detail(self):
189211
self.assertEqual(self.event, response.context['object'])
190212

191213
def test_upcoming_tag(self):
192-
self.assertEqual(len(get_events_upcoming()), 3)
214+
self.assertEqual(len(get_events_upcoming()), 5)
193215
self.assertEqual(len(get_events_upcoming(only_featured=True)), 1)
194216
self.rule.begin = self.now - datetime.timedelta(days=3)
195217
self.rule.finish = self.now - datetime.timedelta(days=2)
196218
self.rule.save()
197-
self.assertEqual(len(get_events_upcoming()), 2)
219+
self.assertEqual(len(get_events_upcoming()), 5)
220+
221+
def test_event_starting_future_year_displays_relevant_year(self):
222+
event = self.event_starts_at_future_year
223+
url = reverse('events:events')
224+
response = self.client.get(url)
225+
self.assertIn(
226+
f'<span id="start-{event.id}">',
227+
response.content.decode()
228+
)
198229

199230
def test_context_data(self):
200231
url = reverse("events:events")
@@ -204,6 +235,23 @@ def test_context_data(self):
204235
self.assertIn("upcoming_events", response.context)
205236
self.assertIn("events_now", response.context)
206237

238+
def test_event_ending_future_year_displays_relevant_year(self):
239+
event = self.event_ends_at_future_year
240+
url = reverse('events:events')
241+
response = self.client.get(url)
242+
self.assertIn(
243+
f'<span id="end-{event.id}">',
244+
response.content.decode()
245+
)
246+
247+
def test_events_scheduled_current_year_does_not_display_current_year(self):
248+
event = self.event_single_day
249+
url = reverse('events:events')
250+
response = self.client.get(url)
251+
self.assertIn( # start date
252+
f'<span id="start-{event.id}" class="say-no-more">',
253+
response.content.decode()
254+
)
207255

208256
class EventSubmitTests(TestCase):
209257
event_submit_url = reverse_lazy('events:event_submit')

templates/events/event_list.html

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ <h3 class="event-title"><a href="{{ object.get_absolute_url }}">{{ object.title|
7373
</h3>
7474
<p>
7575
{% with object.next_time as next_time %}
76-
{% include "events/includes/time_tag.html" %}
76+
{% with object.is_scheduled_to_start_this_year as scheduled_start_this_year %}
77+
{% with object.is_scheduled_to_end_this_year as scheduled_end_this_year %}
78+
{% include "events/includes/time_tag.html" %}
79+
{% endwith %}
80+
{% endwith %}
7781
{% endwith %}
7882

7983
{% if object.venue %}
@@ -98,7 +102,11 @@ <h3 class="event-title"><a
98102
href="{{ object.get_absolute_url }}">{{ object.title|striptags }}</a></h3>
99103
<p>
100104
{% with object.previous_time as next_time %}
101-
{% include "events/includes/time_tag.html" %}
105+
{% with object.is_scheduled_to_start_this_year as scheduled_start_this_year %}
106+
{% with object.is_scheduled_to_end_this_year as scheduled_end_this_year %}
107+
{% include "events/includes/time_tag.html" %}
108+
{% endwith %}
109+
{% endwith %}
102110
{% endwith %}
103111

104112
{% if object.venue %}
Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,32 @@
11
{% if next_time.single_day %}
2-
<time datetime="{{ next_time.dt_start|date:'c' }}">{{ next_time.dt_start|date:"d N" }}<span class="say-no-more"> {{ next_time.dt_start|date:"Y" }}</span>{% if not next_time.all_day %} {{ next_time.dt_start|date:"fA"|lower }} {{ next_time.dt_start|date:"e" }}{% if next_time.valid_dt_end %} – {{ next_time.dt_end|date:"fA"|lower }} {{ next_time.dt_end|date:"e" }}{% endif %}{% endif %}</time>
2+
<time datetime="{{ next_time.dt_start|date:'c' }}">{{ next_time.dt_start|date:"d N" }}
3+
<span id="start-{{ object.id }}"{% if scheduled_start_this_year %} class="say-no-more"{% endif %}>
4+
{{ next_time.dt_start|date:"Y" }}
5+
</span>
6+
7+
<span id="start-{{ object.id }}"{% if scheduled_end_this_year %} class="say-no-more"{% endif %}>
8+
{{ next_time.dt_start|date:"Y" }}
9+
</span>
10+
11+
{% if not next_time.all_day %}
12+
{{ next_time.dt_start|date:"fA"|lower }} {{ next_time.dt_start|date:"e" }}
13+
{% if next_time.valid_dt_end %} – {{ next_time.dt_end|date:"fA"|lower }}
14+
{{ next_time.dt_end|date:"e" }}
15+
{% endif %}
16+
{% endif %}
17+
</time>
318
{% else %}
4-
<time datetime="{{ next_time.dt_start|date:'c' }}">{{ next_time.dt_start|date:"d N" }}{% if next_time.valid_dt_end %} &ndash; {{ next_time.dt_end|date:"d N" }}{% endif %} <span class="say-no-more"> {{ next_time.dt_end|date:"Y" }}</span></time>
19+
<time datetime="{{ next_time.dt_start|date:'c' }}">{{ next_time.dt_start|date:"d N" }}
20+
<span id="start-{{ object.id }}"{% if scheduled_start_this_year %} class="say-no-more"{% endif %}>
21+
{{ next_time.dt_start|date:"Y" }}
22+
</span>
23+
24+
{% if next_time.valid_dt_end %} &ndash;
25+
{{ next_time.dt_end|date:"d N" }}
26+
{% endif %}
27+
28+
<span id="end-{{ object.id }}"{% if scheduled_end_this_year %} class="say-no-more"{% endif %}>
29+
{{ next_time.dt_end|date:"Y" }}
30+
</span>
31+
</time>
532
{% endif %}

0 commit comments

Comments
 (0)