generated from bisco/codex-bootstrap
191 lines
7.2 KiB
Python
191 lines
7.2 KiB
Python
from datetime import timedelta
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
from rest_framework import status
|
|
from rest_framework.test import APITestCase
|
|
|
|
from bookings.models import Reservation, ReservationToken
|
|
from checkins.models import CheckIn
|
|
from shows.models import Performance, Show, Venue
|
|
|
|
|
|
class CheckInApiTests(APITestCase):
|
|
def setUp(self):
|
|
self.show = Show.objects.create(
|
|
title="Open Stage",
|
|
slug="open-stage-checkin-api",
|
|
is_published=True,
|
|
)
|
|
self.venue = Venue.objects.create(
|
|
name="AzioneLab Theatre",
|
|
slug="azionelab-theatre-checkin-api",
|
|
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,
|
|
)
|
|
self.staff_user = get_user_model().objects.create_user(
|
|
username="staff-api",
|
|
password="test",
|
|
is_staff=True,
|
|
)
|
|
self.regular_user = get_user_model().objects.create_user(
|
|
username="regular-api",
|
|
password="test",
|
|
is_staff=False,
|
|
)
|
|
|
|
def test_preview_success_as_staff_user(self):
|
|
reservation = self.create_reservation()
|
|
_, raw_token = self.create_check_in_token(reservation)
|
|
self.client.force_authenticate(user=self.staff_user)
|
|
|
|
response = self.client.post(
|
|
reverse("api-check-in-preview"),
|
|
{"token": raw_token},
|
|
format="json",
|
|
)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(response.data["status"], "valid")
|
|
self.assertEqual(response.data["reservation_id"], reservation.id)
|
|
self.assertEqual(response.data["performance_id"], self.performance.id)
|
|
self.assertEqual(response.data["show_title"], self.show.title)
|
|
self.assertEqual(response.data["party_size"], reservation.party_size)
|
|
self.assertNotIn("name", response.data)
|
|
self.assertNotIn("email", response.data)
|
|
self.assertNotIn("phone", response.data)
|
|
|
|
def test_preview_denied_for_anonymous_user(self):
|
|
reservation = self.create_reservation()
|
|
_, raw_token = self.create_check_in_token(reservation)
|
|
|
|
response = self.client.post(
|
|
reverse("api-check-in-preview"),
|
|
{"token": raw_token},
|
|
format="json",
|
|
)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
|
|
def test_preview_fails_for_invalid_token(self):
|
|
self.client.force_authenticate(user=self.staff_user)
|
|
|
|
response = self.client.post(
|
|
reverse("api-check-in-preview"),
|
|
{"token": "invalid-token"},
|
|
format="json",
|
|
)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
self.assertEqual(response.data["status"], "invalid_token")
|
|
|
|
def test_check_in_success_as_staff_user(self):
|
|
reservation = self.create_reservation()
|
|
_, raw_token = self.create_check_in_token(reservation)
|
|
self.client.force_authenticate(user=self.staff_user)
|
|
|
|
response = self.client.post(
|
|
reverse("api-check-in-confirm"),
|
|
{"token": raw_token},
|
|
format="json",
|
|
)
|
|
|
|
check_in = CheckIn.objects.get(reservation=reservation)
|
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(response.data["status"], "checked_in")
|
|
self.assertEqual(response.data["reservation_id"], reservation.id)
|
|
self.assertEqual(response.data["performance_id"], self.performance.id)
|
|
self.assertEqual(response.data["party_size"], reservation.party_size)
|
|
self.assertEqual(response.data["checked_in_by"], self.staff_user.id)
|
|
self.assertIsNotNone(response.data["checked_in_at"])
|
|
self.assertEqual(check_in.checked_in_by, self.staff_user)
|
|
|
|
def test_check_in_denied_for_anonymous_user(self):
|
|
reservation = self.create_reservation()
|
|
_, raw_token = self.create_check_in_token(reservation)
|
|
|
|
response = self.client.post(
|
|
reverse("api-check-in-confirm"),
|
|
{"token": raw_token},
|
|
format="json",
|
|
)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
|
self.assertFalse(CheckIn.objects.filter(reservation=reservation).exists())
|
|
|
|
def test_check_in_denied_for_non_staff_authenticated_user(self):
|
|
reservation = self.create_reservation()
|
|
_, raw_token = self.create_check_in_token(reservation)
|
|
self.client.force_authenticate(user=self.regular_user)
|
|
|
|
response = self.client.post(
|
|
reverse("api-check-in-confirm"),
|
|
{"token": raw_token},
|
|
format="json",
|
|
)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
|
self.assertFalse(CheckIn.objects.filter(reservation=reservation).exists())
|
|
|
|
def test_check_in_fails_for_pending_reservation(self):
|
|
reservation = self.create_reservation(status=Reservation.Status.PENDING, confirmed_at=None)
|
|
_, raw_token = self.create_check_in_token(reservation)
|
|
self.client.force_authenticate(user=self.staff_user)
|
|
|
|
response = self.client.post(
|
|
reverse("api-check-in-confirm"),
|
|
{"token": raw_token},
|
|
format="json",
|
|
)
|
|
|
|
self.assertEqual(response.status_code, status.HTTP_409_CONFLICT)
|
|
self.assertEqual(response.data["status"], "reservation_not_confirmed")
|
|
self.assertFalse(CheckIn.objects.filter(reservation=reservation).exists())
|
|
|
|
def test_duplicate_check_in_fails(self):
|
|
reservation = self.create_reservation()
|
|
_, raw_token = self.create_check_in_token(reservation)
|
|
self.client.force_authenticate(user=self.staff_user)
|
|
first_response = self.client.post(
|
|
reverse("api-check-in-confirm"),
|
|
{"token": raw_token},
|
|
format="json",
|
|
)
|
|
|
|
second_response = self.client.post(
|
|
reverse("api-check-in-confirm"),
|
|
{"token": raw_token},
|
|
format="json",
|
|
)
|
|
|
|
self.assertEqual(first_response.status_code, status.HTTP_200_OK)
|
|
self.assertEqual(second_response.status_code, status.HTTP_409_CONFLICT)
|
|
self.assertEqual(second_response.data["status"], "already_checked_in")
|
|
self.assertEqual(CheckIn.objects.filter(reservation=reservation).count(), 1)
|
|
|
|
def create_reservation(self, **overrides):
|
|
data = {
|
|
"performance": self.performance,
|
|
"name": "Maria Rossi",
|
|
"email": "maria@example.com",
|
|
"party_size": 2,
|
|
"status": Reservation.Status.CONFIRMED,
|
|
"confirmed_at": timezone.now(),
|
|
}
|
|
data.update(overrides)
|
|
return Reservation.objects.create(**data)
|
|
|
|
def create_check_in_token(self, reservation):
|
|
return ReservationToken.create_token(
|
|
reservation=reservation,
|
|
purpose=ReservationToken.Purpose.CHECK_IN,
|
|
expires_at=self.performance.starts_at + timedelta(days=1),
|
|
)
|