Skip to content

Commit c9efcbc

Browse files
committed
Added tests
1 parent d62c627 commit c9efcbc

File tree

3 files changed

+141
-4
lines changed

3 files changed

+141
-4
lines changed

appointment/tests/test_tasks.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from django.test import TestCase
2+
from unittest.mock import patch
3+
from appointment.tasks import send_email_reminder
4+
from appointment.tests.base.base_test import BaseTest
5+
from django.utils.translation import gettext as _
6+
7+
8+
class SendEmailReminderTest(BaseTest):
9+
10+
@patch('appointment.tasks.send_email')
11+
@patch('appointment.tasks.notify_admin')
12+
def test_send_email_reminder(self, mock_notify_admin, mock_send_email):
13+
# Use BaseTest setup to create an appointment
14+
appointment_request = self.create_appt_request_for_sm1()
15+
appointment = self.create_appointment_for_user1(appointment_request=appointment_request)
16+
17+
# Extract necessary data for the test
18+
to_email = appointment.client.email
19+
first_name = appointment.client.first_name
20+
appointment_id = appointment.id
21+
22+
# Call the function under test
23+
send_email_reminder(to_email, first_name, appointment_id)
24+
25+
# Verify send_email was called with correct parameters
26+
mock_send_email.assert_called_once_with(
27+
recipient_list=[to_email],
28+
subject=_("Reminder: Upcoming Appointment"),
29+
template_url='email_sender/reminder_email.html',
30+
context={'first_name': first_name, 'appointment': appointment}
31+
)
32+
33+
# Verify notify_admin was called with correct parameters
34+
mock_notify_admin.assert_called_once_with(
35+
subject=_("Admin Reminder: Upcoming Appointment"),
36+
template_url='email_sender/reminder_email.html',
37+
context={'first_name': first_name, 'appointment': appointment}
38+
)

appointment/tests/test_utils.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
from django.conf import settings
77
from django.http import HttpRequest
88
from django.test import TestCase
9+
from django.utils import timezone
910
from django.utils.translation import gettext_lazy as _
1011

1112
from appointment.models import Appointment, AppointmentRequest, Config, Service, StaffMember
1213
from appointment.services import get_available_slots, get_finish_button_text
1314
from appointment.settings import APPOINTMENT_BUFFER_TIME, APPOINTMENT_FINISH_TIME, APPOINTMENT_LEAD_TIME, \
1415
APPOINTMENT_SLOT_DURATION, APPOINTMENT_WEBSITE_NAME
15-
from appointment.utils.date_time import convert_str_to_date, get_current_year, get_timestamp, get_timezone
16+
from appointment.utils.date_time import combine_date_and_time, convert_str_to_date, get_current_year, get_timestamp, \
17+
get_timezone
1618
from appointment.utils.db_helpers import get_appointment_buffer_time, get_appointment_finish_time, \
1719
get_appointment_lead_time, get_appointment_slot_duration, get_user_model, get_website_name
1820
from appointment.utils.view_helpers import generate_random_id, get_locale, is_ajax
@@ -204,3 +206,43 @@ def test_get_finish_button_text_paid_service(self):
204206
def test_get_client_model(self):
205207
client_model = get_user_model()
206208
self.assertEqual(client_model, apps.get_model(settings.AUTH_USER_MODEL))
209+
210+
211+
class UtilityDateTimeTestCase(TestCase):
212+
def test_combine_date_and_time_success(self):
213+
"""
214+
Test combining a date and time into a datetime object successfully.
215+
"""
216+
date = datetime.date(2024, 2, 5)
217+
time = datetime.time(14, 30)
218+
expected_datetime = datetime.datetime(2024, 2, 5, 14, 30)
219+
combined_datetime = combine_date_and_time(date, time)
220+
self.assertEqual(combined_datetime, expected_datetime)
221+
222+
def test_combine_date_and_time_with_timezone(self):
223+
"""
224+
Test combining a date and time into a timezone-aware datetime object.
225+
"""
226+
date = datetime.date(2024, 2, 5)
227+
time = datetime.time(14, 30, tzinfo=timezone.utc)
228+
combined_datetime = combine_date_and_time(date, time)
229+
self.assertTrue(timezone.is_aware(combined_datetime), "The datetime object is not timezone-aware.")
230+
self.assertEqual(combined_datetime.tzinfo, timezone.utc)
231+
232+
def test_combine_date_and_time_with_invalid_date(self):
233+
"""
234+
Test handling of invalid date input.
235+
"""
236+
date = "2024-02-05" # Incorrect type. It should be datetime.date
237+
time = datetime.time(14, 30)
238+
with self.assertRaises(TypeError, msg="Expected TypeError when combining with invalid date type"):
239+
combine_date_and_time(date, time)
240+
241+
def test_combine_date_and_time_with_invalid_time(self):
242+
"""
243+
Test handling of invalid time input.
244+
"""
245+
date = datetime.date(2024, 2, 5)
246+
time = "14:30" # Incorrect type. It should be datetime.time
247+
with self.assertRaises(TypeError, msg="Expected TypeError when combining with invalid time type"):
248+
combine_date_and_time(date, time)

appointment/tests/utils/test_db_helpers.py

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111
from django.core.exceptions import FieldDoesNotExist
1212
from django.test import TestCase
1313
from django.urls import reverse
14+
from django.utils import timezone
15+
from django_q.models import Schedule
1416

1517
from appointment.models import DayOff, PaymentInfo
1618
from appointment.tests.base.base_test import BaseTest
1719
from appointment.utils.date_time import get_current_year
18-
from appointment.utils.db_helpers import (calculate_slots, check_day_off_for_staff, create_and_save_appointment,
20+
from appointment.utils.db_helpers import (calculate_slots, cancel_existing_reminder, check_day_off_for_staff,
21+
create_and_save_appointment,
1922
create_payment_info_and_get_url, exclude_booked_slots,
2023
day_off_exists_for_date_range, get_all_staff_members,
2124
get_all_appointments, Config, get_appointment_buffer_time,
@@ -28,7 +31,9 @@
2831
get_staff_member_end_time, get_staff_member_buffer_time,
2932
get_staff_member_slot_duration, get_user_by_email, get_user_model,
3033
get_staff_member_from_user_id_or_logged_in,
31-
get_staff_member_by_user_id, working_hours_exist, is_working_day,
34+
get_staff_member_by_user_id, schedule_email_reminder,
35+
update_appointment_reminder, working_hours_exist,
36+
is_working_day,
3237
get_working_hours_for_staff_and_day,
3338
get_working_hours_by_id, get_website_name, get_times_from_config,
3439
create_new_user, generate_unique_username_from_email, parse_name,
@@ -149,6 +154,59 @@ def get_mock_reverse(url_name, **kwargs):
149154
return reverse(url_name, **kwargs)
150155

151156

157+
class ScheduleEmailReminderTest(BaseTest):
158+
def test_schedule_email_reminder_cluster_running(self):
159+
appointment = self.create_appointment_for_user1()
160+
with patch('appointment.settings.check_q_cluster', return_value=True), \
161+
patch('appointment.utils.db_helpers.schedule') as mock_schedule:
162+
schedule_email_reminder(appointment)
163+
mock_schedule.assert_called_once()
164+
# Further assertions can be made here based on the arguments passed to schedule
165+
166+
def test_schedule_email_reminder_cluster_not_running(self):
167+
appointment = self.create_appointment_for_user2()
168+
with patch('appointment.settings.check_q_cluster', return_value=False), \
169+
patch('appointment.utils.db_helpers.logger') as mock_logger:
170+
schedule_email_reminder(appointment)
171+
mock_logger.warning.assert_called_with(
172+
"Django-Q cluster is not running. Email reminder will not be scheduled.")
173+
174+
175+
class UpdateAppointmentReminderTest(BaseTest):
176+
def test_update_appointment_reminder_date_time_changed(self):
177+
appointment = self.create_appointment_for_user1()
178+
new_date = timezone.now().date() + timezone.timedelta(days=10)
179+
new_start_time = timezone.now().time()
180+
181+
with patch('appointment.utils.db_helpers.schedule_email_reminder') as mock_schedule_email_reminder, \
182+
patch('appointment.utils.db_helpers.cancel_existing_reminder') as mock_cancel_existing_reminder:
183+
update_appointment_reminder(appointment, new_date, new_start_time, True)
184+
mock_cancel_existing_reminder.assert_called_once_with(appointment.id_request)
185+
mock_schedule_email_reminder.assert_called_once()
186+
187+
def test_update_appointment_reminder_no_change(self):
188+
appointment = self.create_appointment_for_user2()
189+
# Use existing date and time
190+
new_date = appointment.appointment_request.date
191+
new_start_time = appointment.appointment_request.start_time
192+
193+
with patch('appointment.utils.db_helpers.schedule_email_reminder') as mock_schedule_email_reminder, \
194+
patch('appointment.utils.db_helpers.cancel_existing_reminder') as mock_cancel_existing_reminder:
195+
update_appointment_reminder(appointment, new_date, new_start_time, appointment.want_reminder)
196+
mock_cancel_existing_reminder.assert_not_called()
197+
mock_schedule_email_reminder.assert_not_called()
198+
199+
200+
class CancelExistingReminderTest(BaseTest):
201+
def test_cancel_existing_reminder(self):
202+
appointment = self.create_appointment_for_user1()
203+
Schedule.objects.create(func='appointment.tasks.send_email_reminder', name=f"reminder_{appointment.id_request}")
204+
205+
self.assertEqual(Schedule.objects.count(), 1)
206+
cancel_existing_reminder(appointment.id_request)
207+
self.assertEqual(Schedule.objects.filter(name=f"reminder_{appointment.id_request}").count(), 0)
208+
209+
152210
class TestCreatePaymentInfoAndGetUrl(BaseTest):
153211

154212
def setUp(self):
@@ -786,4 +844,3 @@ def test_create_new_user_check_password(self):
786844
user = create_new_user(client_data)
787845
password = f"{get_website_name()}{get_current_year()}"
788846
self.assertTrue(user.check_password(password))
789-

0 commit comments

Comments
 (0)