import json from datetime import timedelta from unittest import mock from django.contrib.auth import get_user_model from django.test import Client, TestCase from django.urls import reverse from django.utils import formats, timezone from ..models import Participant, Tirage from .mixins import BdATestHelpers, BdAViewTestCaseMixin User = get_user_model() class InscriptionViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase): url_name = "bda-tirage-inscription" http_methods = ["GET", "POST"] auth_user = "bda_member" auth_forbidden = [None, "bda_other"] bda_testdata = True @property def url_kwargs(self): return {"tirage_id": self.tirage.id} @property def url_expected(self): return "/bda/inscription/{}".format(self.tirage.id) def test_get_opened(self): self.tirage.ouverture = timezone.now() - timedelta(days=1) self.tirage.fermeture = timezone.now() + timedelta(days=1) self.tirage.save() resp = self.client.get(self.url) self.assertEqual(resp.status_code, 200) self.assertFalse(resp.context["messages"]) def test_get_closed_future(self): self.tirage.ouverture = timezone.now() + timedelta(days=1) self.tirage.fermeture = timezone.now() + timedelta(days=2) self.tirage.save() resp = self.client.get(self.url) self.assertEqual(resp.status_code, 200) self.assertIn( "Le tirage n'est pas encore ouvert : ouverture le {}".format( formats.localize(timezone.template_localtime(self.tirage.ouverture)) ), [str(msg) for msg in resp.context["messages"]], ) def test_get_closed_past(self): self.tirage.ouverture = timezone.now() - timedelta(days=2) self.tirage.fermeture = timezone.now() - timedelta(days=1) self.tirage.save() resp = self.client.get(self.url) self.assertEqual(resp.status_code, 200) self.assertIn( " C'est fini : tirage au sort dans la journée !", [str(msg) for msg in resp.context["messages"]], ) def get_base_post_data(self): return { "choixspectacle_set-TOTAL_FORMS": "3", "choixspectacle_set-INITIAL_FORMS": "0", "choixspectacle_set-MIN_NUM_FORMS": "0", "choixspectacle_set-MAX_NUM_FORMS": "1000", } base_post_data = property(get_base_post_data) def test_post(self): self.tirage.ouverture = timezone.now() - timedelta(days=1) self.tirage.fermeture = timezone.now() + timedelta(days=1) self.tirage.save() data = dict( self.base_post_data, **{ "choixspectacle_set-TOTAL_FORMS": "2", "choixspectacle_set-0-id": "", "choixspectacle_set-0-participant": "", "choixspectacle_set-0-spectacle": str(self.show1.pk), "choixspectacle_set-0-double_choice": "1", "choixspectacle_set-0-priority": "2", "choixspectacle_set-1-id": "", "choixspectacle_set-1-participant": "", "choixspectacle_set-1-spectacle": str(self.show2.pk), "choixspectacle_set-1-double_choice": "autoquit", "choixspectacle_set-1-priority": "1", } ) resp = self.client.post(self.url, data) self.assertEqual(resp.status_code, 200) self.assertIn( "Votre inscription a été mise à jour avec succès !", [str(msg) for msg in resp.context["messages"]], ) participant = Participant.objects.get( user=self.users["bda_member"], tirage=self.tirage ) self.assertSetEqual( set( participant.choixspectacle_set.values_list( "priority", "spectacle_id", "double_choice" ) ), {(1, self.show2.pk, "autoquit"), (2, self.show1.pk, "1")}, ) def test_post_state_changed(self): self.tirage.ouverture = timezone.now() - timedelta(days=1) self.tirage.fermeture = timezone.now() + timedelta(days=1) self.tirage.save() data = {"dbstate": "different"} resp = self.client.post(self.url, data) self.assertEqual(resp.status_code, 200) self.assertIn( "Impossible d'enregistrer vos modifications : vous avez apporté d'autres " "modifications entre temps.", [str(msg) for msg in resp.context["messages"]], ) class PlacesViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase): url_name = "bda-places-attribuees" auth_user = "bda_member" auth_forbidden = [None, "bda_other"] bda_testdata = True @property def url_kwargs(self): return {"tirage_id": self.tirage.id} @property def url_expected(self): return "/bda/places/{}".format(self.tirage.id) class EtatPlacesViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase): url_name = "bda-etat-places" auth_user = "bda_member" auth_forbidden = [None, "bda_other"] bda_testdata = True @property def url_kwargs(self): return {"tirage_id": self.tirage.id} @property def url_expected(self): return "/bda/etat-places/{}".format(self.tirage.id) class TirageViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase): url_name = "bda-tirage" http_methods = ["GET", "POST"] auth_user = "bda_staff" auth_forbidden = [None, "bda_other", "bda_member"] bda_testdata = True @property def url_kwargs(self): return {"tirage_id": self.tirage.id} @property def url_expected(self): return "/bda/tirage/{}".format(self.tirage.id) def test_perform_tirage_disabled(self): # Cannot be performed if disabled self.tirage.enable_do_tirage = False self.tirage.save() resp = self.client.get(self.url) self.assertTemplateUsed(resp, "tirage-failed.html") def test_perform_tirage_opened_registrations(self): # 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 = self.client.get(self.url) self.assertTemplateUsed(resp, "tirage-failed.html") def test_perform_tirage(self): # Otherwise, perform the tirage self.tirage.enable_do_tirage = True self.tirage.fermeture = timezone.now() self.tirage.save() resp = self.client.get(self.url) self.assertTemplateNotUsed(resp, "tirage-failed.html") class SpectacleListViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase): url_name = "bda-liste-spectacles" auth_user = "bda_staff" auth_forbidden = [None, "bda_other", "bda_member"] bda_testdata = True @property def url_kwargs(self): return {"tirage_id": self.tirage.id} @property def url_expected(self): return "/bda/spectacles/{}".format(self.tirage.id) class SpectacleViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase): url_name = "bda-spectacle" auth_user = "bda_staff" auth_forbidden = [None, "bda_other", "bda_member"] bda_testdata = True @property def url_kwargs(self): return {"tirage_id": self.tirage.id, "spectacle_id": self.show1.id} @property def url_expected(self): return "/bda/spectacles/{}/{}".format(self.tirage.id, self.show1.id) class UnpaidViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase): url_name = "bda-unpaid" auth_user = "bda_staff" auth_forbidden = [None, "bda_other", "bda_member"] bda_testdata = True @property def url_kwargs(self): return {"tirage_id": self.tirage.id} @property def url_expected(self): return "/bda/spectacles/unpaid/{}".format(self.tirage.id) class SendRemindersViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase): url_name = "bda-rappels" auth_user = "bda_staff" auth_forbidden = [None, "bda_other", "bda_member"] bda_testdata = True @property def url_kwargs(self): return {"spectacle_id": self.show1.id} @property def url_expected(self): return "/bda/mails-rappel/{}".format(self.show1.id) def test_post(self): self.require_custommails() resp = self.client.post(self.url) self.assertEqual(200, resp.status_code) # TODO: check that emails are sent class CatalogueViewTestCase(BdATestHelpers, BdAViewTestCaseMixin, TestCase): auth_user = None auth_forbidden = [] bda_testdata = True def test_api_list(self): url_list = "/bda/catalogue/list" resp = self.client.get(url_list) self.assertJSONEqual( resp.content.decode("utf-8"), [{"id": self.tirage.id, "title": self.tirage.title}], ) def test_api_details(self): url_details = "/bda/catalogue/details?id={}".format(self.tirage.id) resp = self.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}], }, ) def test_api_descriptions(self): url_descriptions = "/bda/catalogue/descriptions?id={}".format(self.tirage.id) resp = self.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)}, ) # ----- BdA Revente --------------------------------------- # def make_participant(name: str, tirage: Tirage) -> User: user = User.objects.create_user(username=name, password=name) user.profile.is_cof = True user.profile.save() Participant.objects.create(user=user, tirage=tirage) return user class TestReventeManageTest(TestCase): def setUp(self): self.tirage = Tirage.objects.create( title="tirage1", ouverture=timezone.now(), fermeture=timezone.now() + timedelta(days=90), ) self.user = make_participant("toto", self.tirage) self.url = reverse("bda-revente-manage", args=[self.tirage.id]) # 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) def test_can_get(self): client = Client() client.force_login(self.user) r = client.get(self.url) self.assertEqual(r.status_code, 200) class TestBdaRevente: pass # TODO