from decimal import Decimal from django.contrib.auth import get_user_model from django.core import mail from django.test import Client, TestCase from django.urls import reverse from django.utils import timezone from events.models import Event, Ticket, TicketOrder from events.services import EventsError, create_ticket_order, mark_paid def _event(**kwargs): defaults = dict( title="Friday Night Prerelease", starts_at=timezone.now() + timezone.timedelta(days=7), venue="Main shop", capacity=8, price=Decimal("25.00"), is_published=True, ) defaults.update(kwargs) return Event.objects.create(**defaults) class EventPublicTests(TestCase): def test_list_hides_drafts_and_past(self): _event(title="Live prerelease") _event(title="Draft night", is_published=False) _event( title="Last week", starts_at=timezone.now() - timezone.timedelta(days=2), ) response = Client().get(reverse("events:list")) self.assertEqual(response.status_code, 200) self.assertContains(response, "Live prerelease") self.assertNotContains(response, "Draft night") self.assertNotContains(response, "Last week") def test_buy_form_renders(self): event = _event() response = Client().get(reverse("events:buy", kwargs={"slug": event.slug})) self.assertEqual(response.status_code, 200) self.assertContains(response, "Pay with Stripe") class EventCapacityTests(TestCase): def test_capacity_blocks_overbook(self): event = _event(capacity=2) create_ticket_order(event, email="a@example.com", quantity=2) with self.assertRaises(EventsError): create_ticket_order(event, email="b@example.com", quantity=1) def test_mark_paid_issues_tickets_and_email(self): event = _event(capacity=4) order = create_ticket_order( event, email="fan@example.com", customer_name="Lee", quantity=2 ) mark_paid(order) order.refresh_from_db() self.assertEqual(order.status, TicketOrder.Status.PAID) self.assertEqual(Ticket.objects.filter(order=order).count(), 2) self.assertEqual(event.tickets_sold, 2) self.assertEqual(len(mail.outbox), 1) self.assertIn(event.title, mail.outbox[0].subject) class EventPortalTests(TestCase): def setUp(self): User = get_user_model() self.user = User.objects.create_user("host", password="test-pass-123", is_staff=True) self.client = Client() self.client.login(username="host", password="test-pass-123") def test_list_requires_login(self): self.assertEqual(Client().get(reverse("events_portal:event_list")).status_code, 302) def test_create_published_event(self): starts = (timezone.now() + timezone.timedelta(days=3)).strftime("%Y-%m-%dT%H:%M") response = self.client.post( reverse("events_portal:event_new"), { "title": "Commander night", "starts_at": starts, "venue": "Back room", "capacity": "16", "price": "10.00", "is_published": "on", }, ) self.assertEqual(response.status_code, 302) event = Event.objects.get() self.assertEqual(event.slug, "commander-night") self.assertTrue(event.is_published) self.assertEqual(event.capacity, 16)