2016-04-06 14:31:33 +01:00
import uuid
2020-03-17 15:15:43 +00:00
from datetime import datetime
2016-04-06 14:31:33 +01:00
2018-02-07 17:49:15 +00:00
import pytest
2020-03-17 15:15:43 +00:00
from freezegun import freeze_time
2018-02-07 17:49:15 +00:00
2020-03-17 15:15:43 +00:00
from app import statsd_client
2022-10-14 14:45:27 +00:00
from app.celery.process_sms_client_response_tasks import (
process_sms_client_response ,
)
2018-02-07 17:49:15 +00:00
from app.clients import ClientException
2020-03-17 15:15:43 +00:00
from app.models import NOTIFICATION_TECHNICAL_FAILURE
2016-04-06 14:31:33 +01:00
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2020-03-17 15:15:43 +00:00
def test_process_sms_client_response_raises_error_if_reference_is_not_a_valid_uuid ( client ):
with pytest . raises ( ValueError ):
process_sms_client_response (
status = '000' , provider_reference = 'something-bad' , client_name = 'sms-client' )
2016-04-06 14:31:33 +01:00
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2022-04-27 18:03:05 +01:00
@pytest.mark.parametrize ( 'client_name' , ( 'Firetext' , 'MMG' ))
2020-03-17 15:15:43 +00:00
def test_process_sms_response_raises_client_exception_for_unknown_status (
sample_notification ,
mocker ,
client_name ,
):
with pytest . raises ( ClientException ) as e :
process_sms_client_response (
status = '000' ,
provider_reference = str ( sample_notification . id ),
client_name = client_name ,
)
2016-04-06 14:31:33 +01:00
2020-03-17 15:15:43 +00:00
assert f " { client_name } callback failed: status { '000' } not found." in str ( e . value )
assert sample_notification . status == NOTIFICATION_TECHNICAL_FAILURE
2016-04-06 14:31:33 +01:00
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2020-06-01 11:45:35 +01:00
@pytest.mark.parametrize ( 'status, detailed_status_code, sms_provider, expected_notification_status, reason' , [
2020-05-27 18:03:55 +01:00
( '0' , None , 'Firetext' , 'delivered' , None ),
( '1' , '101' , 'Firetext' , 'permanent-failure' , 'Unknown Subscriber' ),
( '2' , '102' , 'Firetext' , 'pending' , 'Absent Subscriber' ),
( '2' , '1' , 'MMG' , 'permanent-failure' , "Number does not exist" ),
( '3' , '2' , 'MMG' , 'delivered' , "Delivered to operator" ),
( '4' , '27' , 'MMG' , 'temporary-failure' , "Absent Subscriber" ),
( '5' , '13' , 'MMG' , 'permanent-failure' , "Sender id blacklisted" ),
2020-03-17 15:15:43 +00:00
])
def test_process_sms_client_response_updates_notification_status (
sample_notification ,
mocker ,
status ,
2020-06-01 11:45:35 +01:00
detailed_status_code ,
2020-03-17 15:15:43 +00:00
sms_provider ,
expected_notification_status ,
2020-05-27 18:03:55 +01:00
reason
2020-03-17 15:15:43 +00:00
):
2020-05-27 18:03:55 +01:00
mock_logger = mocker . patch ( 'app.celery.tasks.current_app.logger.info' )
2020-03-17 15:15:43 +00:00
sample_notification . status = 'sending'
2016-04-20 09:45:13 +01:00
2020-06-01 11:45:35 +01:00
process_sms_client_response ( status , str ( sample_notification . id ), sms_provider , detailed_status_code )
2020-05-27 18:03:55 +01:00
2020-06-01 18:02:01 +01:00
message = f " { sms_provider } callback returned status of { expected_notification_status } ( { status } ): { reason } ( { detailed_status_code } ) for reference: { sample_notification . id } " # noqa
2020-05-27 18:03:55 +01:00
mock_logger . assert_any_call ( message )
2020-03-17 15:15:43 +00:00
assert sample_notification . status == expected_notification_status
2016-04-20 09:45:13 +01:00
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2020-06-01 11:45:35 +01:00
@pytest.mark.parametrize ( 'detailed_status_code, expected_notification_status, reason' , [
2020-04-20 18:20:01 +01:00
( '101' , 'permanent-failure' , 'Unknown Subscriber' ),
( '102' , 'temporary-failure' , 'Absent Subscriber' ),
( None , 'temporary-failure' , None ),
2021-03-10 10:39:17 +00:00
( '000' , 'temporary-failure' , 'No error reported' )
2020-04-14 15:55:17 +01:00
])
def test_process_sms_client_response_updates_notification_status_when_called_second_time (
sample_notification ,
mocker ,
2020-06-01 11:45:35 +01:00
detailed_status_code ,
2020-04-14 15:55:17 +01:00
expected_notification_status ,
2020-04-20 18:20:01 +01:00
reason
2020-04-14 15:55:17 +01:00
):
2020-04-20 18:20:01 +01:00
mock_logger = mocker . patch ( 'app.celery.tasks.current_app.logger.info' )
2020-04-14 15:55:17 +01:00
sample_notification . status = 'sending'
process_sms_client_response ( '2' , str ( sample_notification . id ), 'Firetext' )
2020-04-20 18:20:01 +01:00
2020-06-01 11:45:35 +01:00
process_sms_client_response ( '1' , str ( sample_notification . id ), 'Firetext' , detailed_status_code )
2020-04-14 15:55:17 +01:00
2021-03-10 10:39:17 +00:00
if detailed_status_code :
2020-04-20 18:20:01 +01:00
message = f 'Updating notification id { sample_notification . id } to status { expected_notification_status } , reason: { reason } ' # noqa
mock_logger . assert_called_with ( message )
2020-04-14 15:55:17 +01:00
assert sample_notification . status == expected_notification_status
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2020-06-01 11:45:35 +01:00
@pytest.mark.parametrize ( 'detailed_status_code' , [ '102' , None , '000' ])
def test_process_sms_client_response_updates_notification_status_to_pending_with_and_without_failure_code_present (
2020-04-21 13:30:42 +01:00
sample_notification ,
mocker ,
2020-06-01 11:45:35 +01:00
detailed_status_code
2020-04-21 13:30:42 +01:00
):
sample_notification . status = 'sending'
2020-06-01 11:45:35 +01:00
process_sms_client_response ( '2' , str ( sample_notification . id ), 'Firetext' , detailed_status_code )
2020-04-21 13:30:42 +01:00
assert sample_notification . status == 'pending'
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2020-06-01 11:45:35 +01:00
def test_process_sms_client_response_updates_notification_status_when_detailed_status_code_not_recognised (
2020-04-20 18:20:01 +01:00
sample_notification ,
mocker ,
):
2020-04-21 12:06:28 +01:00
mock_logger = mocker . patch ( 'app.celery.tasks.current_app.logger.warning' )
2020-04-20 18:20:01 +01:00
sample_notification . status = 'sending'
process_sms_client_response ( '2' , str ( sample_notification . id ), 'Firetext' )
process_sms_client_response ( '1' , str ( sample_notification . id ), 'Firetext' , '789' )
mock_logger . assert_called_once_with ( 'Failure code 789 from Firetext not recognised' )
assert sample_notification . status == 'temporary-failure'
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2020-03-17 15:15:43 +00:00
def test_sms_response_does_not_send_callback_if_notification_is_not_in_the_db ( sample_service , mocker ):
2021-11-26 15:18:53 +00:00
send_mock = mocker . patch ( 'app.celery.process_sms_client_response_tasks.check_and_queue_callback_task' )
2017-12-05 13:57:46 +00:00
reference = str ( uuid . uuid4 ())
2018-03-21 18:11:10 +00:00
process_sms_client_response ( status = '3' , provider_reference = reference , client_name = 'MMG' )
2017-12-05 13:57:46 +00:00
send_mock . assert_not_called ()
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2020-03-17 15:15:43 +00:00
@freeze_time ( '2001-01-01T12:00:00' )
def test_process_sms_client_response_records_statsd_metrics ( sample_notification , client , mocker ):
mocker . patch ( 'app.statsd_client.incr' )
mocker . patch ( 'app.statsd_client.timing_with_dates' )
2016-04-06 14:31:33 +01:00
2020-03-17 15:15:43 +00:00
sample_notification . status = 'sending'
sample_notification . sent_at = datetime . utcnow ()
2016-04-06 14:31:33 +01:00
2020-03-17 15:15:43 +00:00
process_sms_client_response ( '0' , str ( sample_notification . id ), 'Firetext' )
2018-10-24 11:24:53 +01:00
2020-03-17 15:15:43 +00:00
statsd_client . incr . assert_any_call ( "callback.firetext.delivered" )
statsd_client . timing_with_dates . assert_any_call (
2021-10-20 17:22:59 +01:00
"callback.firetext.delivered.elapsed-time" , datetime . utcnow (), sample_notification . sent_at
2020-03-17 15:15:43 +00:00
)
2018-03-21 18:11:10 +00:00
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2019-06-28 12:19:21 +01:00
def test_process_sms_updates_billable_units_if_zero ( sample_notification ):
sample_notification . billable_units = 0
2020-03-17 15:15:43 +00:00
process_sms_client_response ( '3' , str ( sample_notification . id ), 'MMG' )
2019-06-28 12:19:21 +01:00
assert sample_notification . billable_units == 1
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2020-03-17 15:15:43 +00:00
def test_process_sms_response_does_not_send_service_callback_for_pending_notifications ( sample_notification , mocker ):
2021-11-26 15:18:53 +00:00
send_mock = mocker . patch ( 'app.celery.process_sms_client_response_tasks.check_and_queue_callback_task' )
2020-03-17 15:15:43 +00:00
process_sms_client_response ( '2' , str ( sample_notification . id ), 'Firetext' )
send_mock . assert_not_called ()
2016-04-06 14:31:33 +01:00
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2020-03-17 15:15:43 +00:00
def test_outcome_statistics_called_for_successful_callback ( sample_notification , mocker ):
2021-11-26 15:18:53 +00:00
send_mock = mocker . patch ( 'app.celery.process_sms_client_response_tasks.check_and_queue_callback_task' )
2020-03-17 15:15:43 +00:00
reference = str ( sample_notification . id )
2017-05-09 22:03:57 +01:00
2020-03-17 15:15:43 +00:00
process_sms_client_response ( '3' , reference , 'MMG' )
2021-11-26 15:18:53 +00:00
send_mock . assert_called_once_with ( sample_notification )
2016-04-06 14:31:33 +01:00
2022-07-05 11:27:15 -07:00
@pytest.mark.skip ( reason = "Needs updating for TTS: Update with new providers" )
2020-03-17 15:15:43 +00:00
def test_process_sms_updates_sent_by_with_client_name_if_not_in_noti ( sample_notification ):
sample_notification . sent_by = None
process_sms_client_response ( '3' , str ( sample_notification . id ), 'MMG' )
2017-05-09 22:03:57 +01:00
2020-03-17 15:15:43 +00:00
assert sample_notification . sent_by == 'mmg'