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.
Files changed (28) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/management/commands/rundramatiq.py +174 -202
  3. django_cfg/modules/django_tasks.py +54 -428
  4. django_cfg/modules/dramatiq_setup.py +16 -0
  5. {django_cfg-1.1.61.dist-info → django_cfg-1.1.63.dist-info}/METADATA +145 -4
  6. {django_cfg-1.1.61.dist-info → django_cfg-1.1.63.dist-info}/RECORD +9 -27
  7. django_cfg/apps/accounts/tests/__init__.py +0 -1
  8. django_cfg/apps/accounts/tests/test_models.py +0 -412
  9. django_cfg/apps/accounts/tests/test_otp_views.py +0 -143
  10. django_cfg/apps/accounts/tests/test_serializers.py +0 -331
  11. django_cfg/apps/accounts/tests/test_services.py +0 -401
  12. django_cfg/apps/accounts/tests/test_signals.py +0 -110
  13. django_cfg/apps/accounts/tests/test_views.py +0 -255
  14. django_cfg/apps/newsletter/tests/__init__.py +0 -1
  15. django_cfg/apps/newsletter/tests/run_tests.py +0 -47
  16. django_cfg/apps/newsletter/tests/test_email_integration.py +0 -256
  17. django_cfg/apps/newsletter/tests/test_email_tracking.py +0 -332
  18. django_cfg/apps/newsletter/tests/test_newsletter_manager.py +0 -83
  19. django_cfg/apps/newsletter/tests/test_newsletter_models.py +0 -157
  20. django_cfg/apps/support/tests/__init__.py +0 -0
  21. django_cfg/apps/support/tests/test_models.py +0 -106
  22. django_cfg/apps/tasks/@docs/CONFIGURATION.md +0 -663
  23. django_cfg/apps/tasks/@docs/README.md +0 -195
  24. django_cfg/apps/tasks/@docs/TASKS_QUEUES.md +0 -423
  25. django_cfg/apps/tasks/@docs/TROUBLESHOOTING.md +0 -506
  26. {django_cfg-1.1.61.dist-info → django_cfg-1.1.63.dist-info}/WHEEL +0 -0
  27. {django_cfg-1.1.61.dist-info → django_cfg-1.1.63.dist-info}/entry_points.txt +0 -0
  28. {django_cfg-1.1.61.dist-info → django_cfg-1.1.63.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)