예제 #1
0
def test_ses_callback_should_update_multiple_notification_status_sent(
        client, notify_db_session, sample_email_template, mocker):

    send_mock = mocker.patch(
        'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
    )
    create_notification(
        template=sample_email_template,
        status='sending',
        reference='ref1',
    )
    create_notification(
        template=sample_email_template,
        status='sending',
        reference='ref2',
    )
    create_notification(
        template=sample_email_template,
        status='sending',
        reference='ref3',
    )
    create_service_callback_api(service=sample_email_template.service,
                                url="https://original_url.com")
    assert process_ses_results(ses_notification_callback(reference='ref1'))
    assert process_ses_results(ses_notification_callback(reference='ref2'))
    assert process_ses_results(ses_notification_callback(reference='ref3'))
    assert send_mock.called
예제 #2
0
def test_process_ses_results_retry_called(sample_email_template, notify_db, mocker):
    create_notification(sample_email_template, reference='ref1', sent_at=datetime.utcnow(), status='sending')

    mocker.patch("app.dao.notifications_dao.dao_update_notifications_by_reference", side_effect=Exception("EXPECTED"))
    mocked = mocker.patch('app.celery.process_ses_receipts_tasks.process_ses_results.retry')
    process_ses_results(response=ses_notification_callback(reference='ref1'))
    assert mocked.call_count != 0
예제 #3
0
def test_process_ses_results_in_complaint(sample_email_template, mocker):
    notification = create_notification(template=sample_email_template, reference='ref1')
    mocked = mocker.patch("app.dao.notifications_dao.update_notification_status_by_reference")
    process_ses_results(response=ses_complaint_callback())
    assert mocked.call_count == 0
    complaints = Complaint.query.all()
    assert len(complaints) == 1
    assert complaints[0].notification_id == notification.id
예제 #4
0
def test_process_ses_results_retry_called(notify_db, mocker):
    mocker.patch(
        "app.dao.notifications_dao.update_notification_status_by_reference",
        side_effect=Exception("EXPECTED"))
    mocked = mocker.patch(
        'app.celery.process_ses_receipts_tasks.process_ses_results.retry')
    response = json.loads(ses_notification_callback())
    process_ses_results(response=response)
    assert mocked.call_count != 0
예제 #5
0
def test_process_ses_results_call_to_publish_complaint(mocker, notify_api):
    publish_complaint = mocker.patch(
        'app.celery.process_ses_receipts_tasks.publish_complaint')
    provider_message = ses_complaint_callback()

    complaint, notification, email = get_complaint_notification_and_email(
        mocker)

    mocker.patch('app.celery.process_ses_receipts_tasks.handle_ses_complaint',
                 return_value=(complaint, notification, email))

    process_ses_receipts_tasks.process_ses_results(response=provider_message)

    publish_complaint.assert_called_once_with(complaint, notification, email)
예제 #6
0
def test_ses_callback_should_update_notification_status(
        client, notify_db_session, sample_email_template, mocker):
    with freeze_time('2001-01-01T12:00:00'):
        mocker.patch('app.statsd_client.incr')
        mocker.patch('app.statsd_client.timing_with_dates')
        send_mock = mocker.patch(
            'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
        )
        notification = create_notification(
            template=sample_email_template,
            status='sending',
            reference='ref',
        )
        callback_api = create_service_callback_api(
            service=sample_email_template.service,
            url="https://original_url.com")
        assert get_notification_by_id(notification.id).status == 'sending'

        assert process_ses_results(ses_notification_callback(reference='ref'))
        assert get_notification_by_id(notification.id).status == 'delivered'
        statsd_client.timing_with_dates.assert_any_call(
            "callback.ses.elapsed-time", datetime.utcnow(),
            notification.sent_at)
        statsd_client.incr.assert_any_call("callback.ses.delivered")
        updated_notification = Notification.query.get(notification.id)
        encrypted_data = create_delivery_status_callback_data(
            updated_notification, callback_api)
        send_mock.assert_called_once_with(
            [str(notification.id), encrypted_data], queue="service-callbacks")
예제 #7
0
def test_ses_callback_should_update_notification_status(
        notify_db, notify_db_session, sample_email_template, mocker):
    with freeze_time("2001-01-01T12:00:00"):
        mocker.patch("app.statsd_client.incr")
        mocker.patch("app.statsd_client.timing_with_dates")
        send_mock = mocker.patch(
            "app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async"
        )
        notification = create_sample_notification(
            notify_db,
            notify_db_session,
            template=sample_email_template,
            reference="ref",
            status="sending",
            sent_at=datetime.utcnow(),
        )
        callback_api = create_service_callback_api(
            service=sample_email_template.service,
            url="https://original_url.com")
        assert get_notification_by_id(notification.id).status == "sending"

        assert process_ses_results(ses_notification_callback(reference="ref"))
        notification = get_notification_by_id(notification.id)
        assert notification.status == "delivered"
        assert notification.provider_response is None
        statsd_client.timing_with_dates.assert_any_call(
            "callback.ses.elapsed-time", datetime.utcnow(),
            notification.sent_at)
        statsd_client.incr.assert_any_call("callback.ses.delivered")
        updated_notification = Notification.query.get(notification.id)
        encrypted_data = create_delivery_status_callback_data(
            updated_notification, callback_api)
        send_mock.assert_called_once_with(
            [str(notification.id), encrypted_data], queue="service-callbacks")
예제 #8
0
def test_ses_callback_should_set_status_to_permanent_failure(
    notify_db,
    notify_db_session,
    sample_email_template,
    mocker,
    bounce_subtype,
    provider_response,
):
    send_mock = mocker.patch(
        "app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async"
    )
    notification = create_sample_notification(
        notify_db,
        notify_db_session,
        template=sample_email_template,
        reference="ref",
        status="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 process_ses_results(
        ses_hard_bounce_callback(reference="ref",
                                 bounce_subtype=bounce_subtype))

    notification = get_notification_by_id(notification.id)
    assert notification.status == "permanent-failure"
    assert notification.provider_response == provider_response
    assert send_mock.called
예제 #9
0
def test_ses_callback_should_send_on_complaint_to_user_callback_api(
        sample_email_template, mocker):
    send_mock = mocker.patch(
        "app.celery.service_callback_tasks.send_complaint_to_service.apply_async"
    )
    create_service_callback_api(
        service=sample_email_template.service,
        url="https://original_url.com",
        callback_type="complaint",
    )

    notification = create_notification(
        template=sample_email_template,
        reference="ref1",
        sent_at=datetime.utcnow(),
        status="sending",
    )
    response = ses_complaint_callback()
    assert process_ses_results(response)

    assert send_mock.call_count == 1
    assert encryption.decrypt(send_mock.call_args[0][0][0]) == {
        "complaint_date": "2018-06-05T13:59:58.000000Z",
        "complaint_id": str(Complaint.query.one().id),
        "notification_id": str(notification.id),
        "reference": None,
        "service_callback_api_bearer_token": "some_super_secret",
        "service_callback_api_url": "https://original_url.com",
        "to": "*****@*****.**",
    }
예제 #10
0
def test_ses_callback_should_send_on_complaint_to_user_callback_api(
        sample_email_template, mocker):
    send_mock = mocker.patch(
        'app.celery.service_callback_tasks.send_complaint_to_service.apply_async'
    )
    create_service_callback_api(service=sample_email_template.service,
                                url="https://original_url.com",
                                callback_type="complaint")

    notification = create_notification(template=sample_email_template,
                                       reference='ref1',
                                       sent_at=datetime.utcnow(),
                                       status='sending')
    response = ses_complaint_callback()
    assert process_ses_results(response)

    assert send_mock.call_count == 1
    assert encryption.decrypt(send_mock.call_args[0][0][0]) == {
        'complaint_date': '2018-06-05T13:59:58.000000Z',
        'complaint_id': str(Complaint.query.one().id),
        'notification_id': str(notification.id),
        'reference': None,
        'service_callback_api_bearer_token': 'some_super_secret',
        'service_callback_api_url': 'https://original_url.com',
        'to': '*****@*****.**'
    }
예제 #11
0
def test_ses_callback_should_not_retry_if_notification_is_old(client, notify_db, mocker):
    mock_retry = mocker.patch('app.celery.process_ses_receipts_tasks.process_ses_results.retry')
    mock_logger = mocker.patch('app.celery.process_ses_receipts_tasks.current_app.logger.error')

    with freeze_time('2017-11-21T12:14:03.646Z'):
        assert process_ses_results(ses_notification_callback(reference='ref')) is None
        assert mock_logger.call_count == 0
        assert mock_retry.call_count == 0
예제 #12
0
def test_process_ses_results(sample_email_template):
    create_notification(sample_email_template,
                        reference='ref1',
                        sent_at=datetime.utcnow(),
                        status='sending')

    assert process_ses_results(response=ses_notification_callback(
        reference='ref1'))
예제 #13
0
def test_ses_callback_should_log_if_notification_is_missing(client, notify_db, mocker):
    mock_retry = mocker.patch('app.celery.process_ses_receipts_tasks.process_ses_results.retry')
    mock_logger = mocker.patch('app.celery.process_ses_receipts_tasks.current_app.logger.warning')

    with freeze_time('2017-11-17T12:34:03.646Z'):
        assert process_ses_results(ses_notification_callback(reference='ref')) is None
        assert mock_retry.call_count == 0
        mock_logger.assert_called_once_with('notification not found for reference: ref (update to delivered)')
예제 #14
0
def test_ses_callback_should_update_notification_status_when_receiving_new_delivery_receipt(
        sample_email_template, mocker):
    notification = create_notification(template=sample_email_template,
                                       reference="ref",
                                       status="delivered")

    assert process_ses_results(ses_hard_bounce_callback(reference="ref"))
    assert get_notification_by_id(
        notification.id).status == "permanent-failure"
예제 #15
0
def test_ses_callback_should_retry_if_notification_is_new(notify_db, mocker):
    mock_retry = mocker.patch(
        "app.celery.process_ses_receipts_tasks.process_ses_results.retry")
    mock_logger = mocker.patch(
        "app.celery.process_ses_receipts_tasks.current_app.logger.error")

    with freeze_time("2017-11-17T12:14:03.646Z"):
        assert process_ses_results(
            ses_notification_callback(reference="ref")) is None
        assert mock_logger.call_count == 0
        assert mock_retry.call_count == 1
예제 #16
0
def test_ses_callback_should_send_statsd_statistics(client, notify_db_session,
                                                    sample_email_template,
                                                    mocker):
    with freeze_time('2001-01-01T12:00:00'):
        mocker.patch('app.statsd_client.incr')
        mocker.patch('app.statsd_client.timing_with_dates')

        notification = create_notification(
            template=sample_email_template,
            status='sending',
            reference='ref',
        )

        process_ses_receipts_tasks.process_ses_results(
            ses_notification_callback(reference='ref'))

        statsd_client.timing_with_dates.assert_any_call(
            "callback.ses.elapsed-time", datetime.utcnow(),
            notification.sent_at)
        statsd_client.incr.assert_any_call("callback.ses.delivered")
예제 #17
0
def test_ses_callback_should_not_update_notification_status_if_already_delivered(sample_email_template, mocker):
    mock_dup = mocker.patch('app.celery.process_ses_receipts_tasks.notifications_dao._duplicate_update_warning')
    mock_upd = mocker.patch(
        'app.celery.process_ses_receipts_tasks.notifications_dao.dao_update_notifications_by_reference'
    )
    notification = create_notification(template=sample_email_template, reference='ref', status='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=notification, status='delivered')
    assert mock_upd.call_count == 0
예제 #18
0
def test_ses_callback_should_update_multiple_notification_status_sent(
        notify_db, notify_db_session, sample_email_template, mocker):
    send_mock = mocker.patch(
        "app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async"
    )
    create_sample_notification(
        notify_db,
        notify_db_session,
        template=sample_email_template,
        reference="ref1",
        sent_at=datetime.utcnow(),
        status="sending",
    )

    create_sample_notification(
        notify_db,
        notify_db_session,
        template=sample_email_template,
        reference="ref2",
        sent_at=datetime.utcnow(),
        status="sending",
    )

    create_sample_notification(
        notify_db,
        notify_db_session,
        template=sample_email_template,
        reference="ref3",
        sent_at=datetime.utcnow(),
        status="sending",
    )
    create_service_callback_api(service=sample_email_template.service,
                                url="https://original_url.com")
    assert process_ses_results(ses_notification_callback(reference="ref1"))
    assert process_ses_results(ses_notification_callback(reference="ref2"))
    assert process_ses_results(ses_notification_callback(reference="ref3"))
    assert send_mock.called
예제 #19
0
def test_ses_callback_should_call_send_delivery_status_to_service(
        client, sample_email_template, mocker):
    send_mock = mocker.patch(
        'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
    )
    notification = create_notification(
        template=sample_email_template,
        status='sending',
        reference='ref',
    )

    callback_api = create_service_callback_api(
        service=sample_email_template.service, url="https://original_url.com")
    mocked_callback_api = mocker.Mock(url=callback_api.url,
                                      bearer_token=callback_api.bearer_token)
    process_ses_receipts_tasks.process_ses_results(
        ses_notification_callback(reference='ref'))

    updated_notification = Notification.query.get(notification.id)

    encrypted_data = create_delivery_status_callback_data(
        updated_notification, mocked_callback_api)
    send_mock.assert_called_once_with([str(notification.id), encrypted_data],
                                      queue="service-callbacks")
예제 #20
0
def test_ses_callback_should_set_status_to_temporary_failure(
        client, notify_db_session, sample_email_template, mocker):
    send_mock = mocker.patch(
        'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
    )
    notification = create_notification(
        template=sample_email_template,
        status='sending',
        reference='ref',
    )
    create_service_callback_api(service=notification.service,
                                url="https://original_url.com")
    assert get_notification_by_id(notification.id).status == 'sending'
    assert process_ses_results(ses_soft_bounce_callback(reference='ref'))
    assert get_notification_by_id(
        notification.id).status == 'temporary-failure'
    assert send_mock.called
예제 #21
0
def test_ses_callback_does_not_call_send_delivery_status_if_no_db_entry(
        client, notify_db_session, sample_email_template, mocker):
    with freeze_time('2001-01-01T12:00:00'):

        send_mock = mocker.patch(
            'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
        )
        notification = create_notification(
            template=sample_email_template,
            status='sending',
            reference='ref',
        )

        assert process_ses_receipts_tasks.process_ses_results(
            ses_notification_callback(reference='ref'))
        assert get_notification_by_id(notification.id).status == 'delivered'

        send_mock.assert_not_called()
def test_ses_callback_should_set_status_to_permanent_failure(
        notify_db, notify_db_session, sample_email_template, mocker):
    send_mock = mocker.patch(
        'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
    )
    notification = create_sample_notification(notify_db,
                                              notify_db_session,
                                              template=sample_email_template,
                                              reference='ref',
                                              status='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 process_ses_results(ses_hard_bounce_callback(reference='ref'))
    assert get_notification_by_id(
        notification.id).status == 'permanent-failure'
    assert send_mock.called
예제 #23
0
def test_ses_callback_should_set_status_to_permanent_failure(
        client, notify_db_session, sample_email_template, mocker):
    send_mock = mocker.patch(
        'app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async'
    )
    mock_logger = mocker.patch(
        'app.celery.process_ses_receipts_tasks.current_app.logger.info')
    notification = create_notification(
        template=sample_email_template,
        status='sending',
        reference='ref',
    )
    create_service_callback_api(service=sample_email_template.service,
                                url="https://original_url.com")

    assert get_notification_by_id(notification.id).status == 'sending'
    assert process_ses_results(ses_hard_bounce_callback(reference='ref'))
    assert get_notification_by_id(
        notification.id).status == 'permanent-failure'
    assert send_mock.called
    assert f'SES bounce for notification ID {notification.id}: ' in mock_logger.call_args[
        0][0]
예제 #24
0
def test_ses_callback_does_not_call_send_delivery_status_if_no_db_entry(
        notify_db, notify_db_session, sample_email_template, mocker):
    with freeze_time("2001-01-01T12:00:00"):

        send_mock = mocker.patch(
            "app.celery.service_callback_tasks.send_delivery_status_to_service.apply_async"
        )
        notification = create_sample_notification(
            notify_db,
            notify_db_session,
            template=sample_email_template,
            reference="ref",
            status="sending",
            sent_at=datetime.utcnow(),
        )

        assert get_notification_by_id(notification.id).status == "sending"

        assert process_ses_results(ses_notification_callback(reference="ref"))
        notification = get_notification_by_id(notification.id)
        assert notification.status == "delivered"
        assert notification.provider_response is None

        send_mock.assert_not_called()
예제 #25
0
def test_process_ses_results_does_not_retry_if_errors(notify_db, mocker):
    mocked = mocker.patch(
        'app.celery.process_ses_receipts_tasks.process_ses_results.retry')
    response = json.loads(ses_notification_callback())
    process_ses_results(response=response)
    assert mocked.call_count == 0