From b67503e88305acf2b2cf829d8ed533f4e6ffa2c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Thu, 9 Jul 2020 10:16:08 +0200
Subject: [PATCH 3/5] manager: add a month redirect view for event agenda
 (#44457)

---
 chrono/manager/urls.py  |   5 +
 chrono/manager/views.py |  60 ++++++-----
 tests/test_manager.py   | 218 +++++++++++++++++++++-------------------
 3 files changed, 153 insertions(+), 130 deletions(-)

diff --git a/chrono/manager/urls.py b/chrono/manager/urls.py
index c5642eb..d5e7b3e 100644
--- a/chrono/manager/urls.py
+++ b/chrono/manager/urls.py
@@ -38,6 +38,11 @@ urlpatterns = [
     url(r'^agendas/add/$', views.agenda_add, name='chrono-manager-agenda-add'),
     url(r'^agendas/import/$', views.agendas_import, name='chrono-manager-agendas-import'),
     url(r'^agendas/(?P<pk>\d+)/$', views.agenda_view, name='chrono-manager-agenda-view'),
+    url(
+        r'^agendas/(?P<pk>\d+)/month/$',
+        views.agenda_month_redirect_view,
+        name='chrono-manager-agenda-month-redirect-view',
+    ),
     url(
         r'^agendas/(?P<pk>\d+)/(?P<year>[0-9]{4})/(?P<month>[0-9]+)/$',
         views.agenda_monthly_view,
diff --git a/chrono/manager/views.py b/chrono/manager/views.py
index 1f5301d..a15d232 100644
--- a/chrono/manager/views.py
+++ b/chrono/manager/views.py
@@ -24,9 +24,9 @@ from django.contrib import messages
 from django.core.exceptions import PermissionDenied
 from django.db.models import Q
 from django.db.models import Min, Max
-from django.forms import ValidationError
 from django.http import Http404, HttpResponse, HttpResponseRedirect
 from django.shortcuts import get_object_or_404
+from django.shortcuts import redirect
 from django.template.response import TemplateResponse
 from django.urls import reverse, reverse_lazy
 from django.utils.dates import MONTHS
@@ -613,7 +613,6 @@ agenda_delete = AgendaDeleteView.as_view()
 
 class AgendaView(ViewableAgendaMixin, View):
     def get(self, request, *args, **kwargs):
-        today = datetime.date.today()
         if self.agenda.kind == 'virtual':
             real_agendas = [
                 (agenda, agenda.can_be_viewed(request.user)) for agenda in self.agenda.real_agendas.all()
@@ -631,38 +630,47 @@ class AgendaView(ViewableAgendaMixin, View):
 
         if self.agenda.kind == 'meetings':
             # redirect to today view
-            return HttpResponseRedirect(
-                reverse(
-                    'chrono-manager-agenda-day-view',
-                    kwargs={'pk': self.agenda.id, 'year': today.year, 'month': today.month, 'day': today.day},
-                )
+            today = datetime.date.today()
+            return redirect(
+                'chrono-manager-agenda-day-view',
+                pk=self.agenda.id,
+                year=today.year,
+                month=today.month,
+                day=today.day,
             )
 
         if self.agenda.kind == 'events':
-            # redirect to monthly view, to first month where there are events,
-            # otherwise to latest month with events, otherwise to this month.
-            event = self.agenda.event_set.filter(
-                start_datetime__gte=datetime.date(today.year, today.month, 1)
-            ).first()
-            if not event:
-                event = self.agenda.event_set.filter(
-                    start_datetime__lte=datetime.date(today.year, today.month, 1)
-                ).last()
-            if event:
-                day = event.start_datetime
-            else:
-                day = today
-            return HttpResponseRedirect(
-                reverse(
-                    'chrono-manager-agenda-month-view',
-                    kwargs={'pk': self.agenda.id, 'year': day.year, 'month': day.month},
-                )
-            )
+            return redirect('chrono-manager-agenda-month-redirect-view', pk=self.agenda.pk)
 
 
 agenda_view = AgendaView.as_view()
 
 
+class AgendaMonthRedirectView(ViewableAgendaMixin, View):
+    def get(self, request, *args, **kwargs):
+        if self.agenda.kind != 'events':
+            return redirect('chrono-manager-agenda-view', pk=self.agenda.pk)
+
+        # redirect to monthly view, to first month where there are events,
+        # otherwise to latest month with events, otherwise to this month.
+        today = datetime.date.today()
+        event = self.agenda.event_set.filter(
+            start_datetime__gte=datetime.date(today.year, today.month, 1)
+        ).first()
+        if not event:
+            event = self.agenda.event_set.filter(
+                start_datetime__lte=datetime.date(today.year, today.month, 1)
+            ).last()
+        if event:
+            day = event.start_datetime
+        else:
+            day = today
+        return redirect('chrono-manager-agenda-month-view', pk=self.agenda.pk, year=day.year, month=day.month)
+
+
+agenda_month_redirect_view = AgendaMonthRedirectView.as_view()
+
+
 class AgendaDateView(DateMixin, ViewableAgendaMixin):
     model = Event
     month_format = '%m'
diff --git a/tests/test_manager.py b/tests/test_manager.py
index ac91081..93fe1bc 100644
--- a/tests/test_manager.py
+++ b/tests/test_manager.py
@@ -150,6 +150,74 @@ def test_menu_json(app, admin_user):
     assert resp2.content_type == 'application/javascript'
 
 
+def test_events_agenda_redirect(app, admin_user):
+    agenda = Agenda.objects.create(label=u'Foo Bar', kind='events')
+
+    app = login(app)
+    resp = app.get('/manage/agendas/%s/' % agenda.pk, status=302)
+    assert resp.location.endswith('/manage/agendas/%s/month/' % agenda.pk)
+
+
+@freezegun.freeze_time('2020-07-12')
+def test_events_agenda_month_redirect(app, admin_user):
+    agenda = Agenda.objects.create(label=u'Foo Bar', kind='events')
+
+    app = login(app)
+    # no event, redirect to current month
+    resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
+    assert resp.location.endswith('/manage/agendas/%s/2020/7/' % agenda.pk)
+
+    # only past events, redirect to last event month
+    Event.objects.create(
+        agenda=agenda, places=1, start_datetime=now() - datetime.timedelta(days=60),
+    )
+    resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
+    assert resp.location.endswith('/manage/agendas/%s/2020/5/' % agenda.pk)
+    Event.objects.create(
+        agenda=agenda, places=1, start_datetime=now() - datetime.timedelta(days=30),
+    )
+    resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
+    assert resp.location.endswith('/manage/agendas/%s/2020/6/' % agenda.pk)
+
+    # future events
+    Event.objects.create(
+        agenda=agenda, places=1, start_datetime=now() + datetime.timedelta(days=60),
+    )
+    resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
+    assert resp.location.endswith('/manage/agendas/%s/2020/9/' % agenda.pk)
+    Event.objects.create(
+        agenda=agenda, places=1, start_datetime=now() + datetime.timedelta(days=30),
+    )
+    resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
+    assert resp.location.endswith('/manage/agendas/%s/2020/8/' % agenda.pk)
+
+    # wrong kind
+    agenda.kind = 'virtual'
+    agenda.save()
+    resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
+    assert resp.location.endswith('/manage/agendas/%s/' % agenda.pk)
+    agenda.kind = 'meetings'
+    agenda.save()
+    resp = app.get('/manage/agendas/%s/month/' % agenda.pk, status=302)
+    assert resp.location.endswith('/manage/agendas/%s/' % agenda.pk)
+
+
+@freezegun.freeze_time('2020-07-12')
+def test_meetings_agenda_redirect(app, admin_user):
+    agenda = Agenda.objects.create(label=u'Foo Bar', kind='meetings')
+
+    app = login(app)
+    resp = app.get('/manage/agendas/%s/' % agenda.pk, status=302)
+    assert resp.location.endswith('/manage/agendas/%s/2020/7/12/' % agenda.pk)
+
+
+def test_virtual_agenda_redirect(app, admin_user):
+    agenda = Agenda.objects.create(label=u'Foo Bar', kind='virtual')
+
+    app = login(app)
+    resp = app.get('/manage/agendas/%s/' % agenda.pk)  # no redirection
+
+
 def test_view_agendas_as_manager(app, manager_user):
     agenda = Agenda(label=u'Foo Bar')
     agenda.view_role = manager_user.groups.all()[0]
@@ -639,17 +707,14 @@ def test_add_agenda_as_manager(app, manager_user):
     agenda.view_role = manager_user.groups.all()[0]
     agenda.save()
     app = login(app, username='manager', password='manager')
-    resp = app.get('/manage/', status=200)
-    resp = app.get('/manage/agendas/add/', status=403)
+    app.get('/manage/agendas/add/', status=403)
 
 
 def test_options_agenda(app, admin_user):
     agenda = Agenda(label=u'Foo bar')
     agenda.save()
     app = login(app)
-    resp = app.get('/manage/', status=200)
-    resp = resp.click('Foo bar').follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('Options')
     assert resp.form['label'].value == 'Foo bar'
     resp.form['label'] = 'Foo baz'
@@ -691,8 +756,8 @@ def test_options_agenda_as_manager(app, manager_user):
     agenda.save()
     app = login(app, username='manager', password='manager')
     resp = app.get('/manage/', status=200)
-    resp = resp.click('Foo bar')
-    assert not 'Settings' in resp.text
+    resp = resp.click('Foo bar').follow().follow()
+    assert 'Settings' not in resp.text
     resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=403)
     resp = app.get('/manage/agendas/%s/edit' % agenda.id, status=403)
     agenda.kind = 'meetings'
@@ -707,9 +772,7 @@ def test_options_agenda_as_manager(app, manager_user):
     agenda.edit_role = manager_user.groups.all()[0]
     agenda.save()
 
-    resp = app.get('/manage/', status=200)
-    resp = resp.click('Foo bar').follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('Options')
     assert resp.form['label'].value == 'Foo bar'
     resp.form['label'] = 'Foo baz'
@@ -805,13 +868,12 @@ def test_delete_agenda(app, admin_user):
     agenda.save()
     app = login(app)
     resp = app.get('/manage/', status=200)
-    resp = resp.click('Foo bar').follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('Delete')
     resp = resp.form.submit()
     assert resp.location.endswith('/manage/')
     resp = resp.follow()
-    assert not 'Foo bar' in resp.text
+    assert 'Foo bar' not in resp.text
 
 
 def test_delete_busy_agenda(app, admin_user):
@@ -821,25 +883,19 @@ def test_delete_busy_agenda(app, admin_user):
     event.save()
 
     app = login(app)
-    resp = app.get('/manage/', status=200)
-    resp = resp.click('Foo bar').follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.id)
     resp = resp.click('Delete')
     assert 'Are you sure you want to delete this?' in resp.text
 
     booking = Booking(event=event)
     booking.save()
-    resp = app.get('/manage/', status=200)
-    resp = resp.click('Foo bar').follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.id)
     resp = resp.click('Delete')
     assert 'This cannot be removed' in resp.text
 
     booking.cancellation_datetime = now()
     booking.save()
-    resp = app.get('/manage/', status=200)
-    resp = resp.click('Foo bar').follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.id)
     resp = resp.click('Delete')
     assert 'Are you sure you want to delete this?' in resp.text
 
@@ -855,9 +911,7 @@ def test_delete_agenda_as_manager(app, manager_user):
     agenda.edit_role = manager_user.groups.all()[0]
     agenda.save()
     app = login(app, username='manager', password='manager')
-    resp = app.get('/manage/', status=200)
-    resp = resp.click('Foo bar').follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     assert 'Options' in resp.text
     assert 'Delete' not in resp.text
     resp = app.get('/manage/agendas/%s/delete' % agenda.id, status=403)
@@ -874,8 +928,7 @@ def test_delete_busy_desk(app, admin_user):
 
     app = login(app)
     resp = app.get('/manage/', status=200)
-    resp = resp.click('Foo bar').follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     desk_page = resp.click('Desk A')
     desk_delete_page = desk_page.click('Delete')
     assert 'Are you sure you want to delete this?' in desk_delete_page.text
@@ -964,8 +1017,7 @@ def test_add_event_as_manager(app, manager_user):
     agenda.edit_role = manager_user.groups.all()[0]
     agenda.save()
 
-    resp = app.get('/manage/agendas/%s/' % agenda.id).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     assert '<h2>Settings' in resp.text
     resp = resp.click('New Event')
     resp.form['start_datetime$date'] = '2016-02-15'
@@ -1397,8 +1449,7 @@ def test_meetings_agenda_add_meeting_type(app, admin_user):
     agenda = Agenda(label=u'Foo bar', kind='meetings')
     agenda.save()
     app = login(app)
-    resp = app.get('/manage/agendas/%s/' % agenda.id).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     assert "This agenda doesn't have any meeting type yet." in resp.text
     resp = resp.click('New Meeting Type')
     resp.form['label'] = 'Blah'
@@ -1429,8 +1480,7 @@ def test_meetings_agenda_delete_meeting_type(app, admin_user):
     meeting_type.save()
 
     app = login(app)
-    resp = app.get('/manage/agendas/%s/' % agenda.id).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('Blah')
     resp = resp.click('Delete')
     assert 'Are you sure you want to delete this?' in resp.text
@@ -1442,9 +1492,7 @@ def test_meetings_agenda_delete_meeting_type(app, admin_user):
     assert '__deleted__' in meeting_type.slug
 
     # meeting type not showing up anymore
-    resp = app.get('/manage/', status=200)
-    resp = resp.click('Foo').follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     assert 'Meeting Type Foo' not in resp.text
 
     # it is possible to add a new meeting type with the same slug
@@ -1564,8 +1612,7 @@ def test_meetings_agenda_add_time_period_as_manager(app, manager_user):
     agenda.edit_role = manager_user.groups.all()[0]
     agenda.save()
 
-    resp = app.get('/manage/agendas/%d/' % agenda.id).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     assert 'Add a time period' in resp.text
     assert '/manage/timeperiods/%s/edit' % time_period.id in resp.text
     assert '/manage/timeperiods/%s/delete' % time_period.id in resp.text
@@ -1586,8 +1633,7 @@ def test_meetings_agenda_add_desk(app, admin_user):
     agenda = Agenda.objects.get(slug='foo-bar')
     MeetingType(agenda=agenda, label='Blah').save()
 
-    resp = app.get('/manage/agendas/%s/' % agenda.id).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('New Desk')
     resp.form['label'] = 'Desk A'
     resp = resp.form.submit().follow()
@@ -1643,8 +1689,7 @@ def test_meetings_agenda_delete_desk(app, admin_user):
     agenda = Agenda.objects.get(slug='foo-bar')
     MeetingType(agenda=agenda, label='Blah').save()
 
-    resp = app.get('/manage/agendas/%s/' % agenda.id).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('New Desk')
     resp.form['label'] = 'Desk A'
     resp = resp.form.submit().follow()
@@ -1709,8 +1754,7 @@ def test_meetings_agenda_add_time_period_exception_when_booking_exists(app, admi
     )
     Booking.objects.create(event=event)
     login(app)
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('Add a time period exception')
     resp = resp.form.submit()  # submit empty form
     # fields should be marked with errors
@@ -1739,8 +1783,7 @@ def test_meetings_agenda_add_time_period_exception_when_cancelled_booking_exists
         event=event, cancellation_datetime=make_aware(datetime.datetime(2017, 5, 20, 10, 30))
     )
     login(app)
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('Add a time period exception')
     resp.form['start_datetime$date'] = '2017-05-22'
     resp.form['start_datetime$time'] = '08:00'
@@ -1794,8 +1837,7 @@ def test_meetings_agenda_delete_time_period_exception(app, admin_user):
         weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
     )
     login(app)
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('Add a time period exception')
     today = datetime.datetime.today().replace(hour=0, minute=0, second=0, microsecond=0)
     tomorrow = make_aware(today + datetime.timedelta(days=15))
@@ -1947,8 +1989,7 @@ def test_agenda_import_time_period_exception_from_ics_recurrent(app, admin_user)
         weekday=1, desk=desk, start_time=datetime.time(10, 0), end_time=datetime.time(12, 0)
     )
     login(app)
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('upload')
     ics_with_recurrent_exceptions = b"""BEGIN:VCALENDAR
 VERSION:2.0
@@ -2100,8 +2141,7 @@ def test_meetings_agenda_delete_time_period_exception_source(app, admin_user, fr
     )
     login(app)
     # import a source
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('upload')
     ics_with_recurrent_exceptions = b"""BEGIN:VCALENDAR
 VERSION:2.0
@@ -2120,8 +2160,7 @@ END:VCALENDAR"""
     assert source1.timeperiodexception_set.count() == 2
 
     # import another one
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('upload')
     resp.form['ics_file'] = Upload('exceptions.ics', ics_with_recurrent_exceptions, 'text/calendar')
     resp = resp.form.submit(status=302).follow()
@@ -2130,8 +2169,7 @@ END:VCALENDAR"""
     assert source2.timeperiodexception_set.count() == 2
 
     # delete the second one
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('upload')
     resp = resp.click(href='/manage/time-period-exceptions-source/%d/delete' % source2.pk)
     resp = resp.form.submit().follow()
@@ -2140,8 +2178,7 @@ END:VCALENDAR"""
     assert TimePeriodExceptionSource.objects.filter(pk=source2.pk).exists() is False
 
     # delete the first one
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('upload')
     resp = resp.click(href='/manage/time-period-exceptions-source/%d/delete' % source1.pk)
     resp = resp.form.submit().follow()
@@ -2170,8 +2207,7 @@ END:VCALENDAR"""
 
     login(app)
     # import a source from a file
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('upload')
     resp.form['ics_file'] = Upload('exceptions.ics', ics_file_content, 'text/calendar')
     resp = resp.form.submit(status=302).follow()
@@ -2182,8 +2218,7 @@ END:VCALENDAR"""
     old_ics_file_path = source.ics_file.path
 
     # replace the source
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('upload')
     resp = resp.click(href='/manage/time-period-exceptions-source/%d/replace' % source.pk)
     resp.form['ics_newfile'] = Upload('exceptions.ics', ics_file_content, 'text/calendar')
@@ -2218,8 +2253,7 @@ END:VCALENDAR"""
 
     login(app)
     # import a source from an url
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('upload')
     resp.form['ics_url'] = 'http://example.com/foo.ics'
     mocked_response = mock.Mock()
@@ -2232,8 +2266,7 @@ END:VCALENDAR"""
     exceptions = list(source.timeperiodexception_set.order_by('pk'))
 
     # refresh the source
-    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
-    resp = resp.click('Settings')
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
     resp = resp.click('upload')
     mocked_response = mock.Mock()
     mocked_response.text = ics_url_content
@@ -2249,29 +2282,27 @@ def test_agenda_day_view(app, admin_user, manager_user, api_user):
     agenda = Agenda.objects.create(label='New Example', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='New Desk')
     desk.save()
+    today = datetime.date.today()
 
     meetingtype = MeetingType(agenda=agenda, label='Bar', duration=30)
     meetingtype.save()
 
     login(app)
-    resp = app.get('/manage/agendas/%s/' % agenda.id, status=302)
-    today = datetime.date.today()
-    assert resp.location.endswith('%s/%s/%s/' % (today.year, today.month, today.day))
-    resp = resp.follow()
+    resp = app.get('/manage/agendas/%s/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
     assert 'No opening hours this day.' in resp.text  # no time pediod
 
     timeperiod = TimePeriod(
         desk=desk, weekday=today.weekday(), start_time=datetime.time(10, 0), end_time=datetime.time(18, 0)
     )
     timeperiod.save()
-    resp = app.get('/manage/agendas/%s/' % agenda.id, status=302).follow()
+    resp = app.get('/manage/agendas/%s/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
     assert 'No opening hours this day.' not in resp.text
     assert 'div class="booking' not in resp.text
     assert resp.text.count('<tr') == 9  # 10->18 (not included)
 
     timeperiod.end_time = datetime.time(18, 30)  # end during an hour
     timeperiod.save()
-    resp = app.get('/manage/agendas/%s/' % agenda.id, status=302).follow()
+    resp = app.get('/manage/agendas/%s/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
     assert resp.text.count('<tr') == 10  # 10->18 (included)
 
     # check opening hours cells
@@ -2370,7 +2401,7 @@ def test_agenda_day_view_late_meeting(app, admin_user, manager_user, api_user):
     timeperiod.save()
 
     login(app)
-    resp = app.get('/manage/agendas/%s/' % agenda.id, status=302).follow()
+    resp = app.get('/manage/agendas/%s/%s/%s/%s/' % (agenda.pk, today.year, today.month, today.day))
     assert resp.text.count('<tr') == 15
     assert '<th class="hour">11 p.m.</th>' in resp.text
 
@@ -2432,24 +2463,19 @@ def test_agenda_day_view_event_outside_timeperiod(app, admin_user):
     assert 'style="height: 600%; top: 100%;"' in resp.text
 
 
-def test_agenda_events_month_view(app, admin_user, manager_user, api_user):
+def test_agenda_events_month_view(app, admin_user):
     agenda = Agenda.objects.create(label='Events', kind='events')
+    today = datetime.date.today()
 
     login(app)
-    resp = app.get('/manage/agendas/%s/' % agenda.id, status=302)
-    resp = resp.follow()
+    resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.pk, today.year, today.month))
     assert "This month doesn't have any event configured." in resp.text
-    today = datetime.date.today()
     assert resp.request.url.endswith('%s/%s/' % (today.year, today.month))
 
     # add event in a future month
-    event = Event(label='xyz', start_datetime=now() + datetime.timedelta(days=40), places=10, agenda=agenda)
-    event.save()
-    resp = app.get('/manage/agendas/%s/' % agenda.id).follow()
-    assert 'xyz' in resp.text
-    day = event.start_datetime
-    assert resp.request.url.endswith('%s/%s/' % (day.year, day.month))
-
+    event = Event.objects.create(
+        label='xyz', start_datetime=now() + datetime.timedelta(days=40), places=10, agenda=agenda
+    )
     with CaptureQueriesContext(connection) as ctx:
         app.get(
             '/manage/agendas/%s/%s/%s/' % (agenda.id, event.start_datetime.year, event.start_datetime.month)
@@ -2460,35 +2486,19 @@ def test_agenda_events_month_view(app, admin_user, manager_user, api_user):
     resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
     assert "This month doesn't have any event configured." in resp.text
 
-    # add event in the past
-    event2 = Event(label='zyx', start_datetime=now() - datetime.timedelta(days=40), places=10, agenda=agenda)
-    event2.save()
-    resp = app.get('/manage/agendas/%s/' % agenda.id).follow()
-    assert 'xyz' in resp.text
-    day = event.start_datetime  # still the future event
-    assert resp.request.url.endswith('%s/%s/' % (day.year, day.month))
-
-    # remove future event
-    event.delete()
-    resp = app.get('/manage/agendas/%s/' % agenda.id).follow()
-    assert 'zyx' in resp.text
-    day = event2.start_datetime  # now the past event
-    assert resp.request.url.endswith('%s/%s/' % (day.year, day.month))
-
 
 def test_agenda_month_view(app, admin_user, manager_user, api_user):
     agenda = Agenda.objects.create(label='Passeports', kind='meetings')
     desk = Desk.objects.create(agenda=agenda, label='Desk A')
+    today = datetime.date.today()
 
     meetingtype = MeetingType(agenda=agenda, label='passeport', duration=20)
     meetingtype.save()
 
     login(app)
-    resp = app.get('/manage/agendas/%s/' % agenda.id, status=302)
-    resp = resp.follow()
+    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.pk, today.year, today.month, today.day))
     assert 'Month view' in resp.text
     resp = resp.click('Month view')
-    today = datetime.date.today()
     assert resp.request.url.endswith('%s/%s/' % (today.year, today.month))
 
     assert 'Day view' in resp.text  # date view link should be present
@@ -2501,8 +2511,8 @@ def test_agenda_month_view(app, admin_user, manager_user, api_user):
     )
     timeperiod.save()
     resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
-    assert not 'No opening hours this month.' in resp.text
-    assert not '<div class="booking' in resp.text
+    assert 'No opening hours this month.' not in resp.text
+    assert '<div class="booking' not in resp.text
     first_month_day = today.replace(day=1)
     last_month_day = today.replace(day=1, month=today.month + 1) - datetime.timedelta(days=1)
     start_week_number = first_month_day.isocalendar()[1]
-- 
2.20.1

