generated from bisco/codex-bootstrap
180 lines
6.8 KiB
Python
180 lines
6.8 KiB
Python
from datetime import timedelta
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.core import mail
|
|
from django.test import TestCase
|
|
from django.test.utils import override_settings
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
|
|
from bookings.models import Reservation, ReservationToken
|
|
from checkins.models import CheckIn
|
|
from shows.models import Performance, Show, Venue
|
|
|
|
|
|
@override_settings(
|
|
EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend",
|
|
SITE_BASE_URL="https://tickets.azionelab.example",
|
|
)
|
|
class ReservationAdminTests(TestCase):
|
|
def setUp(self):
|
|
user_model = get_user_model()
|
|
self.admin_user = user_model.objects.create_superuser(
|
|
username="admin-bookings",
|
|
email="admin@example.com",
|
|
password="password123",
|
|
)
|
|
self.client.force_login(self.admin_user)
|
|
self.show = Show.objects.create(
|
|
title="Open Stage",
|
|
slug="open-stage-admin",
|
|
is_published=True,
|
|
)
|
|
self.venue = Venue.objects.create(
|
|
name="AzioneLab Theatre",
|
|
slug="azionelab-theatre-admin",
|
|
address="Via Example 1",
|
|
city="Rome",
|
|
)
|
|
self.performance = Performance.objects.create(
|
|
show=self.show,
|
|
venue=self.venue,
|
|
starts_at=timezone.now() + timedelta(days=7),
|
|
room_capacity=20,
|
|
)
|
|
|
|
def test_reservation_add_page_accepts_preselected_performance(self):
|
|
response = self.client.get(
|
|
reverse("admin:bookings_reservation_add"),
|
|
{"performance": self.performance.id},
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertContains(response, "Create manual reservation")
|
|
self.assertContains(response, "The reservation stays pending")
|
|
|
|
def test_admin_can_create_manual_reservation_with_standard_email_flow(self):
|
|
with self.captureOnCommitCallbacks(execute=True):
|
|
response = self.client.post(
|
|
reverse("admin:bookings_reservation_add"),
|
|
{
|
|
"performance": self.performance.id,
|
|
"name": "Maria Rossi",
|
|
"email": "maria@example.com",
|
|
"phone": "+390600000000",
|
|
"party_size": 2,
|
|
"notes": "Entered by staff at the venue desk.",
|
|
"_save": "Save",
|
|
},
|
|
)
|
|
|
|
reservation = Reservation.objects.get()
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertEqual(reservation.performance, self.performance)
|
|
self.assertEqual(reservation.status, Reservation.Status.PENDING)
|
|
self.assertEqual(reservation.party_size, 2)
|
|
self.assertTrue(
|
|
ReservationToken.objects.filter(
|
|
reservation=reservation,
|
|
purpose=ReservationToken.Purpose.CONFIRMATION,
|
|
).exists()
|
|
)
|
|
self.assertEqual(len(mail.outbox), 1)
|
|
self.assertIn(
|
|
"https://tickets.azionelab.example/api/reservations/confirm/?token=",
|
|
mail.outbox[0].body,
|
|
)
|
|
|
|
def test_token_hash_is_hidden_in_token_admin_views(self):
|
|
reservation = Reservation.objects.create(
|
|
performance=self.performance,
|
|
name="Maria Rossi",
|
|
email="maria@example.com",
|
|
party_size=2,
|
|
)
|
|
token, _ = ReservationToken.create_token(
|
|
reservation=reservation,
|
|
purpose=ReservationToken.Purpose.CONFIRMATION,
|
|
expires_at=timezone.now() + timedelta(hours=2),
|
|
)
|
|
|
|
changelist_response = self.client.get(reverse("admin:bookings_reservationtoken_changelist"))
|
|
change_response = self.client.get(
|
|
reverse("admin:bookings_reservationtoken_change", args=[token.id]),
|
|
)
|
|
|
|
self.assertEqual(changelist_response.status_code, 200)
|
|
self.assertEqual(change_response.status_code, 200)
|
|
self.assertNotContains(changelist_response, token.token_hash)
|
|
self.assertNotContains(change_response, token.token_hash)
|
|
self.assertContains(change_response, token.get_purpose_display())
|
|
self.assertContains(change_response, "Expires at")
|
|
self.assertContains(change_response, "Used at")
|
|
|
|
def test_admin_can_confirm_pending_reservation_manually_and_get_qr_access(self):
|
|
reservation = Reservation.objects.create(
|
|
performance=self.performance,
|
|
name="Maria Rossi",
|
|
email="maria@example.com",
|
|
party_size=2,
|
|
)
|
|
confirmation_token, _ = ReservationToken.create_token(
|
|
reservation=reservation,
|
|
purpose=ReservationToken.Purpose.CONFIRMATION,
|
|
expires_at=timezone.now() + timedelta(hours=2),
|
|
)
|
|
|
|
response = self.client.post(
|
|
reverse("admin:bookings_reservation_manual_confirm", args=[reservation.id]),
|
|
)
|
|
|
|
reservation.refresh_from_db()
|
|
confirmation_token.refresh_from_db()
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertEqual(reservation.status, Reservation.Status.CONFIRMED)
|
|
self.assertIsNotNone(confirmation_token.used_at)
|
|
self.assertContains(response, "Reservation confirmed manually")
|
|
self.assertContains(response, "/api/check-ins/preview/?token=")
|
|
self.assertTrue(
|
|
ReservationToken.objects.filter(
|
|
reservation=reservation,
|
|
purpose=ReservationToken.Purpose.CHECK_IN,
|
|
).exists()
|
|
)
|
|
|
|
def test_admin_can_mark_confirmed_reservation_as_checked_in(self):
|
|
reservation = Reservation.objects.create(
|
|
performance=self.performance,
|
|
name="Checked Guest",
|
|
email="checked@example.com",
|
|
party_size=1,
|
|
status=Reservation.Status.CONFIRMED,
|
|
confirmed_at=timezone.now(),
|
|
)
|
|
|
|
response = self.client.post(
|
|
reverse("admin:bookings_reservation_manual_check_in", args=[reservation.id]),
|
|
)
|
|
|
|
self.assertEqual(response.status_code, 302)
|
|
check_in = CheckIn.objects.get(reservation=reservation)
|
|
self.assertEqual(check_in.checked_in_by, self.admin_user)
|
|
self.assertEqual(check_in.source, CheckIn.Source.MANUAL)
|
|
|
|
def test_reservation_string_is_concise_without_performance_details(self):
|
|
single_guest_reservation = Reservation.objects.create(
|
|
performance=self.performance,
|
|
name="Maria Rossi",
|
|
email="maria@example.com",
|
|
party_size=1,
|
|
)
|
|
group_reservation = Reservation.objects.create(
|
|
performance=self.performance,
|
|
name="Luca Bianchi",
|
|
email="luca@example.com",
|
|
party_size=3,
|
|
)
|
|
|
|
self.assertEqual(str(single_guest_reservation), "Maria Rossi")
|
|
self.assertEqual(str(group_reservation), "Luca Bianchi (3)")
|