Added research mode tasks

- if a service is in research mode the don't send the notifications via the providers (MMG/SES/etc)
- instead set up a task to mimic those services callbacks - this completes the loop, and show stats, delivery receipts and so on.
- Use the "to" field to choose the response, allows users to create successful and errored notifications

temp fail sms, uses  "07833333333"
perm fail sms, uses = "07822222222"
success = "07811111111" (or anything else)

success email = "delivered@simulator.notify"
perm fail = "perm-fail@simulator.notify"
temp fail = "temp-fail@simulator.notify"
This commit is contained in:
Martyn Inglis
2016-05-31 16:55:26 +01:00
parent 9617f0748b
commit 909fac3c05
9 changed files with 315 additions and 15 deletions

View File

@@ -0,0 +1,90 @@
from flask import json
from app.celery.research_mode_tasks import (
send_sms_response,
send_email_response,
mmg_callback,
firetext_callback,
ses_notification_callback,
ses_hard_bounce_callback,
ses_soft_bounce_callback
)
def test_make_mmg_callback(notify_api, rmock):
endpoint = "http://localhost:6011/notifications/sms/mmg"
rmock.request(
"POST",
endpoint,
json={"status": "success"},
status_code=200)
send_sms_response("mmg", "1234", "07811111111")
assert rmock.called
def test_make_firetext_callback(notify_api, rmock):
endpoint = "http://localhost:6011/notifications/sms/firetext"
rmock.request(
"POST",
endpoint,
data="some data",
status_code=200)
send_sms_response("firetext", "1234", "07811111111")
assert rmock.called
def test_make_ses_callback(notify_api, rmock):
endpoint = "http://localhost:6011/notifications/email/ses"
rmock.request(
"POST",
endpoint,
json={"status": "success"},
status_code=200)
send_email_response("ses", "1234", "test@test.com")
assert rmock.called
def test_delivered_mmg_callback():
data = json.loads(mmg_callback("1234", "07811111111"))
assert data['MSISDN'] == "07811111111"
assert data['status'] == "0"
assert data['reference'] == "mmg_reference"
assert data['CID'] == "1234"
def test_perm_failure_mmg_callback():
data = json.loads(mmg_callback("1234", "07822222222"))
assert data['MSISDN'] == "07822222222"
assert data['status'] == "5"
assert data['reference'] == "mmg_reference"
assert data['CID'] == "1234"
def test_temp_failure_mmg_callback():
data = json.loads(mmg_callback("1234", "07833333333"))
assert data['MSISDN'] == "07833333333"
assert data['status'] == "4"
assert data['reference'] == "mmg_reference"
assert data['CID'] == "1234"
def test_delivered_firetext_callback():
assert firetext_callback("1234", "07811111111") == "mobile=07811111111&status=0&time=2016-03-10 14:17:00&reference=1234" # noqa
def test_failure_firetext_callback():
assert firetext_callback("1234", "07822222222") == "mobile=07822222222&status=1&time=2016-03-10 14:17:00&reference=1234" # noqa
def test_delivered_ses_callback():
assert ses_notification_callback("my-reference") == '{\n "Type" : "Notification",\n "MessageId" : "my-reference",\n "TopicArn" : "arn:aws:sns:eu-west-1:123456789012:testing",\n "Message" : "{\\"notificationType\\":\\"Delivery\\",\\"mail\\":{\\"timestamp\\":\\"2016-03-14T12:35:25.909Z\\",\\"source\\":\\"test@test-domain.com\\",\\"sourceArn\\":\\"arn:aws:ses:eu-west-1:123456789012:identity/testing-notify\\",\\"sendingAccountId\\":\\"123456789012\\",\\"messageId\\":\\"ref\\",\\"destination\\":[\\"testing@digital.cabinet-office.gov.uk\\"]},\\"delivery\\":{\\"timestamp\\":\\"2016-03-14T12:35:26.567Z\\",\\"processingTimeMillis\\":658,\\"recipients\\":[\\"testing@digital.cabinet-office.gov.uk\\"],\\"smtpResponse\\":\\"250 2.0.0 OK 1457958926 uo5si26480932wjc.221 - gsmtp\\",\\"reportingMTA\\":\\"a6-238.smtp-out.eu-west-1.amazonses.com\\"}}",\n "Timestamp" : "2016-03-14T12:35:26.665Z",\n "SignatureVersion" : "1",\n "Signature" : "X8d7eTAOZ6wlnrdVVPYanrAlsX0SMPfOzhoTEBnQqYkrNWTqQY91C0f3bxtPdUhUtOowyPAOkTQ4KnZuzphfhVb2p1MyVYMxNKcBFB05/qaCX99+92fjw4x9LeUOwyGwMv5F0Vkfi5qZCcEw69uVrhYLVSTFTrzi/yCtru+yFULMQ6UhbY09GwiP6hjxZMVr8aROQy5lLHglqQzOuSZ4KeD85JjifHdKzlx8jjQ+uj+FLzHXPMAPmPU1JK9kpoHZ1oPshAFgPDpphJe+HwcJ8ezmk+3AEUr3wWli3xF+49y8Z2anASSVp6YI2YP95UT8Rlh3qT3T+V9V8rbSVislxA==",\n "SigningCertURL" : "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-bb750dd426d95ee9390147a5624348ee.pem",\n "UnsubscribeURL" : "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:302763885840:preview-emails:d6aad3ef-83d6-4cf3-a470-54e2e75916da"\n}' # noqa
def test_ses_hard_bounce_callback():
assert ses_hard_bounce_callback("my-reference") == '{\n "Type" : "Notification",\n "MessageId" : "my-reference",\n "TopicArn" : "arn:aws:sns:eu-west-1:123456789012:testing",\n "Message" : "{\\"notificationType\\":\\"Bounce\\",\\"bounce\\":{\\"bounceType\\":\\"Permanent\\",\\"bounceSubType\\":\\"General\\"}, \\"mail\\":{\\"messageId\\":\\"ref\\",\\"timestamp\\":\\"2016-03-14T12:35:25.909Z\\",\\"source\\":\\"test@test-domain.com\\",\\"sourceArn\\":\\"arn:aws:ses:eu-west-1:123456789012:identity/testing-notify\\",\\"sendingAccountId\\":\\"123456789012\\",\\"destination\\":[\\"testing@digital.cabinet-office.gov.uk\\"]},\\"delivery\\":{\\"timestamp\\":\\"2016-03-14T12:35:26.567Z\\",\\"processingTimeMillis\\":658,\\"recipients\\":[\\"testing@digital.cabinet-office.gov.uk\\"],\\"smtpResponse\\":\\"250 2.0.0 OK 1457958926 uo5si26480932wjc.221 - gsmtp\\",\\"reportingMTA\\":\\"a6-238.smtp-out.eu-west-1.amazonses.com\\"}}",\n "Timestamp" : "2016-03-14T12:35:26.665Z",\n "SignatureVersion" : "1",\n "Signature" : "X8d7eTAOZ6wlnrdVVPYanrAlsX0SMPfOzhoTEBnQqYkrNWTqQY91C0f3bxtPdUhUtOowyPAOkTQ4KnZuzphfhVb2p1MyVYMxNKcBFB05/qaCX99+92fjw4x9LeUOwyGwMv5F0Vkfi5qZCcEw69uVrhYLVSTFTrzi/yCtru+yFULMQ6UhbY09GwiP6hjxZMVr8aROQy5lLHglqQzOuSZ4KeD85JjifHdKzlx8jjQ+uj+FLzHXPMAPmPU1JK9kpoHZ1oPshAFgPDpphJe+HwcJ8ezmk+3AEUr3wWli3xF+49y8Z2anASSVp6YI2YP95UT8Rlh3qT3T+V9V8rbSVislxA==",\n "SigningCertURL" : "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-bb750dd426d95ee9390147a5624348ee.pem",\n "UnsubscribeURL" : "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:302763885840:preview-emails:d6aad3ef-83d6-4cf3-a470-54e2e75916da"\n}' # noqa
def ses_soft_bounce_callback():
assert ses_soft_bounce_callback("my-reference") == '{\n "Type" : "Notification",\n "MessageId" : "my-reference",\n "TopicArn" : "arn:aws:sns:eu-west-1:123456789012:testing",\n "Message" : "{\\"notificationType\\":\\"Bounce\\",\\"bounce\\":{\\"bounceType\\":\\"Undetermined\\",\\"bounceSubType\\":\\"General\\"}, \\"mail\\":{\\"messageId\\":\\"ref\\",\\"timestamp\\":\\"2016-03-14T12:35:25.909Z\\",\\"source\\":\\"test@test-domain.com\\",\\"sourceArn\\":\\"arn:aws:ses:eu-west-1:123456789012:identity/testing-notify\\",\\"sendingAccountId\\":\\"123456789012\\",\\"destination\\":[\\"testing@digital.cabinet-office.gov.uk\\"]},\\"delivery\\":{\\"timestamp\\":\\"2016-03-14T12:35:26.567Z\\",\\"processingTimeMillis\\":658,\\"recipients\\":[\\"testing@digital.cabinet-office.gov.uk\\"],\\"smtpResponse\\":\\"250 2.0.0 OK 1457958926 uo5si26480932wjc.221 - gsmtp\\",\\"reportingMTA\\":\\"a6-238.smtp-out.eu-west-1.amazonses.com\\"}}",\n "Timestamp" : "2016-03-14T12:35:26.665Z",\n "SignatureVersion" : "1",\n "Signature" : "X8d7eTAOZ6wlnrdVVPYanrAlsX0SMPfOzhoTEBnQqYkrNWTqQY91C0f3bxtPdUhUtOowyPAOkTQ4KnZuzphfhVb2p1MyVYMxNKcBFB05/qaCX99+92fjw4x9LeUOwyGwMv5F0Vkfi5qZCcEw69uVrhYLVSTFTrzi/yCtru+yFULMQ6UhbY09GwiP6hjxZMVr8aROQy5lLHglqQzOuSZ4KeD85JjifHdKzlx8jjQ+uj+FLzHXPMAPmPU1JK9kpoHZ1oPshAFgPDpphJe+HwcJ8ezmk+3AEUr3wWli3xF+49y8Z2anASSVp6YI2YP95UT8Rlh3qT3T+V9V8rbSVislxA==",\n "SigningCertURL" : "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-bb750dd426d95ee9390147a5624348ee.pem",\n "UnsubscribeURL" : "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:302763885840:preview-emails:d6aad3ef-83d6-4cf3-a470-54e2e75916da"\n}' # noqa

View File

@@ -17,6 +17,10 @@ from app.celery.tasks import (
delete_successful_notifications,
provider_to_use
)
from app.celery.research_mode_tasks import (
send_email_response,
send_sms_response
)
from app import (aws_ses_client, encryption, DATETIME_FORMAT, mmg_client, statsd_client)
from app.clients.email.aws_ses import AwsSesClientException
from app.clients.sms.mmg import MMGClientException
@@ -993,6 +997,86 @@ def test_process_email_job_should_use_reply_to_email_if_present(sample_email_job
)
def test_should_call_send_sms_response_task_if_research_mode(notify_db, sample_service, sample_template, mocker):
notification = _notification_json(
sample_template,
to="+447234123123"
)
mocker.patch('app.encryption.decrypt', return_value=notification)
mocker.patch('app.mmg_client.send_sms')
mocker.patch('app.mmg_client.get_name', return_value="mmg")
mocker.patch('app.celery.research_mode_tasks.send_sms_response.apply_async')
sample_service.research_mode = True
notify_db.session.add(sample_service)
notify_db.session.commit()
notification_id = uuid.uuid4()
now = datetime.utcnow()
send_sms(
sample_service.id,
notification_id,
"encrypted-in-reality",
now.strftime(DATETIME_FORMAT)
)
assert not mmg_client.send_sms.called
send_sms_response.apply_async.assert_called_once_with(('mmg', str(notification_id), "+447234123123"))
persisted_notification = notifications_dao.get_notification(sample_service.id, notification_id)
assert persisted_notification.id == notification_id
assert persisted_notification.to == '+447234123123'
assert persisted_notification.template_id == sample_template.id
assert persisted_notification.status == 'sending'
assert persisted_notification.sent_at > now
assert persisted_notification.created_at == now
assert persisted_notification.sent_by == 'mmg'
def test_should_call_send_email_response_task_if_research_mode(
notify_db,
sample_service,
sample_email_template,
mocker):
notification = _notification_json(
sample_email_template,
to="john@smith.com"
)
reference = uuid.uuid4()
mocker.patch('app.uuid.uuid4', return_value=reference)
mocker.patch('app.encryption.decrypt', return_value=notification)
mocker.patch('app.aws_ses_client.send_email')
mocker.patch('app.aws_ses_client.get_name', return_value="ses")
mocker.patch('app.celery.research_mode_tasks.send_email_response.apply_async')
sample_service.research_mode = True
notify_db.session.add(sample_service)
notify_db.session.commit()
notification_id = uuid.uuid4()
now = datetime.utcnow()
send_email(
sample_service.id,
notification_id,
"myservice@notify.com",
"encrypted-in-reality",
now.strftime(DATETIME_FORMAT)
)
assert not aws_ses_client.send_email.called
send_email_response.apply_async.assert_called_once_with(('ses', str(reference), 'john@smith.com'))
persisted_notification = notifications_dao.get_notification(sample_service.id, notification_id)
assert persisted_notification.id == notification_id
assert persisted_notification.to == 'john@smith.com'
assert persisted_notification.template_id == sample_email_template.id
assert persisted_notification.status == 'sending'
assert persisted_notification.sent_at > now
assert persisted_notification.created_at == now
assert persisted_notification.sent_by == 'ses'
assert persisted_notification.reference == str(reference)
def _notification_json(template, to, personalisation=None, job_id=None, row_number=None):
notification = {
"template": template.id,

View File

@@ -1,3 +1,4 @@
import requests_mock
import pytest
from datetime import (datetime, date)
from app import db
@@ -23,6 +24,12 @@ from app.dao.invited_user_dao import save_invited_user
import uuid
@pytest.yield_fixture
def rmock():
with requests_mock.mock() as rmock:
yield rmock
@pytest.fixture(scope='function')
def service_factory(notify_db, notify_db_session):
class ServiceFactory(object):