-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Moves update_mail inside celery task and make the task async
- Loading branch information
Showing
4 changed files
with
129 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,11 +4,11 @@ | |
import pytest | ||
from django.test import TestCase, override_settings | ||
from django.core.cache import cache | ||
from celery.exceptions import Retry | ||
|
||
from django.conf import settings | ||
from mail.celery_tasks import manage_inbox, notify_users_of_rejected_licences | ||
from celery.exceptions import Retry, MaxRetriesExceededError | ||
|
||
import email.mime.multipart | ||
from mail.celery_tasks import SendSmtpFailureTask, manage_inbox, notify_users_of_rejected_licences | ||
from mail.libraries.email_message_dto import EmailMessageDto | ||
from mail.celery_tasks import send_smtp_task | ||
from mail.celery_tasks import get_lite_api_url | ||
|
@@ -73,6 +73,32 @@ def test_get_url_with_path_from_setting(self): | |
self.assertEqual(result, "https://example.com/foo") | ||
|
||
|
||
class NotifyUsersOfRejectedMailTests(TestCase): | ||
@override_settings(EMAIL_USER="[email protected]", NOTIFY_USERS=["[email protected]"]) # /PS-IGNORE | ||
@mock.patch("mail.celery_tasks.smtp_send") | ||
def test_send_success(self, mock_send): | ||
notify_users_of_rejected_licences("123", "CHIEF_SPIRE_licenceReply_202401180900_42557") | ||
|
||
mock_send.assert_called_once() | ||
|
||
self.assertEqual(len(mock_send.call_args_list), 1) | ||
message = mock_send.call_args[0][0] | ||
self.assertIsInstance(message, email.mime.multipart.MIMEMultipart) | ||
|
||
expected_headers = { | ||
"Content-Type": "multipart/mixed", | ||
"MIME-Version": "1.0", | ||
"From": "[email protected]", # /PS-IGNORE | ||
"To": "[email protected]", # /PS-IGNORE | ||
"Subject": "Licence rejected by HMRC", | ||
} | ||
self.assertDictEqual(dict(message), expected_headers) | ||
|
||
text_payload = message.get_payload(0) | ||
expected_body = "Mail (Id: 123) with subject CHIEF_SPIRE_licenceReply_202401180900_42557 has rejected licences" | ||
self.assertEqual(text_payload.get_payload(), expected_body) | ||
|
||
|
||
class SendEmailTaskTests(TestCase): | ||
def setUp(self): | ||
attachment = "30 \U0001d5c4\U0001d5c6/\U0001d5c1 \u5317\u4EB0" | ||
|
@@ -95,19 +121,14 @@ def test_locking_prevents_multiple_executions(self, mock_cache, mock_smtp_send): | |
# Simulate the lock being released after the first task finishes | ||
mock_cache.delete.return_value = None | ||
|
||
try: | ||
send_smtp_task(self.email_message_dto) | ||
except Retry: | ||
self.fail("First task execution should not raise Retry.") | ||
|
||
with self.assertRaises(Retry): | ||
send_smtp_task(self.email_message_dto) | ||
email_message_data = self.email_message_dto._asdict() | ||
send_smtp_task.apply_async(kwargs={"email_message_data": email_message_data}) | ||
send_smtp_task.apply_async(kwargs={"email_message_data": email_message_data}) | ||
|
||
# Assert smtp_send was called once due to locking | ||
mock_smtp_send.assert_called_once() | ||
# After locked and being released | ||
self.assertEqual(mock_cache.add.call_count, 2) | ||
mock_cache.delete.assert_called_once_with("global_send_email_lock") | ||
# Failed and re-tried so in total 3 times | ||
self.assertEqual(mock_cache.add.call_count, 3) | ||
# Check if lock was deleted | ||
self.assertTrue(mock_cache.delete.called) | ||
|
||
@mock.patch("mail.celery_tasks.send_smtp_task.retry", side_effect=Retry) | ||
@mock.patch("mail.celery_tasks.smtp_send") | ||
|
@@ -116,38 +137,40 @@ def test_retry_on_lock_failure(self, mock_cache, mock_smtp_send, mock_retry): | |
mock_cache.add.return_value = False | ||
mock_smtp_send.return_value = None | ||
|
||
with self.assertRaises(Retry): | ||
send_smtp_task(self.email_message_dto) | ||
email_message_data = self.email_message_dto._asdict() | ||
try: | ||
send_smtp_task.apply_async(kwargs={"email_message_data": email_message_data}) | ||
except Retry: | ||
pass | ||
|
||
mock_retry.assert_called_once() | ||
|
||
retry_call_args = mock_retry.call_args | ||
self.assertIn("countdown", retry_call_args[1]) | ||
retry_delay = retry_call_args[1]["countdown"] | ||
self.assertEqual(retry_delay, 180) | ||
|
||
|
||
class NotifyUsersOfRejectedMailTests(TestCase): | ||
@override_settings(EMAIL_USER="[email protected]", NOTIFY_USERS=["[email protected]"]) # /PS-IGNORE | ||
@mock.patch("mail.celery_tasks.smtp_send") | ||
def test_send_success(self, mock_send): | ||
notify_users_of_rejected_licences("123", "CHIEF_SPIRE_licenceReply_202401180900_42557") | ||
|
||
mock_send.assert_called_once() | ||
|
||
self.assertEqual(len(mock_send.call_args_list), 1) | ||
message = mock_send.call_args[0][0] | ||
self.assertIsInstance(message, email.mime.multipart.MIMEMultipart) | ||
|
||
expected_headers = { | ||
"Content-Type": "multipart/mixed", | ||
"MIME-Version": "1.0", | ||
"From": "[email protected]", # /PS-IGNORE | ||
"To": "[email protected]", # /PS-IGNORE | ||
"Subject": "Licence rejected by HMRC", | ||
} | ||
self.assertDictEqual(dict(message), expected_headers) | ||
|
||
text_payload = message.get_payload(0) | ||
expected_body = "Mail (Id: 123) with subject CHIEF_SPIRE_licenceReply_202401180900_42557 has rejected licences" | ||
self.assertEqual(text_payload.get_payload(), expected_body) | ||
@mock.patch("mail.celery_tasks.logger") | ||
def test_on_failure_logging(self, mock_logger): | ||
# Create an instance of the task | ||
task = SendSmtpFailureTask() | ||
|
||
# Simulated task failure information | ||
exc = MaxRetriesExceededError() | ||
task_id = "test_task_id" | ||
args = ("arg1", "arg2") | ||
kwargs = {"mail_id": "12345"} | ||
einfo = "Simulated exception info" | ||
|
||
# Manually call the on_failure method | ||
task.on_failure(exc, task_id, args, kwargs, einfo) | ||
|
||
# Build the expected message | ||
expected_message = f""" | ||
Task failed permanently after all retries: send_smtp_task | ||
Mail ID: {kwargs['mail_id']} | ||
Exception: {exc} | ||
Args: {args} | ||
Kwargs: {kwargs} | ||
Task ID: {task_id} | ||
Exception Info: {einfo} | ||
""" | ||
|
||
self.assertEqual( | ||
" ".join(mock_logger.critical.call_args[0][0].strip().split()), " ".join(expected_message.strip().split()) | ||
) |