mirror of
https://github.com/GSA/notifications-api.git
synced 2026-01-02 18:50:45 -05:00
1. The number of letters that we send to DVLA will be not be correct (see20ead82463/app/celery/letters_pdf_tasks.py (L136)) This may raise an alert with DVLA when they find we have sent them fewer letter than we have reported. 2. When we get the PDF from S3 we will get a file not found20ead82463/app/celery/letters_pdf_tasks.py (L244)The error will not prevent the collate task from completing but we will see an alert email for the exception and raise questions. Although this situation is very unlikely because we have a 15 minute window between the last letter deadline date and the time we kick off the collate task we should still mitigate these issues. I updated the queries to only return letters with billable_units > 0, all valid letters should have at least 1 billable unit.
741 lines
26 KiB
Python
741 lines
26 KiB
Python
import uuid
|
|
from unittest.mock import ANY
|
|
|
|
import pytest
|
|
from flask import json, url_for
|
|
|
|
from app.config import QueueNames
|
|
from app.models import (
|
|
EMAIL_TYPE,
|
|
INTERNATIONAL_LETTERS,
|
|
KEY_TYPE_NORMAL,
|
|
KEY_TYPE_TEAM,
|
|
KEY_TYPE_TEST,
|
|
LETTER_TYPE,
|
|
NOTIFICATION_CREATED,
|
|
NOTIFICATION_DELIVERED,
|
|
NOTIFICATION_PENDING_VIRUS_CHECK,
|
|
NOTIFICATION_SENDING,
|
|
SMS_TYPE,
|
|
Job,
|
|
Notification,
|
|
)
|
|
from app.notifications.process_letter_notifications import (
|
|
create_letter_notification,
|
|
)
|
|
from app.schema_validation import validate
|
|
from app.v2.errors import RateLimitError
|
|
from app.v2.notifications.notification_schemas import post_letter_response
|
|
from tests import create_service_authorization_header
|
|
from tests.app.db import create_letter_contact, create_service, create_template
|
|
from tests.conftest import set_config_values
|
|
|
|
test_address = {
|
|
'address_line_1': 'test 1',
|
|
'address_line_2': 'test 2',
|
|
'postcode': 'test pc'
|
|
}
|
|
|
|
|
|
def letter_request(client, data, service_id, key_type=KEY_TYPE_NORMAL, _expected_status=201, precompiled=False):
|
|
if precompiled:
|
|
url = url_for('v2_notifications.post_precompiled_letter_notification')
|
|
else:
|
|
url = url_for('v2_notifications.post_notification', notification_type=LETTER_TYPE)
|
|
resp = client.post(
|
|
url,
|
|
data=json.dumps(data),
|
|
headers=[
|
|
('Content-Type', 'application/json'),
|
|
create_service_authorization_header(service_id=service_id, key_type=key_type)
|
|
]
|
|
)
|
|
json_resp = json.loads(resp.get_data(as_text=True))
|
|
assert resp.status_code == _expected_status, json_resp
|
|
return json_resp
|
|
|
|
|
|
@pytest.mark.parametrize('reference', [None, 'reference_from_client'])
|
|
def test_post_letter_notification_returns_201(client, sample_letter_template, mocker, reference):
|
|
mock = mocker.patch('app.celery.tasks.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
data = {
|
|
'template_id': str(sample_letter_template.id),
|
|
'personalisation': {
|
|
'address_line_1': 'Her Royal Highness Queen Elizabeth II',
|
|
'address_line_2': 'Buckingham Palace',
|
|
'address_line_3': 'London',
|
|
'postcode': 'SW1 1AA',
|
|
'name': 'Lizzie'
|
|
}
|
|
}
|
|
|
|
if reference:
|
|
data.update({'reference': reference})
|
|
|
|
resp_json = letter_request(client, data, service_id=sample_letter_template.service_id)
|
|
|
|
assert validate(resp_json, post_letter_response) == resp_json
|
|
assert Job.query.count() == 0
|
|
notification = Notification.query.one()
|
|
assert notification.status == NOTIFICATION_CREATED
|
|
assert resp_json['id'] == str(notification.id)
|
|
assert resp_json['reference'] == reference
|
|
assert resp_json['content']['subject'] == sample_letter_template.subject
|
|
assert resp_json['content']['body'] == sample_letter_template.content
|
|
assert 'v2/notifications/{}'.format(notification.id) in resp_json['uri']
|
|
assert resp_json['template']['id'] == str(sample_letter_template.id)
|
|
assert resp_json['template']['version'] == sample_letter_template.version
|
|
assert (
|
|
'services/{}/templates/{}'.format(
|
|
sample_letter_template.service_id,
|
|
sample_letter_template.id
|
|
) in resp_json['template']['uri']
|
|
)
|
|
assert not resp_json['scheduled_for']
|
|
assert not notification.reply_to_text
|
|
mock.assert_called_once_with([str(notification.id)], queue=QueueNames.CREATE_LETTERS_PDF)
|
|
|
|
|
|
def test_post_letter_notification_sets_postage(
|
|
client, notify_db_session, mocker
|
|
):
|
|
service = create_service(service_permissions=[LETTER_TYPE])
|
|
template = create_template(service, template_type="letter", postage="first")
|
|
mocker.patch('app.celery.tasks.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
data = {
|
|
'template_id': str(template.id),
|
|
'personalisation': {
|
|
'address_line_1': 'Her Royal Highness Queen Elizabeth II',
|
|
'address_line_2': 'Buckingham Palace',
|
|
'address_line_3': 'London',
|
|
'postcode': 'SW1 1AA',
|
|
'name': 'Lizzie'
|
|
}
|
|
}
|
|
|
|
resp_json = letter_request(client, data, service_id=service.id)
|
|
|
|
assert validate(resp_json, post_letter_response) == resp_json
|
|
notification = Notification.query.one()
|
|
assert notification.postage == "first"
|
|
|
|
|
|
def test_post_letter_notification_formats_postcode(
|
|
client, notify_db_session, mocker
|
|
):
|
|
service = create_service(service_permissions=[LETTER_TYPE])
|
|
template = create_template(service, template_type="letter")
|
|
mocker.patch('app.celery.tasks.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
data = {
|
|
'template_id': str(template.id),
|
|
'personalisation': {
|
|
'address_line_1': 'Her Royal Highness Queen Elizabeth II',
|
|
'address_line_2': 'Buckingham Palace',
|
|
'address_line_3': 'London',
|
|
'postcode': ' Sw1 1aa ',
|
|
'name': 'Lizzie'
|
|
}
|
|
}
|
|
|
|
resp_json = letter_request(client, data, service_id=service.id)
|
|
|
|
assert validate(resp_json, post_letter_response) == resp_json
|
|
notification = Notification.query.one()
|
|
# We store what the client gives us, and only reformat it when
|
|
# generating the PDF
|
|
assert notification.personalisation["postcode"] == ' Sw1 1aa '
|
|
|
|
|
|
def test_post_letter_notification_stores_country(
|
|
client, notify_db_session, mocker
|
|
):
|
|
service = create_service(service_permissions=[LETTER_TYPE, INTERNATIONAL_LETTERS])
|
|
template = create_template(service, template_type="letter")
|
|
mocker.patch('app.celery.tasks.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
data = {
|
|
'template_id': str(template.id),
|
|
'personalisation': {
|
|
'address_line_1': 'Kaiser Wilhelm II',
|
|
'address_line_2': 'Kronprinzenpalais',
|
|
'address_line_5': ' deutschland ',
|
|
}
|
|
}
|
|
|
|
resp_json = letter_request(client, data, service_id=service.id)
|
|
|
|
assert validate(resp_json, post_letter_response) == resp_json
|
|
notification = Notification.query.one()
|
|
# In the personalisation we store what the client gives us
|
|
assert notification.personalisation["address_line_1"] == 'Kaiser Wilhelm II'
|
|
assert notification.personalisation["address_line_2"] == 'Kronprinzenpalais'
|
|
assert notification.personalisation["address_line_5"] == ' deutschland '
|
|
# In the to field we store the whole address with the canonical country
|
|
assert notification.to == (
|
|
'Kaiser Wilhelm II\n'
|
|
'Kronprinzenpalais\n'
|
|
'Germany'
|
|
)
|
|
assert notification.postage == 'europe'
|
|
assert notification.international
|
|
|
|
|
|
def test_post_letter_notification_international_sets_rest_of_world(
|
|
client, notify_db_session, mocker
|
|
):
|
|
service = create_service(service_permissions=[LETTER_TYPE, INTERNATIONAL_LETTERS])
|
|
template = create_template(service, template_type="letter")
|
|
mocker.patch('app.celery.tasks.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
data = {
|
|
'template_id': str(template.id),
|
|
'personalisation': {
|
|
'address_line_1': 'Prince Harry',
|
|
'address_line_2': 'Toronto',
|
|
'address_line_5': 'Canada',
|
|
}
|
|
}
|
|
|
|
resp_json = letter_request(client, data, service_id=service.id)
|
|
|
|
assert validate(resp_json, post_letter_response) == resp_json
|
|
notification = Notification.query.one()
|
|
|
|
assert notification.postage == 'rest-of-world'
|
|
|
|
|
|
@pytest.mark.parametrize('permissions, personalisation, expected_error', (
|
|
(
|
|
[LETTER_TYPE],
|
|
{
|
|
'address_line_1': 'Her Royal Highness Queen Elizabeth II',
|
|
'address_line_2': 'Buckingham Palace',
|
|
'address_line_3': 'London',
|
|
'postcode': 'not a real postcode',
|
|
'name': 'Lizzie'
|
|
},
|
|
'Must be a real UK postcode',
|
|
),
|
|
(
|
|
[LETTER_TYPE],
|
|
{
|
|
'address_line_1': 'Her Royal Highness Queen Elizabeth II',
|
|
'address_line_2': ']Buckingham Palace',
|
|
'postcode': 'SW1A 1AA',
|
|
'name': 'Lizzie'
|
|
},
|
|
'Address lines must not start with any of the following characters: @ ( ) = [ ] ” \\ / , < >',
|
|
),
|
|
(
|
|
[LETTER_TYPE, INTERNATIONAL_LETTERS],
|
|
{
|
|
'address_line_1': 'Her Royal Highness Queen Elizabeth II',
|
|
'address_line_2': 'Buckingham Palace',
|
|
'address_line_3': 'London',
|
|
'postcode': 'not a real postcode',
|
|
'name': 'Lizzie'
|
|
},
|
|
'Last line of address must be a real UK postcode or another country',
|
|
),
|
|
))
|
|
def test_post_letter_notification_throws_error_for_bad_address(
|
|
client, notify_db_session, mocker, permissions, personalisation, expected_error
|
|
):
|
|
service = create_service(service_permissions=permissions)
|
|
template = create_template(service, template_type="letter", postage="first")
|
|
mocker.patch('app.celery.tasks.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
data = {
|
|
'template_id': str(template.id),
|
|
'personalisation': personalisation
|
|
}
|
|
|
|
error_json = letter_request(client, data, service_id=service.id, _expected_status=400)
|
|
|
|
assert error_json['status_code'] == 400
|
|
assert error_json['errors'] == [{
|
|
'error': 'ValidationError',
|
|
'message': expected_error
|
|
}]
|
|
|
|
|
|
@pytest.mark.parametrize('env', [
|
|
'staging',
|
|
'live',
|
|
])
|
|
def test_post_letter_notification_with_test_key_creates_pdf_and_sets_status_to_delivered(
|
|
notify_api, client, sample_letter_template, mocker, env):
|
|
|
|
data = {
|
|
'template_id': str(sample_letter_template.id),
|
|
'personalisation': {
|
|
'address_line_1': 'Her Royal Highness Queen Elizabeth II',
|
|
'address_line_2': 'Buckingham Palace',
|
|
'address_line_3': 'London',
|
|
'postcode': 'SW1 1AA',
|
|
'name': 'Lizzie'
|
|
},
|
|
'reference': 'foo'
|
|
}
|
|
|
|
fake_create_letter_task = mocker.patch('app.celery.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
fake_create_dvla_response_task = mocker.patch(
|
|
'app.celery.research_mode_tasks.create_fake_letter_response_file.apply_async')
|
|
|
|
with set_config_values(notify_api, {
|
|
'NOTIFY_ENVIRONMENT': env
|
|
}):
|
|
letter_request(client, data, service_id=sample_letter_template.service_id, key_type=KEY_TYPE_TEST)
|
|
|
|
notification = Notification.query.one()
|
|
|
|
fake_create_letter_task.assert_called_once_with([str(notification.id)], queue='research-mode-tasks')
|
|
assert not fake_create_dvla_response_task.called
|
|
assert notification.status == NOTIFICATION_DELIVERED
|
|
assert notification.updated_at is not None
|
|
|
|
|
|
@pytest.mark.parametrize('env', [
|
|
'development',
|
|
'preview',
|
|
])
|
|
def test_post_letter_notification_with_test_key_creates_pdf_and_sets_status_to_sending_and_sends_fake_response_file(
|
|
notify_api, client, sample_letter_template, mocker, env):
|
|
|
|
data = {
|
|
'template_id': str(sample_letter_template.id),
|
|
'personalisation': {
|
|
'address_line_1': 'Her Royal Highness Queen Elizabeth II',
|
|
'address_line_2': 'Buckingham Palace',
|
|
'address_line_3': 'London',
|
|
'postcode': 'SW1 1AA',
|
|
'name': 'Lizzie'
|
|
},
|
|
'reference': 'foo'
|
|
}
|
|
|
|
fake_create_letter_task = mocker.patch('app.celery.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
fake_create_dvla_response_task = mocker.patch(
|
|
'app.celery.research_mode_tasks.create_fake_letter_response_file.apply_async')
|
|
with set_config_values(notify_api, {
|
|
'NOTIFY_ENVIRONMENT': env
|
|
}):
|
|
letter_request(client, data, service_id=sample_letter_template.service_id, key_type=KEY_TYPE_TEST)
|
|
|
|
notification = Notification.query.one()
|
|
|
|
fake_create_letter_task.assert_called_once_with([str(notification.id)], queue='research-mode-tasks')
|
|
assert fake_create_dvla_response_task.called
|
|
assert notification.status == NOTIFICATION_SENDING
|
|
|
|
|
|
def test_post_letter_notification_returns_400_and_missing_template(
|
|
client,
|
|
sample_service_full_permissions
|
|
):
|
|
data = {
|
|
'template_id': str(uuid.uuid4()),
|
|
'personalisation': test_address
|
|
}
|
|
|
|
error_json = letter_request(client, data, service_id=sample_service_full_permissions.id, _expected_status=400)
|
|
|
|
assert error_json['status_code'] == 400
|
|
assert error_json['errors'] == [{'error': 'BadRequestError', 'message': 'Template not found'}]
|
|
|
|
|
|
def test_post_letter_notification_returns_400_for_empty_personalisation(
|
|
client,
|
|
sample_service_full_permissions,
|
|
sample_letter_template
|
|
):
|
|
data = {
|
|
'template_id': str(sample_letter_template.id),
|
|
'personalisation': {'address_line_1': '', 'address_line_2': '', 'postcode': ''}
|
|
}
|
|
|
|
error_json = letter_request(client, data, service_id=sample_service_full_permissions.id, _expected_status=400)
|
|
|
|
assert error_json['status_code'] == 400
|
|
assert all([e['error'] == 'ValidationError' for e in error_json['errors']])
|
|
assert set([e['message'] for e in error_json['errors']]) == {
|
|
'Address must be at least 3 lines',
|
|
}
|
|
|
|
|
|
def test_post_notification_returns_400_for_missing_letter_contact_block_personalisation(
|
|
client,
|
|
sample_service,
|
|
):
|
|
letter_contact_block = create_letter_contact(
|
|
service=sample_service, contact_block='((contact block))', is_default=True
|
|
)
|
|
template = create_template(
|
|
service=sample_service,
|
|
template_type='letter',
|
|
reply_to=letter_contact_block.id,
|
|
)
|
|
data = {
|
|
'template_id': str(template.id),
|
|
'personalisation': {
|
|
'address_line_1': 'Line 1',
|
|
'address_line_2': 'Line 2',
|
|
'postcode': 'SW1A 1AA',
|
|
},
|
|
}
|
|
|
|
error_json = letter_request(
|
|
client,
|
|
data,
|
|
service_id=sample_service.id,
|
|
_expected_status=400,
|
|
)
|
|
|
|
assert error_json['status_code'] == 400
|
|
assert error_json['errors'] == [{
|
|
'error': 'BadRequestError',
|
|
'message': 'Missing personalisation: contact block'
|
|
}]
|
|
|
|
|
|
def test_notification_returns_400_for_missing_template_field(
|
|
client,
|
|
sample_service_full_permissions
|
|
):
|
|
data = {
|
|
'personalisation': test_address
|
|
}
|
|
|
|
error_json = letter_request(client, data, service_id=sample_service_full_permissions.id, _expected_status=400)
|
|
|
|
assert error_json['status_code'] == 400
|
|
assert error_json['errors'] == [{
|
|
'error': 'ValidationError',
|
|
'message': 'template_id is a required property'
|
|
}]
|
|
|
|
|
|
def test_notification_returns_400_if_address_doesnt_have_underscores(
|
|
client,
|
|
sample_letter_template
|
|
):
|
|
data = {
|
|
'template_id': str(sample_letter_template.id),
|
|
'personalisation': {
|
|
'address line 1': 'Her Royal Highness Queen Elizabeth II',
|
|
'address-line-2': 'Buckingham Palace',
|
|
'postcode': 'SW1 1AA',
|
|
}
|
|
}
|
|
|
|
error_json = letter_request(client, data, service_id=sample_letter_template.service_id, _expected_status=400)
|
|
|
|
assert error_json['status_code'] == 400
|
|
assert error_json['errors'] == [
|
|
{
|
|
'error': 'ValidationError',
|
|
'message': 'Address must be at least 3 lines'
|
|
}
|
|
]
|
|
|
|
|
|
def test_returns_a_429_limit_exceeded_if_rate_limit_exceeded(
|
|
client,
|
|
sample_letter_template,
|
|
mocker
|
|
):
|
|
persist_mock = mocker.patch('app.v2.notifications.post_notifications.persist_notification')
|
|
mocker.patch(
|
|
'app.v2.notifications.post_notifications.check_rate_limiting',
|
|
side_effect=RateLimitError('LIMIT', 'INTERVAL', 'TYPE')
|
|
)
|
|
|
|
data = {
|
|
'template_id': str(sample_letter_template.id),
|
|
'personalisation': test_address
|
|
}
|
|
|
|
error_json = letter_request(client, data, service_id=sample_letter_template.service_id, _expected_status=429)
|
|
|
|
assert error_json['status_code'] == 429
|
|
assert error_json['errors'] == [{
|
|
'error': 'RateLimitError',
|
|
'message': 'Exceeded rate limit for key type TYPE of LIMIT requests per INTERVAL seconds'
|
|
}]
|
|
|
|
assert not persist_mock.called
|
|
|
|
|
|
@pytest.mark.parametrize('service_args, expected_status, expected_message', [
|
|
(
|
|
{'service_permissions': [EMAIL_TYPE, SMS_TYPE]},
|
|
400,
|
|
'Service is not allowed to send letters',
|
|
),
|
|
(
|
|
{'restricted': True},
|
|
403,
|
|
'Cannot send letters when service is in trial mode',
|
|
)
|
|
])
|
|
def test_post_letter_notification_returns_403_if_not_allowed_to_send_notification(
|
|
client,
|
|
notify_db_session,
|
|
service_args,
|
|
expected_status,
|
|
expected_message,
|
|
):
|
|
service = create_service(**service_args)
|
|
template = create_template(service, template_type=LETTER_TYPE)
|
|
|
|
data = {
|
|
'template_id': str(template.id),
|
|
'personalisation': test_address
|
|
}
|
|
|
|
error_json = letter_request(client, data, service_id=service.id, _expected_status=expected_status)
|
|
assert error_json['status_code'] == expected_status
|
|
assert error_json['errors'] == [
|
|
{'error': 'BadRequestError', 'message': expected_message}
|
|
]
|
|
|
|
|
|
def test_post_letter_notification_doesnt_accept_team_key(client, sample_letter_template, mocker):
|
|
mocker.patch('app.celery.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
data = {
|
|
'template_id': str(sample_letter_template.id),
|
|
'personalisation': {'address_line_1': 'Foo', 'address_line_2': 'Bar', 'postcode': 'Baz'}
|
|
}
|
|
|
|
error_json = letter_request(
|
|
client,
|
|
data,
|
|
sample_letter_template.service_id,
|
|
key_type=KEY_TYPE_TEAM,
|
|
_expected_status=403
|
|
)
|
|
|
|
assert error_json['status_code'] == 403
|
|
assert error_json['errors'] == [{'error': 'BadRequestError', 'message': 'Cannot send letters with a team api key'}]
|
|
|
|
|
|
def test_post_letter_notification_doesnt_send_in_trial(client, sample_trial_letter_template, mocker):
|
|
mocker.patch('app.celery.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
data = {
|
|
'template_id': str(sample_trial_letter_template.id),
|
|
'personalisation': {'address_line_1': 'Foo', 'address_line_2': 'Bar', 'postcode': 'Baz'}
|
|
}
|
|
|
|
error_json = letter_request(
|
|
client,
|
|
data,
|
|
sample_trial_letter_template.service_id,
|
|
_expected_status=403
|
|
)
|
|
|
|
assert error_json['status_code'] == 403
|
|
assert error_json['errors'] == [
|
|
{'error': 'BadRequestError', 'message': 'Cannot send letters when service is in trial mode'}]
|
|
|
|
|
|
def test_post_letter_notification_is_delivered_but_still_creates_pdf_if_in_trial_mode_and_using_test_key(
|
|
client,
|
|
sample_trial_letter_template,
|
|
mocker
|
|
):
|
|
fake_create_letter_task = mocker.patch('app.celery.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
|
|
data = {
|
|
"template_id": sample_trial_letter_template.id,
|
|
"personalisation": {'address_line_1': 'Foo', 'address_line_2': 'Bar', 'postcode': 'BA5 5AB'}
|
|
}
|
|
|
|
letter_request(client, data=data, service_id=sample_trial_letter_template.service_id, key_type=KEY_TYPE_TEST)
|
|
|
|
notification = Notification.query.one()
|
|
assert notification.status == NOTIFICATION_DELIVERED
|
|
fake_create_letter_task.assert_called_once_with([str(notification.id)], queue='research-mode-tasks')
|
|
|
|
|
|
def test_post_letter_notification_is_delivered_and_has_pdf_uploaded_to_test_letters_bucket_using_test_key(
|
|
client,
|
|
notify_user,
|
|
mocker
|
|
):
|
|
sample_letter_service = create_service(service_permissions=['letter'])
|
|
mocker.patch('app.celery.letters_pdf_tasks.notify_celery.send_task')
|
|
s3mock = mocker.patch('app.v2.notifications.post_notifications.upload_letter_pdf', return_value='test.pdf')
|
|
data = {
|
|
"reference": "letter-reference",
|
|
"content": "bGV0dGVyLWNvbnRlbnQ="
|
|
}
|
|
letter_request(
|
|
client,
|
|
data=data,
|
|
service_id=str(sample_letter_service.id),
|
|
key_type=KEY_TYPE_TEST,
|
|
precompiled=True)
|
|
|
|
notification = Notification.query.one()
|
|
assert notification.status == NOTIFICATION_PENDING_VIRUS_CHECK
|
|
s3mock.assert_called_once_with(ANY, b'letter-content', precompiled=True)
|
|
|
|
|
|
def test_post_letter_notification_ignores_reply_to_text_for_service(
|
|
client, notify_db_session, mocker
|
|
):
|
|
mocker.patch('app.celery.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
|
|
service = create_service(service_permissions=[LETTER_TYPE])
|
|
create_letter_contact(service=service, contact_block='ignored', is_default=True)
|
|
template = create_template(service=service, template_type='letter')
|
|
data = {
|
|
"template_id": template.id,
|
|
"personalisation": {'address_line_1': 'Foo', 'address_line_2': 'Bar', 'postcode': 'BA5 5AB'}
|
|
}
|
|
letter_request(client, data=data, service_id=service.id, key_type=KEY_TYPE_NORMAL)
|
|
|
|
notifications = Notification.query.all()
|
|
assert len(notifications) == 1
|
|
assert notifications[0].reply_to_text is None
|
|
|
|
|
|
def test_post_letter_notification_persists_notification_reply_to_text_for_template(
|
|
client, notify_db_session, mocker
|
|
):
|
|
mocker.patch('app.celery.letters_pdf_tasks.get_pdf_for_templated_letter.apply_async')
|
|
|
|
service = create_service(service_permissions=[LETTER_TYPE])
|
|
create_letter_contact(service=service, contact_block='the default', is_default=True)
|
|
template_letter_contact = create_letter_contact(service=service, contact_block='not the default', is_default=False)
|
|
template = create_template(service=service, template_type='letter', reply_to=template_letter_contact.id)
|
|
data = {
|
|
"template_id": template.id,
|
|
"personalisation": {'address_line_1': 'Foo', 'address_line_2': 'Bar', 'postcode': 'BA5 5AB'}
|
|
}
|
|
letter_request(client, data=data, service_id=service.id, key_type=KEY_TYPE_NORMAL)
|
|
|
|
notifications = Notification.query.all()
|
|
assert len(notifications) == 1
|
|
assert notifications[0].reply_to_text == 'not the default'
|
|
|
|
|
|
def test_post_precompiled_letter_with_invalid_base64(client, notify_user, mocker):
|
|
sample_service = create_service(service_permissions=['letter'])
|
|
mocker.patch('app.v2.notifications.post_notifications.upload_letter_pdf')
|
|
|
|
data = {
|
|
"reference": "letter-reference",
|
|
"content": "hi"
|
|
}
|
|
auth_header = create_service_authorization_header(service_id=sample_service.id)
|
|
response = client.post(
|
|
path="v2/notifications/letter",
|
|
data=json.dumps(data),
|
|
headers=[('Content-Type', 'application/json'), auth_header])
|
|
|
|
assert response.status_code == 400, response.get_data(as_text=True)
|
|
resp_json = json.loads(response.get_data(as_text=True))
|
|
assert resp_json['errors'][0]['message'] == 'Cannot decode letter content (invalid base64 encoding)'
|
|
|
|
assert not Notification.query.first()
|
|
|
|
|
|
@pytest.mark.parametrize('notification_postage, expected_postage', [
|
|
('second', 'second'),
|
|
('first', 'first'),
|
|
(None, 'second')
|
|
])
|
|
def test_post_precompiled_letter_notification_returns_201(
|
|
client, notify_user, mocker, notification_postage, expected_postage
|
|
):
|
|
sample_service = create_service(service_permissions=['letter'])
|
|
s3mock = mocker.patch('app.v2.notifications.post_notifications.upload_letter_pdf')
|
|
mocker.patch('app.celery.letters_pdf_tasks.notify_celery.send_task')
|
|
data = {
|
|
"reference": "letter-reference",
|
|
"content": "bGV0dGVyLWNvbnRlbnQ="
|
|
}
|
|
if notification_postage:
|
|
data["postage"] = notification_postage
|
|
auth_header = create_service_authorization_header(service_id=sample_service.id)
|
|
response = client.post(
|
|
path="v2/notifications/letter",
|
|
data=json.dumps(data),
|
|
headers=[('Content-Type', 'application/json'), auth_header])
|
|
|
|
assert response.status_code == 201, response.get_data(as_text=True)
|
|
|
|
s3mock.assert_called_once_with(ANY, b'letter-content', precompiled=True)
|
|
|
|
notification = Notification.query.one()
|
|
|
|
assert notification.billable_units == 0
|
|
assert notification.status == NOTIFICATION_PENDING_VIRUS_CHECK
|
|
assert notification.postage == expected_postage
|
|
|
|
resp_json = json.loads(response.get_data(as_text=True))
|
|
assert resp_json == {'id': str(notification.id), 'reference': 'letter-reference', 'postage': expected_postage}
|
|
|
|
|
|
def test_post_precompiled_letter_notification_if_s3_upload_fails_notification_is_not_persisted(
|
|
client, notify_user, mocker
|
|
):
|
|
sample_service = create_service(service_permissions=['letter'])
|
|
persist_letter_mock = mocker.patch('app.v2.notifications.post_notifications.create_letter_notification',
|
|
side_effect=create_letter_notification)
|
|
s3mock = mocker.patch('app.v2.notifications.post_notifications.upload_letter_pdf', side_effect=Exception())
|
|
mocker.patch('app.celery.letters_pdf_tasks.notify_celery.send_task')
|
|
data = {
|
|
"reference": "letter-reference",
|
|
"content": "bGV0dGVyLWNvbnRlbnQ="
|
|
}
|
|
|
|
auth_header = create_service_authorization_header(service_id=sample_service.id)
|
|
with pytest.raises(expected_exception=Exception):
|
|
client.post(
|
|
path="v2/notifications/letter",
|
|
data=json.dumps(data),
|
|
headers=[('Content-Type', 'application/json'), auth_header])
|
|
|
|
assert s3mock.called
|
|
assert persist_letter_mock.called
|
|
assert Notification.query.count() == 0
|
|
|
|
|
|
def test_post_letter_notification_throws_error_for_invalid_postage(client, notify_user, mocker):
|
|
sample_service = create_service(service_permissions=['letter'])
|
|
data = {
|
|
"reference": "letter-reference",
|
|
"content": "bGV0dGVyLWNvbnRlbnQ=",
|
|
"postage": "space unicorn"
|
|
}
|
|
auth_header = create_service_authorization_header(service_id=sample_service.id)
|
|
response = client.post(
|
|
path="v2/notifications/letter",
|
|
data=json.dumps(data),
|
|
headers=[('Content-Type', 'application/json'), auth_header])
|
|
|
|
assert response.status_code == 400, response.get_data(as_text=True)
|
|
resp_json = json.loads(response.get_data(as_text=True))
|
|
assert resp_json['errors'][0]['message'] == "postage invalid. It must be first, second, europe or rest-of-world."
|
|
|
|
assert not Notification.query.first()
|
|
|
|
|
|
@pytest.mark.parametrize('content_type',
|
|
['application/json', 'application/text'])
|
|
def test_post_letter_notification_when_payload_is_invalid_json_returns_400(
|
|
client, sample_service, content_type):
|
|
auth_header = create_service_authorization_header(service_id=sample_service.id)
|
|
payload_not_json = {
|
|
"template_id": "dont-convert-to-json",
|
|
}
|
|
response = client.post(
|
|
path='/v2/notifications/letter',
|
|
data=payload_not_json,
|
|
headers=[('Content-Type', content_type), auth_header],
|
|
)
|
|
|
|
assert response.status_code == 400
|
|
error_msg = json.loads(response.get_data(as_text=True))["errors"][0]["message"]
|
|
|
|
assert error_msg == 'Invalid JSON supplied in POST data'
|