Files
notifications-admin/tests/app/test_utils.py
Chris Hill-Scott c1a5cad0d6 Add function to estimate letter delivery date
Letter delivery depends on:
- how long it takes to print
- how long it takes to post

Both of these process are impacted by weekends, because people don’t
work on weekends.

It also depends on if you submit your letter before or after 5pm,
because that’s the cut off time for getting a letter printed on a given
day – ie after 5pm on Monday is effectively the same as Tuesday and so
on.

But I reckon all our users need to know is roughly how long it will take
until the letter turns up on the user’s doorstep. So this commit adds
a function to calculate this. Doesn’t surface it on the front end _yet_.
2017-07-12 15:11:39 +01:00

200 lines
6.3 KiB
Python

from pathlib import Path
from io import StringIO
from csv import DictReader
import pytest
from collections import OrderedDict
from app.utils import (
email_safe,
generate_notifications_csv,
generate_previous_dict,
generate_next_dict,
Spreadsheet,
get_estimated_delivery_date_for_letters,
)
from tests import notification_json, single_notification_json
def _get_notifications_csv(
service_id,
page=1,
row_number=1,
recipient='foo@bar.com',
template_name='foo',
template_type='sms',
job_name='bar.csv',
status='Delivered',
created_at='Thursday 19 April at 12:00',
rows=1,
with_links=False
):
links = {}
if with_links:
links = {
'prev': '/service/{}/notifications?page=0'.format(service_id),
'next': '/service/{}/notifications?page=1'.format(service_id),
'last': '/service/{}/notifications?page=2'.format(service_id)
}
data = {
'notifications': [{
"row_number": row_number,
"recipient": recipient,
"template_name": template_name,
"template_type": template_type,
"job_name": job_name,
"status": status,
"created_at": created_at
} for i in range(rows)],
'total': rows,
'page_size': 50,
'links': links
}
return data
@pytest.fixture(scope='function')
def _get_notifications_csv_mock(
mocker,
api_user_active
):
return mocker.patch(
'app.notification_api_client.get_notifications_for_service',
side_effect=_get_notifications_csv
)
@pytest.mark.parametrize('service_name, safe_email', [
('name with spaces', 'name.with.spaces'),
('singleword', 'singleword'),
('UPPER CASE', 'upper.case'),
('Service - with dash', 'service.with.dash'),
('lots of spaces', 'lots.of.spaces'),
('name.with.dots', 'name.with.dots'),
('name-with-other-delimiters', 'namewithotherdelimiters'),
('.leading', 'leading'),
('trailing.', 'trailing'),
('üńïçödë wördś', 'unicode.words'),
])
def test_email_safe_return_dot_separated_email_domain(service_name, safe_email):
assert email_safe(service_name) == safe_email
def test_generate_previous_dict(client):
ret = generate_previous_dict('main.view_jobs', 'foo', 2, {})
assert 'page=1' in ret['url']
assert ret['title'] == 'Previous page'
assert ret['label'] == 'page 1'
def test_generate_next_dict(client):
ret = generate_next_dict('main.view_jobs', 'foo', 2, {})
assert 'page=3' in ret['url']
assert ret['title'] == 'Next page'
assert ret['label'] == 'page 3'
def test_generate_previous_next_dict_adds_other_url_args(client):
ret = generate_next_dict('main.view_notifications', 'foo', 2, {'message_type': 'blah'})
assert 'notifications/blah' in ret['url']
def test_can_create_spreadsheet_from_large_excel_file():
with open(str(Path.cwd() / 'tests' / 'spreadsheet_files' / 'excel 2007.xlsx'), 'rb') as xl:
ret = Spreadsheet.from_file(xl, filename='xl.xlsx')
assert ret.as_csv_data
def test_can_create_spreadsheet_from_dict():
assert Spreadsheet.from_dict(OrderedDict(
foo='bar',
name='Jane',
)).as_csv_data == (
"foo,name\r\n"
"bar,Jane\r\n"
)
def test_can_create_spreadsheet_from_dict_with_filename():
assert Spreadsheet.from_dict({}, filename='empty.csv').as_dict['file_name'] == "empty.csv"
def test_generate_notifications_csv_returns_correct_csv_file(_get_notifications_csv_mock):
csv_content = generate_notifications_csv(service_id='1234')
csv_file = DictReader(StringIO('\n'.join(csv_content)))
assert csv_file.fieldnames == ['Row number', 'Recipient', 'Template', 'Type', 'Job', 'Status', 'Time']
def test_generate_notifications_csv_only_calls_once_if_no_next_link(_get_notifications_csv_mock):
list(generate_notifications_csv(service_id='1234'))
assert _get_notifications_csv_mock.call_count == 1
def test_generate_notifications_csv_calls_twice_if_next_link(mocker):
service_id = '1234'
response_with_links = _get_notifications_csv(service_id, rows=7, with_links=True)
response_with_no_links = _get_notifications_csv(service_id, rows=3, with_links=False)
mock_get_notifications = mocker.patch(
'app.notification_api_client.get_notifications_for_service',
side_effect=[
response_with_links,
response_with_no_links,
]
)
csv_content = generate_notifications_csv(service_id=service_id)
csv = DictReader(StringIO('\n'.join(csv_content)))
assert len(list(csv)) == 10
assert mock_get_notifications.call_count == 2
# mock_calls[0][2] is the kwargs from first call
assert mock_get_notifications.mock_calls[0][2]['page'] == 1
assert mock_get_notifications.mock_calls[1][2]['page'] == 2
@pytest.mark.parametrize('upload_time, expected_estimate', [
# BST
# ==================================================================
# First thing Monday
('2017-07-10 00:00:01', ('Thursday', 'Friday')),
# Monday at 16:59 BST
('2017-07-10 15:59:59', ('Thursday', 'Friday')),
# Monday at 17:00 BST
('2017-07-10 16:00:01', ('Friday', 'Saturday')),
# Tuesday before 17:00 BST
('2017-07-11 12:00:00', ('Friday', 'Saturday')),
# Wednesday before 17:00 BST
('2017-07-12 12:00:00', ('Saturday', 'Monday')),
# Thursday before 17:00 BST
('2017-07-13 12:00:00', ('Monday', 'Tuesday')),
# Friday anytime
('2017-07-14 00:00:00', ('Wednesday', 'Thursday')),
('2017-07-14 12:00:00', ('Wednesday', 'Thursday')),
('2017-07-14 22:00:00', ('Wednesday', 'Thursday')),
# Saturday anytime
('2017-07-14 12:00:00', ('Wednesday', 'Thursday')),
# Sunday before 1700 BST
('2017-07-15 15:59:59', ('Wednesday', 'Thursday')),
# Sunday after 17:00 BST
('2017-07-16 16:00:01', ('Thursday', 'Friday')),
# GMT
# ==================================================================
# Monday at 16:59 GMT
('2017-01-02 16:59:59', ('Thursday', 'Friday')),
# Monday at 17:00 GMT
('2017-01-02 17:00:01', ('Friday', 'Saturday')),
])
def test_get_estimated_delivery_date_for_letter(upload_time, expected_estimate):
assert tuple(
day.strftime('%A')
for day in get_estimated_delivery_date_for_letters(upload_time)
) == expected_estimate