Add tests for letters as pdf permission

- test that `create_letters_pdf` only gets called when `letters_as_pdf` permission set
- test that `build_dvla_file` does not get called when `letters_as_pdf` permission set
- test creating the pdf call to notifications template preview service
- test uploading the data to s3 calls upload_letters_pdf function
This commit is contained in:
Ken Tsang
2017-12-08 17:40:00 +00:00
parent 7970cd3d4e
commit aca52952d8

View File

@@ -9,8 +9,9 @@ from flask import current_app
from freezegun import freeze_time from freezegun import freeze_time
from requests import RequestException from requests import RequestException
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from celery.exceptions import Retry from celery.exceptions import Retry, MaxRetriesExceededError
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from sqlalchemy.orm.exc import NoResultFound
from notifications_utils.template import SMSMessageTemplate, WithSubjectTemplate, LetterDVLATemplate from notifications_utils.template import SMSMessageTemplate, WithSubjectTemplate, LetterDVLATemplate
from app import (encryption, DATETIME_FORMAT) from app import (encryption, DATETIME_FORMAT)
@@ -20,6 +21,9 @@ from app.celery.scheduled_tasks import check_job_status
from app.celery.tasks import ( from app.celery.tasks import (
build_dvla_file, build_dvla_file,
create_dvla_file_contents_for_job, create_dvla_file_contents_for_job,
create_letters_pdf,
get_letters_pdf,
job_complete,
process_job, process_job,
process_row, process_row,
save_sms, save_sms,
@@ -32,7 +36,7 @@ from app.celery.tasks import (
send_inbound_sms_to_service, send_inbound_sms_to_service,
) )
from app.config import QueueNames from app.config import QueueNames
from app.dao import jobs_dao, services_dao from app.dao import jobs_dao, services_dao, service_permissions_dao
from app.models import ( from app.models import (
Job, Job,
Notification, Notification,
@@ -47,6 +51,7 @@ from app.models import (
SMS_TYPE SMS_TYPE
) )
from tests.conftest import set_config_values
from tests.app import load_example_csv from tests.app import load_example_csv
from tests.app.conftest import ( from tests.app.conftest import (
sample_service as create_sample_service, sample_service as create_sample_service,
@@ -94,6 +99,7 @@ def test_should_have_decorated_tasks_functions():
assert save_sms.__wrapped__.__name__ == 'save_sms' assert save_sms.__wrapped__.__name__ == 'save_sms'
assert save_email.__wrapped__.__name__ == 'save_email' assert save_email.__wrapped__.__name__ == 'save_email'
assert save_letter.__wrapped__.__name__ == 'save_letter' assert save_letter.__wrapped__.__name__ == 'save_letter'
assert create_letters_pdf.__wrapped__.__name__ == 'create_letters_pdf'
@pytest.fixture @pytest.fixture
@@ -1039,6 +1045,50 @@ def test_save_letter_saves_letter_to_database(mocker, notify_db_session):
assert notification_db.reply_to_text == "Address contact" assert notification_db.reply_to_text == "Address contact"
def test_save_letter_saves_letter_calls_create_letters_as_pdf_with_letters_as_pdf_permission(
mocker, notify_db_session, sample_letter_job):
service_permissions_dao.dao_add_service_permission(sample_letter_job.service.id, 'letters_as_pdf')
mock_create_letters_pdf = mocker.patch('app.celery.tasks.create_letters_pdf.apply_async')
personalisation = {
'addressline1': 'Foo',
'addressline2': 'Bar',
'postcode': 'Flob',
}
notification_json = _notification_json(
template=sample_letter_job.template,
to='Foo',
personalisation=personalisation,
job_id=sample_letter_job.id,
row_number=1
)
notification_id = uuid.uuid4()
save_letter(
sample_letter_job.service_id,
notification_id,
encryption.encrypt(notification_json),
)
assert mock_create_letters_pdf.called
mock_create_letters_pdf.assert_called_once_with(
[str(notification_id)],
queue=QueueNames.CREATE_LETTERS_PDF
)
def test_job_complete_does_not_call_build_dvla_file_with_letters_as_pdf_permission(
mocker, notify_db_session, sample_letter_job):
service_permissions_dao.dao_add_service_permission(sample_letter_job.service.id, 'letters_as_pdf')
mock_build_dvla_files = mocker.patch('app.celery.tasks.build_dvla_file.apply_async')
job_complete(sample_letter_job, sample_letter_job.service, sample_letter_job.template.template_type)
assert not sample_letter_job.service.research_mode
assert not mock_build_dvla_files.called
assert sample_letter_job.job_status == JOB_STATUS_FINISHED
def test_should_cancel_job_if_service_is_inactive(sample_service, def test_should_cancel_job_if_service_is_inactive(sample_service,
sample_job, sample_job,
mocker): mocker):
@@ -1455,3 +1505,83 @@ def test_process_incomplete_job_letter(mocker, sample_letter_template):
assert mock_build_dvla.called assert mock_build_dvla.called
assert mock_letter_saver.call_count == 8 assert mock_letter_saver.call_count == 8
@pytest.mark.parametrize('personalisation', [{'name': 'test'}, None])
def test_get_letters_pdf_calls_notifications_template_preview_service_correctly(
notify_api, mocker, client, sample_letter_template, personalisation):
contact_block = 'Mr Foo,\n1 Test Street,\nLondon\nN1'
dvla_org_id = '002'
with set_config_values(notify_api, {
'TEMPLATE_PREVIEW_API_HOST': 'http://localhost/notifications-template-preview',
'TEMPLATE_PREVIEW_API_KEY': 'test-key'
}):
with requests_mock.Mocker() as request_mock:
mock_post = request_mock.post(
'http://localhost/notifications-template-preview/print.pdf', content=b'\x00\x01', status_code=200)
get_letters_pdf(
sample_letter_template, contact_block=contact_block, org_id=dvla_org_id, values=personalisation)
assert mock_post.last_request.json() == {
'values': personalisation,
'letter_contact_block': contact_block,
'dvla_org_id': dvla_org_id,
'template': {
'subject': sample_letter_template.subject,
'content': sample_letter_template.content
}
}
def test_create_letters_pdf_calls_upload_letters_pdf(mocker, sample_letter_notification):
mocker.patch('app.celery.tasks.get_letters_pdf', return_value=b'\x00\x01')
mock_s3 = mocker.patch('app.celery.tasks.s3.upload_letters_pdf')
create_letters_pdf(sample_letter_notification.id)
mock_s3.assert_called_with(
reference=sample_letter_notification.reference,
crown=True,
filedata=b'\x00\x01'
)
def test_create_letters_pdf_non_existent_notification(notify_api, mocker, fake_uuid):
with pytest.raises(expected_exception=NoResultFound):
create_letters_pdf(fake_uuid)
def test_create_letters_pdf_handles_request_errors(mocker, sample_letter_notification):
mock_get_letters_pdf = mocker.patch('app.celery.tasks.get_letters_pdf', side_effect=RequestException)
mock_retry = mocker.patch('app.celery.tasks.create_letters_pdf.retry')
create_letters_pdf(sample_letter_notification.id)
assert mock_get_letters_pdf.called
assert mock_retry.called
def test_create_letters_pdf_handles_s3_errors(mocker, sample_letter_notification):
mocker.patch('app.celery.tasks.get_letters_pdf')
mock_s3 = mocker.patch('app.celery.tasks.s3.upload_letters_pdf', side_effect=ClientError({}, 'operation_name'))
mock_retry = mocker.patch('app.celery.tasks.create_letters_pdf.retry')
create_letters_pdf(sample_letter_notification.id)
assert mock_s3.called
assert mock_retry.called
def test_create_letters_pdf_sets_technical_failure_max_retries(mocker, sample_letter_notification):
mock_get_letters_pdf = mocker.patch('app.celery.tasks.get_letters_pdf', side_effect=RequestException)
mock_retry = mocker.patch('app.celery.tasks.create_letters_pdf.retry', side_effect=MaxRetriesExceededError)
mock_update_noti = mocker.patch('app.celery.tasks.update_notification_status_by_id')
create_letters_pdf(sample_letter_notification.id)
assert mock_get_letters_pdf.called
assert mock_retry.called
assert mock_update_noti.called
mock_update_noti.assert_called_once_with(sample_letter_notification.id, 'technical-failure')