django-cfg 1.1.61__py3-none-any.whl → 1.1.63__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_cfg/__init__.py +1 -1
- django_cfg/management/commands/rundramatiq.py +174 -202
- django_cfg/modules/django_tasks.py +54 -428
- django_cfg/modules/dramatiq_setup.py +16 -0
- {django_cfg-1.1.61.dist-info → django_cfg-1.1.63.dist-info}/METADATA +145 -4
- {django_cfg-1.1.61.dist-info → django_cfg-1.1.63.dist-info}/RECORD +9 -27
- django_cfg/apps/accounts/tests/__init__.py +0 -1
- django_cfg/apps/accounts/tests/test_models.py +0 -412
- django_cfg/apps/accounts/tests/test_otp_views.py +0 -143
- django_cfg/apps/accounts/tests/test_serializers.py +0 -331
- django_cfg/apps/accounts/tests/test_services.py +0 -401
- django_cfg/apps/accounts/tests/test_signals.py +0 -110
- django_cfg/apps/accounts/tests/test_views.py +0 -255
- django_cfg/apps/newsletter/tests/__init__.py +0 -1
- django_cfg/apps/newsletter/tests/run_tests.py +0 -47
- django_cfg/apps/newsletter/tests/test_email_integration.py +0 -256
- django_cfg/apps/newsletter/tests/test_email_tracking.py +0 -332
- django_cfg/apps/newsletter/tests/test_newsletter_manager.py +0 -83
- django_cfg/apps/newsletter/tests/test_newsletter_models.py +0 -157
- django_cfg/apps/support/tests/__init__.py +0 -0
- django_cfg/apps/support/tests/test_models.py +0 -106
- django_cfg/apps/tasks/@docs/CONFIGURATION.md +0 -663
- django_cfg/apps/tasks/@docs/README.md +0 -195
- django_cfg/apps/tasks/@docs/TASKS_QUEUES.md +0 -423
- django_cfg/apps/tasks/@docs/TROUBLESHOOTING.md +0 -506
- {django_cfg-1.1.61.dist-info → django_cfg-1.1.63.dist-info}/WHEEL +0 -0
- {django_cfg-1.1.61.dist-info → django_cfg-1.1.63.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.1.61.dist-info → django_cfg-1.1.63.dist-info}/licenses/LICENSE +0 -0
@@ -1,401 +0,0 @@
|
|
1
|
-
from django.test import TestCase
|
2
|
-
from django.contrib.auth import get_user_model
|
3
|
-
from django.utils import timezone
|
4
|
-
from unittest.mock import patch
|
5
|
-
from datetime import timedelta
|
6
|
-
|
7
|
-
from ..services import OTPService
|
8
|
-
from ..models import OTPSecret, RegistrationSource, UserRegistrationSource
|
9
|
-
|
10
|
-
User = get_user_model()
|
11
|
-
|
12
|
-
|
13
|
-
class OTPServiceTest(TestCase):
|
14
|
-
"""Test OTPService."""
|
15
|
-
|
16
|
-
def setUp(self):
|
17
|
-
self.email = "test@example.com"
|
18
|
-
self.source_url = "https://reforms.ai"
|
19
|
-
|
20
|
-
@patch("django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_otp_notification")
|
21
|
-
def test_request_otp_new_user(self, mock_email):
|
22
|
-
"""Test OTP request for new user."""
|
23
|
-
mock_email.return_value = True
|
24
|
-
|
25
|
-
success, error_type = OTPService.request_email_otp(self.email)
|
26
|
-
|
27
|
-
self.assertTrue(success)
|
28
|
-
self.assertEqual(error_type, "success")
|
29
|
-
|
30
|
-
# User should be created
|
31
|
-
user = User.objects.get(email=self.email)
|
32
|
-
self.assertIsNotNone(user)
|
33
|
-
|
34
|
-
# OTP should be created
|
35
|
-
otp = OTPSecret.objects.get(recipient=self.email, channel_type='email')
|
36
|
-
self.assertIsNotNone(otp)
|
37
|
-
self.assertEqual(len(otp.secret), 6)
|
38
|
-
self.assertTrue(otp.secret.isdigit())
|
39
|
-
|
40
|
-
# OTP notification should be sent
|
41
|
-
mock_email.assert_called_once()
|
42
|
-
|
43
|
-
@patch("django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_otp_notification")
|
44
|
-
def test_request_otp_new_user_with_source_url(self, mock_email):
|
45
|
-
"""Test OTP request for new user with source_url."""
|
46
|
-
mock_email.return_value = True
|
47
|
-
|
48
|
-
success, error_type = OTPService.request_email_otp(self.email, self.source_url)
|
49
|
-
|
50
|
-
self.assertTrue(success)
|
51
|
-
self.assertEqual(error_type, "success")
|
52
|
-
|
53
|
-
# User should be created
|
54
|
-
user = User.objects.get(email=self.email)
|
55
|
-
self.assertIsNotNone(user)
|
56
|
-
|
57
|
-
# Source should be created
|
58
|
-
source = RegistrationSource.objects.get(url=self.source_url)
|
59
|
-
self.assertIsNotNone(source)
|
60
|
-
self.assertEqual(source.name, "reforms.ai")
|
61
|
-
|
62
|
-
# User-source relationship should be created
|
63
|
-
user_source = UserRegistrationSource.objects.get(user=user, source=source)
|
64
|
-
self.assertIsNotNone(user_source)
|
65
|
-
self.assertTrue(user_source.first_registration)
|
66
|
-
|
67
|
-
# OTP should be created
|
68
|
-
otp = OTPSecret.objects.get(recipient=self.email, channel_type='email')
|
69
|
-
self.assertIsNotNone(otp)
|
70
|
-
|
71
|
-
@patch("django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_otp_notification")
|
72
|
-
def test_request_otp_existing_user(self, mock_email):
|
73
|
-
"""Test OTP request for existing user."""
|
74
|
-
mock_email.return_value = True
|
75
|
-
|
76
|
-
# Create existing user
|
77
|
-
User.objects.create_user(email=self.email, username="existing_user")
|
78
|
-
|
79
|
-
success, error_type = OTPService.request_email_otp(self.email)
|
80
|
-
|
81
|
-
self.assertTrue(success)
|
82
|
-
self.assertEqual(error_type, "success")
|
83
|
-
|
84
|
-
# Should not create duplicate user
|
85
|
-
users = User.objects.filter(email=self.email)
|
86
|
-
self.assertEqual(users.count(), 1)
|
87
|
-
|
88
|
-
@patch("django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_otp_notification")
|
89
|
-
def test_request_otp_existing_user_with_source_url(self, mock_email):
|
90
|
-
"""Test OTP request for existing user with source_url."""
|
91
|
-
mock_email.return_value = True
|
92
|
-
|
93
|
-
# Create existing user
|
94
|
-
user = User.objects.create_user(email=self.email, username="existing_user")
|
95
|
-
|
96
|
-
success, error_type = OTPService.request_email_otp(self.email, self.source_url)
|
97
|
-
|
98
|
-
self.assertTrue(success)
|
99
|
-
self.assertEqual(error_type, "success")
|
100
|
-
|
101
|
-
# Source should be created
|
102
|
-
source = RegistrationSource.objects.get(url=self.source_url)
|
103
|
-
self.assertIsNotNone(source)
|
104
|
-
|
105
|
-
# User-source relationship should be created
|
106
|
-
user_source = UserRegistrationSource.objects.get(user=user, source=source)
|
107
|
-
self.assertIsNotNone(user_source)
|
108
|
-
self.assertFalse(user_source.first_registration) # Not first registration
|
109
|
-
|
110
|
-
@patch("django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_otp_notification")
|
111
|
-
def test_request_otp_reuse_active(self, mock_email):
|
112
|
-
"""Test OTP request reuses active OTP."""
|
113
|
-
mock_email.return_value = True
|
114
|
-
|
115
|
-
# Create existing OTP with known secret
|
116
|
-
existing_otp = OTPSecret.create_for_email(self.email)
|
117
|
-
existing_secret = existing_otp.secret
|
118
|
-
|
119
|
-
success, error_type = OTPService.request_email_otp(self.email)
|
120
|
-
|
121
|
-
self.assertTrue(success)
|
122
|
-
self.assertEqual(error_type, "success")
|
123
|
-
|
124
|
-
# Should reuse existing OTP
|
125
|
-
otp_count = OTPSecret.objects.filter(recipient=self.email, channel_type='email').count()
|
126
|
-
self.assertEqual(otp_count, 1)
|
127
|
-
|
128
|
-
# Should use existing secret
|
129
|
-
otp = OTPSecret.objects.get(recipient=self.email, channel_type='email')
|
130
|
-
self.assertEqual(otp.secret, existing_secret)
|
131
|
-
|
132
|
-
@patch("django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_otp_notification")
|
133
|
-
def test_request_otp_email_failure(self, mock_email):
|
134
|
-
"""Test OTP request when email fails."""
|
135
|
-
mock_email.side_effect = Exception("Email service error")
|
136
|
-
|
137
|
-
success, error_type = OTPService.request_email_otp(self.email)
|
138
|
-
|
139
|
-
self.assertFalse(success)
|
140
|
-
self.assertEqual(error_type, "email_send_failed")
|
141
|
-
|
142
|
-
def test_request_otp_invalid_email(self):
|
143
|
-
"""Test OTP request with invalid email."""
|
144
|
-
success, error_type = OTPService.request_email_otp("")
|
145
|
-
|
146
|
-
self.assertFalse(success)
|
147
|
-
self.assertEqual(error_type, "invalid_email")
|
148
|
-
|
149
|
-
def test_verify_otp_success(self):
|
150
|
-
"""Test successful OTP verification."""
|
151
|
-
# Create user and OTP
|
152
|
-
user = User.objects.create_user(email=self.email, username="testuser")
|
153
|
-
otp = OTPSecret.create_for_email(self.email)
|
154
|
-
otp.secret = "123456" # Set known secret for test
|
155
|
-
otp.save()
|
156
|
-
|
157
|
-
# Verify OTP
|
158
|
-
result_user = OTPService.verify_email_otp(self.email, "123456")
|
159
|
-
|
160
|
-
self.assertIsNotNone(result_user)
|
161
|
-
self.assertEqual(result_user, user)
|
162
|
-
|
163
|
-
# OTP should be marked as used
|
164
|
-
otp.refresh_from_db()
|
165
|
-
self.assertTrue(otp.is_used)
|
166
|
-
|
167
|
-
def test_verify_otp_success_with_source_url(self):
|
168
|
-
"""Test successful OTP verification with source_url."""
|
169
|
-
# Create user and OTP
|
170
|
-
user = User.objects.create_user(email=self.email, username="testuser")
|
171
|
-
otp = OTPSecret.create_for_email(self.email)
|
172
|
-
otp.secret = "123456" # Set known secret for test
|
173
|
-
otp.save()
|
174
|
-
|
175
|
-
# Verify OTP with source_url
|
176
|
-
result_user = OTPService.verify_email_otp(self.email, "123456", self.source_url)
|
177
|
-
|
178
|
-
self.assertIsNotNone(result_user)
|
179
|
-
self.assertEqual(result_user, user)
|
180
|
-
|
181
|
-
# Source should be created
|
182
|
-
source = RegistrationSource.objects.get(url=self.source_url)
|
183
|
-
self.assertIsNotNone(source)
|
184
|
-
|
185
|
-
# User-source relationship should be created
|
186
|
-
user_source = UserRegistrationSource.objects.get(user=user, source=source)
|
187
|
-
self.assertIsNotNone(user_source)
|
188
|
-
self.assertFalse(user_source.first_registration) # Not first registration
|
189
|
-
|
190
|
-
def test_verify_otp_invalid_code(self):
|
191
|
-
"""Test OTP verification with invalid code."""
|
192
|
-
# Create user and OTP
|
193
|
-
User.objects.create_user(email=self.email, username="testuser")
|
194
|
-
otp = OTPSecret.create_for_email(self.email)
|
195
|
-
otp.secret = "123456" # Set known secret for test
|
196
|
-
otp.save()
|
197
|
-
|
198
|
-
# Try to verify with wrong code
|
199
|
-
result_user = OTPService.verify_email_otp(self.email, "654321")
|
200
|
-
|
201
|
-
self.assertIsNone(result_user)
|
202
|
-
|
203
|
-
def test_verify_otp_expired(self):
|
204
|
-
"""Test OTP verification with expired OTP."""
|
205
|
-
# Create user and expired OTP
|
206
|
-
User.objects.create_user(email=self.email, username="testuser")
|
207
|
-
expired_time = timezone.now() - timedelta(minutes=11)
|
208
|
-
otp = OTPSecret.create_for_email(self.email)
|
209
|
-
otp.secret = "123456" # Set known secret for test
|
210
|
-
otp.expires_at = expired_time
|
211
|
-
otp.save()
|
212
|
-
|
213
|
-
# Try to verify expired OTP
|
214
|
-
result_user = OTPService.verify_email_otp(self.email, "123456")
|
215
|
-
|
216
|
-
self.assertIsNone(result_user)
|
217
|
-
|
218
|
-
def test_verify_otp_used(self):
|
219
|
-
"""Test OTP verification with used OTP."""
|
220
|
-
# Create user and used OTP
|
221
|
-
User.objects.create_user(email=self.email, username="testuser")
|
222
|
-
otp = OTPSecret.create_for_email(self.email)
|
223
|
-
otp.secret = "123456" # Set known secret for test
|
224
|
-
otp.is_used = True
|
225
|
-
otp.save()
|
226
|
-
|
227
|
-
# Try to verify used OTP
|
228
|
-
result_user = OTPService.verify_email_otp(self.email, "123456")
|
229
|
-
|
230
|
-
self.assertIsNone(result_user)
|
231
|
-
|
232
|
-
def test_verify_otp_no_user(self):
|
233
|
-
"""Test OTP verification when user doesn't exist."""
|
234
|
-
# Create OTP but no user
|
235
|
-
otp = OTPSecret.create_for_email(self.email)
|
236
|
-
otp.secret = "123456" # Set known secret for test
|
237
|
-
otp.save()
|
238
|
-
|
239
|
-
# Try to verify OTP
|
240
|
-
result_user = OTPService.verify_email_otp(self.email, "123456")
|
241
|
-
|
242
|
-
self.assertIsNone(result_user)
|
243
|
-
|
244
|
-
def test_verify_otp_invalid_input(self):
|
245
|
-
"""Test OTP verification with invalid input."""
|
246
|
-
# Test with empty email
|
247
|
-
result_user = OTPService.verify_email_otp("", "123456")
|
248
|
-
self.assertIsNone(result_user)
|
249
|
-
|
250
|
-
# Test with empty OTP
|
251
|
-
result_user = OTPService.verify_email_otp(self.email, "")
|
252
|
-
self.assertIsNone(result_user)
|
253
|
-
|
254
|
-
# Test with None values
|
255
|
-
result_user = OTPService.verify_email_otp(None, "123456")
|
256
|
-
self.assertIsNone(result_user)
|
257
|
-
|
258
|
-
result_user = OTPService.verify_email_otp(self.email, None)
|
259
|
-
self.assertIsNone(result_user)
|
260
|
-
|
261
|
-
|
262
|
-
class PhoneOTPServiceTest(TestCase):
|
263
|
-
"""Test Phone OTP Service functionality."""
|
264
|
-
|
265
|
-
def setUp(self):
|
266
|
-
self.phone = "+1234567890"
|
267
|
-
self.email = "test@example.com"
|
268
|
-
|
269
|
-
@patch("django_cfg.apps.accounts.services.otp_service.send_whatsapp_otp")
|
270
|
-
def test_request_phone_otp_new_user(self, mock_whatsapp_otp):
|
271
|
-
"""Test phone OTP request for new user."""
|
272
|
-
mock_whatsapp_otp.return_value = (True, "OTP sent successfully")
|
273
|
-
|
274
|
-
success, error_type = OTPService.request_phone_otp(self.phone)
|
275
|
-
|
276
|
-
self.assertTrue(success)
|
277
|
-
self.assertEqual(error_type, "success")
|
278
|
-
|
279
|
-
# User should be created with temp email
|
280
|
-
users = User.objects.filter(phone=self.phone)
|
281
|
-
self.assertEqual(users.count(), 1)
|
282
|
-
user = users.first()
|
283
|
-
self.assertIsNotNone(user)
|
284
|
-
self.assertTrue(user.email.startswith("phone_"))
|
285
|
-
|
286
|
-
# OTP should be created for phone
|
287
|
-
otp = OTPSecret.objects.get(recipient=self.phone, channel_type='phone')
|
288
|
-
self.assertIsNotNone(otp)
|
289
|
-
self.assertEqual(len(otp.secret), 6)
|
290
|
-
self.assertTrue(otp.secret.isdigit())
|
291
|
-
self.assertEqual(otp.channel_type, 'phone') # Phone channel
|
292
|
-
|
293
|
-
# WhatsApp OTP should be sent
|
294
|
-
mock_whatsapp_otp.assert_called_once()
|
295
|
-
|
296
|
-
@patch("django_cfg.apps.accounts.services.otp_service.send_whatsapp_otp")
|
297
|
-
def test_request_phone_otp_existing_user(self, mock_whatsapp_otp):
|
298
|
-
"""Test phone OTP request for existing user."""
|
299
|
-
mock_whatsapp_otp.return_value = (True, "OTP sent successfully")
|
300
|
-
|
301
|
-
# Create existing user with phone
|
302
|
-
User.objects.create_user(
|
303
|
-
email=self.email,
|
304
|
-
username="existing_user",
|
305
|
-
phone=self.phone
|
306
|
-
)
|
307
|
-
|
308
|
-
success, error_type = OTPService.request_phone_otp(self.phone)
|
309
|
-
|
310
|
-
self.assertTrue(success)
|
311
|
-
self.assertEqual(error_type, "success")
|
312
|
-
|
313
|
-
# Should not create duplicate user
|
314
|
-
users = User.objects.filter(phone=self.phone)
|
315
|
-
self.assertEqual(users.count(), 1)
|
316
|
-
|
317
|
-
def test_request_phone_otp_invalid_phone(self):
|
318
|
-
"""Test phone OTP request with invalid phone."""
|
319
|
-
success, error_type = OTPService.request_phone_otp("invalid-phone")
|
320
|
-
|
321
|
-
self.assertFalse(success)
|
322
|
-
self.assertEqual(error_type, "invalid_phone")
|
323
|
-
|
324
|
-
@patch("django_cfg.apps.accounts.services.otp_service.verify_otp")
|
325
|
-
def test_verify_phone_otp_success(self, mock_verify_otp):
|
326
|
-
"""Test successful phone OTP verification."""
|
327
|
-
mock_verify_otp.return_value = (True, "OTP verified successfully")
|
328
|
-
|
329
|
-
# Create user with phone
|
330
|
-
user = User.objects.create_user(
|
331
|
-
email=self.email,
|
332
|
-
username="testuser",
|
333
|
-
phone=self.phone
|
334
|
-
)
|
335
|
-
|
336
|
-
# Create phone OTP
|
337
|
-
otp = OTPSecret.create_for_phone(self.phone)
|
338
|
-
otp.secret = "123456" # Set known secret for test
|
339
|
-
otp.save()
|
340
|
-
|
341
|
-
# Verify OTP
|
342
|
-
result_user = OTPService.verify_phone_otp(self.phone, "123456")
|
343
|
-
|
344
|
-
self.assertIsNotNone(result_user)
|
345
|
-
self.assertEqual(result_user, user)
|
346
|
-
self.assertTrue(result_user.phone_verified) # Should mark phone as verified
|
347
|
-
|
348
|
-
# Mock verify_otp was called
|
349
|
-
mock_verify_otp.assert_called_once_with(self.phone, "123456")
|
350
|
-
|
351
|
-
@patch("django_cfg.apps.accounts.services.otp_service.verify_otp")
|
352
|
-
def test_verify_phone_otp_invalid_code(self, mock_verify_otp):
|
353
|
-
"""Test phone OTP verification with invalid code."""
|
354
|
-
mock_verify_otp.return_value = (False, "Invalid OTP code")
|
355
|
-
|
356
|
-
# Create user with phone
|
357
|
-
User.objects.create_user(
|
358
|
-
email=self.email,
|
359
|
-
username="testuser",
|
360
|
-
phone=self.phone
|
361
|
-
)
|
362
|
-
|
363
|
-
# Create phone OTP
|
364
|
-
otp = OTPSecret.create_for_phone(self.phone)
|
365
|
-
otp.secret = "123456" # Set known secret for test
|
366
|
-
otp.save()
|
367
|
-
|
368
|
-
# Try to verify with wrong code
|
369
|
-
result_user = OTPService.verify_phone_otp(self.phone, "654321")
|
370
|
-
|
371
|
-
self.assertIsNone(result_user)
|
372
|
-
|
373
|
-
def test_phone_validation(self):
|
374
|
-
"""Test phone number validation."""
|
375
|
-
from ..services.otp_service import OTPService
|
376
|
-
|
377
|
-
# Valid phones
|
378
|
-
self.assertTrue(OTPService._validate_phone("+1234567890"))
|
379
|
-
self.assertTrue(OTPService._validate_phone("+12345678901234"))
|
380
|
-
|
381
|
-
# Invalid phones
|
382
|
-
self.assertFalse(OTPService._validate_phone("1234567890")) # No +
|
383
|
-
self.assertFalse(OTPService._validate_phone("+0234567890")) # Starts with 0
|
384
|
-
self.assertFalse(OTPService._validate_phone("")) # Empty
|
385
|
-
self.assertFalse(OTPService._validate_phone("+12")) # Too short
|
386
|
-
|
387
|
-
def test_channel_detection(self):
|
388
|
-
"""Test automatic channel detection."""
|
389
|
-
from ..services.otp_service import OTPService
|
390
|
-
|
391
|
-
# Email detection
|
392
|
-
self.assertEqual(OTPService._determine_channel("test@example.com"), "email")
|
393
|
-
self.assertEqual(OTPService._determine_channel("user+tag@domain.co.uk"), "email")
|
394
|
-
|
395
|
-
# Phone detection
|
396
|
-
self.assertEqual(OTPService._determine_channel("+1234567890"), "phone")
|
397
|
-
self.assertEqual(OTPService._determine_channel("1234567890"), "phone")
|
398
|
-
self.assertEqual(OTPService._determine_channel("(555) 123-4567"), "phone")
|
399
|
-
|
400
|
-
# Default to email for unclear cases
|
401
|
-
self.assertEqual(OTPService._determine_channel("unclear"), "email")
|
@@ -1,110 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Tests for account signals and email notifications.
|
3
|
-
"""
|
4
|
-
|
5
|
-
import logging
|
6
|
-
from unittest.mock import patch, MagicMock
|
7
|
-
from django.test import TestCase
|
8
|
-
from django.contrib.auth import get_user_model
|
9
|
-
from django.utils import timezone
|
10
|
-
|
11
|
-
from django_cfg.apps.accounts.signals import trigger_login_notification
|
12
|
-
from django_cfg.apps.accounts.utils.notifications import AccountNotifications
|
13
|
-
|
14
|
-
User = get_user_model()
|
15
|
-
|
16
|
-
|
17
|
-
class AccountSignalsTestCase(TestCase):
|
18
|
-
"""Test cases for account signals."""
|
19
|
-
|
20
|
-
def setUp(self):
|
21
|
-
"""Set up test data."""
|
22
|
-
self.user_data = {
|
23
|
-
"email": "test@example.com",
|
24
|
-
"username": "testuser",
|
25
|
-
"first_name": "Test",
|
26
|
-
"last_name": "User",
|
27
|
-
}
|
28
|
-
|
29
|
-
def test_user_registration_signal_disabled(self):
|
30
|
-
"""Test that welcome email is NOT sent automatically when new user is created."""
|
31
|
-
# This test verifies that the signal is disabled by checking that the signal function is commented out
|
32
|
-
|
33
|
-
# Read the signals.py file to verify the signal is disabled
|
34
|
-
import inspect
|
35
|
-
from django_cfg.apps.accounts import signals
|
36
|
-
|
37
|
-
# Get the source code of the signals module
|
38
|
-
source = inspect.getsource(signals)
|
39
|
-
|
40
|
-
# Check that send_user_registration_email is commented out
|
41
|
-
self.assertIn("# @receiver(post_save, sender=User)", source)
|
42
|
-
self.assertIn("# def send_user_registration_email", source)
|
43
|
-
|
44
|
-
print("✅ Welcome email signal is properly disabled")
|
45
|
-
|
46
|
-
def test_user_profile_update_signal(self):
|
47
|
-
"""Test that security alert is sent when user profile is updated."""
|
48
|
-
with patch(
|
49
|
-
"django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_profile_update_notification"
|
50
|
-
) as mock_send_security:
|
51
|
-
user = User.objects.create(**self.user_data)
|
52
|
-
|
53
|
-
# Change email directly on the user object and save
|
54
|
-
user.email = "newemail@example.com"
|
55
|
-
user.save()
|
56
|
-
|
57
|
-
# Check that the signal was triggered
|
58
|
-
mock_send_security.assert_called()
|
59
|
-
args, kwargs = mock_send_security.call_args
|
60
|
-
# The second argument should be the changes list
|
61
|
-
self.assertIn("email address", args[1])
|
62
|
-
|
63
|
-
def test_signal_error_handling(self):
|
64
|
-
"""Test that signals handle errors gracefully."""
|
65
|
-
with patch(
|
66
|
-
"django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_profile_update_notification",
|
67
|
-
side_effect=Exception("Email service error"),
|
68
|
-
):
|
69
|
-
user = User.objects.create(**self.user_data)
|
70
|
-
# Change profile to trigger signal
|
71
|
-
user.email = "newemail@example.com"
|
72
|
-
user.save()
|
73
|
-
# Test passes if no exception is raised
|
74
|
-
|
75
|
-
def test_multiple_profile_changes(self):
|
76
|
-
"""Test that security alert is sent for multiple profile changes."""
|
77
|
-
with patch(
|
78
|
-
"django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_profile_update_notification"
|
79
|
-
) as mock_send:
|
80
|
-
user = User.objects.create(**self.user_data)
|
81
|
-
|
82
|
-
# Change multiple fields directly on the user object
|
83
|
-
user.email = "newemail@example.com"
|
84
|
-
user.username = "newusername"
|
85
|
-
user.first_name = "New"
|
86
|
-
user.save()
|
87
|
-
|
88
|
-
mock_send.assert_called()
|
89
|
-
args, kwargs = mock_send.call_args
|
90
|
-
# The second argument should be the changes list
|
91
|
-
changes_list = args[1]
|
92
|
-
self.assertIn("email address", changes_list)
|
93
|
-
self.assertIn("username", changes_list)
|
94
|
-
self.assertIn("name", changes_list)
|
95
|
-
|
96
|
-
def test_login_notification_signal(self):
|
97
|
-
"""Test that login notification is sent when user logs in."""
|
98
|
-
user = User.objects.create(**self.user_data)
|
99
|
-
|
100
|
-
with patch(
|
101
|
-
"django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_login_notification"
|
102
|
-
) as mock_send_login:
|
103
|
-
# Simulate login signal
|
104
|
-
trigger_login_notification(user=user, ip_address="127.0.0.1")
|
105
|
-
|
106
|
-
# Check that the signal was triggered
|
107
|
-
mock_send_login.assert_called()
|
108
|
-
args, kwargs = mock_send_login.call_args
|
109
|
-
# Check that the user is passed as first argument
|
110
|
-
self.assertEqual(args[0], user)
|