2
2
# Path: appointment/tests/utils/test_db_helpers.py
3
3
4
4
import datetime
5
+ from unittest import skip
5
6
from unittest .mock import MagicMock , PropertyMock , patch
6
7
7
8
from django .apps import apps
12
13
from django .test .client import RequestFactory
13
14
from django .urls import reverse
14
15
from django .utils import timezone
15
- from django_q .models import Schedule
16
16
17
+ from appointment .logger_config import get_logger
17
18
from appointment .models import Config , DayOff , PaymentInfo
18
19
from appointment .tests .base .base_test import BaseTest
19
20
from appointment .tests .mixins .base_mixin import ConfigMixin
31
32
staff_change_allowed_on_reschedule , update_appointment_reminder , username_in_user_model , working_hours_exist
32
33
)
33
34
35
+ logger = get_logger (__name__ )
36
+
37
+ # Check if django-q is installed in settings
38
+ DJANGO_Q_AVAILABLE = 'django_q' in settings .INSTALLED_APPS
39
+
40
+ # Check if django-q is installed as a dependency
41
+ try :
42
+ from django_q .models import Schedule
43
+ from django_q .tasks import schedule
44
+
45
+ DJANGO_Q_AVAILABLE = True
46
+ except ImportError :
47
+ DJANGO_Q_AVAILABLE = False
48
+ Schedule = None
49
+ schedule = None
50
+
51
+
52
+ @skip ("Django-Q is not available" )
53
+ class DjangoQUnavailableTest (TestCase ):
54
+ def test_placeholder (self ):
55
+ self .skipTest ("Django-Q is not available" )
56
+
34
57
35
58
class TestCalculateSlots (TestCase ):
36
59
def setUp (self ):
@@ -165,18 +188,12 @@ def test_another_staff_member_no_day_off(self):
165
188
self .assertFalse (check_day_off_for_staff (self .staff_member2 , "2023-10-06" ))
166
189
167
190
168
- class TestCreateAndSaveAppointment (BaseTest ):
169
-
191
+ class TestCreateAndSaveAppointment (BaseTest , TestCase ):
170
192
def setUp (self ):
171
- super ().setUp () # Call the parent class setup
172
- # Specific setups for this test class
173
- self .ar = self .create_appt_request_for_sm1 ()
193
+ super ().setUp ()
174
194
self .factory = RequestFactory ()
175
195
self .request = self .factory .get ('/' )
176
-
177
- def tearDown (self ):
178
- Appointment .objects .all ().delete ()
179
- AppointmentRequest .objects .all ().delete ()
196
+ self .ar = self .create_appt_request_for_sm1 ()
180
197
181
198
def test_create_and_save_appointment (self ):
182
199
client_data = {
@@ -190,7 +207,8 @@ def test_create_and_save_appointment(self):
190
207
'additional_info' : 'Please bring a Zat gun.'
191
208
}
192
209
193
- appointment = create_and_save_appointment (self .ar , client_data , appointment_data , self .request )
210
+ with patch ('appointment.utils.db_helpers.schedule_email_reminder' ) as mock_schedule_reminder :
211
+ appointment = create_and_save_appointment (self .ar , client_data , appointment_data , self .request )
194
212
195
213
self .assertIsNotNone (appointment )
196
214
self .assertEqual (appointment .client .email , client_data ['email' ])
@@ -199,6 +217,32 @@ def test_create_and_save_appointment(self):
199
217
self .assertEqual (appointment .address , appointment_data ['address' ])
200
218
self .assertEqual (appointment .additional_info , appointment_data ['additional_info' ])
201
219
220
+ if DJANGO_Q_AVAILABLE :
221
+ mock_schedule_reminder .assert_called_once ()
222
+ else :
223
+ mock_schedule_reminder .assert_not_called ()
224
+
225
+ @patch ('appointment.utils.db_helpers.DJANGO_Q_AVAILABLE' , False )
226
+ def test_create_and_save_appointment_without_django_q (self ):
227
+ client_data = {
228
+
229
+ 'name' : 'samantha.carter' ,
230
+ }
231
+ appointment_data = {
232
+ 'phone' : '987654321' ,
233
+ 'want_reminder' : True ,
234
+ 'address' : '456, SGC, Colorado Springs, USA' ,
235
+ 'additional_info' : 'Bring naquadah generator.'
236
+ }
237
+
238
+ with patch ('appointment.utils.db_helpers.logger.warning' ) as mock_logger_warning :
239
+ appointment = create_and_save_appointment (self .ar , client_data , appointment_data , self .request )
240
+
241
+ self .assertIsNotNone (appointment )
242
+ self .assertEqual (appointment .client .email , client_data ['email' ])
243
+ mock_logger_warning .assert_called_with (
244
+ f"Email reminder requested for appointment { appointment .id } , but django-q is not available." )
245
+
202
246
203
247
def get_mock_reverse (url_name , ** kwargs ):
204
248
"""A mocked version of the reverse function."""
@@ -208,6 +252,13 @@ def get_mock_reverse(url_name, **kwargs):
208
252
209
253
210
254
class ScheduleEmailReminderTest (BaseTest ):
255
+ @classmethod
256
+ def setUpClass (cls ):
257
+ if not DJANGO_Q_AVAILABLE :
258
+ import unittest
259
+ raise unittest .SkipTest ("Django-Q is not available" )
260
+ super ().setUpClass ()
261
+
211
262
def setUp (self ):
212
263
super ().setUp ()
213
264
self .factory = RequestFactory ()
@@ -217,6 +268,7 @@ def setUp(self):
217
268
def tearDown (self ):
218
269
Appointment .objects .all ().delete ()
219
270
AppointmentRequest .objects .all ().delete ()
271
+ super ().tearDown ()
220
272
221
273
def test_schedule_email_reminder_cluster_running (self ):
222
274
with patch ('appointment.settings.check_q_cluster' , return_value = True ), \
@@ -233,7 +285,14 @@ def test_schedule_email_reminder_cluster_not_running(self):
233
285
"Django-Q cluster is not running. Email reminder will not be scheduled." )
234
286
235
287
236
- class UpdateAppointmentReminderTest (BaseTest ):
288
+ class UpdateAppointmentReminderTest (BaseTest , TestCase ):
289
+ @classmethod
290
+ def setUpClass (cls ):
291
+ if not DJANGO_Q_AVAILABLE :
292
+ import unittest
293
+ raise unittest .SkipTest ("Django-Q is not available" )
294
+ super ().setUpClass ()
295
+
237
296
def setUp (self ):
238
297
super ().setUp ()
239
298
self .factory = RequestFactory ()
@@ -243,6 +302,7 @@ def setUp(self):
243
302
def tearDown (self ):
244
303
Appointment .objects .all ().delete ()
245
304
AppointmentRequest .objects .all ().delete ()
305
+ super ().tearDown ()
246
306
247
307
def test_update_appointment_reminder_date_time_changed (self ):
248
308
appointment = self .create_appt_for_sm1 ()
@@ -267,7 +327,7 @@ def test_update_appointment_reminder_no_change(self):
267
327
mock_cancel_existing_reminder .assert_not_called ()
268
328
mock_schedule_email_reminder .assert_not_called ()
269
329
270
- @patch ('appointment.utils.db_helpers.logger' ) # Adjust the import path as necessary
330
+ @patch ('appointment.utils.db_helpers.logger' )
271
331
def test_reminder_not_scheduled_due_to_user_preference (self , mock_logger ):
272
332
# Scenario where user does not want a reminder
273
333
want_reminder = False
@@ -281,7 +341,7 @@ def test_reminder_not_scheduled_due_to_user_preference(self, mock_logger):
281
341
f"Reminder for appointment { self .appointment .id } is not scheduled per user's preference or past datetime."
282
342
)
283
343
284
- @patch ('appointment.utils.db_helpers.logger' ) # Adjust the import path as necessary
344
+ @patch ('appointment.utils.db_helpers.logger' )
285
345
def test_reminder_not_scheduled_due_to_past_datetime (self , mock_logger ):
286
346
# Scenario where the new datetime is in the past
287
347
want_reminder = True
@@ -371,6 +431,8 @@ def test_staff_change_not_allowed(self, mock_config_first):
371
431
372
432
class CancelExistingReminderTest (BaseTest ):
373
433
def test_cancel_existing_reminder (self ):
434
+ if not DJANGO_Q_AVAILABLE :
435
+ return
374
436
appointment = self .create_appt_for_sm1 ()
375
437
Schedule .objects .create (func = 'appointment.tasks.send_email_reminder' , name = f"reminder_{ appointment .id_request } " )
376
438
0 commit comments