From e9b901337e0d7f547ba25848d8957c8f34f660d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sat, 6 Jan 2018 12:13:15 +0100 Subject: [PATCH] A few tests for BdA views --- bda/tests.py | 105 ------------------- bda/tests/__init__.py | 0 bda/tests/test_views.py | 222 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 222 insertions(+), 105 deletions(-) delete mode 100644 bda/tests.py create mode 100644 bda/tests/__init__.py create mode 100644 bda/tests/test_views.py diff --git a/bda/tests.py b/bda/tests.py deleted file mode 100644 index 97a220c9..00000000 --- a/bda/tests.py +++ /dev/null @@ -1,105 +0,0 @@ -import json - -from django.contrib.auth.models import User -from django.test import TestCase, Client -from django.utils import timezone - -from .models import Tirage, Spectacle, Salle, CategorieSpectacle - - -class TestBdAViews(TestCase): - def setUp(self): - self.tirage = Tirage.objects.create( - title="Test tirage", - appear_catalogue=True, - ouverture=timezone.now(), - fermeture=timezone.now(), - ) - self.category = CategorieSpectacle.objects.create(name="Category") - self.location = Salle.objects.create(name="here") - Spectacle.objects.bulk_create([ - Spectacle( - title="foo", date=timezone.now(), location=self.location, - price=0, slots=42, tirage=self.tirage, listing=False, - category=self.category - ), - Spectacle( - title="bar", date=timezone.now(), location=self.location, - price=1, slots=142, tirage=self.tirage, listing=False, - category=self.category - ), - Spectacle( - title="baz", date=timezone.now(), location=self.location, - price=2, slots=242, tirage=self.tirage, listing=False, - category=self.category - ), - ]) - - self.bda_user = User.objects.create_user( - username="bda_user", password="bda4ever" - ) - self.bda_user.profile.is_cof = True - self.bda_user.profile.is_buro = True - self.bda_user.profile.save() - - def bda_participants(self): - """The BdA participants views can be queried""" - client = Client() - show = self.tirage.spectacle_set.first() - - client.login(self.bda_user.username, "bda4ever") - tirage_resp = client.get("/bda/spectacles/{}".format(self.tirage.id)) - show_resp = client.get( - "/bda/spectacles/{}/{}".format(self.tirage.id, show.id) - ) - reminder_url = "/bda/mails-rappel/{}".format(show.id) - reminder_get_resp = client.get(reminder_url) - reminder_post_resp = client.post(reminder_url) - self.assertEqual(200, tirage_resp.status_code) - self.assertEqual(200, show_resp.status_code) - self.assertEqual(200, reminder_get_resp.status_code) - self.assertEqual(200, reminder_post_resp.status_code) - - def test_catalogue(self): - """Test the catalogue JSON API""" - client = Client() - - # The `list` hook - resp = client.get("/bda/catalogue/list") - self.assertJSONEqual( - resp.content.decode("utf-8"), - [{"id": self.tirage.id, "title": self.tirage.title}] - ) - - # The `details` hook - resp = client.get( - "/bda/catalogue/details?id={}".format(self.tirage.id) - ) - self.assertJSONEqual( - resp.content.decode("utf-8"), - { - "categories": [{ - "id": self.category.id, - "name": self.category.name - }], - "locations": [{ - "id": self.location.id, - "name": self.location.name - }], - } - ) - - # The `descriptions` hook - resp = client.get( - "/bda/catalogue/descriptions?id={}".format(self.tirage.id) - ) - raw = resp.content.decode("utf-8") - try: - results = json.loads(raw) - except ValueError: - self.fail("Not valid JSON: {}".format(raw)) - self.assertEqual(len(results), 3) - self.assertEqual( - {(s["title"], s["price"], s["slots"]) for s in results}, - {("foo", 0, 42), ("bar", 1, 142), ("baz", 2, 242)} - ) diff --git a/bda/tests/__init__.py b/bda/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bda/tests/test_views.py b/bda/tests/test_views.py new file mode 100644 index 00000000..125d5d57 --- /dev/null +++ b/bda/tests/test_views.py @@ -0,0 +1,222 @@ +import json + +from datetime import timedelta +from unittest import mock + +from django.contrib.auth.models import User +from django.template.defaultfilters import urlencode +from django.test import TestCase, Client +from django.utils import timezone + +from ..models import Tirage, Spectacle, Salle, CategorieSpectacle + + +def create_user(username, is_cof=False, is_buro=False): + user = User.objects.create_user(username=username, password=username) + user.profile.is_cof = is_cof + user.profile.is_buro = is_buro + user.profile.save() + return user + + +def user_is_cof(user): + return (user is not None) and user.profile.is_cof + + +def user_is_staff(user): + return (user is not None) and user.profile.is_buro + + +class BdATestHelpers: + def setUp(self): + # Some user with different access privileges + staff = create_user(username="bda_staff", is_cof=True, is_buro=True) + staff_c = Client() + staff_c.force_login(staff) + + member = create_user(username="bda_member", is_cof=True) + member_c = Client() + member_c.force_login(member) + + other = create_user(username="bda_other") + other_c = Client() + other_c.force_login(other) + + self.client_matrix = [ + (staff, staff_c), + (member, member_c), + (other, other_c), + (None, Client()) + ] + + def check_restricted_access(self, url, validate_user=user_is_cof, redirect_url=None): + def craft_redirect_url(user): + if redirect_url: + return redirect_url + elif user is None: + # client is not logged in + return "/login?next={}".format(urlencode(urlencode(url))) + else: + return "/" + + for (user, client) in self.client_matrix: + resp = client.get(url, follow=True) + if validate_user(user): + self.assertEqual(200, resp.status_code) + else: + self.assertRedirects(resp, craft_redirect_url(user)) + + +class TestBdAViews(BdATestHelpers, TestCase): + def setUp(self): + # Signals handlers on login/logout send messages. + # Due to the way the Django' test Client performs login, this raise an + # error. As workaround, we mock the Django' messages module. + patcher_messages = mock.patch('gestioncof.signals.messages') + patcher_messages.start() + self.addCleanup(patcher_messages.stop) + # Set up the helpers + BdATestHelpers.setUp(self) + # Some BdA stuff + self.tirage = Tirage.objects.create( + title="Test tirage", + appear_catalogue=True, + ouverture=timezone.now(), + fermeture=timezone.now(), + ) + self.category = CategorieSpectacle.objects.create(name="Category") + self.location = Salle.objects.create(name="here") + Spectacle.objects.bulk_create([ + Spectacle( + title="foo", date=timezone.now(), location=self.location, + price=0, slots=42, tirage=self.tirage, listing=False, + category=self.category + ), + Spectacle( + title="bar", date=timezone.now(), location=self.location, + price=1, slots=142, tirage=self.tirage, listing=False, + category=self.category + ), + Spectacle( + title="baz", date=timezone.now(), location=self.location, + price=2, slots=242, tirage=self.tirage, listing=False, + category=self.category + ), + ]) + + def test_bda_inscriptions(self): + # TODO: test the form + url = "/bda/inscription/{}".format(self.tirage.id) + self.check_restricted_access(url) + + def test_bda_places(self): + url = "/bda/places/{}".format(self.tirage.id) + self.check_restricted_access(url) + + def test_etat_places(self): + url = "/bda/etat-places/{}".format(self.tirage.id) + self.check_restricted_access(url) + + def test_perform_tirage(self): + # Only staff member can perform a tirage + url = "/bda/tirage/{}".format(self.tirage.id) + self.check_restricted_access(url, validate_user=user_is_staff) + + _, staff_c = self.client_matrix[0] + # Cannot be performed if disabled + self.tirage.enable_do_tirage = False + self.tirage.save() + resp = staff_c.get(url) + self.assertTemplateUsed(resp, "tirage-failed.html") + # Cannot be performed if registrations are still open + self.tirage.enable_do_tirage = True + self.tirage.fermeture = timezone.now() + timedelta(seconds=3600) + self.tirage.save() + resp = staff_c.get(url) + self.assertTemplateUsed(resp, "tirage-failed.html") + # Otherwise, perform the tirage + self.tirage.fermeture = timezone.now() + self.tirage.save() + resp = staff_c.get(url) + self.assertTemplateNotUsed(resp, "tirage-failed.html") + + def test_spectacles_list(self): + url = "/bda/spectacles/{}".format(self.tirage.id) + self.check_restricted_access(url, validate_user=user_is_staff) + + def test_spectacle_detail(self): + show = self.tirage.spectacle_set.first() + url = "/bda/spectacles/{}/{}".format(self.tirage.id, show.id) + self.check_restricted_access(url, validate_user=user_is_staff) + + def test_tirage_unpaid(self): + url = "/bda/spectacles/unpaid/{}".format(self.tirage.id) + self.check_restricted_access(url, validate_user=user_is_staff) + + def test_send_reminders(self): + # Just get the page + url = "/bda/mails-rappel/{}".format(self.tirage.id) + self.check_restricted_access(url, validate_user=user_is_staff) + # Actually send the reminder emails + # TODO: first load the emails into the database + _, staff_c = self.client_matrix[0] + resp = staff_c.post(url) + self.assertEqual(200, resp.status_code) + # TODO: check that emails are sent + + def test_catalogue_api(self): + url_list = "/bda/catalogue/list" + url_details = "/bda/catalogue/details?id={}".format(self.tirage.id) + url_descriptions = "/bda/catalogue/descriptions?id={}".format(self.tirage.id) + + # Anyone can get + def anyone_can_get(url): + self.check_restricted_access(url, validate_user=lambda user: True) + + anyone_can_get(url_list) + anyone_can_get(url_details) + anyone_can_get(url_descriptions) + + # The resulting JSON contains the information + _, client = self.client_matrix[0] + + # List + resp = client.get(url_list) + self.assertJSONEqual( + resp.content.decode("utf-8"), + [{"id": self.tirage.id, "title": self.tirage.title}] + ) + + # Details + resp = client.get(url_details) + self.assertJSONEqual( + resp.content.decode("utf-8"), + { + "categories": [{ + "id": self.category.id, + "name": self.category.name + }], + "locations": [{ + "id": self.location.id, + "name": self.location.name + }], + } + ) + + # Descriptions + resp = client.get(url_descriptions) + raw = resp.content.decode("utf-8") + try: + results = json.loads(raw) + except ValueError: + self.fail("Not valid JSON: {}".format(raw)) + self.assertEqual(len(results), 3) + self.assertEqual( + {(s["title"], s["price"], s["slots"]) for s in results}, + {("foo", 0, 42), ("bar", 1, 142), ("baz", 2, 242)} + ) + + +class TestBdaRevente: + pass + # TODO