mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-04-30 06:01:06 -04:00
This repeats the pattern we already have for previewing a letter,
where we assume the error is because the notification has already
been sent and redirect the user to see it.
I've improved the original pattern a bit:
- I've DRYed-up the low-level boto code and moved the error handler
there so it can be reused.
- I've introduced a custom exception, which the calling code can
choose to log.
- I've introduced the moto library, which we use elsewhere, to make
it easier to test S3 code.
I've used an error level log when sending a notification - now that
we have a more descriptive log, we can verify the assumption is true
and then make an informed decision to downgrade the log.
In future we may want to merge this handler with the similar code
in utils [1], but we'll need to be careful as the utils handler is
superficial - it doesn't check the reason for the error.
[1]: bce0f4e596/notifications_utils/s3.py (L52)
121 lines
3.6 KiB
Python
121 lines
3.6 KiB
Python
import urllib
|
|
import uuid
|
|
|
|
import boto3
|
|
import botocore
|
|
import pytest
|
|
from flask import current_app
|
|
from moto import mock_s3
|
|
|
|
from app.s3_client.s3_letter_upload_client import (
|
|
LetterMetadata,
|
|
LetterNotFoundError,
|
|
backup_original_letter_to_s3,
|
|
get_letter_metadata,
|
|
upload_letter_to_s3,
|
|
)
|
|
|
|
|
|
def test_backup_original_letter_to_s3(mocker, notify_admin):
|
|
s3_mock = mocker.patch('app.s3_client.s3_letter_upload_client.utils_s3upload')
|
|
upload_id = uuid.uuid4()
|
|
|
|
backup_original_letter_to_s3(
|
|
'pdf_data',
|
|
upload_id=upload_id,
|
|
)
|
|
|
|
s3_mock.assert_called_once_with(
|
|
bucket_name=current_app.config['PRECOMPILED_ORIGINALS_BACKUP_LETTERS'],
|
|
file_location=f'{str(upload_id)}.pdf',
|
|
filedata='pdf_data',
|
|
region=current_app.config['AWS_REGION']
|
|
)
|
|
|
|
|
|
def test_upload_letter_to_s3(mocker):
|
|
s3_mock = mocker.patch('app.s3_client.s3_letter_upload_client.utils_s3upload')
|
|
|
|
recipient = 'Bugs Bunny\n123 Big Hole\nLooney Town'
|
|
upload_letter_to_s3(
|
|
'pdf_data',
|
|
file_location='service_id/upload_id.pdf',
|
|
status='valid',
|
|
page_count=3,
|
|
filename='my_doc',
|
|
recipient=recipient
|
|
)
|
|
|
|
s3_mock.assert_called_once_with(
|
|
bucket_name=current_app.config['TRANSIENT_UPLOADED_LETTERS'],
|
|
file_location='service_id/upload_id.pdf',
|
|
filedata='pdf_data',
|
|
metadata={'status': 'valid', 'page_count': '3', 'filename': 'my_doc',
|
|
'recipient': urllib.parse.quote(recipient)},
|
|
region=current_app.config['AWS_REGION']
|
|
)
|
|
|
|
|
|
def test_upload_letter_to_s3_with_message_and_invalid_pages(mocker):
|
|
s3_mock = mocker.patch('app.s3_client.s3_letter_upload_client.utils_s3upload')
|
|
|
|
upload_letter_to_s3(
|
|
'pdf_data',
|
|
file_location='service_id/upload_id.pdf',
|
|
status='invalid',
|
|
page_count=3,
|
|
filename='my_doc',
|
|
message='This file failed',
|
|
invalid_pages=[1, 2, 5])
|
|
|
|
s3_mock.assert_called_once_with(
|
|
bucket_name=current_app.config['TRANSIENT_UPLOADED_LETTERS'],
|
|
file_location='service_id/upload_id.pdf',
|
|
filedata='pdf_data',
|
|
metadata={
|
|
'status': 'invalid',
|
|
'page_count': '3',
|
|
'filename': 'my_doc',
|
|
'message': 'This file failed',
|
|
'invalid_pages': '[1, 2, 5]'
|
|
},
|
|
region=current_app.config['AWS_REGION']
|
|
)
|
|
|
|
|
|
def test_lettermetadata_gets_non_special_keys():
|
|
metadata = LetterMetadata({"key": "value", "not_key_to_decode": "%C2%A3"})
|
|
assert metadata.get("key") == "value"
|
|
assert metadata.get("other_key") is None
|
|
assert metadata.get("other_key", "default") == "default"
|
|
assert metadata.get("not_key_to_decode") == "%C2%A3"
|
|
|
|
|
|
def test_lettermetadata_unquotes_special_keys():
|
|
metadata = LetterMetadata({"filename": "%C2%A3hello", "recipient": "%C2%A3hi"})
|
|
assert metadata.get("filename") == "£hello"
|
|
assert metadata.get("recipient") == "£hi"
|
|
|
|
|
|
@mock_s3
|
|
@pytest.mark.parametrize('will_raise_custom_error,expected_exception', [
|
|
(True, LetterNotFoundError),
|
|
(False, botocore.exceptions.ClientError)
|
|
])
|
|
def test_get_letter_s3_object_raises_custom_error(
|
|
will_raise_custom_error,
|
|
expected_exception
|
|
):
|
|
bucket_name = current_app.config['TRANSIENT_UPLOADED_LETTERS']
|
|
s3 = boto3.client('s3', region_name='eu-west-1')
|
|
|
|
# bucket not existing will trigger some other error
|
|
if will_raise_custom_error:
|
|
s3.create_bucket(
|
|
Bucket=bucket_name,
|
|
CreateBucketConfiguration={'LocationConstraint': 'eu-west-1'}
|
|
)
|
|
|
|
with pytest.raises(expected_exception):
|
|
get_letter_metadata('service', 'file')
|