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,143 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Tests for OTP views with controlled welcome email notifications.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from django.test import TestCase
|
6
|
-
from django.contrib.auth import get_user_model
|
7
|
-
from django.urls import reverse
|
8
|
-
from django.utils import timezone
|
9
|
-
from unittest.mock import patch, MagicMock
|
10
|
-
from datetime import timedelta
|
11
|
-
from rest_framework.test import APIClient
|
12
|
-
from rest_framework import status
|
13
|
-
|
14
|
-
from ..models import OTPSecret
|
15
|
-
from ..utils.notifications import AccountNotifications
|
16
|
-
|
17
|
-
User = get_user_model()
|
18
|
-
|
19
|
-
|
20
|
-
class OTPViewWelcomeEmailTestCase(TestCase):
|
21
|
-
"""Test cases for controlled welcome email in OTP views."""
|
22
|
-
|
23
|
-
def setUp(self):
|
24
|
-
"""Set up test data."""
|
25
|
-
self.client = APIClient()
|
26
|
-
self.email = "test@example.com"
|
27
|
-
self.otp_code = "123456"
|
28
|
-
|
29
|
-
@patch("django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_welcome_email")
|
30
|
-
def test_welcome_email_sent_for_new_user(self, mock_welcome_email):
|
31
|
-
"""Test that welcome email is sent only for new users during OTP verification."""
|
32
|
-
# Create a new user (simulating recent registration)
|
33
|
-
user = User.objects.create_user(email=self.email, username="newuser")
|
34
|
-
|
35
|
-
# Create OTP for the user
|
36
|
-
otp = OTPSecret.create_for_email(self.email)
|
37
|
-
otp.secret = self.otp_code
|
38
|
-
otp.save()
|
39
|
-
|
40
|
-
# Mock the OTP verification to return the new user
|
41
|
-
with patch("django_cfg.apps.accounts.services.otp_service.OTPService.verify_email_otp") as mock_verify:
|
42
|
-
mock_verify.return_value = user
|
43
|
-
|
44
|
-
# Make OTP verification request
|
45
|
-
response = self.client.post(
|
46
|
-
reverse("cfg_accounts:otp-verify-otp"),
|
47
|
-
data={
|
48
|
-
"identifier": self.email,
|
49
|
-
"otp": self.otp_code,
|
50
|
-
},
|
51
|
-
format="json"
|
52
|
-
)
|
53
|
-
|
54
|
-
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
55
|
-
|
56
|
-
# Welcome email should be sent for new user
|
57
|
-
mock_welcome_email.assert_called_once_with(
|
58
|
-
user, send_email=True, send_telegram=False
|
59
|
-
)
|
60
|
-
|
61
|
-
@patch("django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_welcome_email")
|
62
|
-
def test_no_welcome_email_for_existing_user(self, mock_welcome_email):
|
63
|
-
"""Test that welcome email is NOT sent for existing users during OTP verification."""
|
64
|
-
# Create an existing user (older than 5 minutes)
|
65
|
-
old_time = timezone.now() - timedelta(minutes=10)
|
66
|
-
user = User.objects.create_user(email=self.email, username="olduser")
|
67
|
-
user.date_joined = old_time
|
68
|
-
user.save()
|
69
|
-
|
70
|
-
# Create OTP for the user
|
71
|
-
otp = OTPSecret.create_for_email(self.email)
|
72
|
-
otp.secret = self.otp_code
|
73
|
-
otp.save()
|
74
|
-
|
75
|
-
# Mock the OTP verification to return the existing user
|
76
|
-
with patch("django_cfg.apps.accounts.services.otp_service.OTPService.verify_email_otp") as mock_verify:
|
77
|
-
mock_verify.return_value = user
|
78
|
-
|
79
|
-
# Make OTP verification request
|
80
|
-
response = self.client.post(
|
81
|
-
reverse("cfg_accounts:otp-verify-otp"),
|
82
|
-
data={
|
83
|
-
"identifier": self.email,
|
84
|
-
"otp": self.otp_code,
|
85
|
-
},
|
86
|
-
format="json"
|
87
|
-
)
|
88
|
-
|
89
|
-
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
90
|
-
|
91
|
-
# Welcome email should NOT be sent for existing user
|
92
|
-
mock_welcome_email.assert_not_called()
|
93
|
-
|
94
|
-
@patch("django_cfg.apps.accounts.utils.notifications.AccountNotifications.send_welcome_email")
|
95
|
-
def test_welcome_email_error_handling(self, mock_welcome_email):
|
96
|
-
"""Test that OTP verification succeeds even if welcome email fails."""
|
97
|
-
# Create a new user
|
98
|
-
user = User.objects.create_user(email=self.email, username="newuser")
|
99
|
-
|
100
|
-
# Create OTP for the user
|
101
|
-
otp = OTPSecret.create_for_email(self.email)
|
102
|
-
otp.secret = self.otp_code
|
103
|
-
otp.save()
|
104
|
-
|
105
|
-
# Mock welcome email to raise an exception
|
106
|
-
mock_welcome_email.side_effect = Exception("Email service error")
|
107
|
-
|
108
|
-
# Mock the OTP verification to return the new user
|
109
|
-
with patch("django_cfg.apps.accounts.services.otp_service.OTPService.verify_email_otp") as mock_verify:
|
110
|
-
mock_verify.return_value = user
|
111
|
-
|
112
|
-
# Make OTP verification request
|
113
|
-
response = self.client.post(
|
114
|
-
reverse("cfg_accounts:otp-verify-otp"),
|
115
|
-
data={
|
116
|
-
"identifier": self.email,
|
117
|
-
"otp": self.otp_code,
|
118
|
-
},
|
119
|
-
format="json"
|
120
|
-
)
|
121
|
-
|
122
|
-
# OTP verification should still succeed
|
123
|
-
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
124
|
-
self.assertIn("access", response.data)
|
125
|
-
self.assertIn("refresh", response.data)
|
126
|
-
|
127
|
-
# Welcome email should have been attempted
|
128
|
-
mock_welcome_email.assert_called_once()
|
129
|
-
|
130
|
-
def test_integration_with_notifications_class(self):
|
131
|
-
"""Test integration with AccountNotifications class methods."""
|
132
|
-
# Create a user
|
133
|
-
user = User.objects.create_user(email=self.email, username="testuser")
|
134
|
-
|
135
|
-
# Test that AccountNotifications methods exist and are callable
|
136
|
-
self.assertTrue(hasattr(AccountNotifications, "send_welcome_email"))
|
137
|
-
self.assertTrue(hasattr(AccountNotifications, "send_otp_notification"))
|
138
|
-
self.assertTrue(hasattr(AccountNotifications, "send_otp_verification_success"))
|
139
|
-
|
140
|
-
# Test that methods are static
|
141
|
-
self.assertTrue(callable(AccountNotifications.send_welcome_email))
|
142
|
-
self.assertTrue(callable(AccountNotifications.send_otp_notification))
|
143
|
-
self.assertTrue(callable(AccountNotifications.send_otp_verification_success))
|
@@ -1,331 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from django.test import TestCase
|
3
|
-
from django.contrib.auth import get_user_model
|
4
|
-
from django_cfg.apps.accounts.serializers.profile import (
|
5
|
-
UserProfileUpdateSerializer,
|
6
|
-
RegistrationSourceSerializer,
|
7
|
-
UserRegistrationSourceSerializer,
|
8
|
-
UserWithSourcesSerializer,
|
9
|
-
)
|
10
|
-
from django_cfg.apps.accounts.serializers.otp import OTPRequestSerializer, OTPVerifySerializer
|
11
|
-
from django_cfg.apps.accounts.models import RegistrationSource, UserRegistrationSource
|
12
|
-
|
13
|
-
User = get_user_model()
|
14
|
-
|
15
|
-
# Disable Telegram notifications in tests
|
16
|
-
os.environ["TELEGRAM_DISABLED"] = "true"
|
17
|
-
|
18
|
-
|
19
|
-
class UserProfileUpdateSerializerTest(TestCase):
|
20
|
-
def setUp(self):
|
21
|
-
self.user = User.objects.create(
|
22
|
-
username="testuser",
|
23
|
-
email="test@example.com",
|
24
|
-
first_name="John",
|
25
|
-
last_name="Doe",
|
26
|
-
)
|
27
|
-
|
28
|
-
def test_valid_first_name_update(self):
|
29
|
-
"""Test valid first name update."""
|
30
|
-
data = {"first_name": "Jane"}
|
31
|
-
serializer = UserProfileUpdateSerializer(self.user, data=data, partial=True)
|
32
|
-
self.assertTrue(serializer.is_valid())
|
33
|
-
self.assertEqual(serializer.validated_data["first_name"], "Jane")
|
34
|
-
|
35
|
-
def test_first_name_too_short(self):
|
36
|
-
"""Test first name validation - too short."""
|
37
|
-
data = {"first_name": "J"}
|
38
|
-
serializer = UserProfileUpdateSerializer(self.user, data=data, partial=True)
|
39
|
-
self.assertFalse(serializer.is_valid())
|
40
|
-
self.assertIn("first_name", serializer.errors)
|
41
|
-
|
42
|
-
def test_valid_last_name_update(self):
|
43
|
-
"""Test valid last name update."""
|
44
|
-
data = {"last_name": "Smith"}
|
45
|
-
serializer = UserProfileUpdateSerializer(self.user, data=data, partial=True)
|
46
|
-
self.assertTrue(serializer.is_valid())
|
47
|
-
self.assertEqual(serializer.validated_data["last_name"], "Smith")
|
48
|
-
|
49
|
-
def test_last_name_too_short(self):
|
50
|
-
"""Test last name validation - too short."""
|
51
|
-
data = {"last_name": "S"}
|
52
|
-
serializer = UserProfileUpdateSerializer(self.user, data=data, partial=True)
|
53
|
-
self.assertFalse(serializer.is_valid())
|
54
|
-
self.assertIn("last_name", serializer.errors)
|
55
|
-
|
56
|
-
def test_valid_phone_update(self):
|
57
|
-
"""Test valid phone update."""
|
58
|
-
data = {"phone": "+1 (555) 123-4567"}
|
59
|
-
serializer = UserProfileUpdateSerializer(self.user, data=data, partial=True)
|
60
|
-
self.assertTrue(serializer.is_valid())
|
61
|
-
self.assertEqual(serializer.validated_data["phone"], "+1 (555) 123-4567")
|
62
|
-
|
63
|
-
def test_invalid_phone(self):
|
64
|
-
"""Test phone validation - invalid format."""
|
65
|
-
data = {"phone": "invalid-phone"}
|
66
|
-
serializer = UserProfileUpdateSerializer(self.user, data=data, partial=True)
|
67
|
-
self.assertFalse(serializer.is_valid())
|
68
|
-
self.assertIn("phone", serializer.errors)
|
69
|
-
|
70
|
-
def test_multiple_fields_update(self):
|
71
|
-
"""Test updating multiple fields at once."""
|
72
|
-
data = {
|
73
|
-
"first_name": "Jane",
|
74
|
-
"last_name": "Smith",
|
75
|
-
"company": "Tech Corp",
|
76
|
-
"position": "Developer",
|
77
|
-
}
|
78
|
-
serializer = UserProfileUpdateSerializer(self.user, data=data, partial=True)
|
79
|
-
self.assertTrue(serializer.is_valid())
|
80
|
-
self.assertEqual(serializer.validated_data["first_name"], "Jane")
|
81
|
-
self.assertEqual(serializer.validated_data["last_name"], "Smith")
|
82
|
-
self.assertEqual(serializer.validated_data["company"], "Tech Corp")
|
83
|
-
self.assertEqual(serializer.validated_data["position"], "Developer")
|
84
|
-
|
85
|
-
|
86
|
-
class RegistrationSourceSerializerTest(TestCase):
|
87
|
-
def setUp(self):
|
88
|
-
self.source = RegistrationSource.objects.create(
|
89
|
-
url="https://reforms.ai",
|
90
|
-
name="Unreal Dashboard",
|
91
|
-
description="Main dashboard for Unreal project",
|
92
|
-
is_active=True,
|
93
|
-
)
|
94
|
-
|
95
|
-
def test_source_serializer_fields(self):
|
96
|
-
"""Test RegistrationSource serializer includes all required fields."""
|
97
|
-
serializer = RegistrationSourceSerializer(self.source)
|
98
|
-
data = serializer.data
|
99
|
-
|
100
|
-
self.assertIn("id", data)
|
101
|
-
self.assertIn("url", data)
|
102
|
-
self.assertIn("name", data)
|
103
|
-
self.assertIn("description", data)
|
104
|
-
self.assertIn("is_active", data)
|
105
|
-
self.assertIn("created_at", data)
|
106
|
-
self.assertIn("updated_at", data)
|
107
|
-
|
108
|
-
self.assertEqual(data["url"], "https://reforms.ai")
|
109
|
-
self.assertEqual(data["name"], "Unreal Dashboard")
|
110
|
-
self.assertEqual(data["description"], "Main dashboard for Unreal project")
|
111
|
-
self.assertTrue(data["is_active"])
|
112
|
-
|
113
|
-
def test_source_serializer_validation(self):
|
114
|
-
"""Test RegistrationSource serializer validation."""
|
115
|
-
data = {
|
116
|
-
"url": "https://test.example.com",
|
117
|
-
"name": "Test Source",
|
118
|
-
"description": "Test description",
|
119
|
-
"is_active": True,
|
120
|
-
}
|
121
|
-
serializer = RegistrationSourceSerializer(data=data)
|
122
|
-
self.assertTrue(serializer.is_valid())
|
123
|
-
|
124
|
-
|
125
|
-
class UserRegistrationSourceSerializerTest(TestCase):
|
126
|
-
def setUp(self):
|
127
|
-
self.user = User.objects.create(username="testuser", email="test@example.com")
|
128
|
-
self.source = RegistrationSource.objects.create(
|
129
|
-
url="https://reforms.ai", name="Unreal Dashboard"
|
130
|
-
)
|
131
|
-
self.user_source = UserRegistrationSource.objects.create(
|
132
|
-
user=self.user, source=self.source, first_registration=True
|
133
|
-
)
|
134
|
-
|
135
|
-
def test_user_source_serializer_fields(self):
|
136
|
-
"""Test UserRegistrationSource serializer includes all required fields."""
|
137
|
-
serializer = UserRegistrationSourceSerializer(self.user_source)
|
138
|
-
data = serializer.data
|
139
|
-
|
140
|
-
self.assertIn("id", data)
|
141
|
-
self.assertIn("user", data)
|
142
|
-
self.assertIn("source", data)
|
143
|
-
self.assertIn("first_registration", data)
|
144
|
-
self.assertIn("registration_date", data)
|
145
|
-
|
146
|
-
self.assertEqual(data["user"], self.user.id)
|
147
|
-
self.assertTrue(data["first_registration"])
|
148
|
-
|
149
|
-
# Check nested source data
|
150
|
-
source_data = data["source"]
|
151
|
-
self.assertEqual(source_data["url"], "https://reforms.ai")
|
152
|
-
self.assertEqual(source_data["name"], "Unreal Dashboard")
|
153
|
-
|
154
|
-
def test_user_source_serializer_validation(self):
|
155
|
-
"""Test UserRegistrationSource serializer validation."""
|
156
|
-
data = {
|
157
|
-
"user": self.user.id,
|
158
|
-
"source": self.source.id,
|
159
|
-
"first_registration": False,
|
160
|
-
}
|
161
|
-
serializer = UserRegistrationSourceSerializer(data=data)
|
162
|
-
self.assertTrue(serializer.is_valid())
|
163
|
-
|
164
|
-
|
165
|
-
class UserWithSourcesSerializerTest(TestCase):
|
166
|
-
def setUp(self):
|
167
|
-
self.user = User.objects.create(
|
168
|
-
username="testuser",
|
169
|
-
email="test@example.com",
|
170
|
-
first_name="John",
|
171
|
-
last_name="Doe",
|
172
|
-
)
|
173
|
-
self.source1 = RegistrationSource.objects.create(
|
174
|
-
url="https://reforms.ai", name="Unreal Dashboard"
|
175
|
-
)
|
176
|
-
self.source2 = RegistrationSource.objects.create(
|
177
|
-
url="https://app.example.com", name="Example App"
|
178
|
-
)
|
179
|
-
self.user_source1 = UserRegistrationSource.objects.create(
|
180
|
-
user=self.user, source=self.source1, first_registration=True
|
181
|
-
)
|
182
|
-
self.user_source2 = UserRegistrationSource.objects.create(
|
183
|
-
user=self.user, source=self.source2, first_registration=False
|
184
|
-
)
|
185
|
-
|
186
|
-
def test_user_with_sources_serializer_fields(self):
|
187
|
-
"""Test UserWithSources serializer includes sources information."""
|
188
|
-
serializer = UserWithSourcesSerializer(self.user)
|
189
|
-
data = serializer.data
|
190
|
-
|
191
|
-
# Check basic user fields
|
192
|
-
self.assertIn("id", data)
|
193
|
-
self.assertIn("email", data)
|
194
|
-
self.assertIn("first_name", data)
|
195
|
-
self.assertIn("last_name", data)
|
196
|
-
|
197
|
-
# Check sources fields
|
198
|
-
self.assertIn("sources", data)
|
199
|
-
self.assertIn("primary_source", data)
|
200
|
-
|
201
|
-
# Check sources data
|
202
|
-
sources = data["sources"]
|
203
|
-
self.assertEqual(len(sources), 2)
|
204
|
-
|
205
|
-
# Check primary source
|
206
|
-
primary_source = data["primary_source"]
|
207
|
-
self.assertIsNotNone(primary_source)
|
208
|
-
self.assertEqual(primary_source["url"], "https://reforms.ai")
|
209
|
-
self.assertEqual(primary_source["name"], "Unreal Dashboard")
|
210
|
-
|
211
|
-
def test_user_with_sources_no_sources(self):
|
212
|
-
"""Test UserWithSources serializer for user without sources."""
|
213
|
-
user_without_sources = User.objects.create(
|
214
|
-
username="nosources", email="nosources@example.com"
|
215
|
-
)
|
216
|
-
serializer = UserWithSourcesSerializer(user_without_sources)
|
217
|
-
data = serializer.data
|
218
|
-
|
219
|
-
self.assertEqual(len(data["sources"]), 0)
|
220
|
-
self.assertIsNone(data["primary_source"])
|
221
|
-
|
222
|
-
|
223
|
-
class OTPRequestSerializerTest(TestCase):
|
224
|
-
def test_valid_otp_request(self):
|
225
|
-
"""Test valid OTP request with source_url."""
|
226
|
-
data = {
|
227
|
-
"email": "test@example.com",
|
228
|
-
"source_url": "https://reforms.ai",
|
229
|
-
}
|
230
|
-
serializer = OTPRequestSerializer(data=data)
|
231
|
-
self.assertTrue(serializer.is_valid())
|
232
|
-
self.assertEqual(serializer.validated_data["email"], "test@example.com")
|
233
|
-
self.assertEqual(
|
234
|
-
serializer.validated_data["source_url"], "https://reforms.ai"
|
235
|
-
)
|
236
|
-
|
237
|
-
def test_valid_otp_request_without_source_url(self):
|
238
|
-
"""Test valid OTP request without source_url."""
|
239
|
-
data = {"email": "test@example.com"}
|
240
|
-
serializer = OTPRequestSerializer(data=data)
|
241
|
-
self.assertTrue(serializer.is_valid())
|
242
|
-
self.assertEqual(serializer.validated_data["email"], "test@example.com")
|
243
|
-
self.assertNotIn("source_url", serializer.validated_data)
|
244
|
-
|
245
|
-
def test_valid_otp_request_empty_source_url(self):
|
246
|
-
"""Test valid OTP request with empty source_url."""
|
247
|
-
data = {"email": "test@example.com", "source_url": ""}
|
248
|
-
serializer = OTPRequestSerializer(data=data)
|
249
|
-
self.assertTrue(serializer.is_valid())
|
250
|
-
self.assertEqual(serializer.validated_data["email"], "test@example.com")
|
251
|
-
self.assertIsNone(serializer.validated_data.get("source_url"))
|
252
|
-
|
253
|
-
def test_invalid_email(self):
|
254
|
-
"""Test invalid email in OTP request."""
|
255
|
-
data = {
|
256
|
-
"email": "invalid-email",
|
257
|
-
"source_url": "https://reforms.ai",
|
258
|
-
}
|
259
|
-
serializer = OTPRequestSerializer(data=data)
|
260
|
-
self.assertFalse(serializer.is_valid())
|
261
|
-
self.assertIn("email", serializer.errors)
|
262
|
-
|
263
|
-
def test_missing_email(self):
|
264
|
-
"""Test missing email in OTP request."""
|
265
|
-
data = {"source_url": "https://reforms.ai"}
|
266
|
-
serializer = OTPRequestSerializer(data=data)
|
267
|
-
self.assertFalse(serializer.is_valid())
|
268
|
-
self.assertIn("email", serializer.errors)
|
269
|
-
|
270
|
-
def test_invalid_source_url(self):
|
271
|
-
"""Test invalid source_url in OTP request."""
|
272
|
-
data = {"email": "test@example.com", "source_url": "not-a-url"}
|
273
|
-
serializer = OTPRequestSerializer(data=data)
|
274
|
-
self.assertFalse(serializer.is_valid())
|
275
|
-
self.assertIn("source_url", serializer.errors)
|
276
|
-
|
277
|
-
|
278
|
-
class OTPVerifySerializerTest(TestCase):
|
279
|
-
def test_valid_otp_verify(self):
|
280
|
-
"""Test valid OTP verification with source_url."""
|
281
|
-
data = {
|
282
|
-
"email": "test@example.com",
|
283
|
-
"otp": "123456",
|
284
|
-
"source_url": "https://reforms.ai",
|
285
|
-
}
|
286
|
-
serializer = OTPVerifySerializer(data=data)
|
287
|
-
self.assertTrue(serializer.is_valid())
|
288
|
-
self.assertEqual(serializer.validated_data["email"], "test@example.com")
|
289
|
-
self.assertEqual(serializer.validated_data["otp"], "123456")
|
290
|
-
self.assertEqual(
|
291
|
-
serializer.validated_data["source_url"], "https://reforms.ai"
|
292
|
-
)
|
293
|
-
|
294
|
-
def test_valid_otp_verify_without_source_url(self):
|
295
|
-
"""Test valid OTP verification without source_url."""
|
296
|
-
data = {"email": "test@example.com", "otp": "123456"}
|
297
|
-
serializer = OTPVerifySerializer(data=data)
|
298
|
-
self.assertTrue(serializer.is_valid())
|
299
|
-
self.assertEqual(serializer.validated_data["email"], "test@example.com")
|
300
|
-
self.assertEqual(serializer.validated_data["otp"], "123456")
|
301
|
-
self.assertNotIn("source_url", serializer.validated_data)
|
302
|
-
|
303
|
-
def test_invalid_otp_format(self):
|
304
|
-
"""Test invalid OTP format."""
|
305
|
-
data = {
|
306
|
-
"email": "test@example.com",
|
307
|
-
"otp": "12345", # Too short
|
308
|
-
"source_url": "https://reforms.ai",
|
309
|
-
}
|
310
|
-
serializer = OTPVerifySerializer(data=data)
|
311
|
-
self.assertFalse(serializer.is_valid())
|
312
|
-
self.assertIn("otp", serializer.errors)
|
313
|
-
|
314
|
-
def test_invalid_otp_characters(self):
|
315
|
-
"""Test invalid OTP characters."""
|
316
|
-
data = {
|
317
|
-
"email": "test@example.com",
|
318
|
-
"otp": "12345a", # Contains letter
|
319
|
-
"source_url": "https://reforms.ai",
|
320
|
-
}
|
321
|
-
serializer = OTPVerifySerializer(data=data)
|
322
|
-
self.assertFalse(serializer.is_valid())
|
323
|
-
self.assertIn("otp", serializer.errors)
|
324
|
-
|
325
|
-
def test_missing_required_fields(self):
|
326
|
-
"""Test missing required fields."""
|
327
|
-
data = {"source_url": "https://reforms.ai"}
|
328
|
-
serializer = OTPVerifySerializer(data=data)
|
329
|
-
self.assertFalse(serializer.is_valid())
|
330
|
-
self.assertIn("email", serializer.errors)
|
331
|
-
self.assertIn("otp", serializer.errors)
|