django-cfg 1.1.61__py3-none-any.whl → 1.1.62__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.62.dist-info}/METADATA +1 -1
- {django_cfg-1.1.61.dist-info → django_cfg-1.1.62.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.62.dist-info}/WHEEL +0 -0
- {django_cfg-1.1.61.dist-info → django_cfg-1.1.62.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.1.61.dist-info → django_cfg-1.1.62.dist-info}/licenses/LICENSE +0 -0
@@ -1,332 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Tests for email tracking functionality.
|
3
|
-
"""
|
4
|
-
|
5
|
-
import uuid
|
6
|
-
from django.test import TestCase, Client
|
7
|
-
from django.contrib.auth import get_user_model
|
8
|
-
from django.urls import reverse
|
9
|
-
from django.utils import timezone
|
10
|
-
from unittest.mock import patch, MagicMock
|
11
|
-
|
12
|
-
from ..models import Newsletter, EmailLog, NewsletterSubscription, NewsletterCampaign
|
13
|
-
from ..services.email_service import NewsletterEmailService
|
14
|
-
|
15
|
-
User = get_user_model()
|
16
|
-
|
17
|
-
|
18
|
-
class EmailTrackingTestCase(TestCase):
|
19
|
-
"""Test cases for email tracking functionality"""
|
20
|
-
|
21
|
-
def setUp(self):
|
22
|
-
"""Set up test data"""
|
23
|
-
self.client = Client()
|
24
|
-
|
25
|
-
# Create test user
|
26
|
-
self.user = User.objects.create_user(
|
27
|
-
username='testuser',
|
28
|
-
email='test@example.com',
|
29
|
-
password='testpass123',
|
30
|
-
is_active=True
|
31
|
-
)
|
32
|
-
|
33
|
-
# Create test newsletter
|
34
|
-
self.newsletter = Newsletter.objects.create(
|
35
|
-
title='Test Newsletter',
|
36
|
-
description='Test newsletter content',
|
37
|
-
is_active=True
|
38
|
-
)
|
39
|
-
|
40
|
-
# Create email log
|
41
|
-
self.email_log = EmailLog.objects.create(
|
42
|
-
user=self.user,
|
43
|
-
newsletter=self.newsletter,
|
44
|
-
recipient='test@example.com',
|
45
|
-
subject='Test Subject',
|
46
|
-
body='<p>Test body</p>',
|
47
|
-
status=EmailLog.EmailLogStatus.SENT
|
48
|
-
)
|
49
|
-
|
50
|
-
def test_email_log_tracking_fields(self):
|
51
|
-
"""Test that email log has tracking fields"""
|
52
|
-
self.assertIsNone(self.email_log.opened_at)
|
53
|
-
self.assertIsNone(self.email_log.clicked_at)
|
54
|
-
self.assertFalse(self.email_log.is_opened)
|
55
|
-
self.assertFalse(self.email_log.is_clicked)
|
56
|
-
|
57
|
-
def test_mark_opened(self):
|
58
|
-
"""Test marking email as opened"""
|
59
|
-
# Initially not opened
|
60
|
-
self.assertFalse(self.email_log.is_opened)
|
61
|
-
self.assertIsNone(self.email_log.opened_at)
|
62
|
-
|
63
|
-
# Mark as opened
|
64
|
-
self.email_log.mark_opened()
|
65
|
-
|
66
|
-
# Check that it's marked as opened
|
67
|
-
self.assertTrue(self.email_log.is_opened)
|
68
|
-
self.assertIsNotNone(self.email_log.opened_at)
|
69
|
-
|
70
|
-
# Mark as opened again - should not change timestamp
|
71
|
-
original_opened_at = self.email_log.opened_at
|
72
|
-
self.email_log.mark_opened()
|
73
|
-
self.assertEqual(self.email_log.opened_at, original_opened_at)
|
74
|
-
|
75
|
-
def test_mark_clicked(self):
|
76
|
-
"""Test marking email link as clicked"""
|
77
|
-
# Initially not clicked
|
78
|
-
self.assertFalse(self.email_log.is_clicked)
|
79
|
-
self.assertIsNone(self.email_log.clicked_at)
|
80
|
-
|
81
|
-
# Mark as clicked
|
82
|
-
self.email_log.mark_clicked()
|
83
|
-
|
84
|
-
# Check that it's marked as clicked
|
85
|
-
self.assertTrue(self.email_log.is_clicked)
|
86
|
-
self.assertIsNotNone(self.email_log.clicked_at)
|
87
|
-
|
88
|
-
# Mark as clicked again - should not change timestamp
|
89
|
-
original_clicked_at = self.email_log.clicked_at
|
90
|
-
self.email_log.mark_clicked()
|
91
|
-
self.assertEqual(self.email_log.clicked_at, original_clicked_at)
|
92
|
-
|
93
|
-
def test_track_email_open_view(self):
|
94
|
-
"""Test email open tracking view"""
|
95
|
-
# Get tracking URL
|
96
|
-
url = reverse('cfg_newsletter:track-open', kwargs={'email_log_id': self.email_log.id})
|
97
|
-
|
98
|
-
# Make request to tracking pixel
|
99
|
-
response = self.client.get(url)
|
100
|
-
|
101
|
-
# Check response
|
102
|
-
self.assertEqual(response.status_code, 200)
|
103
|
-
self.assertEqual(response['Content-Type'], 'image/gif')
|
104
|
-
|
105
|
-
# Check that email log was marked as opened
|
106
|
-
self.email_log.refresh_from_db()
|
107
|
-
self.assertTrue(self.email_log.is_opened)
|
108
|
-
self.assertIsNotNone(self.email_log.opened_at)
|
109
|
-
|
110
|
-
def test_track_email_open_invalid_id(self):
|
111
|
-
"""Test email open tracking with invalid ID"""
|
112
|
-
# Use random UUID
|
113
|
-
invalid_id = uuid.uuid4()
|
114
|
-
url = reverse('cfg_newsletter:track-open', kwargs={'email_log_id': invalid_id})
|
115
|
-
|
116
|
-
# Make request - should still return pixel but not crash
|
117
|
-
response = self.client.get(url)
|
118
|
-
self.assertEqual(response.status_code, 200)
|
119
|
-
self.assertEqual(response['Content-Type'], 'image/gif')
|
120
|
-
|
121
|
-
def test_track_email_click_view(self):
|
122
|
-
"""Test email click tracking view"""
|
123
|
-
# Get tracking URL with redirect
|
124
|
-
redirect_url = 'https://example.com/target'
|
125
|
-
url = reverse('cfg_newsletter:track-click', kwargs={'email_log_id': self.email_log.id})
|
126
|
-
url += f'?url={redirect_url}'
|
127
|
-
|
128
|
-
# Make request to tracking URL
|
129
|
-
response = self.client.get(url)
|
130
|
-
|
131
|
-
# Check redirect response
|
132
|
-
self.assertEqual(response.status_code, 302)
|
133
|
-
self.assertEqual(response.url, redirect_url)
|
134
|
-
|
135
|
-
# Check that email log was marked as clicked
|
136
|
-
self.email_log.refresh_from_db()
|
137
|
-
self.assertTrue(self.email_log.is_clicked)
|
138
|
-
self.assertIsNotNone(self.email_log.clicked_at)
|
139
|
-
|
140
|
-
def test_track_email_click_no_url(self):
|
141
|
-
"""Test email click tracking without redirect URL"""
|
142
|
-
# Get tracking URL without redirect
|
143
|
-
url = reverse('cfg_newsletter:track-click', kwargs={'email_log_id': self.email_log.id})
|
144
|
-
|
145
|
-
# Make request to tracking URL
|
146
|
-
response = self.client.get(url)
|
147
|
-
|
148
|
-
# Check redirect to default URL
|
149
|
-
self.assertEqual(response.status_code, 302)
|
150
|
-
self.assertEqual(response.url, '/')
|
151
|
-
|
152
|
-
# Check that email log was marked as clicked
|
153
|
-
self.email_log.refresh_from_db()
|
154
|
-
self.assertTrue(self.email_log.is_clicked)
|
155
|
-
|
156
|
-
def test_track_email_click_invalid_id(self):
|
157
|
-
"""Test email click tracking with invalid ID"""
|
158
|
-
# Use random UUID
|
159
|
-
invalid_id = uuid.uuid4()
|
160
|
-
redirect_url = 'https://example.com/target'
|
161
|
-
url = reverse('cfg_newsletter:track-click', kwargs={'email_log_id': invalid_id})
|
162
|
-
url += f'?url={redirect_url}'
|
163
|
-
|
164
|
-
# Make request - should still redirect but not crash
|
165
|
-
response = self.client.get(url)
|
166
|
-
self.assertEqual(response.status_code, 302)
|
167
|
-
self.assertEqual(response.url, redirect_url)
|
168
|
-
|
169
|
-
|
170
|
-
class EmailServiceTrackingTestCase(TestCase):
|
171
|
-
"""Test cases for email service tracking integration"""
|
172
|
-
|
173
|
-
def setUp(self):
|
174
|
-
"""Set up test data"""
|
175
|
-
# Create test user
|
176
|
-
self.user = User.objects.create_user(
|
177
|
-
username='testuser',
|
178
|
-
email='test@example.com',
|
179
|
-
password='testpass123',
|
180
|
-
is_active=True
|
181
|
-
)
|
182
|
-
|
183
|
-
# Create newsletter subscription
|
184
|
-
self.newsletter = Newsletter.objects.create(
|
185
|
-
title='Test Newsletter Service',
|
186
|
-
description='Test newsletter content',
|
187
|
-
is_active=True
|
188
|
-
)
|
189
|
-
|
190
|
-
NewsletterSubscription.objects.create(
|
191
|
-
user=self.user,
|
192
|
-
newsletter=self.newsletter,
|
193
|
-
email=self.user.email,
|
194
|
-
is_active=True
|
195
|
-
)
|
196
|
-
|
197
|
-
self.email_service = NewsletterEmailService()
|
198
|
-
|
199
|
-
@patch('django_cfg.modules.django_email.DjangoEmailService.send_template_with_tracking')
|
200
|
-
def test_send_bulk_email_with_tracking(self, mock_send_tracking):
|
201
|
-
"""Test sending bulk email with tracking enabled"""
|
202
|
-
# Mock successful sending
|
203
|
-
mock_send_tracking.return_value = 1
|
204
|
-
|
205
|
-
# Send bulk email with tracking
|
206
|
-
result = self.email_service.send_bulk_email(
|
207
|
-
recipients=['test@example.com'],
|
208
|
-
subject='Test Subject',
|
209
|
-
email_title='Test Title',
|
210
|
-
main_text='Test content',
|
211
|
-
enable_tracking=True,
|
212
|
-
newsletter=self.newsletter
|
213
|
-
)
|
214
|
-
|
215
|
-
# Check result
|
216
|
-
self.assertEqual(result['sent_count'], 1)
|
217
|
-
self.assertEqual(result['failed_count'], 0)
|
218
|
-
|
219
|
-
# Check that email log was created
|
220
|
-
email_logs = EmailLog.objects.filter(newsletter=self.newsletter)
|
221
|
-
self.assertEqual(email_logs.count(), 1)
|
222
|
-
|
223
|
-
email_log = email_logs.first()
|
224
|
-
self.assertEqual(email_log.status, EmailLog.EmailLogStatus.SENT)
|
225
|
-
self.assertIsNotNone(email_log.sent_at)
|
226
|
-
|
227
|
-
# Check that tracking method was called
|
228
|
-
mock_send_tracking.assert_called_once()
|
229
|
-
call_args = mock_send_tracking.call_args
|
230
|
-
self.assertIn('email_log_id', call_args.kwargs)
|
231
|
-
self.assertEqual(call_args.kwargs['email_log_id'], str(email_log.id))
|
232
|
-
|
233
|
-
@patch('django_cfg.modules.django_email.DjangoEmailService.send_template')
|
234
|
-
def test_send_bulk_email_without_tracking(self, mock_send):
|
235
|
-
"""Test sending bulk email without tracking"""
|
236
|
-
# Mock successful sending
|
237
|
-
mock_send.return_value = 1
|
238
|
-
|
239
|
-
# Send bulk email without tracking
|
240
|
-
result = self.email_service.send_bulk_email(
|
241
|
-
recipients=['test@example.com'],
|
242
|
-
subject='Test Subject',
|
243
|
-
email_title='Test Title',
|
244
|
-
main_text='Test content',
|
245
|
-
enable_tracking=False,
|
246
|
-
newsletter=self.newsletter
|
247
|
-
)
|
248
|
-
|
249
|
-
# Check result
|
250
|
-
self.assertEqual(result['sent_count'], 1)
|
251
|
-
self.assertEqual(result['failed_count'], 0)
|
252
|
-
|
253
|
-
# Check that regular send method was called (not tracking)
|
254
|
-
mock_send.assert_called_once()
|
255
|
-
|
256
|
-
# Email log should NOT be created when tracking is disabled
|
257
|
-
email_logs = EmailLog.objects.filter(newsletter=self.newsletter)
|
258
|
-
self.assertEqual(email_logs.count(), 0) # No logs when tracking disabled
|
259
|
-
|
260
|
-
def test_send_newsletter_email_with_tracking(self):
|
261
|
-
"""Test sending newsletter email with tracking enabled"""
|
262
|
-
# Send newsletter email (no mocking - test real functionality)
|
263
|
-
result = self.email_service.send_newsletter_email(
|
264
|
-
newsletter=self.newsletter,
|
265
|
-
subject='Test Newsletter',
|
266
|
-
email_title='Newsletter Title',
|
267
|
-
main_text='Newsletter content',
|
268
|
-
send_to_all=True # Send to all subscribers
|
269
|
-
)
|
270
|
-
|
271
|
-
# Check result
|
272
|
-
self.assertEqual(result['sent_count'], 1)
|
273
|
-
self.assertEqual(result['failed_count'], 0)
|
274
|
-
|
275
|
-
# Check that email log was created with tracking
|
276
|
-
email_logs = EmailLog.objects.filter(newsletter=self.newsletter)
|
277
|
-
self.assertEqual(email_logs.count(), 1)
|
278
|
-
|
279
|
-
email_log = email_logs.first()
|
280
|
-
self.assertEqual(email_log.status, EmailLog.EmailLogStatus.SENT)
|
281
|
-
|
282
|
-
|
283
|
-
class EmailTemplateTrackingTestCase(TestCase):
|
284
|
-
"""Test cases for email template tracking integration"""
|
285
|
-
|
286
|
-
def setUp(self):
|
287
|
-
"""Set up test data"""
|
288
|
-
self.user = User.objects.create_user(
|
289
|
-
username='testuser',
|
290
|
-
email='test@example.com',
|
291
|
-
password='testpass123',
|
292
|
-
is_active=True
|
293
|
-
)
|
294
|
-
|
295
|
-
self.newsletter = Newsletter.objects.create(
|
296
|
-
title='Test Newsletter',
|
297
|
-
description='Test newsletter content',
|
298
|
-
is_active=True
|
299
|
-
)
|
300
|
-
|
301
|
-
self.email_log = EmailLog.objects.create(
|
302
|
-
user=self.user,
|
303
|
-
newsletter=self.newsletter,
|
304
|
-
recipient='test@example.com',
|
305
|
-
subject='Test Subject',
|
306
|
-
body='<p>Test body</p>',
|
307
|
-
status=EmailLog.EmailLogStatus.SENT
|
308
|
-
)
|
309
|
-
|
310
|
-
@patch('django_cfg.modules.django_email.DjangoEmailService._prepare_template_context')
|
311
|
-
def test_template_context_with_tracking(self, mock_prepare_context):
|
312
|
-
"""Test that template context includes tracking URLs"""
|
313
|
-
from django_cfg.modules.django_email import DjangoEmailService
|
314
|
-
|
315
|
-
# Mock context preparation
|
316
|
-
mock_prepare_context.return_value = {
|
317
|
-
'email_title': 'Test Title',
|
318
|
-
'tracking_pixel_url': f'http://example.com/api/newsletter/track/open/{self.email_log.id}/',
|
319
|
-
'tracking_click_url': f'http://example.com/api/newsletter/track/click/{self.email_log.id}'
|
320
|
-
}
|
321
|
-
|
322
|
-
service = DjangoEmailService()
|
323
|
-
context = service._prepare_template_context(
|
324
|
-
{'email_title': 'Test Title'},
|
325
|
-
email_log_id=str(self.email_log.id)
|
326
|
-
)
|
327
|
-
|
328
|
-
# Check that tracking URLs are included
|
329
|
-
self.assertIn('tracking_pixel_url', context)
|
330
|
-
self.assertIn('tracking_click_url', context)
|
331
|
-
self.assertIn(str(self.email_log.id), context['tracking_pixel_url'])
|
332
|
-
self.assertIn(str(self.email_log.id), context['tracking_click_url'])
|
@@ -1,83 +0,0 @@
|
|
1
|
-
import threading
|
2
|
-
import time
|
3
|
-
from unittest.mock import patch, MagicMock
|
4
|
-
from django.test import TestCase, override_settings
|
5
|
-
from django.contrib.auth import get_user_model
|
6
|
-
from django.utils import timezone
|
7
|
-
|
8
|
-
from ..models import Newsletter, EmailLog
|
9
|
-
# NewsletterManager is no longer used - tests updated to reflect current architecture
|
10
|
-
|
11
|
-
User = get_user_model()
|
12
|
-
|
13
|
-
|
14
|
-
class NewsletterManagerTestCase(TestCase):
|
15
|
-
"""Test cases for Newsletter model functionality"""
|
16
|
-
|
17
|
-
def setUp(self):
|
18
|
-
"""Set up test data"""
|
19
|
-
|
20
|
-
# Create test user
|
21
|
-
self.user = User.objects.create_user(
|
22
|
-
username='testuser',
|
23
|
-
email='test@example.com',
|
24
|
-
password='testpass123',
|
25
|
-
is_active=True,
|
26
|
-
)
|
27
|
-
|
28
|
-
# Create test newsletter
|
29
|
-
self.newsletter = Newsletter.objects.create(
|
30
|
-
title='Test Newsletter',
|
31
|
-
description='Test newsletter content',
|
32
|
-
is_active=True
|
33
|
-
)
|
34
|
-
|
35
|
-
def test_newsletter_creation(self):
|
36
|
-
"""Test newsletter creation"""
|
37
|
-
self.assertEqual(self.newsletter.title, 'Test Newsletter')
|
38
|
-
self.assertEqual(self.newsletter.description, 'Test newsletter content')
|
39
|
-
self.assertTrue(self.newsletter.is_active)
|
40
|
-
|
41
|
-
def test_newsletter_filtering(self):
|
42
|
-
"""Test newsletter filtering by active status"""
|
43
|
-
# Create inactive newsletter
|
44
|
-
inactive_newsletter = Newsletter.objects.create(
|
45
|
-
title='Inactive Newsletter',
|
46
|
-
description='Inactive content',
|
47
|
-
is_active=False
|
48
|
-
)
|
49
|
-
|
50
|
-
active_newsletters = Newsletter.objects.filter(is_active=True)
|
51
|
-
self.assertEqual(active_newsletters.count(), 1)
|
52
|
-
self.assertEqual(active_newsletters.first(), self.newsletter)
|
53
|
-
|
54
|
-
def test_newsletter_str_representation(self):
|
55
|
-
"""Test newsletter string representation"""
|
56
|
-
# Newsletter model __str__ method returns just the title
|
57
|
-
self.assertEqual(str(self.newsletter), self.newsletter.title)
|
58
|
-
|
59
|
-
def test_newsletter_ordering(self):
|
60
|
-
"""Test newsletter ordering by creation date"""
|
61
|
-
# Create another newsletter
|
62
|
-
newer_newsletter = Newsletter.objects.create(
|
63
|
-
title='Newer Newsletter',
|
64
|
-
description='Newer content',
|
65
|
-
is_active=True
|
66
|
-
)
|
67
|
-
|
68
|
-
newsletters = list(Newsletter.objects.all())
|
69
|
-
# Should be ordered by created_at descending
|
70
|
-
self.assertEqual(newsletters[0], newer_newsletter)
|
71
|
-
self.assertEqual(newsletters[1], self.newsletter)
|
72
|
-
|
73
|
-
def test_newsletter_meta_options(self):
|
74
|
-
"""Test newsletter model meta options"""
|
75
|
-
meta = Newsletter._meta
|
76
|
-
|
77
|
-
self.assertEqual(meta.verbose_name, 'Newsletter')
|
78
|
-
self.assertEqual(meta.verbose_name_plural, 'Newsletters')
|
79
|
-
self.assertEqual(meta.ordering, ['-created_at'])
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
@@ -1,157 +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
|
-
|
6
|
-
from ..models import Newsletter, EmailLog
|
7
|
-
# NewsletterManager is no longer used
|
8
|
-
|
9
|
-
User = get_user_model()
|
10
|
-
|
11
|
-
|
12
|
-
class NewsletterModelTestCase(TestCase):
|
13
|
-
"""Test cases for Newsletter model with custom manager"""
|
14
|
-
|
15
|
-
def setUp(self):
|
16
|
-
"""Set up test data"""
|
17
|
-
# Create test user
|
18
|
-
self.user = User.objects.create_user(
|
19
|
-
username='testuser',
|
20
|
-
email='test@example.com',
|
21
|
-
password='testpass123',
|
22
|
-
is_active=True
|
23
|
-
)
|
24
|
-
|
25
|
-
# Create test newsletters
|
26
|
-
self.active_newsletter = Newsletter.objects.create(
|
27
|
-
title='Active Newsletter',
|
28
|
-
description='Active content',
|
29
|
-
is_active=True
|
30
|
-
)
|
31
|
-
|
32
|
-
self.inactive_newsletter = Newsletter.objects.create(
|
33
|
-
title='Inactive Newsletter',
|
34
|
-
description='Inactive content',
|
35
|
-
is_active=False
|
36
|
-
)
|
37
|
-
|
38
|
-
def test_newsletter_str_representation(self):
|
39
|
-
"""Test string representation of newsletter"""
|
40
|
-
# Newsletter model __str__ method returns just the title
|
41
|
-
self.assertEqual(
|
42
|
-
str(self.active_newsletter),
|
43
|
-
self.active_newsletter.title
|
44
|
-
)
|
45
|
-
|
46
|
-
def test_newsletter_default_active_status(self):
|
47
|
-
"""Test that new newsletter is active by default"""
|
48
|
-
newsletter = Newsletter.objects.create(
|
49
|
-
title='New Newsletter',
|
50
|
-
description='New content'
|
51
|
-
)
|
52
|
-
self.assertTrue(newsletter.is_active)
|
53
|
-
|
54
|
-
def test_newsletter_active_field(self):
|
55
|
-
"""Test newsletter active field"""
|
56
|
-
self.assertTrue(self.active_newsletter.is_active)
|
57
|
-
self.assertFalse(self.inactive_newsletter.is_active)
|
58
|
-
|
59
|
-
def test_newsletter_ordering(self):
|
60
|
-
"""Test that newsletters are ordered by created_at descending"""
|
61
|
-
newsletters = list(Newsletter.objects.all())
|
62
|
-
|
63
|
-
# Check that newsletters are ordered by created_at descending
|
64
|
-
for i in range(len(newsletters) - 1):
|
65
|
-
self.assertGreaterEqual(
|
66
|
-
newsletters[i].created_at,
|
67
|
-
newsletters[i + 1].created_at
|
68
|
-
)
|
69
|
-
|
70
|
-
def test_newsletter_creation_fields(self):
|
71
|
-
"""Test newsletter creation with required fields"""
|
72
|
-
newsletter = Newsletter.objects.create(
|
73
|
-
title='Test Newsletter',
|
74
|
-
description='Test content'
|
75
|
-
)
|
76
|
-
self.assertEqual(newsletter.title, 'Test Newsletter')
|
77
|
-
self.assertEqual(newsletter.description, 'Test content')
|
78
|
-
self.assertTrue(newsletter.is_active) # Default value
|
79
|
-
|
80
|
-
def test_newsletter_filtering(self):
|
81
|
-
"""Test newsletter filtering by active status"""
|
82
|
-
active_newsletters = Newsletter.objects.filter(is_active=True)
|
83
|
-
inactive_newsletters = Newsletter.objects.filter(is_active=False)
|
84
|
-
|
85
|
-
self.assertEqual(active_newsletters.count(), 1)
|
86
|
-
self.assertEqual(inactive_newsletters.count(), 1)
|
87
|
-
self.assertIn(self.active_newsletter, active_newsletters)
|
88
|
-
self.assertIn(self.inactive_newsletter, inactive_newsletters)
|
89
|
-
|
90
|
-
def test_newsletter_meta_options(self):
|
91
|
-
"""Test newsletter model meta options"""
|
92
|
-
meta = Newsletter._meta
|
93
|
-
|
94
|
-
self.assertEqual(meta.verbose_name, 'Newsletter')
|
95
|
-
self.assertEqual(meta.verbose_name_plural, 'Newsletters')
|
96
|
-
self.assertEqual(meta.ordering, ['-created_at'])
|
97
|
-
|
98
|
-
|
99
|
-
class NewsletterEmailLogRelationshipTestCase(TestCase):
|
100
|
-
"""Test relationship between Newsletter and EmailLog"""
|
101
|
-
|
102
|
-
def setUp(self):
|
103
|
-
"""Set up test data"""
|
104
|
-
# Create test users
|
105
|
-
self.user1 = User.objects.create_user(
|
106
|
-
username='user1',
|
107
|
-
email='user1@example.com',
|
108
|
-
password='testpass123',
|
109
|
-
is_active=True
|
110
|
-
)
|
111
|
-
|
112
|
-
self.user2 = User.objects.create_user(
|
113
|
-
username='user2',
|
114
|
-
email='user2@example.com',
|
115
|
-
password='testpass123',
|
116
|
-
is_active=True
|
117
|
-
)
|
118
|
-
|
119
|
-
# Create test newsletter
|
120
|
-
self.newsletter = Newsletter.objects.create(
|
121
|
-
title='Test Newsletter',
|
122
|
-
description='Test newsletter content',
|
123
|
-
is_active=True
|
124
|
-
)
|
125
|
-
|
126
|
-
def test_newsletter_email_logs_relationship(self):
|
127
|
-
"""Test relationship between Newsletter and EmailLog"""
|
128
|
-
# Create email logs for the newsletter
|
129
|
-
EmailLog.objects.create(
|
130
|
-
user=self.user1,
|
131
|
-
newsletter=self.newsletter,
|
132
|
-
recipient='user1@example.com',
|
133
|
-
subject='Test Subject',
|
134
|
-
body='<p>Test body</p>',
|
135
|
-
status=EmailLog.EmailLogStatus.SENT
|
136
|
-
)
|
137
|
-
|
138
|
-
EmailLog.objects.create(
|
139
|
-
user=self.user2,
|
140
|
-
newsletter=self.newsletter,
|
141
|
-
recipient='user2@example.com',
|
142
|
-
subject='Test Subject',
|
143
|
-
body='<p>Test body</p>',
|
144
|
-
status=EmailLog.EmailLogStatus.SENT
|
145
|
-
)
|
146
|
-
|
147
|
-
# Check that newsletter has email logs
|
148
|
-
self.assertEqual(self.newsletter.email_logs.count(), 2)
|
149
|
-
|
150
|
-
# Check that we can access email logs through newsletter
|
151
|
-
email_logs = list(self.newsletter.email_logs.all())
|
152
|
-
self.assertEqual(len(email_logs), 2)
|
153
|
-
|
154
|
-
# Check email log details (order may vary)
|
155
|
-
users_in_logs = {log.user for log in email_logs}
|
156
|
-
self.assertIn(self.user1, users_in_logs)
|
157
|
-
self.assertIn(self.user2, users_in_logs)
|
File without changes
|
@@ -1,106 +0,0 @@
|
|
1
|
-
from django.test import TestCase, override_settings
|
2
|
-
from django.contrib.auth import get_user_model
|
3
|
-
from unittest.mock import patch
|
4
|
-
from ..models import Ticket, Message
|
5
|
-
|
6
|
-
User = get_user_model()
|
7
|
-
|
8
|
-
class TicketModelTest(TestCase):
|
9
|
-
def setUp(self):
|
10
|
-
self.user = get_user_model().objects.create(username='testuser', email='user@example.com')
|
11
|
-
|
12
|
-
def test_create_ticket_default_status(self):
|
13
|
-
ticket = Ticket.objects.create(user=self.user, subject='Test subject')
|
14
|
-
self.assertEqual(Ticket.TicketStatus, Ticket.TicketStatus.OPEN)
|
15
|
-
self.assertEqual(str(ticket), f"Ticket #{ticket.pk} - {self.user.username} (Open)")
|
16
|
-
self.assertTrue(ticket.uuid)
|
17
|
-
|
18
|
-
def test_ticket_status_choices(self):
|
19
|
-
ticket = Ticket.objects.create(user=self.user, subject='Test', status=Ticket.TicketStatus.RESOLVED)
|
20
|
-
self.assertEqual(Ticket.TicketStatus, Ticket.TicketStatus.RESOLVED)
|
21
|
-
self.assertEqual(ticket.get_status_display(), 'Resolved')
|
22
|
-
|
23
|
-
def test_ticket_ordering(self):
|
24
|
-
"""Test that tickets are ordered by created_at descending."""
|
25
|
-
ticket1 = Ticket.objects.create(user=self.user, subject='First ticket')
|
26
|
-
ticket2 = Ticket.objects.create(user=self.user, subject='Second ticket')
|
27
|
-
|
28
|
-
# Get tickets in default ordering
|
29
|
-
tickets = list(Ticket.objects.all())
|
30
|
-
|
31
|
-
# Should be ordered by created_at descending (newest first)
|
32
|
-
self.assertEqual(tickets[0], ticket2)
|
33
|
-
self.assertEqual(tickets[1], ticket1)
|
34
|
-
|
35
|
-
|
36
|
-
class UserModelTest(TestCase):
|
37
|
-
def test_display_username_with_username(self):
|
38
|
-
"""Test display_username property with username."""
|
39
|
-
user = User.objects.create(
|
40
|
-
username='test_user_123',
|
41
|
-
email='test@example.com'
|
42
|
-
)
|
43
|
-
self.assertEqual(user.display_username, 'Test User 123')
|
44
|
-
|
45
|
-
def test_display_username_with_special_chars(self):
|
46
|
-
"""Test display_username property with special characters."""
|
47
|
-
user = User.objects.create(
|
48
|
-
username='test-user.123',
|
49
|
-
email='test@example.com'
|
50
|
-
)
|
51
|
-
self.assertEqual(user.display_username, 'Test User 123')
|
52
|
-
|
53
|
-
def test_display_username_fallback_to_name(self):
|
54
|
-
"""Test display_username property falls back to full name."""
|
55
|
-
user = User.objects.create(
|
56
|
-
username='',
|
57
|
-
email='test@example.com',
|
58
|
-
first_name='John',
|
59
|
-
last_name='Doe'
|
60
|
-
)
|
61
|
-
self.assertEqual(user.display_username, 'John Doe')
|
62
|
-
|
63
|
-
def test_display_username_fallback_to_email(self):
|
64
|
-
"""Test display_username property falls back to email."""
|
65
|
-
user = User.objects.create(
|
66
|
-
username='',
|
67
|
-
email='john.doe@example.com'
|
68
|
-
)
|
69
|
-
self.assertEqual(user.display_username, 'John.doe')
|
70
|
-
|
71
|
-
|
72
|
-
class MessageModelTest(TestCase):
|
73
|
-
def setUp(self):
|
74
|
-
self.user = get_user_model().objects.create(username='testuser', email='user@example.com')
|
75
|
-
self.admin = get_user_model().objects.create(username='admin', is_staff=True, email='admin@example.com')
|
76
|
-
self.ticket = Ticket.objects.create(user=self.user, subject='Test subject')
|
77
|
-
|
78
|
-
def test_create_message_user(self):
|
79
|
-
msg = Message.objects.create(ticket=self.ticket, sender=self.user, text='Hello')
|
80
|
-
self.assertEqual(msg.ticket, self.ticket)
|
81
|
-
self.assertEqual(msg.sender, self.user)
|
82
|
-
self.assertFalse(msg.sender.is_staff)
|
83
|
-
self.assertEqual(msg.text, 'Hello')
|
84
|
-
self.assertTrue(msg.uuid)
|
85
|
-
|
86
|
-
def test_create_message_admin(self):
|
87
|
-
msg = Message.objects.create(ticket=self.ticket, sender=self.admin, text='Admin reply')
|
88
|
-
self.assertEqual(msg.ticket, self.ticket)
|
89
|
-
self.assertEqual(msg.sender, self.admin)
|
90
|
-
self.assertTrue(msg.sender.is_staff)
|
91
|
-
self.assertEqual(msg.text, 'Admin reply')
|
92
|
-
self.assertTrue(msg.uuid)
|
93
|
-
|
94
|
-
def test_message_ordering(self):
|
95
|
-
Message.objects.create(ticket=self.ticket, sender=self.user, text='First')
|
96
|
-
Message.objects.create(ticket=self.ticket, sender=self.user, text='Second')
|
97
|
-
messages = list(self.ticket.messages.all())
|
98
|
-
self.assertEqual(messages[0].text, 'First')
|
99
|
-
self.assertEqual(messages[1].text, 'Second')
|
100
|
-
|
101
|
-
@override_settings(EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend')
|
102
|
-
@patch('django.core.mail.EmailMultiAlternatives.send')
|
103
|
-
def test_send_support_reply_email(self, mock_send):
|
104
|
-
msg = Message.objects.create(ticket=self.ticket, sender=self.admin, text='Admin reply')
|
105
|
-
Message.objects.send_support_reply_email(msg)
|
106
|
-
self.assertTrue(mock_send.called)
|