mirror of
https://github.com/GSA/notifications-api.git
synced 2026-08-19 05:58:53 -04:00
merge from main
This commit is contained in:
@@ -17,7 +17,8 @@ from app.celery.nightly_tasks import (
|
||||
save_daily_notification_processing_time,
|
||||
timeout_notifications,
|
||||
)
|
||||
from app.models import EMAIL_TYPE, SMS_TYPE, FactProcessingTime, Job
|
||||
from app.enums import NotificationType, TemplateType
|
||||
from app.models import FactProcessingTime, Job
|
||||
from tests.app.db import (
|
||||
create_job,
|
||||
create_notification,
|
||||
@@ -95,16 +96,24 @@ def test_will_remove_csv_files_for_jobs_older_than_retention_period(
|
||||
service_1 = create_service(service_name="service 1")
|
||||
service_2 = create_service(service_name="service 2")
|
||||
create_service_data_retention(
|
||||
service=service_1, notification_type=SMS_TYPE, days_of_retention=3
|
||||
service=service_1, notification_type=NotificationType.SMS, days_of_retention=3
|
||||
)
|
||||
create_service_data_retention(
|
||||
service=service_2, notification_type=EMAIL_TYPE, days_of_retention=30
|
||||
service=service_2,
|
||||
notification_type=NotificationType.EMAIL,
|
||||
days_of_retention=30,
|
||||
)
|
||||
sms_template_service_1 = create_template(service=service_1)
|
||||
email_template_service_1 = create_template(service=service_1, template_type="email")
|
||||
email_template_service_1 = create_template(
|
||||
service=service_1,
|
||||
template_type=TemplateType.EMAIL,
|
||||
)
|
||||
|
||||
sms_template_service_2 = create_template(service=service_2)
|
||||
email_template_service_2 = create_template(service=service_2, template_type="email")
|
||||
email_template_service_2 = create_template(
|
||||
service=service_2,
|
||||
template_type=TemplateType.EMAIL,
|
||||
)
|
||||
|
||||
four_days_ago = datetime.utcnow() - timedelta(days=4)
|
||||
eight_days_ago = datetime.utcnow() - timedelta(days=8)
|
||||
@@ -140,7 +149,7 @@ def test_delete_sms_notifications_older_than_retention_calls_child_task(
|
||||
"app.celery.nightly_tasks._delete_notifications_older_than_retention_by_type"
|
||||
)
|
||||
delete_sms_notifications_older_than_retention()
|
||||
mocked.assert_called_once_with("sms")
|
||||
mocked.assert_called_once_with(NotificationType.SMS)
|
||||
|
||||
|
||||
def test_delete_email_notifications_older_than_retentions_calls_child_task(
|
||||
@@ -150,7 +159,7 @@ def test_delete_email_notifications_older_than_retentions_calls_child_task(
|
||||
"app.celery.nightly_tasks._delete_notifications_older_than_retention_by_type"
|
||||
)
|
||||
delete_email_notifications_older_than_retention()
|
||||
mocked_notifications.assert_called_once_with("email")
|
||||
mocked_notifications.assert_called_once_with(NotificationType.EMAIL)
|
||||
|
||||
|
||||
@freeze_time("2021-12-13T10:00")
|
||||
@@ -274,21 +283,25 @@ def test_delete_notifications_task_calls_task_for_services_with_data_retention_o
|
||||
email_service = create_service(service_name="b")
|
||||
letter_service = create_service(service_name="c")
|
||||
|
||||
create_service_data_retention(sms_service, notification_type="sms")
|
||||
create_service_data_retention(email_service, notification_type="email")
|
||||
create_service_data_retention(letter_service, notification_type="letter")
|
||||
create_service_data_retention(sms_service, notification_type=NotificationType.SMS)
|
||||
create_service_data_retention(
|
||||
email_service, notification_type=NotificationType.EMAIL
|
||||
)
|
||||
create_service_data_retention(
|
||||
letter_service, notification_type=NotificationType.LETTER
|
||||
)
|
||||
|
||||
mock_subtask = mocker.patch(
|
||||
"app.celery.nightly_tasks.delete_notifications_for_service_and_type"
|
||||
)
|
||||
|
||||
_delete_notifications_older_than_retention_by_type("sms")
|
||||
_delete_notifications_older_than_retention_by_type(NotificationType.SMS)
|
||||
|
||||
mock_subtask.apply_async.assert_called_once_with(
|
||||
queue="reporting-tasks",
|
||||
kwargs={
|
||||
"service_id": sms_service.id,
|
||||
"notification_type": "sms",
|
||||
"notification_type": NotificationType.SMS,
|
||||
# three days of retention, its morn of 5th, so we want to keep all messages from 4th, 3rd and 2nd.
|
||||
"datetime_to_delete_before": date(2021, 6, 2),
|
||||
},
|
||||
@@ -308,7 +321,7 @@ def test_delete_notifications_task_calls_task_for_services_with_data_retention_b
|
||||
"app.celery.nightly_tasks.delete_notifications_for_service_and_type"
|
||||
)
|
||||
|
||||
_delete_notifications_older_than_retention_by_type("sms")
|
||||
_delete_notifications_older_than_retention_by_type(NotificationType.SMS)
|
||||
|
||||
assert mock_subtask.apply_async.call_count == 2
|
||||
mock_subtask.apply_async.assert_has_calls(
|
||||
@@ -318,7 +331,7 @@ def test_delete_notifications_task_calls_task_for_services_with_data_retention_b
|
||||
queue=ANY,
|
||||
kwargs={
|
||||
"service_id": service_14_days.id,
|
||||
"notification_type": "sms",
|
||||
"notification_type": NotificationType.SMS,
|
||||
"datetime_to_delete_before": date(2021, 3, 21),
|
||||
},
|
||||
),
|
||||
@@ -326,7 +339,7 @@ def test_delete_notifications_task_calls_task_for_services_with_data_retention_b
|
||||
queue=ANY,
|
||||
kwargs={
|
||||
"service_id": service_3_days.id,
|
||||
"notification_type": "sms",
|
||||
"notification_type": NotificationType.SMS,
|
||||
"datetime_to_delete_before": date(2021, 4, 1),
|
||||
},
|
||||
),
|
||||
@@ -345,10 +358,12 @@ def test_delete_notifications_task_calls_task_for_services_that_have_sent_notifi
|
||||
create_template(service_will_delete_1)
|
||||
create_template(service_will_delete_2)
|
||||
nothing_to_delete_sms_template = create_template(
|
||||
service_nothing_to_delete, template_type="sms"
|
||||
service_nothing_to_delete,
|
||||
template_type=TemplateType.SMS,
|
||||
)
|
||||
nothing_to_delete_email_template = create_template(
|
||||
service_nothing_to_delete, template_type="email"
|
||||
service_nothing_to_delete,
|
||||
template_type=TemplateType.EMAIL,
|
||||
)
|
||||
|
||||
# will be deleted as service has no custom retention, but past our default 7 days
|
||||
@@ -375,7 +390,7 @@ def test_delete_notifications_task_calls_task_for_services_that_have_sent_notifi
|
||||
"app.celery.nightly_tasks.delete_notifications_for_service_and_type"
|
||||
)
|
||||
|
||||
_delete_notifications_older_than_retention_by_type("sms")
|
||||
_delete_notifications_older_than_retention_by_type(NotificationType.SMS)
|
||||
|
||||
assert mock_subtask.apply_async.call_count == 2
|
||||
mock_subtask.apply_async.assert_has_calls(
|
||||
@@ -385,7 +400,7 @@ def test_delete_notifications_task_calls_task_for_services_that_have_sent_notifi
|
||||
queue=ANY,
|
||||
kwargs={
|
||||
"service_id": service_will_delete_1.id,
|
||||
"notification_type": "sms",
|
||||
"notification_type": NotificationType.SMS,
|
||||
"datetime_to_delete_before": date(2021, 3, 26),
|
||||
},
|
||||
),
|
||||
@@ -393,7 +408,7 @@ def test_delete_notifications_task_calls_task_for_services_that_have_sent_notifi
|
||||
queue=ANY,
|
||||
kwargs={
|
||||
"service_id": service_will_delete_2.id,
|
||||
"notification_type": "sms",
|
||||
"notification_type": NotificationType.SMS,
|
||||
"datetime_to_delete_before": date(2021, 3, 26),
|
||||
},
|
||||
),
|
||||
|
||||
@@ -16,6 +16,7 @@ from app.celery.test_key_tasks import (
|
||||
ses_soft_bounce_callback,
|
||||
)
|
||||
from app.dao.notifications_dao import get_notification_by_id
|
||||
from app.enums import CallbackType, NotificationStatus
|
||||
from app.models import Complaint
|
||||
from tests.app.conftest import create_sample_notification
|
||||
from tests.app.db import (
|
||||
@@ -136,7 +137,7 @@ def test_process_ses_results(sample_email_template):
|
||||
sample_email_template,
|
||||
reference="ref1",
|
||||
sent_at=datetime.utcnow(),
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
)
|
||||
|
||||
assert process_ses_results(response=ses_notification_callback(reference="ref1"))
|
||||
@@ -147,7 +148,7 @@ def test_process_ses_results_retry_called(sample_email_template, mocker):
|
||||
sample_email_template,
|
||||
reference="ref1",
|
||||
sent_at=datetime.utcnow(),
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
)
|
||||
mocker.patch(
|
||||
"app.dao.notifications_dao._update_notification_status",
|
||||
@@ -196,15 +197,20 @@ def test_ses_callback_should_update_notification_status(
|
||||
notify_db_session,
|
||||
template=sample_email_template,
|
||||
reference="ref",
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
sent_at=datetime.utcnow(),
|
||||
)
|
||||
create_service_callback_api(
|
||||
service=sample_email_template.service, url="https://original_url.com"
|
||||
)
|
||||
assert get_notification_by_id(notification.id).status == "sending"
|
||||
assert (
|
||||
get_notification_by_id(notification.id).status == NotificationStatus.SENDING
|
||||
)
|
||||
assert process_ses_results(ses_notification_callback(reference="ref"))
|
||||
assert get_notification_by_id(notification.id).status == "delivered"
|
||||
assert (
|
||||
get_notification_by_id(notification.id).status
|
||||
== NotificationStatus.DELIVERED
|
||||
)
|
||||
send_mock.assert_called_once_with(
|
||||
[str(notification.id), ANY], queue="service-callbacks"
|
||||
)
|
||||
@@ -222,11 +228,15 @@ def test_ses_callback_should_not_update_notification_status_if_already_delivered
|
||||
"app.celery.process_ses_receipts_tasks.notifications_dao._update_notification_status"
|
||||
)
|
||||
notification = create_notification(
|
||||
template=sample_email_template, reference="ref", status="delivered"
|
||||
template=sample_email_template,
|
||||
reference="ref",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
)
|
||||
assert process_ses_results(ses_notification_callback(reference="ref")) is None
|
||||
assert get_notification_by_id(notification.id).status == "delivered"
|
||||
mock_dup.assert_called_once_with(notification, "delivered")
|
||||
assert (
|
||||
get_notification_by_id(notification.id).status == NotificationStatus.DELIVERED
|
||||
)
|
||||
mock_dup.assert_called_once_with(notification, NotificationStatus.DELIVERED)
|
||||
assert mock_upd.call_count == 0
|
||||
|
||||
|
||||
@@ -283,12 +293,17 @@ def test_ses_callback_does_not_call_send_delivery_status_if_no_db_entry(
|
||||
notify_db_session,
|
||||
template=sample_email_template,
|
||||
reference="ref",
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
sent_at=datetime.utcnow(),
|
||||
)
|
||||
assert get_notification_by_id(notification.id).status == "sending"
|
||||
assert (
|
||||
get_notification_by_id(notification.id).status == NotificationStatus.SENDING
|
||||
)
|
||||
assert process_ses_results(ses_notification_callback(reference="ref"))
|
||||
assert get_notification_by_id(notification.id).status == "delivered"
|
||||
assert (
|
||||
get_notification_by_id(notification.id).status
|
||||
== NotificationStatus.DELIVERED
|
||||
)
|
||||
send_mock.assert_not_called()
|
||||
|
||||
|
||||
@@ -304,7 +319,7 @@ def test_ses_callback_should_update_multiple_notification_status_sent(
|
||||
template=sample_email_template,
|
||||
reference="ref1",
|
||||
sent_at=datetime.utcnow(),
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
)
|
||||
create_sample_notification(
|
||||
_notify_db,
|
||||
@@ -312,7 +327,7 @@ def test_ses_callback_should_update_multiple_notification_status_sent(
|
||||
template=sample_email_template,
|
||||
reference="ref2",
|
||||
sent_at=datetime.utcnow(),
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
)
|
||||
create_sample_notification(
|
||||
_notify_db,
|
||||
@@ -320,7 +335,7 @@ def test_ses_callback_should_update_multiple_notification_status_sent(
|
||||
template=sample_email_template,
|
||||
reference="ref3",
|
||||
sent_at=datetime.utcnow(),
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
)
|
||||
create_service_callback_api(
|
||||
service=sample_email_template.service, url="https://original_url.com"
|
||||
@@ -342,15 +357,18 @@ def test_ses_callback_should_set_status_to_temporary_failure(
|
||||
notify_db_session,
|
||||
template=sample_email_template,
|
||||
reference="ref",
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
sent_at=datetime.utcnow(),
|
||||
)
|
||||
create_service_callback_api(
|
||||
service=notification.service, url="https://original_url.com"
|
||||
)
|
||||
assert get_notification_by_id(notification.id).status == "sending"
|
||||
assert get_notification_by_id(notification.id).status == NotificationStatus.SENDING
|
||||
assert process_ses_results(ses_soft_bounce_callback(reference="ref"))
|
||||
assert get_notification_by_id(notification.id).status == "temporary-failure"
|
||||
assert (
|
||||
get_notification_by_id(notification.id).status
|
||||
== NotificationStatus.TEMPORARY_FAILURE
|
||||
)
|
||||
assert send_mock.called
|
||||
|
||||
|
||||
@@ -365,15 +383,18 @@ def test_ses_callback_should_set_status_to_permanent_failure(
|
||||
notify_db_session,
|
||||
template=sample_email_template,
|
||||
reference="ref",
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
sent_at=datetime.utcnow(),
|
||||
)
|
||||
create_service_callback_api(
|
||||
service=sample_email_template.service, url="https://original_url.com"
|
||||
)
|
||||
assert get_notification_by_id(notification.id).status == "sending"
|
||||
assert get_notification_by_id(notification.id).status == NotificationStatus.SENDING
|
||||
assert process_ses_results(ses_hard_bounce_callback(reference="ref"))
|
||||
assert get_notification_by_id(notification.id).status == "permanent-failure"
|
||||
assert (
|
||||
get_notification_by_id(notification.id).status
|
||||
== NotificationStatus.PERMANENT_FAILURE
|
||||
)
|
||||
assert send_mock.called
|
||||
|
||||
|
||||
@@ -386,13 +407,13 @@ def test_ses_callback_should_send_on_complaint_to_user_callback_api(
|
||||
create_service_callback_api(
|
||||
service=sample_email_template.service,
|
||||
url="https://original_url.com",
|
||||
callback_type="complaint",
|
||||
callback_type=CallbackType.COMPLAINT,
|
||||
)
|
||||
notification = create_notification(
|
||||
template=sample_email_template,
|
||||
reference="ref1",
|
||||
sent_at=datetime.utcnow(),
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
)
|
||||
response = ses_complaint_callback()
|
||||
assert process_ses_results(response)
|
||||
|
||||
@@ -11,6 +11,7 @@ from app.clients.email.aws_ses import (
|
||||
AwsSesClientThrottlingSendRateException,
|
||||
)
|
||||
from app.clients.sms import SmsClientResponseException
|
||||
from app.enums import NotificationStatus
|
||||
from app.exceptions import NotificationTechnicalFailureException
|
||||
|
||||
|
||||
@@ -55,7 +56,7 @@ def test_should_retry_and_log_warning_if_SmsClientResponseException_for_deliver_
|
||||
)
|
||||
mocker.patch("app.celery.provider_tasks.deliver_sms.retry")
|
||||
mock_logger_warning = mocker.patch("app.celery.tasks.current_app.logger.warning")
|
||||
assert sample_notification.status == "created"
|
||||
assert sample_notification.status == NotificationStatus.CREATED
|
||||
|
||||
deliver_sms(sample_notification.id)
|
||||
|
||||
@@ -75,7 +76,7 @@ def test_should_retry_and_log_exception_for_non_SmsClientResponseException_excep
|
||||
"app.celery.tasks.current_app.logger.exception"
|
||||
)
|
||||
|
||||
assert sample_notification.status == "created"
|
||||
assert sample_notification.status == NotificationStatus.CREATED
|
||||
deliver_sms(sample_notification.id)
|
||||
|
||||
assert provider_tasks.deliver_sms.retry.called is True
|
||||
@@ -105,7 +106,7 @@ def test_should_go_into_technical_error_if_exceeds_retries_on_deliver_sms_task(
|
||||
queue="retry-tasks", countdown=0
|
||||
)
|
||||
|
||||
assert sample_notification.status == "temporary-failure"
|
||||
assert sample_notification.status == NotificationStatus.TEMPORARY_FAILURE
|
||||
assert mock_logger_exception.called
|
||||
|
||||
|
||||
@@ -163,7 +164,7 @@ def test_should_go_into_technical_error_if_exceeds_retries_on_deliver_email_task
|
||||
assert str(sample_notification.id) in str(e.value)
|
||||
|
||||
provider_tasks.deliver_email.retry.assert_called_with(queue="retry-tasks")
|
||||
assert sample_notification.status == "technical-failure"
|
||||
assert sample_notification.status == NotificationStatus.TECHNICAL_FAILURE
|
||||
|
||||
|
||||
def test_should_technical_error_and_not_retry_if_EmailClientNonRetryableException(
|
||||
@@ -178,7 +179,7 @@ def test_should_technical_error_and_not_retry_if_EmailClientNonRetryableExceptio
|
||||
deliver_email(sample_notification.id)
|
||||
|
||||
assert provider_tasks.deliver_email.retry.called is False
|
||||
assert sample_notification.status == "technical-failure"
|
||||
assert sample_notification.status == NotificationStatus.TECHNICAL_FAILURE
|
||||
|
||||
|
||||
def test_should_retry_and_log_exception_for_deliver_email_task(
|
||||
@@ -204,7 +205,7 @@ def test_should_retry_and_log_exception_for_deliver_email_task(
|
||||
deliver_email(sample_notification.id)
|
||||
|
||||
assert provider_tasks.deliver_email.retry.called is True
|
||||
assert sample_notification.status == "created"
|
||||
assert sample_notification.status == NotificationStatus.CREATED
|
||||
assert mock_logger_exception.called
|
||||
|
||||
|
||||
@@ -232,6 +233,6 @@ def test_if_ses_send_rate_throttle_then_should_retry_and_log_warning(
|
||||
deliver_email(sample_notification.id)
|
||||
|
||||
assert provider_tasks.deliver_email.retry.called is True
|
||||
assert sample_notification.status == "created"
|
||||
assert sample_notification.status == NotificationStatus.CREATED
|
||||
assert not mock_logger_exception.called
|
||||
assert mock_logger_warning.called
|
||||
|
||||
@@ -13,17 +13,8 @@ from app.celery.reporting_tasks import (
|
||||
)
|
||||
from app.config import QueueNames
|
||||
from app.dao.fact_billing_dao import get_rate
|
||||
from app.models import (
|
||||
EMAIL_TYPE,
|
||||
KEY_TYPE_NORMAL,
|
||||
KEY_TYPE_TEAM,
|
||||
KEY_TYPE_TEST,
|
||||
NOTIFICATION_TYPES,
|
||||
SMS_TYPE,
|
||||
FactBilling,
|
||||
FactNotificationStatus,
|
||||
Notification,
|
||||
)
|
||||
from app.enums import KeyType, NotificationStatus, NotificationType, TemplateType
|
||||
from app.models import FactBilling, FactNotificationStatus, Notification
|
||||
from tests.app.db import (
|
||||
create_notification,
|
||||
create_notification_history,
|
||||
@@ -36,9 +27,9 @@ from tests.app.db import (
|
||||
def mocker_get_rate(
|
||||
non_letter_rates, notification_type, local_date, rate_multiplier=None
|
||||
):
|
||||
if notification_type == SMS_TYPE:
|
||||
if notification_type == NotificationType.SMS:
|
||||
return Decimal(1.33)
|
||||
elif notification_type == EMAIL_TYPE:
|
||||
elif notification_type == NotificationType.EMAIL:
|
||||
return Decimal(0)
|
||||
|
||||
|
||||
@@ -83,7 +74,7 @@ def test_create_nightly_notification_status_triggers_tasks(
|
||||
kwargs={
|
||||
"service_id": sample_service.id,
|
||||
"process_day": "2019-07-31",
|
||||
"notification_type": SMS_TYPE,
|
||||
"notification_type": NotificationType.SMS,
|
||||
},
|
||||
queue=QueueNames.REPORTING,
|
||||
)
|
||||
@@ -94,8 +85,8 @@ def test_create_nightly_notification_status_triggers_tasks(
|
||||
"notification_date, expected_types_aggregated",
|
||||
[
|
||||
("2019-08-01", set()),
|
||||
("2019-07-31", {EMAIL_TYPE, SMS_TYPE}),
|
||||
("2019-07-28", {EMAIL_TYPE, SMS_TYPE}),
|
||||
("2019-07-31", {NotificationType.EMAIL, NotificationType.SMS}),
|
||||
("2019-07-28", {NotificationType.EMAIL, NotificationType.SMS}),
|
||||
("2019-07-21", set()),
|
||||
],
|
||||
)
|
||||
@@ -110,7 +101,7 @@ def test_create_nightly_notification_status_triggers_relevant_tasks(
|
||||
"app.celery.reporting_tasks.create_nightly_notification_status_for_service_and_day"
|
||||
).apply_async
|
||||
|
||||
for notification_type in NOTIFICATION_TYPES:
|
||||
for notification_type in NotificationType:
|
||||
template = create_template(sample_service, template_type=notification_type)
|
||||
create_notification(template=template, created_at=notification_date)
|
||||
|
||||
@@ -131,13 +122,13 @@ def test_create_nightly_billing_for_day_checks_history(
|
||||
create_notification(
|
||||
created_at=yesterday,
|
||||
template=sample_template,
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
)
|
||||
|
||||
create_notification_history(
|
||||
created_at=yesterday,
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
)
|
||||
|
||||
records = FactBilling.query.all()
|
||||
@@ -148,7 +139,7 @@ def test_create_nightly_billing_for_day_checks_history(
|
||||
assert len(records) == 1
|
||||
|
||||
record = records[0]
|
||||
assert record.notification_type == SMS_TYPE
|
||||
assert record.notification_type == NotificationType.SMS
|
||||
assert record.notifications_sent == 2
|
||||
|
||||
|
||||
@@ -173,7 +164,7 @@ def test_create_nightly_billing_for_day_sms_rate_multiplier(
|
||||
create_notification(
|
||||
created_at=yesterday,
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
sent_by="sns",
|
||||
international=False,
|
||||
rate_multiplier=1.0,
|
||||
@@ -182,7 +173,7 @@ def test_create_nightly_billing_for_day_sms_rate_multiplier(
|
||||
create_notification(
|
||||
created_at=yesterday,
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
sent_by="sns",
|
||||
international=False,
|
||||
rate_multiplier=second_rate,
|
||||
@@ -213,7 +204,7 @@ def test_create_nightly_billing_for_day_different_templates(
|
||||
create_notification(
|
||||
created_at=yesterday,
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
sent_by="sns",
|
||||
international=False,
|
||||
rate_multiplier=1.0,
|
||||
@@ -222,7 +213,7 @@ def test_create_nightly_billing_for_day_different_templates(
|
||||
create_notification(
|
||||
created_at=yesterday,
|
||||
template=sample_email_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
sent_by="sns",
|
||||
international=False,
|
||||
rate_multiplier=0,
|
||||
@@ -257,7 +248,7 @@ def test_create_nightly_billing_for_day_same_sent_by(
|
||||
create_notification(
|
||||
created_at=yesterday,
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
sent_by="sns",
|
||||
international=False,
|
||||
rate_multiplier=1.0,
|
||||
@@ -266,7 +257,7 @@ def test_create_nightly_billing_for_day_same_sent_by(
|
||||
create_notification(
|
||||
created_at=yesterday,
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
sent_by="sns",
|
||||
international=False,
|
||||
rate_multiplier=1.0,
|
||||
@@ -297,7 +288,7 @@ def test_create_nightly_billing_for_day_null_sent_by_sms(
|
||||
create_notification(
|
||||
created_at=yesterday,
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
sent_by=None,
|
||||
international=False,
|
||||
rate_multiplier=1.0,
|
||||
@@ -321,14 +312,14 @@ def test_create_nightly_billing_for_day_null_sent_by_sms(
|
||||
|
||||
def test_get_rate_for_sms_and_email(notify_db_session):
|
||||
non_letter_rates = [
|
||||
create_rate(datetime(2017, 12, 1), 0.15, SMS_TYPE),
|
||||
create_rate(datetime(2017, 12, 1), 0, EMAIL_TYPE),
|
||||
create_rate(datetime(2017, 12, 1), 0.15, NotificationType.SMS),
|
||||
create_rate(datetime(2017, 12, 1), 0, NotificationType.EMAIL),
|
||||
]
|
||||
|
||||
rate = get_rate(non_letter_rates, SMS_TYPE, date(2018, 1, 1))
|
||||
rate = get_rate(non_letter_rates, NotificationType.SMS, date(2018, 1, 1))
|
||||
assert rate == Decimal(0.15)
|
||||
|
||||
rate = get_rate(non_letter_rates, EMAIL_TYPE, date(2018, 1, 1))
|
||||
rate = get_rate(non_letter_rates, NotificationType.EMAIL, date(2018, 1, 1))
|
||||
assert rate == Decimal(0)
|
||||
|
||||
|
||||
@@ -343,7 +334,7 @@ def test_create_nightly_billing_for_day_use_BST(
|
||||
create_notification(
|
||||
created_at=datetime(2018, 3, 26, 4, 1),
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
rate_multiplier=1.0,
|
||||
billable_units=1,
|
||||
)
|
||||
@@ -351,7 +342,7 @@ def test_create_nightly_billing_for_day_use_BST(
|
||||
create_notification(
|
||||
created_at=datetime(2018, 3, 25, 23, 59),
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
rate_multiplier=1.0,
|
||||
billable_units=2,
|
||||
)
|
||||
@@ -360,7 +351,7 @@ def test_create_nightly_billing_for_day_use_BST(
|
||||
create_notification(
|
||||
created_at=datetime(2018, 3, 24, 23, 59),
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
rate_multiplier=1.0,
|
||||
billable_units=4,
|
||||
)
|
||||
@@ -385,7 +376,7 @@ def test_create_nightly_billing_for_day_update_when_record_exists(
|
||||
create_notification(
|
||||
created_at=datetime.now() - timedelta(days=1),
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
sent_by=None,
|
||||
international=False,
|
||||
rate_multiplier=1.0,
|
||||
@@ -406,7 +397,7 @@ def test_create_nightly_billing_for_day_update_when_record_exists(
|
||||
create_notification(
|
||||
created_at=datetime.now() - timedelta(days=1),
|
||||
template=sample_template,
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
sent_by=None,
|
||||
international=False,
|
||||
rate_multiplier=1.0,
|
||||
@@ -424,25 +415,38 @@ def test_create_nightly_notification_status_for_service_and_day(notify_db_sessio
|
||||
first_service = create_service(service_name="First Service")
|
||||
first_template = create_template(service=first_service)
|
||||
second_service = create_service(service_name="second Service")
|
||||
second_template = create_template(service=second_service, template_type="email")
|
||||
second_template = create_template(
|
||||
service=second_service,
|
||||
template_type=TemplateType.EMAIL,
|
||||
)
|
||||
|
||||
process_day = datetime.utcnow().date() - timedelta(days=5)
|
||||
with freeze_time(datetime.combine(process_day, time.max)):
|
||||
create_notification(template=first_template, status="delivered")
|
||||
create_notification(template=second_template, status="failed")
|
||||
create_notification(
|
||||
template=first_template,
|
||||
status=NotificationStatus.DELIVERED,
|
||||
)
|
||||
create_notification(template=second_template, status=NotificationStatus.FAILED)
|
||||
|
||||
# team API key notifications are included
|
||||
create_notification(
|
||||
template=second_template, status="sending", key_type=KEY_TYPE_TEAM
|
||||
template=second_template,
|
||||
status=NotificationStatus.SENDING,
|
||||
key_type=KeyType.TEAM,
|
||||
)
|
||||
|
||||
# test notifications are ignored
|
||||
create_notification(
|
||||
template=second_template, status="sending", key_type=KEY_TYPE_TEST
|
||||
template=second_template,
|
||||
status=NotificationStatus.SENDING,
|
||||
key_type=KeyType.TEST,
|
||||
)
|
||||
|
||||
# historical notifications are included
|
||||
create_notification_history(template=second_template, status="delivered")
|
||||
create_notification_history(
|
||||
template=second_template,
|
||||
status=NotificationStatus.DELIVERED,
|
||||
)
|
||||
|
||||
# these created notifications from a different day get ignored
|
||||
with freeze_time(
|
||||
@@ -454,10 +458,14 @@ def test_create_nightly_notification_status_for_service_and_day(notify_db_sessio
|
||||
assert len(FactNotificationStatus.query.all()) == 0
|
||||
|
||||
create_nightly_notification_status_for_service_and_day(
|
||||
str(process_day), first_service.id, "sms"
|
||||
str(process_day),
|
||||
first_service.id,
|
||||
NotificationType.SMS,
|
||||
)
|
||||
create_nightly_notification_status_for_service_and_day(
|
||||
str(process_day), second_service.id, "email"
|
||||
str(process_day),
|
||||
second_service.id,
|
||||
NotificationType.EMAIL,
|
||||
)
|
||||
|
||||
new_fact_data = FactNotificationStatus.query.order_by(
|
||||
@@ -467,39 +475,43 @@ def test_create_nightly_notification_status_for_service_and_day(notify_db_sessio
|
||||
|
||||
assert len(new_fact_data) == 4
|
||||
|
||||
email_delivered_row = new_fact_data[0]
|
||||
assert email_delivered_row.template_id == second_template.id
|
||||
assert email_delivered_row.service_id == second_service.id
|
||||
assert email_delivered_row.notification_type == "email"
|
||||
assert email_delivered_row.notification_status == "delivered"
|
||||
assert email_delivered_row.notification_count == 1
|
||||
assert email_delivered_row.key_type == KEY_TYPE_NORMAL
|
||||
email_delivered = (NotificationType.EMAIL, NotificationStatus.DELIVERED)
|
||||
email_sending = (NotificationType.EMAIL, NotificationStatus.SENDING)
|
||||
email_failure = (NotificationType.EMAIL, NotificationStatus.FAILED)
|
||||
sms_delivered = (NotificationType.SMS, NotificationStatus.DELIVERED)
|
||||
|
||||
email_sending_row = new_fact_data[1]
|
||||
assert email_sending_row.template_id == second_template.id
|
||||
assert email_sending_row.service_id == second_service.id
|
||||
assert email_sending_row.notification_type == "email"
|
||||
assert email_sending_row.notification_status == "failed"
|
||||
assert email_sending_row.notification_count == 1
|
||||
assert email_sending_row.key_type == KEY_TYPE_NORMAL
|
||||
|
||||
email_failure_row = new_fact_data[2]
|
||||
assert email_failure_row.local_date == process_day
|
||||
assert email_failure_row.template_id == second_template.id
|
||||
assert email_failure_row.service_id == second_service.id
|
||||
assert email_failure_row.job_id == UUID("00000000-0000-0000-0000-000000000000")
|
||||
assert email_failure_row.notification_type == "email"
|
||||
assert email_failure_row.notification_status == "sending"
|
||||
assert email_failure_row.notification_count == 1
|
||||
assert email_failure_row.key_type == KEY_TYPE_TEAM
|
||||
|
||||
sms_delivered_row = new_fact_data[3]
|
||||
assert sms_delivered_row.template_id == first_template.id
|
||||
assert sms_delivered_row.service_id == first_service.id
|
||||
assert sms_delivered_row.notification_type == "sms"
|
||||
assert sms_delivered_row.notification_status == "delivered"
|
||||
assert sms_delivered_row.notification_count == 1
|
||||
assert sms_delivered_row.key_type == KEY_TYPE_NORMAL
|
||||
for row in new_fact_data:
|
||||
current = (row.notification_type, row.notification_status)
|
||||
if current == email_delivered:
|
||||
assert row.template_id == second_template.id
|
||||
assert row.service_id == second_service.id
|
||||
assert row.notification_type == NotificationType.EMAIL
|
||||
assert row.notification_status == NotificationStatus.DELIVERED
|
||||
assert row.notification_count == 1
|
||||
assert row.key_type == KeyType.NORMAL
|
||||
elif current == email_failure:
|
||||
assert row.template_id == second_template.id
|
||||
assert row.service_id == second_service.id
|
||||
assert row.notification_type == NotificationType.EMAIL
|
||||
assert row.notification_status == NotificationStatus.FAILED
|
||||
assert row.notification_count == 1
|
||||
assert row.key_type == KeyType.NORMAL
|
||||
elif current == email_sending:
|
||||
assert row.local_date == process_day
|
||||
assert row.template_id == second_template.id
|
||||
assert row.service_id == second_service.id
|
||||
assert row.job_id == UUID("00000000-0000-0000-0000-000000000000")
|
||||
assert row.notification_type == NotificationType.EMAIL
|
||||
assert row.notification_status == NotificationStatus.SENDING
|
||||
assert row.notification_count == 1
|
||||
assert row.key_type == KeyType.TEAM
|
||||
elif current == sms_delivered:
|
||||
assert row.template_id == first_template.id
|
||||
assert row.service_id == first_service.id
|
||||
assert row.notification_type == NotificationType.SMS
|
||||
assert row.notification_status == NotificationStatus.DELIVERED
|
||||
assert row.notification_count == 1
|
||||
assert row.key_type == KeyType.NORMAL
|
||||
|
||||
|
||||
def test_create_nightly_notification_status_for_service_and_day_overwrites_old_data(
|
||||
@@ -510,22 +522,28 @@ def test_create_nightly_notification_status_for_service_and_day_overwrites_old_d
|
||||
process_day = datetime.utcnow().date()
|
||||
|
||||
# first run: one notification, expect one row (just one status)
|
||||
notification = create_notification(template=first_template, status="sending")
|
||||
notification = create_notification(
|
||||
template=first_template, status=NotificationStatus.SENDING
|
||||
)
|
||||
create_nightly_notification_status_for_service_and_day(
|
||||
str(process_day), first_service.id, "sms"
|
||||
str(process_day),
|
||||
first_service.id,
|
||||
NotificationType.SMS,
|
||||
)
|
||||
|
||||
new_fact_data = FactNotificationStatus.query.all()
|
||||
|
||||
assert len(new_fact_data) == 1
|
||||
assert new_fact_data[0].notification_count == 1
|
||||
assert new_fact_data[0].notification_status == "sending"
|
||||
assert new_fact_data[0].notification_status == NotificationStatus.SENDING
|
||||
|
||||
# second run: status changed, still expect one row (one status)
|
||||
notification.status = "delivered"
|
||||
create_notification(template=first_template, status="created")
|
||||
notification.status = NotificationStatus.DELIVERED
|
||||
create_notification(template=first_template, status=NotificationStatus.CREATED)
|
||||
create_nightly_notification_status_for_service_and_day(
|
||||
str(process_day), first_service.id, "sms"
|
||||
str(process_day),
|
||||
first_service.id,
|
||||
NotificationType.SMS,
|
||||
)
|
||||
|
||||
updated_fact_data = FactNotificationStatus.query.order_by(
|
||||
@@ -534,9 +552,9 @@ def test_create_nightly_notification_status_for_service_and_day_overwrites_old_d
|
||||
|
||||
assert len(updated_fact_data) == 2
|
||||
assert updated_fact_data[0].notification_count == 1
|
||||
assert updated_fact_data[0].notification_status == "created"
|
||||
assert updated_fact_data[0].notification_status == NotificationStatus.CREATED
|
||||
assert updated_fact_data[1].notification_count == 1
|
||||
assert updated_fact_data[1].notification_status == "delivered"
|
||||
assert updated_fact_data[1].notification_status == NotificationStatus.DELIVERED
|
||||
|
||||
|
||||
# the job runs at 04:30am EST time.
|
||||
@@ -545,22 +563,32 @@ def test_create_nightly_notification_status_for_service_and_day_respects_bst(
|
||||
sample_template,
|
||||
):
|
||||
create_notification(
|
||||
sample_template, status="delivered", created_at=datetime(2019, 4, 2, 5, 0)
|
||||
sample_template,
|
||||
status=NotificationStatus.DELIVERED,
|
||||
created_at=datetime(2019, 4, 2, 5, 0),
|
||||
) # too new
|
||||
|
||||
create_notification(
|
||||
sample_template, status="created", created_at=datetime(2019, 4, 2, 5, 59)
|
||||
sample_template,
|
||||
status=NotificationStatus.CREATED,
|
||||
created_at=datetime(2019, 4, 2, 5, 59),
|
||||
)
|
||||
create_notification(
|
||||
sample_template, status="created", created_at=datetime(2019, 4, 1, 4, 0)
|
||||
sample_template,
|
||||
status=NotificationStatus.CREATED,
|
||||
created_at=datetime(2019, 4, 1, 4, 0),
|
||||
)
|
||||
|
||||
create_notification(
|
||||
sample_template, status="delivered", created_at=datetime(2019, 3, 21, 17, 59)
|
||||
sample_template,
|
||||
status=NotificationStatus.DELIVERED,
|
||||
created_at=datetime(2019, 3, 21, 17, 59),
|
||||
) # too old
|
||||
|
||||
create_nightly_notification_status_for_service_and_day(
|
||||
"2019-04-01", sample_template.service_id, "sms"
|
||||
"2019-04-01",
|
||||
sample_template.service_id,
|
||||
NotificationType.SMS,
|
||||
)
|
||||
|
||||
noti_status = FactNotificationStatus.query.order_by(
|
||||
@@ -569,4 +597,4 @@ def test_create_nightly_notification_status_for_service_and_day_respects_bst(
|
||||
assert len(noti_status) == 1
|
||||
|
||||
assert noti_status[0].local_date == date(2019, 4, 1)
|
||||
assert noti_status[0].notification_status == "created"
|
||||
assert noti_status[0].notification_status == NotificationStatus.CREATED
|
||||
|
||||
@@ -19,12 +19,7 @@ from app.celery.scheduled_tasks import (
|
||||
)
|
||||
from app.config import QueueNames, Test
|
||||
from app.dao.jobs_dao import dao_get_job_by_id
|
||||
from app.models import (
|
||||
JOB_STATUS_ERROR,
|
||||
JOB_STATUS_FINISHED,
|
||||
JOB_STATUS_IN_PROGRESS,
|
||||
JOB_STATUS_PENDING,
|
||||
)
|
||||
from app.enums import JobStatus, NotificationStatus, TemplateType
|
||||
from tests.app import load_example_csv
|
||||
from tests.app.db import create_job, create_notification, create_template
|
||||
|
||||
@@ -106,13 +101,15 @@ def test_should_update_scheduled_jobs_and_put_on_queue(mocker, sample_template):
|
||||
|
||||
one_minute_in_the_past = datetime.utcnow() - timedelta(minutes=1)
|
||||
job = create_job(
|
||||
sample_template, job_status="scheduled", scheduled_for=one_minute_in_the_past
|
||||
sample_template,
|
||||
job_status=JobStatus.SCHEDULED,
|
||||
scheduled_for=one_minute_in_the_past,
|
||||
)
|
||||
|
||||
run_scheduled_jobs()
|
||||
|
||||
updated_job = dao_get_job_by_id(job.id)
|
||||
assert updated_job.job_status == "pending"
|
||||
assert updated_job.job_status == JobStatus.PENDING
|
||||
mocked.assert_called_with([str(job.id)], queue="job-tasks")
|
||||
|
||||
|
||||
@@ -123,22 +120,26 @@ def test_should_update_all_scheduled_jobs_and_put_on_queue(sample_template, mock
|
||||
ten_minutes_in_the_past = datetime.utcnow() - timedelta(minutes=10)
|
||||
twenty_minutes_in_the_past = datetime.utcnow() - timedelta(minutes=20)
|
||||
job_1 = create_job(
|
||||
sample_template, job_status="scheduled", scheduled_for=one_minute_in_the_past
|
||||
sample_template,
|
||||
job_status=JobStatus.SCHEDULED,
|
||||
scheduled_for=one_minute_in_the_past,
|
||||
)
|
||||
job_2 = create_job(
|
||||
sample_template, job_status="scheduled", scheduled_for=ten_minutes_in_the_past
|
||||
sample_template,
|
||||
job_status=JobStatus.SCHEDULED,
|
||||
scheduled_for=ten_minutes_in_the_past,
|
||||
)
|
||||
job_3 = create_job(
|
||||
sample_template,
|
||||
job_status="scheduled",
|
||||
job_status=JobStatus.SCHEDULED,
|
||||
scheduled_for=twenty_minutes_in_the_past,
|
||||
)
|
||||
|
||||
run_scheduled_jobs()
|
||||
|
||||
assert dao_get_job_by_id(job_1.id).job_status == "pending"
|
||||
assert dao_get_job_by_id(job_2.id).job_status == "pending"
|
||||
assert dao_get_job_by_id(job_2.id).job_status == "pending"
|
||||
assert dao_get_job_by_id(job_1.id).job_status == JobStatus.PENDING
|
||||
assert dao_get_job_by_id(job_2.id).job_status == JobStatus.PENDING
|
||||
assert dao_get_job_by_id(job_2.id).job_status == JobStatus.PENDING
|
||||
|
||||
mocked.assert_has_calls(
|
||||
[
|
||||
@@ -156,7 +157,7 @@ def test_check_job_status_task_calls_process_incomplete_jobs(mocker, sample_temp
|
||||
notification_count=3,
|
||||
created_at=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_IN_PROGRESS,
|
||||
job_status=JobStatus.IN_PROGRESS,
|
||||
)
|
||||
create_notification(template=sample_template, job=job)
|
||||
check_job_status()
|
||||
@@ -174,7 +175,7 @@ def test_check_job_status_task_calls_process_incomplete_jobs_when_scheduled_job_
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_IN_PROGRESS,
|
||||
job_status=JobStatus.IN_PROGRESS,
|
||||
)
|
||||
check_job_status()
|
||||
|
||||
@@ -190,7 +191,7 @@ def test_check_job_status_task_calls_process_incomplete_jobs_for_pending_schedul
|
||||
notification_count=3,
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_PENDING,
|
||||
job_status=JobStatus.PENDING,
|
||||
)
|
||||
|
||||
check_job_status()
|
||||
@@ -207,7 +208,7 @@ def test_check_job_status_task_does_not_call_process_incomplete_jobs_for_non_sch
|
||||
template=sample_template,
|
||||
notification_count=3,
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
job_status=JOB_STATUS_PENDING,
|
||||
job_status=JobStatus.PENDING,
|
||||
)
|
||||
check_job_status()
|
||||
|
||||
@@ -224,7 +225,7 @@ def test_check_job_status_task_calls_process_incomplete_jobs_for_multiple_jobs(
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_IN_PROGRESS,
|
||||
job_status=JobStatus.IN_PROGRESS,
|
||||
)
|
||||
job_2 = create_job(
|
||||
template=sample_template,
|
||||
@@ -232,7 +233,7 @@ def test_check_job_status_task_calls_process_incomplete_jobs_for_multiple_jobs(
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_IN_PROGRESS,
|
||||
job_status=JobStatus.IN_PROGRESS,
|
||||
)
|
||||
check_job_status()
|
||||
|
||||
@@ -249,21 +250,21 @@ def test_check_job_status_task_only_sends_old_tasks(mocker, sample_template):
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_IN_PROGRESS,
|
||||
job_status=JobStatus.IN_PROGRESS,
|
||||
)
|
||||
create_job(
|
||||
template=sample_template,
|
||||
notification_count=3,
|
||||
created_at=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=29),
|
||||
job_status=JOB_STATUS_IN_PROGRESS,
|
||||
job_status=JobStatus.IN_PROGRESS,
|
||||
)
|
||||
create_job(
|
||||
template=sample_template,
|
||||
notification_count=3,
|
||||
created_at=datetime.utcnow() - timedelta(minutes=50),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=29),
|
||||
job_status=JOB_STATUS_PENDING,
|
||||
job_status=JobStatus.PENDING,
|
||||
)
|
||||
check_job_status()
|
||||
|
||||
@@ -279,21 +280,21 @@ def test_check_job_status_task_sets_jobs_to_error(mocker, sample_template):
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_IN_PROGRESS,
|
||||
job_status=JobStatus.IN_PROGRESS,
|
||||
)
|
||||
job_2 = create_job(
|
||||
template=sample_template,
|
||||
notification_count=3,
|
||||
created_at=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=29),
|
||||
job_status=JOB_STATUS_IN_PROGRESS,
|
||||
job_status=JobStatus.IN_PROGRESS,
|
||||
)
|
||||
check_job_status()
|
||||
|
||||
# job 2 not in celery task
|
||||
mock_celery.assert_called_once_with([[str(job.id)]], queue=QueueNames.JOBS)
|
||||
assert job.job_status == JOB_STATUS_ERROR
|
||||
assert job_2.job_status == JOB_STATUS_IN_PROGRESS
|
||||
assert job.job_status == JobStatus.ERROR
|
||||
assert job_2.job_status == JobStatus.IN_PROGRESS
|
||||
|
||||
|
||||
def test_replay_created_notifications(notify_db_session, sample_service, mocker):
|
||||
@@ -304,36 +305,44 @@ def test_replay_created_notifications(notify_db_session, sample_service, mocker)
|
||||
"app.celery.provider_tasks.deliver_sms.apply_async"
|
||||
)
|
||||
|
||||
sms_template = create_template(service=sample_service, template_type="sms")
|
||||
email_template = create_template(service=sample_service, template_type="email")
|
||||
sms_template = create_template(
|
||||
service=sample_service, template_type=TemplateType.SMS
|
||||
)
|
||||
email_template = create_template(
|
||||
service=sample_service, template_type=TemplateType.EMAIL
|
||||
)
|
||||
older_than = (60 * 60) + (60 * 15) # 1 hour 15 minutes
|
||||
# notifications expected to be resent
|
||||
old_sms = create_notification(
|
||||
template=sms_template,
|
||||
created_at=datetime.utcnow() - timedelta(seconds=older_than),
|
||||
status="created",
|
||||
status=NotificationStatus.CREATED,
|
||||
)
|
||||
old_email = create_notification(
|
||||
template=email_template,
|
||||
created_at=datetime.utcnow() - timedelta(seconds=older_than),
|
||||
status="created",
|
||||
status=NotificationStatus.CREATED,
|
||||
)
|
||||
# notifications that are not to be resent
|
||||
create_notification(
|
||||
template=sms_template,
|
||||
created_at=datetime.utcnow() - timedelta(seconds=older_than),
|
||||
status="sending",
|
||||
status=NotificationStatus.SENDING,
|
||||
)
|
||||
create_notification(
|
||||
template=email_template,
|
||||
created_at=datetime.utcnow() - timedelta(seconds=older_than),
|
||||
status="delivered",
|
||||
status=NotificationStatus.DELIVERED,
|
||||
)
|
||||
create_notification(
|
||||
template=sms_template, created_at=datetime.utcnow(), status="created"
|
||||
template=sms_template,
|
||||
created_at=datetime.utcnow(),
|
||||
status=NotificationStatus.CREATED,
|
||||
)
|
||||
create_notification(
|
||||
template=email_template, created_at=datetime.utcnow(), status="created"
|
||||
template=email_template,
|
||||
created_at=datetime.utcnow(),
|
||||
status=NotificationStatus.CREATED,
|
||||
)
|
||||
|
||||
replay_created_notifications()
|
||||
@@ -352,14 +361,14 @@ def test_check_job_status_task_does_not_raise_error(sample_template):
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_FINISHED,
|
||||
job_status=JobStatus.FINISHED,
|
||||
)
|
||||
create_job(
|
||||
template=sample_template,
|
||||
notification_count=3,
|
||||
created_at=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_FINISHED,
|
||||
job_status=JobStatus.FINISHED,
|
||||
)
|
||||
|
||||
check_job_status()
|
||||
@@ -389,7 +398,7 @@ def test_check_for_missing_rows_in_completed_jobs_ignores_old_and_new_jobs(
|
||||
job = create_job(
|
||||
template=sample_email_template,
|
||||
notification_count=5,
|
||||
job_status=JOB_STATUS_FINISHED,
|
||||
job_status=JobStatus.FINISHED,
|
||||
processing_finished=datetime.utcnow() - offset,
|
||||
)
|
||||
for i in range(0, 4):
|
||||
@@ -411,7 +420,7 @@ def test_check_for_missing_rows_in_completed_jobs(mocker, sample_email_template)
|
||||
job = create_job(
|
||||
template=sample_email_template,
|
||||
notification_count=5,
|
||||
job_status=JOB_STATUS_FINISHED,
|
||||
job_status=JobStatus.FINISHED,
|
||||
processing_finished=datetime.utcnow() - timedelta(minutes=20),
|
||||
)
|
||||
for i in range(0, 4):
|
||||
@@ -438,7 +447,7 @@ def test_check_for_missing_rows_in_completed_jobs_calls_save_email(
|
||||
job = create_job(
|
||||
template=sample_email_template,
|
||||
notification_count=5,
|
||||
job_status=JOB_STATUS_FINISHED,
|
||||
job_status=JobStatus.FINISHED,
|
||||
processing_finished=datetime.utcnow() - timedelta(minutes=20),
|
||||
)
|
||||
for i in range(0, 4):
|
||||
@@ -468,7 +477,7 @@ def test_check_for_missing_rows_in_completed_jobs_uses_sender_id(
|
||||
job = create_job(
|
||||
template=sample_email_template,
|
||||
notification_count=5,
|
||||
job_status=JOB_STATUS_FINISHED,
|
||||
job_status=JobStatus.FINISHED,
|
||||
processing_finished=datetime.utcnow() - timedelta(minutes=20),
|
||||
)
|
||||
for i in range(0, 4):
|
||||
|
||||
@@ -10,6 +10,7 @@ from app.celery.service_callback_tasks import (
|
||||
send_complaint_to_service,
|
||||
send_delivery_status_to_service,
|
||||
)
|
||||
from app.enums import CallbackType, NotificationStatus, NotificationType
|
||||
from app.utils import DATETIME_FORMAT
|
||||
from tests.app.db import (
|
||||
create_complaint,
|
||||
@@ -20,11 +21,16 @@ from tests.app.db import (
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("notification_type", ["email", "sms"])
|
||||
@pytest.mark.parametrize(
|
||||
"notification_type", [NotificationType.EMAIL, NotificationType.SMS]
|
||||
)
|
||||
def test_send_delivery_status_to_service_post_https_request_to_service_with_encrypted_data(
|
||||
notify_db_session, notification_type
|
||||
):
|
||||
callback_api, template = _set_up_test_data(notification_type, "delivery_status")
|
||||
callback_api, template = _set_up_test_data(
|
||||
notification_type,
|
||||
CallbackType.DELIVERY_STATUS,
|
||||
)
|
||||
datestr = datetime(2017, 6, 20)
|
||||
|
||||
notification = create_notification(
|
||||
@@ -32,7 +38,7 @@ def test_send_delivery_status_to_service_post_https_request_to_service_with_encr
|
||||
created_at=datestr,
|
||||
updated_at=datestr,
|
||||
sent_at=datestr,
|
||||
status="sent",
|
||||
status=NotificationStatus.SENT,
|
||||
)
|
||||
encrypted_status_update = _set_up_data_for_status_update(callback_api, notification)
|
||||
with requests_mock.Mocker() as request_mock:
|
||||
@@ -64,16 +70,20 @@ def test_send_delivery_status_to_service_post_https_request_to_service_with_encr
|
||||
assert request_mock.request_history[0].method == "POST"
|
||||
assert actual_data == json.dumps(mock_data)
|
||||
assert request_mock.request_history[0].headers["Content-type"] == "application/json"
|
||||
assert request_mock.request_history[0].headers[
|
||||
"Authorization"
|
||||
] == "Bearer {}".format(callback_api.bearer_token)
|
||||
assert (
|
||||
request_mock.request_history[0].headers["Authorization"]
|
||||
== f"Bearer {callback_api.bearer_token}"
|
||||
)
|
||||
|
||||
|
||||
def test_send_complaint_to_service_posts_https_request_to_service_with_encrypted_data(
|
||||
notify_db_session,
|
||||
):
|
||||
with freeze_time("2001-01-01T12:00:00"):
|
||||
callback_api, template = _set_up_test_data("email", "complaint")
|
||||
callback_api, template = _set_up_test_data(
|
||||
NotificationType.EMAIL,
|
||||
CallbackType.COMPLAINT,
|
||||
)
|
||||
|
||||
notification = create_notification(template=template)
|
||||
complaint = create_complaint(
|
||||
@@ -102,24 +112,31 @@ def test_send_complaint_to_service_posts_https_request_to_service_with_encrypted
|
||||
request_mock.request_history[0].headers["Content-type"]
|
||||
== "application/json"
|
||||
)
|
||||
assert request_mock.request_history[0].headers[
|
||||
"Authorization"
|
||||
] == "Bearer {}".format(callback_api.bearer_token)
|
||||
assert (
|
||||
request_mock.request_history[0].headers["Authorization"]
|
||||
== f"Bearer {callback_api.bearer_token}"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("notification_type", ["email", "sms"])
|
||||
@pytest.mark.parametrize(
|
||||
"notification_type",
|
||||
[NotificationType.EMAIL, NotificationType.SMS],
|
||||
)
|
||||
@pytest.mark.parametrize("status_code", [429, 500, 503])
|
||||
def test__send_data_to_service_callback_api_retries_if_request_returns_error_code_with_encrypted_data(
|
||||
notify_db_session, mocker, notification_type, status_code
|
||||
):
|
||||
callback_api, template = _set_up_test_data(notification_type, "delivery_status")
|
||||
callback_api, template = _set_up_test_data(
|
||||
notification_type,
|
||||
CallbackType.DELIVERY_STATUS,
|
||||
)
|
||||
datestr = datetime(2017, 6, 20)
|
||||
notification = create_notification(
|
||||
template=template,
|
||||
created_at=datestr,
|
||||
updated_at=datestr,
|
||||
sent_at=datestr,
|
||||
status="sent",
|
||||
status=NotificationStatus.SENT,
|
||||
)
|
||||
encrypted_data = _set_up_data_for_status_update(callback_api, notification)
|
||||
mocked = mocker.patch(
|
||||
@@ -135,18 +152,24 @@ def test__send_data_to_service_callback_api_retries_if_request_returns_error_cod
|
||||
assert mocked.call_args[1]["queue"] == "service-callbacks-retry"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("notification_type", ["email", "sms"])
|
||||
@pytest.mark.parametrize(
|
||||
"notification_type",
|
||||
[NotificationType.EMAIL, NotificationType.SMS],
|
||||
)
|
||||
def test__send_data_to_service_callback_api_does_not_retry_if_request_returns_404_with_encrypted_data(
|
||||
notify_db_session, mocker, notification_type
|
||||
):
|
||||
callback_api, template = _set_up_test_data(notification_type, "delivery_status")
|
||||
callback_api, template = _set_up_test_data(
|
||||
notification_type,
|
||||
CallbackType.DELIVERY_STATUS,
|
||||
)
|
||||
datestr = datetime(2017, 6, 20)
|
||||
notification = create_notification(
|
||||
template=template,
|
||||
created_at=datestr,
|
||||
updated_at=datestr,
|
||||
sent_at=datestr,
|
||||
status="sent",
|
||||
status=NotificationStatus.SENT,
|
||||
)
|
||||
encrypted_data = _set_up_data_for_status_update(callback_api, notification)
|
||||
mocked = mocker.patch(
|
||||
@@ -164,14 +187,17 @@ def test__send_data_to_service_callback_api_does_not_retry_if_request_returns_40
|
||||
def test_send_delivery_status_to_service_succeeds_if_sent_at_is_none(
|
||||
notify_db_session, mocker
|
||||
):
|
||||
callback_api, template = _set_up_test_data("email", "delivery_status")
|
||||
callback_api, template = _set_up_test_data(
|
||||
NotificationType.EMAIL,
|
||||
CallbackType.DELIVERY_STATUS,
|
||||
)
|
||||
datestr = datetime(2017, 6, 20)
|
||||
notification = create_notification(
|
||||
template=template,
|
||||
created_at=datestr,
|
||||
updated_at=datestr,
|
||||
sent_at=None,
|
||||
status="technical-failure",
|
||||
status=NotificationStatus.TECHNICAL_FAILURE,
|
||||
)
|
||||
encrypted_data = _set_up_data_for_status_update(callback_api, notification)
|
||||
mocked = mocker.patch(
|
||||
|
||||
@@ -29,17 +29,14 @@ from app.celery.tasks import (
|
||||
)
|
||||
from app.config import QueueNames
|
||||
from app.dao import jobs_dao, service_email_reply_to_dao, service_sms_sender_dao
|
||||
from app.models import (
|
||||
EMAIL_TYPE,
|
||||
JOB_STATUS_ERROR,
|
||||
JOB_STATUS_FINISHED,
|
||||
JOB_STATUS_IN_PROGRESS,
|
||||
KEY_TYPE_NORMAL,
|
||||
NOTIFICATION_CREATED,
|
||||
SMS_TYPE,
|
||||
Job,
|
||||
Notification,
|
||||
from app.enums import (
|
||||
JobStatus,
|
||||
KeyType,
|
||||
NotificationStatus,
|
||||
NotificationType,
|
||||
TemplateType,
|
||||
)
|
||||
from app.models import Job, Notification
|
||||
from app.serialised_models import SerialisedService, SerialisedTemplate
|
||||
from app.utils import DATETIME_FORMAT
|
||||
from tests.app import load_example_csv
|
||||
@@ -119,7 +116,7 @@ def test_should_process_sms_job(sample_job, mocker):
|
||||
queue="database-tasks",
|
||||
)
|
||||
job = jobs_dao.dao_get_job_by_id(sample_job.id)
|
||||
assert job.job_status == "finished"
|
||||
assert job.job_status == JobStatus.FINISHED
|
||||
|
||||
|
||||
def test_should_process_sms_job_with_sender_id(sample_job, mocker, fake_uuid):
|
||||
@@ -141,7 +138,7 @@ def test_should_process_sms_job_with_sender_id(sample_job, mocker, fake_uuid):
|
||||
|
||||
|
||||
def test_should_not_process_job_if_already_pending(sample_template, mocker):
|
||||
job = create_job(template=sample_template, job_status="scheduled")
|
||||
job = create_job(template=sample_template, job_status=JobStatus.SCHEDULED)
|
||||
|
||||
mocker.patch("app.celery.tasks.s3.get_job_and_metadata_from_s3")
|
||||
mocker.patch("app.celery.tasks.process_row")
|
||||
@@ -156,7 +153,7 @@ def test_should_process_job_if_send_limits_are_not_exceeded(
|
||||
notify_api, notify_db_session, mocker
|
||||
):
|
||||
service = create_service(message_limit=10)
|
||||
template = create_template(service=service, template_type="email")
|
||||
template = create_template(service=service, template_type=TemplateType.EMAIL)
|
||||
job = create_job(template=template, notification_count=10)
|
||||
|
||||
mocker.patch(
|
||||
@@ -172,7 +169,7 @@ def test_should_process_job_if_send_limits_are_not_exceeded(
|
||||
service_id=str(job.service.id), job_id=str(job.id)
|
||||
)
|
||||
job = jobs_dao.dao_get_job_by_id(job.id)
|
||||
assert job.job_status == "finished"
|
||||
assert job.job_status == JobStatus.FINISHED
|
||||
tasks.save_email.apply_async.assert_called_with(
|
||||
(
|
||||
str(job.service_id),
|
||||
@@ -197,7 +194,7 @@ def test_should_not_create_save_task_for_empty_file(sample_job, mocker):
|
||||
service_id=str(sample_job.service.id), job_id=str(sample_job.id)
|
||||
)
|
||||
job = jobs_dao.dao_get_job_by_id(sample_job.id)
|
||||
assert job.job_status == "finished"
|
||||
assert job.job_status == JobStatus.FINISHED
|
||||
assert tasks.save_sms.apply_async.called is False
|
||||
|
||||
|
||||
@@ -241,7 +238,7 @@ def test_should_process_email_job(email_job_with_placeholders, mocker):
|
||||
queue="database-tasks",
|
||||
)
|
||||
job = jobs_dao.dao_get_job_by_id(email_job_with_placeholders.id)
|
||||
assert job.job_status == "finished"
|
||||
assert job.job_status == JobStatus.FINISHED
|
||||
|
||||
|
||||
def test_should_process_email_job_with_sender_id(
|
||||
@@ -296,7 +293,7 @@ def test_should_process_all_sms_job(sample_job_with_placeholdered_template, mock
|
||||
}
|
||||
assert tasks.save_sms.apply_async.call_count == 10
|
||||
job = jobs_dao.dao_get_job_by_id(sample_job_with_placeholdered_template.id)
|
||||
assert job.job_status == "finished"
|
||||
assert job.job_status == JobStatus.FINISHED
|
||||
|
||||
|
||||
# -------------- process_row tests -------------- #
|
||||
@@ -305,17 +302,15 @@ def test_should_process_all_sms_job(sample_job_with_placeholdered_template, mock
|
||||
@pytest.mark.parametrize(
|
||||
"template_type, expected_function, expected_queue",
|
||||
[
|
||||
(SMS_TYPE, "save_sms", "database-tasks"),
|
||||
(EMAIL_TYPE, "save_email", "database-tasks"),
|
||||
(TemplateType.SMS, "save_sms", "database-tasks"),
|
||||
(TemplateType.EMAIL, "save_email", "database-tasks"),
|
||||
],
|
||||
)
|
||||
def test_process_row_sends_letter_task(
|
||||
template_type, expected_function, expected_queue, mocker
|
||||
):
|
||||
mocker.patch("app.celery.tasks.create_uuid", return_value="noti_uuid")
|
||||
task_mock = mocker.patch(
|
||||
"app.celery.tasks.{}.apply_async".format(expected_function)
|
||||
)
|
||||
task_mock = mocker.patch(f"app.celery.tasks.{expected_function}.apply_async")
|
||||
encrypt_mock = mocker.patch("app.celery.tasks.encryption.encrypt")
|
||||
template = Mock(id="template_id", template_type=template_type)
|
||||
job = Mock(id="job_id", template_version="temp_vers")
|
||||
@@ -362,7 +357,7 @@ def test_process_row_when_sender_id_is_provided(mocker, fake_uuid):
|
||||
mocker.patch("app.celery.tasks.create_uuid", return_value="noti_uuid")
|
||||
task_mock = mocker.patch("app.celery.tasks.save_sms.apply_async")
|
||||
encrypt_mock = mocker.patch("app.celery.tasks.encryption.encrypt")
|
||||
template = Mock(id="template_id", template_type=SMS_TYPE)
|
||||
template = Mock(id="template_id", template_type=TemplateType.SMS)
|
||||
job = Mock(id="job_id", template_version="temp_vers")
|
||||
service = Mock(id="service_id", research_mode=False)
|
||||
|
||||
@@ -423,13 +418,13 @@ def test_should_send_template_to_correct_sms_task_and_persist(
|
||||
persisted_notification.template_version
|
||||
== sample_template_with_placeholders.version
|
||||
)
|
||||
assert persisted_notification.status == "created"
|
||||
assert persisted_notification.status == NotificationStatus.CREATED
|
||||
assert persisted_notification.created_at <= datetime.utcnow()
|
||||
assert not persisted_notification.sent_at
|
||||
assert not persisted_notification.sent_by
|
||||
assert not persisted_notification.job_id
|
||||
assert persisted_notification.personalisation == {}
|
||||
assert persisted_notification.notification_type == "sms"
|
||||
assert persisted_notification.notification_type == NotificationType.SMS
|
||||
mocked_deliver_sms.assert_called_once_with(
|
||||
[str(persisted_notification.id)], queue="send-sms-tasks"
|
||||
)
|
||||
@@ -459,13 +454,13 @@ def test_should_save_sms_if_restricted_service_and_valid_number(
|
||||
assert persisted_notification.to == "1"
|
||||
assert persisted_notification.template_id == template.id
|
||||
assert persisted_notification.template_version == template.version
|
||||
assert persisted_notification.status == "created"
|
||||
assert persisted_notification.status == NotificationStatus.CREATED
|
||||
assert persisted_notification.created_at <= datetime.utcnow()
|
||||
assert not persisted_notification.sent_at
|
||||
assert not persisted_notification.sent_by
|
||||
assert not persisted_notification.job_id
|
||||
assert not persisted_notification.personalisation
|
||||
assert persisted_notification.notification_type == "sms"
|
||||
assert persisted_notification.notification_type == NotificationType.SMS
|
||||
provider_tasks.deliver_sms.apply_async.assert_called_once_with(
|
||||
[str(persisted_notification.id)], queue="send-sms-tasks"
|
||||
)
|
||||
@@ -478,7 +473,11 @@ def test_save_email_should_save_default_email_reply_to_text_on_notification(
|
||||
create_reply_to_email(
|
||||
service=service, email_address="reply_to@digital.fake.gov", is_default=True
|
||||
)
|
||||
template = create_template(service=service, template_type="email", subject="Hello")
|
||||
template = create_template(
|
||||
service=service,
|
||||
template_type=TemplateType.EMAIL,
|
||||
subject="Hello",
|
||||
)
|
||||
|
||||
notification = _notification_json(template, to="test@example.com")
|
||||
mocker.patch("app.celery.provider_tasks.deliver_email.apply_async")
|
||||
@@ -539,7 +538,11 @@ def test_should_not_save_email_if_restricted_service_and_invalid_email_address(
|
||||
):
|
||||
user = create_user()
|
||||
service = create_service(user=user, restricted=True)
|
||||
template = create_template(service=service, template_type="email", subject="Hello")
|
||||
template = create_template(
|
||||
service=service,
|
||||
template_type=TemplateType.EMAIL,
|
||||
subject="Hello",
|
||||
)
|
||||
notification = _notification_json(template, to="test@example.com")
|
||||
|
||||
notification_id = uuid.uuid4()
|
||||
@@ -554,7 +557,10 @@ def test_should_not_save_email_if_restricted_service_and_invalid_email_address(
|
||||
|
||||
def test_should_save_sms_template_to_and_persist_with_job_id(sample_job, mocker):
|
||||
notification = _notification_json(
|
||||
sample_job.template, to="+447234123123", job_id=sample_job.id, row_number=2
|
||||
sample_job.template,
|
||||
to="+447234123123",
|
||||
job_id=sample_job.id,
|
||||
row_number=2,
|
||||
)
|
||||
mocker.patch("app.celery.provider_tasks.deliver_sms.apply_async")
|
||||
|
||||
@@ -569,14 +575,14 @@ def test_should_save_sms_template_to_and_persist_with_job_id(sample_job, mocker)
|
||||
assert persisted_notification.to == "1"
|
||||
assert persisted_notification.job_id == sample_job.id
|
||||
assert persisted_notification.template_id == sample_job.template.id
|
||||
assert persisted_notification.status == "created"
|
||||
assert persisted_notification.status == NotificationStatus.CREATED
|
||||
assert not persisted_notification.sent_at
|
||||
assert persisted_notification.created_at >= now
|
||||
assert not persisted_notification.sent_by
|
||||
assert persisted_notification.job_row_number == 2
|
||||
assert persisted_notification.api_key_id is None
|
||||
assert persisted_notification.key_type == KEY_TYPE_NORMAL
|
||||
assert persisted_notification.notification_type == "sms"
|
||||
assert persisted_notification.key_type == KeyType.NORMAL
|
||||
assert persisted_notification.notification_type == NotificationType.SMS
|
||||
|
||||
provider_tasks.deliver_sms.apply_async.assert_called_once_with(
|
||||
[str(persisted_notification.id)], queue="send-sms-tasks"
|
||||
@@ -641,13 +647,13 @@ def test_should_use_email_template_and_persist(
|
||||
)
|
||||
assert persisted_notification.created_at >= now
|
||||
assert not persisted_notification.sent_at
|
||||
assert persisted_notification.status == "created"
|
||||
assert persisted_notification.status == NotificationStatus.CREATED
|
||||
assert not persisted_notification.sent_by
|
||||
assert persisted_notification.job_row_number == 1
|
||||
assert persisted_notification.personalisation == {}
|
||||
assert persisted_notification.api_key_id is None
|
||||
assert persisted_notification.key_type == KEY_TYPE_NORMAL
|
||||
assert persisted_notification.notification_type == "email"
|
||||
assert persisted_notification.key_type == KeyType.NORMAL
|
||||
assert persisted_notification.notification_type == NotificationType.EMAIL
|
||||
|
||||
provider_tasks.deliver_email.apply_async.assert_called_once_with(
|
||||
[str(persisted_notification.id)], queue="send-email-tasks"
|
||||
@@ -683,9 +689,9 @@ def test_save_email_should_use_template_version_from_job_not_latest(
|
||||
assert persisted_notification.template_version == version_on_notification
|
||||
assert persisted_notification.created_at >= now
|
||||
assert not persisted_notification.sent_at
|
||||
assert persisted_notification.status == "created"
|
||||
assert persisted_notification.status == NotificationStatus.CREATED
|
||||
assert not persisted_notification.sent_by
|
||||
assert persisted_notification.notification_type == "email"
|
||||
assert persisted_notification.notification_type == NotificationType.EMAIL
|
||||
provider_tasks.deliver_email.apply_async.assert_called_once_with(
|
||||
[str(persisted_notification.id)], queue="send-email-tasks"
|
||||
)
|
||||
@@ -711,12 +717,12 @@ def test_should_use_email_template_subject_placeholders(
|
||||
assert (
|
||||
persisted_notification.template_id == sample_email_template_with_placeholders.id
|
||||
)
|
||||
assert persisted_notification.status == "created"
|
||||
assert persisted_notification.status == NotificationStatus.CREATED
|
||||
assert persisted_notification.created_at >= now
|
||||
assert not persisted_notification.sent_by
|
||||
assert persisted_notification.personalisation == {}
|
||||
assert not persisted_notification.reference
|
||||
assert persisted_notification.notification_type == "email"
|
||||
assert persisted_notification.notification_type == NotificationType.EMAIL
|
||||
provider_tasks.deliver_email.apply_async.assert_called_once_with(
|
||||
[str(persisted_notification.id)], queue="send-email-tasks"
|
||||
)
|
||||
@@ -729,11 +735,15 @@ def test_save_email_uses_the_reply_to_text_when_provided(sample_email_template,
|
||||
service = sample_email_template.service
|
||||
notification_id = uuid.uuid4()
|
||||
service_email_reply_to_dao.add_reply_to_email_address_for_service(
|
||||
service.id, "default@example.com", True
|
||||
service.id,
|
||||
"default@example.com",
|
||||
True,
|
||||
)
|
||||
other_email_reply_to = (
|
||||
service_email_reply_to_dao.add_reply_to_email_address_for_service(
|
||||
service.id, "other@example.com", False
|
||||
service.id,
|
||||
"other@example.com",
|
||||
False,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -744,7 +754,7 @@ def test_save_email_uses_the_reply_to_text_when_provided(sample_email_template,
|
||||
sender_id=other_email_reply_to.id,
|
||||
)
|
||||
persisted_notification = Notification.query.one()
|
||||
assert persisted_notification.notification_type == "email"
|
||||
assert persisted_notification.notification_type == NotificationType.EMAIL
|
||||
assert persisted_notification.reply_to_text == "other@example.com"
|
||||
|
||||
|
||||
@@ -757,7 +767,9 @@ def test_save_email_uses_the_default_reply_to_text_if_sender_id_is_none(
|
||||
service = sample_email_template.service
|
||||
notification_id = uuid.uuid4()
|
||||
service_email_reply_to_dao.add_reply_to_email_address_for_service(
|
||||
service.id, "default@example.com", True
|
||||
service.id,
|
||||
"default@example.com",
|
||||
True,
|
||||
)
|
||||
|
||||
save_email(
|
||||
@@ -767,7 +779,7 @@ def test_save_email_uses_the_default_reply_to_text_if_sender_id_is_none(
|
||||
sender_id=None,
|
||||
)
|
||||
persisted_notification = Notification.query.one()
|
||||
assert persisted_notification.notification_type == "email"
|
||||
assert persisted_notification.notification_type == NotificationType.EMAIL
|
||||
assert persisted_notification.reply_to_text == "default@example.com"
|
||||
|
||||
|
||||
@@ -790,11 +802,11 @@ def test_should_use_email_template_and_persist_without_personalisation(
|
||||
assert persisted_notification.template_id == sample_email_template.id
|
||||
assert persisted_notification.created_at >= now
|
||||
assert not persisted_notification.sent_at
|
||||
assert persisted_notification.status == "created"
|
||||
assert persisted_notification.status == NotificationStatus.CREATED
|
||||
assert not persisted_notification.sent_by
|
||||
assert not persisted_notification.personalisation
|
||||
assert not persisted_notification.reference
|
||||
assert persisted_notification.notification_type == "email"
|
||||
assert persisted_notification.notification_type == NotificationType.EMAIL
|
||||
provider_tasks.deliver_email.apply_async.assert_called_once_with(
|
||||
[str(persisted_notification.id)], queue="send-email-tasks"
|
||||
)
|
||||
@@ -928,7 +940,9 @@ def test_save_sms_uses_non_default_sms_sender_reply_to_text_if_provided(
|
||||
service = create_service_with_defined_sms_sender(sms_sender_value="2028675309")
|
||||
template = create_template(service=service)
|
||||
new_sender = service_sms_sender_dao.dao_add_sms_sender_for_service(
|
||||
service.id, "new-sender", False
|
||||
service.id,
|
||||
"new-sender",
|
||||
False,
|
||||
)
|
||||
|
||||
notification = _notification_json(template, to="202-867-5301")
|
||||
@@ -955,7 +969,7 @@ def test_should_cancel_job_if_service_is_inactive(sample_service, sample_job, mo
|
||||
process_job(sample_job.id)
|
||||
|
||||
job = jobs_dao.dao_get_job_by_id(sample_job.id)
|
||||
assert job.job_status == "cancelled"
|
||||
assert job.job_status == JobStatus.CANCELLED
|
||||
s3.get_job_from_s3.assert_not_called()
|
||||
tasks.process_row.assert_not_called()
|
||||
|
||||
@@ -1023,9 +1037,10 @@ def test_send_inbound_sms_to_service_post_https_request_to_service(
|
||||
assert request_mock.request_history[0].method == "POST"
|
||||
assert request_mock.request_history[0].text == json.dumps(data)
|
||||
assert request_mock.request_history[0].headers["Content-type"] == "application/json"
|
||||
assert request_mock.request_history[0].headers[
|
||||
"Authorization"
|
||||
] == "Bearer {}".format(inbound_api.bearer_token)
|
||||
assert (
|
||||
request_mock.request_history[0].headers["Authorization"]
|
||||
== f"Bearer {inbound_api.bearer_token}"
|
||||
)
|
||||
|
||||
|
||||
def test_send_inbound_sms_to_service_does_not_send_request_when_inbound_sms_does_not_exist(
|
||||
@@ -1145,7 +1160,7 @@ def test_process_incomplete_job_sms(mocker, sample_template):
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_ERROR,
|
||||
job_status=JobStatus.ERROR,
|
||||
)
|
||||
|
||||
create_notification(sample_template, job, 0)
|
||||
@@ -1157,7 +1172,7 @@ def test_process_incomplete_job_sms(mocker, sample_template):
|
||||
|
||||
completed_job = Job.query.filter(Job.id == job.id).one()
|
||||
|
||||
assert completed_job.job_status == JOB_STATUS_FINISHED
|
||||
assert completed_job.job_status == JobStatus.FINISHED
|
||||
|
||||
assert (
|
||||
save_sms.call_count == 8
|
||||
@@ -1177,7 +1192,7 @@ def test_process_incomplete_job_with_notifications_all_sent(mocker, sample_templ
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_ERROR,
|
||||
job_status=JobStatus.ERROR,
|
||||
)
|
||||
|
||||
create_notification(sample_template, job, 0)
|
||||
@@ -1197,7 +1212,7 @@ def test_process_incomplete_job_with_notifications_all_sent(mocker, sample_templ
|
||||
|
||||
completed_job = Job.query.filter(Job.id == job.id).one()
|
||||
|
||||
assert completed_job.job_status == JOB_STATUS_FINISHED
|
||||
assert completed_job.job_status == JobStatus.FINISHED
|
||||
|
||||
assert (
|
||||
mock_save_sms.call_count == 0
|
||||
@@ -1217,7 +1232,7 @@ def test_process_incomplete_jobs_sms(mocker, sample_template):
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_ERROR,
|
||||
job_status=JobStatus.ERROR,
|
||||
)
|
||||
create_notification(sample_template, job, 0)
|
||||
create_notification(sample_template, job, 1)
|
||||
@@ -1231,7 +1246,7 @@ def test_process_incomplete_jobs_sms(mocker, sample_template):
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_ERROR,
|
||||
job_status=JobStatus.ERROR,
|
||||
)
|
||||
|
||||
create_notification(sample_template, job2, 0)
|
||||
@@ -1248,9 +1263,9 @@ def test_process_incomplete_jobs_sms(mocker, sample_template):
|
||||
completed_job = Job.query.filter(Job.id == job.id).one()
|
||||
completed_job2 = Job.query.filter(Job.id == job2.id).one()
|
||||
|
||||
assert completed_job.job_status == JOB_STATUS_FINISHED
|
||||
assert completed_job.job_status == JobStatus.FINISHED
|
||||
|
||||
assert completed_job2.job_status == JOB_STATUS_FINISHED
|
||||
assert completed_job2.job_status == JobStatus.FINISHED
|
||||
|
||||
assert (
|
||||
mock_save_sms.call_count == 12
|
||||
@@ -1270,7 +1285,7 @@ def test_process_incomplete_jobs_no_notifications_added(mocker, sample_template)
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_ERROR,
|
||||
job_status=JobStatus.ERROR,
|
||||
)
|
||||
|
||||
assert Notification.query.filter(Notification.job_id == job.id).count() == 0
|
||||
@@ -1279,7 +1294,7 @@ def test_process_incomplete_jobs_no_notifications_added(mocker, sample_template)
|
||||
|
||||
completed_job = Job.query.filter(Job.id == job.id).one()
|
||||
|
||||
assert completed_job.job_status == JOB_STATUS_FINISHED
|
||||
assert completed_job.job_status == JobStatus.FINISHED
|
||||
|
||||
assert mock_save_sms.call_count == 10 # There are 10 in the csv file
|
||||
|
||||
@@ -1327,7 +1342,7 @@ def test_process_incomplete_job_email(mocker, sample_email_template):
|
||||
created_at=datetime.utcnow() - timedelta(hours=2),
|
||||
scheduled_for=datetime.utcnow() - timedelta(minutes=31),
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_ERROR,
|
||||
job_status=JobStatus.ERROR,
|
||||
)
|
||||
|
||||
create_notification(sample_email_template, job, 0)
|
||||
@@ -1339,7 +1354,7 @@ def test_process_incomplete_job_email(mocker, sample_email_template):
|
||||
|
||||
completed_job = Job.query.filter(Job.id == job.id).one()
|
||||
|
||||
assert completed_job.job_status == JOB_STATUS_FINISHED
|
||||
assert completed_job.job_status == JobStatus.FINISHED
|
||||
|
||||
assert (
|
||||
mock_email_saver.call_count == 8
|
||||
@@ -1357,20 +1372,20 @@ def test_process_incomplete_jobs_sets_status_to_in_progress_and_resets_processin
|
||||
job1 = create_job(
|
||||
sample_template,
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=30),
|
||||
job_status=JOB_STATUS_ERROR,
|
||||
job_status=JobStatus.ERROR,
|
||||
)
|
||||
job2 = create_job(
|
||||
sample_template,
|
||||
processing_started=datetime.utcnow() - timedelta(minutes=31),
|
||||
job_status=JOB_STATUS_ERROR,
|
||||
job_status=JobStatus.ERROR,
|
||||
)
|
||||
|
||||
process_incomplete_jobs([str(job1.id), str(job2.id)])
|
||||
|
||||
assert job1.job_status == JOB_STATUS_IN_PROGRESS
|
||||
assert job1.job_status == JobStatus.IN_PROGRESS
|
||||
assert job1.processing_started == datetime.utcnow()
|
||||
|
||||
assert job2.job_status == JOB_STATUS_IN_PROGRESS
|
||||
assert job2.job_status == JobStatus.IN_PROGRESS
|
||||
assert job2.processing_started == datetime.utcnow()
|
||||
|
||||
assert mock_process_incomplete_job.mock_calls == [
|
||||
@@ -1380,12 +1395,15 @@ def test_process_incomplete_jobs_sets_status_to_in_progress_and_resets_processin
|
||||
|
||||
|
||||
@freeze_time("2020-03-25 14:30")
|
||||
@pytest.mark.parametrize("notification_type", ["sms", "email"])
|
||||
@pytest.mark.parametrize(
|
||||
"notification_type",
|
||||
[NotificationType.SMS, NotificationType.EMAIL],
|
||||
)
|
||||
def test_save_api_email_or_sms(mocker, sample_service, notification_type):
|
||||
template = (
|
||||
create_template(sample_service)
|
||||
if notification_type == SMS_TYPE
|
||||
else create_template(sample_service, template_type=EMAIL_TYPE)
|
||||
if notification_type == NotificationType.SMS
|
||||
else create_template(sample_service, template_type=TemplateType.EMAIL)
|
||||
)
|
||||
mock_provider_task = mocker.patch(
|
||||
f"app.celery.provider_tasks.deliver_{notification_type}.apply_async"
|
||||
@@ -1403,11 +1421,11 @@ def test_save_api_email_or_sms(mocker, sample_service, notification_type):
|
||||
"client_reference": "our email",
|
||||
"reply_to_text": None,
|
||||
"document_download_count": 0,
|
||||
"status": NOTIFICATION_CREATED,
|
||||
"status": NotificationStatus.CREATED,
|
||||
"created_at": datetime.utcnow().strftime(DATETIME_FORMAT),
|
||||
}
|
||||
|
||||
if notification_type == EMAIL_TYPE:
|
||||
if notification_type == NotificationType.EMAIL:
|
||||
data.update({"to": "jane.citizen@example.com"})
|
||||
expected_queue = QueueNames.SEND_EMAIL
|
||||
else:
|
||||
@@ -1417,7 +1435,7 @@ def test_save_api_email_or_sms(mocker, sample_service, notification_type):
|
||||
encrypted = encryption.encrypt(data)
|
||||
|
||||
assert len(Notification.query.all()) == 0
|
||||
if notification_type == EMAIL_TYPE:
|
||||
if notification_type == NotificationType.EMAIL:
|
||||
save_api_email(encrypted_notification=encrypted)
|
||||
else:
|
||||
save_api_sms(encrypted_notification=encrypted)
|
||||
@@ -1430,14 +1448,16 @@ def test_save_api_email_or_sms(mocker, sample_service, notification_type):
|
||||
|
||||
|
||||
@freeze_time("2020-03-25 14:30")
|
||||
@pytest.mark.parametrize("notification_type", ["sms", "email"])
|
||||
@pytest.mark.parametrize(
|
||||
"notification_type", [NotificationType.SMS, NotificationType.EMAIL]
|
||||
)
|
||||
def test_save_api_email_dont_retry_if_notification_already_exists(
|
||||
sample_service, mocker, notification_type
|
||||
):
|
||||
template = (
|
||||
create_template(sample_service)
|
||||
if notification_type == SMS_TYPE
|
||||
else create_template(sample_service, template_type=EMAIL_TYPE)
|
||||
if notification_type == NotificationType.SMS
|
||||
else create_template(sample_service, template_type=TemplateType.EMAIL)
|
||||
)
|
||||
mock_provider_task = mocker.patch(
|
||||
f"app.celery.provider_tasks.deliver_{notification_type}.apply_async"
|
||||
@@ -1455,11 +1475,11 @@ def test_save_api_email_dont_retry_if_notification_already_exists(
|
||||
"client_reference": "our email",
|
||||
"reply_to_text": "our.email@gov.uk",
|
||||
"document_download_count": 0,
|
||||
"status": NOTIFICATION_CREATED,
|
||||
"status": NotificationStatus.CREATED,
|
||||
"created_at": datetime.utcnow().strftime(DATETIME_FORMAT),
|
||||
}
|
||||
|
||||
if notification_type == EMAIL_TYPE:
|
||||
if notification_type == NotificationType.EMAIL:
|
||||
data.update({"to": "jane.citizen@example.com"})
|
||||
expected_queue = QueueNames.SEND_EMAIL
|
||||
else:
|
||||
@@ -1469,14 +1489,14 @@ def test_save_api_email_dont_retry_if_notification_already_exists(
|
||||
encrypted = encryption.encrypt(data)
|
||||
assert len(Notification.query.all()) == 0
|
||||
|
||||
if notification_type == EMAIL_TYPE:
|
||||
if notification_type == NotificationType.EMAIL:
|
||||
save_api_email(encrypted_notification=encrypted)
|
||||
else:
|
||||
save_api_sms(encrypted_notification=encrypted)
|
||||
notifications = Notification.query.all()
|
||||
assert len(notifications) == 1
|
||||
# call the task again with the same notification
|
||||
if notification_type == EMAIL_TYPE:
|
||||
if notification_type == NotificationType.EMAIL:
|
||||
save_api_email(encrypted_notification=encrypted)
|
||||
else:
|
||||
save_api_sms(encrypted_notification=encrypted)
|
||||
@@ -1495,13 +1515,13 @@ def test_save_api_email_dont_retry_if_notification_already_exists(
|
||||
save_email,
|
||||
"app.celery.provider_tasks.deliver_email.apply_async",
|
||||
"test@example.com",
|
||||
{"template_type": "email", "subject": "Hello"},
|
||||
{"template_type": TemplateType.EMAIL, "subject": "Hello"},
|
||||
),
|
||||
(
|
||||
save_sms,
|
||||
"app.celery.provider_tasks.deliver_sms.apply_async",
|
||||
"202-867-5309",
|
||||
{"template_type": "sms"},
|
||||
{"template_type": TemplateType.SMS},
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -1552,8 +1572,18 @@ def test_save_tasks_use_cached_service_and_template(
|
||||
@pytest.mark.parametrize(
|
||||
"notification_type, task_function, expected_queue, recipient",
|
||||
(
|
||||
("sms", save_api_sms, QueueNames.SEND_SMS, "+447700900855"),
|
||||
("email", save_api_email, QueueNames.SEND_EMAIL, "jane.citizen@example.com"),
|
||||
(
|
||||
NotificationType.SMS,
|
||||
save_api_sms,
|
||||
QueueNames.SEND_SMS,
|
||||
"+447700900855",
|
||||
),
|
||||
(
|
||||
NotificationType.EMAIL,
|
||||
save_api_email,
|
||||
QueueNames.SEND_EMAIL,
|
||||
"jane.citizen@example.com",
|
||||
),
|
||||
),
|
||||
)
|
||||
def test_save_api_tasks_use_cache(
|
||||
@@ -1590,7 +1620,7 @@ def test_save_api_tasks_use_cache(
|
||||
"client_reference": "our email",
|
||||
"reply_to_text": "our.email@gov.uk",
|
||||
"document_download_count": 0,
|
||||
"status": NOTIFICATION_CREATED,
|
||||
"status": NotificationStatus.CREATED,
|
||||
"created_at": datetime.utcnow().strftime(DATETIME_FORMAT),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -12,7 +12,8 @@ from app.celery.test_key_tasks import (
|
||||
sns_callback,
|
||||
)
|
||||
from app.config import QueueNames
|
||||
from app.models import NOTIFICATION_DELIVERED, NOTIFICATION_FAILED, Notification
|
||||
from app.enums import NotificationStatus
|
||||
from app.models import Notification
|
||||
from tests.conftest import Matcher
|
||||
|
||||
dvla_response_file_matcher = Matcher(
|
||||
@@ -28,14 +29,17 @@ def test_make_sns_callback(notify_api, rmock, mocker):
|
||||
)
|
||||
n = Notification()
|
||||
n.id = 1234
|
||||
n.status = NOTIFICATION_DELIVERED
|
||||
n.status = NotificationStatus.DELIVERED
|
||||
get_notification_by_id.return_value = n
|
||||
rmock.request("POST", endpoint, json={"status": "success"}, status_code=200)
|
||||
send_sms_response("sns", "1234")
|
||||
|
||||
assert rmock.called
|
||||
assert rmock.request_history[0].url == endpoint
|
||||
assert json.loads(rmock.request_history[0].text)["status"] == "delivered"
|
||||
assert (
|
||||
json.loads(rmock.request_history[0].text)["status"]
|
||||
== NotificationStatus.DELIVERED
|
||||
)
|
||||
|
||||
|
||||
def test_callback_logs_on_api_call_failure(notify_api, rmock, mocker):
|
||||
@@ -45,7 +49,7 @@ def test_callback_logs_on_api_call_failure(notify_api, rmock, mocker):
|
||||
)
|
||||
n = Notification()
|
||||
n.id = 1234
|
||||
n.status = NOTIFICATION_FAILED
|
||||
n.status = NotificationStatus.FAILED
|
||||
get_notification_by_id.return_value = n
|
||||
|
||||
rmock.request(
|
||||
@@ -81,9 +85,9 @@ def test_delivered_sns_callback(mocker):
|
||||
)
|
||||
n = Notification()
|
||||
n.id = 1234
|
||||
n.status = NOTIFICATION_DELIVERED
|
||||
n.status = NotificationStatus.DELIVERED
|
||||
get_notification_by_id.return_value = n
|
||||
|
||||
data = json.loads(sns_callback("1234"))
|
||||
assert data["status"] == "delivered"
|
||||
assert data["status"] == NotificationStatus.DELIVERED
|
||||
assert data["CID"] == "1234"
|
||||
|
||||
Reference in New Issue
Block a user