From c239f28f171fc899ca9b6824e003e24833bf482f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?=
Date: Sat, 20 Jan 2018 17:02:23 +0100
Subject: [PATCH 1/5] syncmails should be able to be silent
---
gestioncof/management/commands/syncmails.py | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/gestioncof/management/commands/syncmails.py b/gestioncof/management/commands/syncmails.py
index 1d3dddb8..74ad152d 100644
--- a/gestioncof/management/commands/syncmails.py
+++ b/gestioncof/management/commands/syncmails.py
@@ -63,8 +63,9 @@ class Command(BaseCommand):
except CustomMail.DoesNotExist:
mail = CustomMail.objects.create(**fields)
status['synced'] += 1
- self.stdout.write(
- 'SYNCED {:s}'.format(fields['shortname']))
+ if options['verbosity']:
+ self.stdout.write(
+ 'SYNCED {:s}'.format(fields['shortname']))
assoc['mails'][obj['pk']] = mail
# Variables
@@ -79,8 +80,9 @@ class Command(BaseCommand):
except Variable.DoesNotExist:
Variable.objects.create(**fields)
- # C'est agréable d'avoir le résultat affiché
- self.stdout.write(
- '{synced:d} mails synchronized {unchanged:d} unchanged'
- .format(**status)
- )
+ if options['verbosity']:
+ # C'est agréable d'avoir le résultat affiché
+ self.stdout.write(
+ '{synced:d} mails synchronized {unchanged:d} unchanged'
+ .format(**status)
+ )
From 7e0ecd8e0f707f912b66cb438778048b877e203e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?=
Date: Sun, 21 Jan 2018 17:51:23 +0100
Subject: [PATCH 2/5] Add assertion to check ical data is as expected
---
shared/tests/testcases.py | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/shared/tests/testcases.py b/shared/tests/testcases.py
index 15792383..14a5fbfe 100644
--- a/shared/tests/testcases.py
+++ b/shared/tests/testcases.py
@@ -8,6 +8,8 @@ from django.test import Client
from django.utils import timezone
from django.utils.functional import cached_property
+import icalendar
+
User = get_user_model()
@@ -92,6 +94,40 @@ class TestCaseMixin:
else:
self.assertEqual(actual, expected)
+ def _test_event_equal(self, event, exp):
+ for k, v_desc in exp.items():
+ if isinstance(v_desc, tuple):
+ v_getter = v_desc[0]
+ v = v_desc[1]
+ else:
+ v_getter = lambda v: v
+ v = v_desc
+ if v_getter(event[k.upper()]) != v:
+ return False
+ return True
+
+ def _find_event(self, ev, l):
+ for i, elt in enumerate(l):
+ if self._test_event_equal(ev, elt):
+ return elt, i
+ return False, -1
+
+ def assertCalEqual(self, ical_content, expected):
+ remaining = expected.copy()
+ unexpected = []
+
+ cal = icalendar.Calendar.from_ical(ical_content)
+
+ for ev in cal.walk('vevent'):
+ found, i_found = self._find_event(ev, remaining)
+ if found:
+ remaining.pop(i_found)
+ else:
+ unexpected.append(ev)
+
+ self.assertListEqual(unexpected, [])
+ self.assertListEqual(remaining, [])
+
class ViewTestCaseMixin(TestCaseMixin):
"""
From 2e6a54c7dbb8cff5077d35230e063712aa90b3d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?=
Date: Sun, 21 Jan 2018 17:52:53 +0100
Subject: [PATCH 3/5] cof -- Add tests for calendar views
---
gestioncof/tests/test_views.py | 151 +++++++++++++++++++++++++++++++++
1 file changed, 151 insertions(+)
create mode 100644 gestioncof/tests/test_views.py
diff --git a/gestioncof/tests/test_views.py b/gestioncof/tests/test_views.py
new file mode 100644
index 00000000..e33fe2f2
--- /dev/null
+++ b/gestioncof/tests/test_views.py
@@ -0,0 +1,151 @@
+import uuid
+from datetime import timedelta
+
+from django.contrib import messages
+from django.contrib.messages.api import get_messages
+from django.contrib.messages.storage.base import Message
+from django.test import TestCase
+
+from bda.models import Salle, Tirage
+from gestioncof.models import CalendarSubscription
+from gestioncof.tests.testcases import ViewTestCaseMixin
+
+
+class CalendarViewTests(ViewTestCaseMixin, TestCase):
+ url_name = 'calendar'
+ url_expected = '/calendar/subscription'
+
+ auth_user = 'member'
+ auth_forbidden = [None, 'user']
+
+ post_expected_message = Message(
+ messages.SUCCESS, "Calendrier mis à jour avec succès.")
+
+ def test_get(self):
+ r = self.client.get(self.url)
+ self.assertEqual(r.status_code, 200)
+
+ def test_post_new(self):
+ r = self.client.post(self.url, {
+ 'subscribe_to_events': True,
+ 'subscribe_to_my_shows': True,
+ 'other_shows': [],
+ })
+
+ self.assertEqual(r.status_code, 200)
+ self.assertIn(self.post_expected_message, get_messages(r.wsgi_request))
+ cs = self.users['member'].calendarsubscription
+ self.assertTrue(cs.subscribe_to_events)
+ self.assertTrue(cs.subscribe_to_my_shows)
+
+ def test_post_edit(self):
+ u = self.users['member']
+ token = uuid.uuid4()
+ cs = CalendarSubscription.objects.create(token=token, user=u)
+
+ r = self.client.post(self.url, {
+ 'other_shows': [],
+ })
+
+ self.assertEqual(r.status_code, 200)
+ self.assertIn(self.post_expected_message, get_messages(r.wsgi_request))
+ cs.refresh_from_db()
+ self.assertEqual(cs.token, token)
+ self.assertFalse(cs.subscribe_to_events)
+ self.assertFalse(cs.subscribe_to_my_shows)
+
+ def test_post_other_shows(self):
+ t = Tirage.objects.create(
+ ouverture=self.now,
+ fermeture=self.now,
+ active=True,
+ )
+ l = Salle.objects.create()
+ s = t.spectacle_set.create(
+ date=self.now, price=3.5, slots=20, location=l, listing=True)
+
+ r = self.client.post(self.url, {'other_shows': [str(s.pk)]})
+
+ self.assertEqual(r.status_code, 200)
+
+
+class CalendarICSViewTests(ViewTestCaseMixin, TestCase):
+ url_name = 'gestioncof.views.calendar_ics'
+
+ auth_user = None
+ auth_forbidden = []
+
+ @property
+ def url_kwargs(self):
+ return {'token': self.token}
+
+ @property
+ def url_expected(self):
+ return '/calendar/{}/calendar.ics'.format(self.token)
+
+ def setUp(self):
+ super().setUp()
+
+ self.token = uuid.uuid4()
+
+ self.t = Tirage.objects.create(
+ ouverture=self.now,
+ fermeture=self.now,
+ active=True,
+ )
+ l = Salle.objects.create(name='Location')
+ self.s1 = self.t.spectacle_set.create(
+ price=1, slots=10, location=l, listing=True,
+ title='Spectacle 1', date=self.now + timedelta(days=1),
+ )
+ self.s2 = self.t.spectacle_set.create(
+ price=2, slots=20, location=l, listing=True,
+ title='Spectacle 2', date=self.now + timedelta(days=2),
+ )
+ self.s3 = self.t.spectacle_set.create(
+ price=3, slots=30, location=l, listing=True,
+ title='Spectacle 3', date=self.now + timedelta(days=3),
+ )
+
+ def test(self):
+ u = self.users['user']
+ p = u.participant_set.create(tirage=self.t)
+ p.attribution_set.create(spectacle=self.s1)
+
+ self.cs = CalendarSubscription.objects.create(
+ user=u, token=self.token,
+ subscribe_to_my_shows=True, subscribe_to_events=True,
+ )
+ self.cs.other_shows.add(self.s2)
+
+ r = self.client.get(self.url)
+
+ def get_dt_from_ical(v):
+ return v.dt
+
+ self.assertCalEqual(r.content.decode('utf-8'), [
+ {
+ 'summary': 'Spectacle 1',
+ 'dtstart': (get_dt_from_ical, (
+ (self.now + timedelta(days=1)).replace(microsecond=0)
+ )),
+ 'dtend': (get_dt_from_ical, (
+ (self.now + timedelta(days=1, hours=2)).replace(
+ microsecond=0)
+ )),
+ 'location': 'Location',
+ 'uid': 'show-{}-{}@example.com'.format(self.s1.pk, self.t.pk),
+ },
+ {
+ 'summary': 'Spectacle 2',
+ 'dtstart': (get_dt_from_ical, (
+ (self.now + timedelta(days=2)).replace(microsecond=0)
+ )),
+ 'dtend': (get_dt_from_ical, (
+ (self.now + timedelta(days=2, hours=2)).replace(
+ microsecond=0)
+ )),
+ 'location': 'Location',
+ 'uid': 'show-{}-{}@example.com'.format(self.s2.pk, self.t.pk),
+ },
+ ])
From acf284862a57f1857a2049067d4bb081a797fffc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?=
Date: Sun, 21 Jan 2018 18:00:56 +0100
Subject: [PATCH 4/5] Users should be able to refuse to subscribe to shows and
events
---
gestioncof/forms.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/gestioncof/forms.py b/gestioncof/forms.py
index 2124b7c8..5a25b815 100644
--- a/gestioncof/forms.py
+++ b/gestioncof/forms.py
@@ -351,10 +351,12 @@ EventFormset = formset_factory(AdminEventForm, BaseEventRegistrationFormset)
class CalendarForm(forms.ModelForm):
subscribe_to_events = forms.BooleanField(
initial=True,
- label="Événements du COF")
+ label="Événements du COF",
+ required=False)
subscribe_to_my_shows = forms.BooleanField(
initial=True,
- label="Les spectacles pour lesquels j'ai obtenu une place")
+ label="Les spectacles pour lesquels j'ai obtenu une place",
+ required=False)
other_shows = forms.ModelMultipleChoiceField(
label="Spectacles supplémentaires",
queryset=Spectacle.objects.filter(tirage__active=True),
From 38539a9d53607efd417bee8d4d1d930999e39d78 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aur=C3=A9lien=20Delobelle?=
Date: Sun, 21 Jan 2018 18:03:01 +0100
Subject: [PATCH 5/5] Name url to export calendar to ical
---
gestioncof/templates/gestioncof/calendar_subscription.html | 2 +-
gestioncof/tests/test_views.py | 2 +-
gestioncof/urls.py | 3 ++-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/gestioncof/templates/gestioncof/calendar_subscription.html b/gestioncof/templates/gestioncof/calendar_subscription.html
index b13cb7f2..4b9e3cbb 100644
--- a/gestioncof/templates/gestioncof/calendar_subscription.html
+++ b/gestioncof/templates/gestioncof/calendar_subscription.html
@@ -12,7 +12,7 @@ souscrire aux événements du COF et/ou aux spectacles BdA.
{% if token %}
Votre calendrier (compatible avec toutes les applications d'agenda) se trouve à
-cette adresse.
+cette adresse.
- Pour l'ajouter à Thunderbird (lightning), il faut copier ce lien et aller
diff --git a/gestioncof/tests/test_views.py b/gestioncof/tests/test_views.py
index e33fe2f2..06d6be4a 100644
--- a/gestioncof/tests/test_views.py
+++ b/gestioncof/tests/test_views.py
@@ -70,7 +70,7 @@ class CalendarViewTests(ViewTestCaseMixin, TestCase):
class CalendarICSViewTests(ViewTestCaseMixin, TestCase):
- url_name = 'gestioncof.views.calendar_ics'
+ url_name = 'calendar.ics'
auth_user = None
auth_forbidden = []
diff --git a/gestioncof/urls.py b/gestioncof/urls.py
index 2be609b3..dde543a5 100644
--- a/gestioncof/urls.py
+++ b/gestioncof/urls.py
@@ -52,7 +52,8 @@ events_patterns = [
calendar_patterns = [
url(r'^subscription$', views.calendar,
name='calendar'),
- url(r'^(?P[a-z0-9-]+)/calendar.ics$', views.calendar_ics)
+ url(r'^(?P[a-z0-9-]+)/calendar.ics$', views.calendar_ics,
+ name='calendar.ics'),
]
clubs_patterns = [