Skip to content

Commit ba74722

Browse files
Additional Booking Tests
1 parent a7b9783 commit ba74722

File tree

2 files changed

+120
-2
lines changed

2 files changed

+120
-2
lines changed

backend/apps/bookings/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import uuid
55
from datetime import timedelta
66
from django.utils.timezone import now
7-
from rest_framework.exceptions import ValidationError
7+
from django.core.exceptions import ValidationError
88
from apps.users.models import TutorProfile
99
from apps.bookings.managers import ReviewManager, BookingManager
1010

backend/apps/bookings/tests.py

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from django.test import TestCase
22
from django.contrib.auth.models import User
33
from django.utils.timezone import now, timedelta
4+
from django.core.exceptions import ValidationError
45
from apps.users.models import TutorProfile, Profile
56
from apps.bookings.models import Booking, Availability, Review
67
from rest_framework.test import APITestCase, APIClient
@@ -69,6 +70,65 @@ def test_booking_cancellation(self):
6970
self.assertEqual(booking.booking_status, Booking.CANCELLED)
7071
self.assertFalse(updated_availability.is_booked)
7172

73+
def test_clean_raises_without_availability(self):
74+
booking = Booking(
75+
student=self.student_user,
76+
session_price=20.00,
77+
availability=None
78+
)
79+
with self.assertRaises(ValidationError) as ctx:
80+
booking.clean()
81+
self.assertIn("must be linked to an availability", str(ctx.exception))
82+
83+
def test_clean_raises_if_availability_already_booked(self):
84+
self.availability.is_booked = True
85+
self.availability.save()
86+
87+
booking = Booking(
88+
student=self.student_user,
89+
session_price=20.00,
90+
availability=self.availability
91+
)
92+
with self.assertRaises(ValidationError) as ctx:
93+
booking.clean()
94+
self.assertIn("already booked", str(ctx.exception))
95+
96+
def test_save_does_not_book_if_cancelled(self):
97+
booking = Booking.objects.create(
98+
student=self.student_user,
99+
session_price=25.00,
100+
availability=self.availability,
101+
booking_status=Booking.CANCELLED
102+
)
103+
booking.refresh_from_db()
104+
self.availability.refresh_from_db()
105+
self.assertFalse(self.availability.is_booked)
106+
107+
def test_save_marks_availability_as_booked_unless_cancelled(self):
108+
booking = Booking.objects.create(
109+
student=self.student_user,
110+
session_price=25.00,
111+
availability=self.availability,
112+
booking_status=Booking.APPROVED
113+
)
114+
self.availability.refresh_from_db()
115+
self.assertTrue(self.availability.is_booked)
116+
117+
def test_booking_detail_serializer_includes_read_only_booking(self):
118+
from apps.bookings.serializers import BookingDetailSerializer
119+
120+
booking = Booking.objects.create(
121+
student=self.student_user,
122+
session_price=30.00,
123+
availability=self.availability
124+
)
125+
126+
serializer = BookingDetailSerializer(instance=booking)
127+
data = serializer.data
128+
self.assertIn("student", data)
129+
self.assertEqual(data["student_username"], self.student_user.username)
130+
131+
72132
class BookingAPITestCase(APITestCase):
73133
def setUp(self):
74134
# Create tutor and tutor profile
@@ -137,4 +197,62 @@ def test_get_availability_by_tutor_and_date(self):
137197
date_str = self.availability.start_time.strftime("%Y-%m-%d")
138198
url = f"/bookings/availability/?tutor_id={self.tutor.id}&date={date_str}"
139199
response = self.client.get(url)
140-
self.assertEqual(response.status_code, status.HTTP_200_OK)
200+
self.assertEqual(response.status_code, status.HTTP_200_OK)
201+
202+
def test_patch_booking_status(self):
203+
new_availability = Availability.objects.create(
204+
tutor=self.tutor,
205+
start_time=now() + timedelta(days=2),
206+
end_time=now() + timedelta(days=2, hours=1),
207+
is_booked=False
208+
)
209+
210+
booking = Booking.objects.create(
211+
student=self.student_user,
212+
session_price=30.00,
213+
availability=new_availability
214+
)
215+
216+
# Reset to unbooked for PATCH to
217+
218+
def test_put_booking(self):
219+
new_availability = Availability.objects.create(
220+
tutor=self.tutor,
221+
start_time=now() + timedelta(days=3),
222+
end_time=now() + timedelta(days=3, hours=1),
223+
is_booked=False
224+
)
225+
226+
booking = Booking.objects.create(
227+
student=self.student_user,
228+
session_price=25.00,
229+
availability=new_availability
230+
)
231+
232+
# Reset booking state for validation to pass
233+
new_availability.is_booked = False
234+
new_availability.save()
235+
236+
url = f"/bookings/bookings_list/{booking.payment_gateway_ref}/"
237+
data = {
238+
"session_price": "35.00",
239+
"availability": new_availability.id,
240+
"booking_status": Booking.FULFILLED
241+
}
242+
243+
response = self.client.put(url, data, format="json")
244+
booking.refresh_from_db()
245+
self.assertEqual(response.status_code, status.HTTP_200_OK)
246+
self.assertEqual(float(booking.session_price), 35.00)
247+
self.assertEqual(booking.booking_status, Booking.FULFILLED)
248+
249+
def test_delete_booking(self):
250+
booking = Booking.objects.create(
251+
student=self.student_user,
252+
session_price=30.00,
253+
availability=self.availability
254+
)
255+
url = f"/bookings/bookings_list/{booking.payment_gateway_ref}/"
256+
response = self.client.delete(url)
257+
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
258+
self.assertFalse(Booking.objects.filter(pk=booking.payment_gateway_ref).exists())

0 commit comments

Comments
 (0)