2017-06-13 10:32:36 +01:00
|
|
|
|
import json
|
|
|
|
|
|
import uuid
|
2018-07-10 15:49:57 +01:00
|
|
|
|
from functools import partial
|
2018-02-20 11:22:17 +00:00
|
|
|
|
from urllib.parse import parse_qs, quote, urlparse
|
2017-06-13 10:32:36 +01:00
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
from bs4 import BeautifulSoup
|
2018-02-20 11:22:17 +00:00
|
|
|
|
from flask import url_for
|
|
|
|
|
|
from freezegun import freeze_time
|
2018-04-25 14:12:58 +01:00
|
|
|
|
|
|
|
|
|
|
from app.main.views.jobs import get_status_filters, get_time_left
|
2018-10-26 15:58:44 +01:00
|
|
|
|
from app.models.service import Service
|
2017-10-02 12:34:10 +01:00
|
|
|
|
from tests.conftest import (
|
|
|
|
|
|
SERVICE_ONE_ID,
|
2018-06-13 14:16:10 +01:00
|
|
|
|
active_caseworking_user,
|
|
|
|
|
|
active_user_view_permissions,
|
2018-07-10 15:49:57 +01:00
|
|
|
|
active_user_with_permissions,
|
2017-10-02 12:34:10 +01:00
|
|
|
|
mock_get_notifications,
|
|
|
|
|
|
normalize_spaces,
|
|
|
|
|
|
)
|
2018-02-20 11:22:17 +00:00
|
|
|
|
|
2017-06-13 10:32:36 +01:00
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
2018-11-15 17:04:11 +00:00
|
|
|
|
"user,extra_args,expected_update_endpoint,expected_limit_days,page_title", [
|
|
|
|
|
|
(
|
|
|
|
|
|
active_user_view_permissions,
|
|
|
|
|
|
{'message_type': 'email'},
|
|
|
|
|
|
'/email.json',
|
|
|
|
|
|
7,
|
|
|
|
|
|
'Emails',
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
active_user_view_permissions,
|
|
|
|
|
|
{'message_type': 'sms'},
|
|
|
|
|
|
'/sms.json',
|
|
|
|
|
|
7,
|
|
|
|
|
|
'Text messages',
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
active_caseworking_user,
|
|
|
|
|
|
{},
|
|
|
|
|
|
'.json',
|
|
|
|
|
|
None,
|
|
|
|
|
|
'Sent messages',
|
|
|
|
|
|
),
|
2017-06-13 10:32:36 +01:00
|
|
|
|
]
|
|
|
|
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
|
"status_argument, expected_api_call", [
|
|
|
|
|
|
(
|
|
|
|
|
|
'',
|
|
|
|
|
|
[
|
2018-03-19 15:25:26 +00:00
|
|
|
|
'created', 'pending', 'sending', 'pending-virus-check',
|
2018-09-06 16:34:23 +01:00
|
|
|
|
'delivered', 'sent', 'returned-letter',
|
2018-12-04 15:07:20 +00:00
|
|
|
|
'failed', 'temporary-failure', 'permanent-failure', 'technical-failure',
|
2019-01-10 15:54:31 +00:00
|
|
|
|
'virus-scan-failed', 'validation-failed'
|
2017-06-13 10:32:36 +01:00
|
|
|
|
]
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'sending',
|
2018-03-19 15:25:26 +00:00
|
|
|
|
['sending', 'created', 'pending', 'pending-virus-check']
|
2017-06-13 10:32:36 +01:00
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'delivered',
|
2018-09-06 16:34:23 +01:00
|
|
|
|
['delivered', 'sent', 'returned-letter']
|
2017-06-13 10:32:36 +01:00
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'failed',
|
2019-01-10 15:54:31 +00:00
|
|
|
|
[
|
|
|
|
|
|
'failed', 'temporary-failure', 'permanent-failure', 'technical-failure',
|
|
|
|
|
|
'virus-scan-failed', 'validation-failed'
|
|
|
|
|
|
]
|
2017-06-13 10:32:36 +01:00
|
|
|
|
)
|
|
|
|
|
|
]
|
|
|
|
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
|
"page_argument, expected_page_argument", [
|
|
|
|
|
|
(1, 1),
|
|
|
|
|
|
(22, 22),
|
|
|
|
|
|
(None, 1)
|
|
|
|
|
|
]
|
|
|
|
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
|
"to_argument, expected_to_argument", [
|
|
|
|
|
|
('', ''),
|
|
|
|
|
|
('+447900900123', '+447900900123'),
|
|
|
|
|
|
('test@example.com', 'test@example.com'),
|
|
|
|
|
|
]
|
|
|
|
|
|
)
|
|
|
|
|
|
def test_can_show_notifications(
|
2018-07-13 16:21:22 +01:00
|
|
|
|
client_request,
|
2017-06-13 10:32:36 +01:00
|
|
|
|
logged_in_client,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_notifications,
|
2018-05-09 13:53:02 +01:00
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2018-07-30 17:40:32 +01:00
|
|
|
|
mock_has_no_jobs,
|
2018-07-13 16:21:22 +01:00
|
|
|
|
user,
|
|
|
|
|
|
extra_args,
|
|
|
|
|
|
expected_update_endpoint,
|
2018-11-15 17:04:11 +00:00
|
|
|
|
expected_limit_days,
|
2017-06-13 10:32:36 +01:00
|
|
|
|
page_title,
|
|
|
|
|
|
status_argument,
|
|
|
|
|
|
expected_api_call,
|
|
|
|
|
|
page_argument,
|
|
|
|
|
|
expected_page_argument,
|
|
|
|
|
|
to_argument,
|
|
|
|
|
|
expected_to_argument,
|
2018-06-13 14:16:10 +01:00
|
|
|
|
mocker,
|
|
|
|
|
|
fake_uuid,
|
2017-06-13 10:32:36 +01:00
|
|
|
|
):
|
2018-07-13 16:21:22 +01:00
|
|
|
|
client_request.login(user(fake_uuid))
|
2017-06-13 11:05:57 +01:00
|
|
|
|
if expected_to_argument:
|
2018-07-13 16:21:22 +01:00
|
|
|
|
page = client_request.post(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=service_one['id'],
|
|
|
|
|
|
status=status_argument,
|
|
|
|
|
|
page=page_argument,
|
|
|
|
|
|
_data={
|
2017-06-13 11:05:57 +01:00
|
|
|
|
'to': to_argument
|
2018-07-13 16:21:22 +01:00
|
|
|
|
},
|
|
|
|
|
|
_expected_status=200,
|
|
|
|
|
|
**extra_args
|
2017-06-13 11:05:57 +01:00
|
|
|
|
)
|
|
|
|
|
|
else:
|
2018-07-13 16:21:22 +01:00
|
|
|
|
page = client_request.get(
|
2017-06-13 11:05:57 +01:00
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=service_one['id'],
|
|
|
|
|
|
status=status_argument,
|
|
|
|
|
|
page=page_argument,
|
2018-07-13 16:21:22 +01:00
|
|
|
|
**extra_args
|
|
|
|
|
|
)
|
2017-06-24 17:12:45 +01:00
|
|
|
|
text_of_first_row = page.select('tbody tr')[0].text
|
|
|
|
|
|
assert '07123456789' in text_of_first_row
|
|
|
|
|
|
assert (
|
|
|
|
|
|
'template content' in text_of_first_row or
|
|
|
|
|
|
'template subject' in text_of_first_row
|
|
|
|
|
|
)
|
|
|
|
|
|
assert 'Delivered' in text_of_first_row
|
2017-06-13 10:32:36 +01:00
|
|
|
|
assert page_title in page.h1.text.strip()
|
|
|
|
|
|
|
|
|
|
|
|
path_to_json = page.find("div", {'data-key': 'notifications'})['data-resource']
|
|
|
|
|
|
|
|
|
|
|
|
url = urlparse(path_to_json)
|
2018-07-13 16:21:22 +01:00
|
|
|
|
assert url.path == '/services/{}/notifications{}'.format(
|
|
|
|
|
|
service_one['id'],
|
|
|
|
|
|
expected_update_endpoint,
|
|
|
|
|
|
)
|
2017-06-13 10:32:36 +01:00
|
|
|
|
query_dict = parse_qs(url.query)
|
|
|
|
|
|
if status_argument:
|
|
|
|
|
|
assert query_dict['status'] == [status_argument]
|
|
|
|
|
|
if expected_page_argument:
|
|
|
|
|
|
assert query_dict['page'] == [str(expected_page_argument)]
|
2017-06-13 11:20:41 +01:00
|
|
|
|
assert 'to' not in query_dict
|
2017-06-13 10:32:36 +01:00
|
|
|
|
|
|
|
|
|
|
mock_get_notifications.assert_called_with(
|
2018-11-15 17:04:11 +00:00
|
|
|
|
limit_days=expected_limit_days,
|
2017-06-13 10:32:36 +01:00
|
|
|
|
page=expected_page_argument,
|
|
|
|
|
|
service_id=service_one['id'],
|
|
|
|
|
|
status=expected_api_call,
|
2018-07-13 16:21:22 +01:00
|
|
|
|
template_type=list(extra_args.values()),
|
2017-06-13 10:32:36 +01:00
|
|
|
|
to=expected_to_argument,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
json_response = logged_in_client.get(url_for(
|
|
|
|
|
|
'main.get_notifications_as_json',
|
|
|
|
|
|
service_id=service_one['id'],
|
2018-07-13 16:21:22 +01:00
|
|
|
|
status=status_argument,
|
|
|
|
|
|
**extra_args
|
2017-06-13 10:32:36 +01:00
|
|
|
|
))
|
|
|
|
|
|
json_content = json.loads(json_response.get_data(as_text=True))
|
2018-08-13 17:07:49 +01:00
|
|
|
|
assert json_content.keys() == {'counts', 'notifications', 'service_data_retention_days'}
|
2017-06-13 10:32:36 +01:00
|
|
|
|
|
|
|
|
|
|
|
2018-11-15 17:04:11 +00:00
|
|
|
|
def test_can_show_notifications_if_data_retention_not_available(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mock_get_notifications,
|
|
|
|
|
|
mock_get_service_statistics,
|
|
|
|
|
|
mock_has_no_jobs,
|
|
|
|
|
|
):
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
status='sending,delivered,failed',
|
|
|
|
|
|
)
|
|
|
|
|
|
assert page.h1.text.strip() == 'Messages'
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-07-10 15:49:57 +01:00
|
|
|
|
@pytest.mark.parametrize('user, query_parameters, expected_download_link', [
|
|
|
|
|
|
(
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
{},
|
|
|
|
|
|
partial(
|
|
|
|
|
|
url_for,
|
|
|
|
|
|
'.download_notifications_csv',
|
|
|
|
|
|
message_type=None,
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
{'status': 'failed'},
|
|
|
|
|
|
partial(
|
|
|
|
|
|
url_for,
|
|
|
|
|
|
'.download_notifications_csv',
|
|
|
|
|
|
status='failed'
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
{'message_type': 'sms'},
|
|
|
|
|
|
partial(
|
|
|
|
|
|
url_for,
|
|
|
|
|
|
'.download_notifications_csv',
|
|
|
|
|
|
message_type='sms',
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
active_user_view_permissions,
|
|
|
|
|
|
{},
|
|
|
|
|
|
partial(
|
|
|
|
|
|
url_for,
|
|
|
|
|
|
'.download_notifications_csv',
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
active_caseworking_user,
|
|
|
|
|
|
{},
|
|
|
|
|
|
lambda service_id: None,
|
|
|
|
|
|
),
|
|
|
|
|
|
])
|
|
|
|
|
|
def test_link_to_download_notifications(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
mock_get_notifications,
|
|
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2018-07-30 17:40:32 +01:00
|
|
|
|
mock_has_no_jobs,
|
2018-07-10 15:49:57 +01:00
|
|
|
|
user,
|
|
|
|
|
|
query_parameters,
|
|
|
|
|
|
expected_download_link,
|
|
|
|
|
|
):
|
|
|
|
|
|
client_request.login(user(fake_uuid))
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
**query_parameters
|
|
|
|
|
|
)
|
|
|
|
|
|
download_link = page.select_one('a[download=download]')
|
|
|
|
|
|
assert (
|
|
|
|
|
|
download_link['href'] if download_link else None
|
|
|
|
|
|
) == expected_download_link(service_id=SERVICE_ONE_ID)
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-08-09 17:51:34 +01:00
|
|
|
|
def test_download_not_available_to_users_without_dashboard(
|
2018-07-10 15:49:57 +01:00
|
|
|
|
client_request,
|
|
|
|
|
|
active_caseworking_user,
|
|
|
|
|
|
):
|
|
|
|
|
|
client_request.login(active_caseworking_user)
|
|
|
|
|
|
client_request.get(
|
|
|
|
|
|
'main.download_notifications_csv',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_expected_status=403,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-19 15:25:26 +00:00
|
|
|
|
def test_letters_with_status_virus_scan_failed_shows_a_failure_description(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
logged_in_client,
|
|
|
|
|
|
service_one,
|
2018-05-09 13:53:02 +01:00
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2018-03-19 15:25:26 +00:00
|
|
|
|
):
|
|
|
|
|
|
mock_get_notifications(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
is_precompiled_letter=True,
|
|
|
|
|
|
noti_status='virus-scan-failed'
|
|
|
|
|
|
)
|
|
|
|
|
|
response = logged_in_client.get(url_for(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=service_one['id'],
|
|
|
|
|
|
message_type='letter',
|
|
|
|
|
|
status='',
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
|
|
|
|
error_description = page.find('div', attrs={'class': 'table-field-status-error'}).text.strip()
|
|
|
|
|
|
assert 'Virus detected\n' in error_description
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('letter_status', [
|
|
|
|
|
|
'pending-virus-check', 'virus-scan-failed'
|
|
|
|
|
|
])
|
|
|
|
|
|
def test_should_not_show_preview_link_for_precompiled_letters_in_virus_states(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
logged_in_client,
|
|
|
|
|
|
service_one,
|
2018-05-09 13:53:02 +01:00
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2018-03-19 15:25:26 +00:00
|
|
|
|
letter_status,
|
|
|
|
|
|
):
|
|
|
|
|
|
mock_get_notifications(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
is_precompiled_letter=True,
|
|
|
|
|
|
noti_status=letter_status
|
|
|
|
|
|
)
|
|
|
|
|
|
response = logged_in_client.get(url_for(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=service_one['id'],
|
|
|
|
|
|
message_type='letter',
|
|
|
|
|
|
status='',
|
|
|
|
|
|
))
|
|
|
|
|
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
|
|
|
|
|
|
|
|
|
|
assert not page.find('a', attrs={'class': 'file-list-filename'})
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-06-24 17:12:45 +01:00
|
|
|
|
def test_shows_message_when_no_notifications(
|
|
|
|
|
|
client_request,
|
2018-05-09 13:53:02 +01:00
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2017-06-24 17:12:45 +01:00
|
|
|
|
mock_get_notifications_with_no_notifications,
|
|
|
|
|
|
):
|
|
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
message_type='sms',
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert normalize_spaces(page.select('tbody tr')[0].text) == (
|
2018-07-10 17:06:06 +01:00
|
|
|
|
'No messages found (messages are kept for 7 days)'
|
2017-06-24 17:12:45 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-06-13 11:05:57 +01:00
|
|
|
|
@pytest.mark.parametrize((
|
|
|
|
|
|
'initial_query_arguments,'
|
|
|
|
|
|
'form_post_data,'
|
2018-08-07 14:44:09 +01:00
|
|
|
|
'expected_search_box_label,'
|
2017-06-13 11:05:57 +01:00
|
|
|
|
'expected_search_box_contents'
|
|
|
|
|
|
), [
|
2018-08-07 14:44:09 +01:00
|
|
|
|
(
|
|
|
|
|
|
{},
|
|
|
|
|
|
{},
|
|
|
|
|
|
'Search by phone number or email address',
|
|
|
|
|
|
'',
|
|
|
|
|
|
),
|
2017-06-13 10:32:36 +01:00
|
|
|
|
(
|
|
|
|
|
|
{
|
|
|
|
|
|
'message_type': 'sms',
|
|
|
|
|
|
},
|
2017-06-13 11:05:57 +01:00
|
|
|
|
{},
|
2018-08-07 14:44:09 +01:00
|
|
|
|
'Search by phone number',
|
2017-06-13 10:32:36 +01:00
|
|
|
|
'',
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
{
|
|
|
|
|
|
'message_type': 'sms',
|
2017-06-13 11:05:57 +01:00
|
|
|
|
},
|
|
|
|
|
|
{
|
2017-06-13 10:32:36 +01:00
|
|
|
|
'to': '+33(0)5-12-34-56-78',
|
|
|
|
|
|
},
|
2018-08-07 14:44:09 +01:00
|
|
|
|
'Search by phone number',
|
2017-06-13 10:32:36 +01:00
|
|
|
|
'+33(0)5-12-34-56-78',
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
{
|
|
|
|
|
|
'status': 'failed',
|
|
|
|
|
|
'message_type': 'email',
|
|
|
|
|
|
'page': '99',
|
2017-06-13 11:05:57 +01:00
|
|
|
|
},
|
|
|
|
|
|
{
|
2017-06-13 10:32:36 +01:00
|
|
|
|
'to': 'test@example.com',
|
|
|
|
|
|
},
|
2018-08-07 14:44:09 +01:00
|
|
|
|
'Search by email address',
|
2017-06-13 10:32:36 +01:00
|
|
|
|
'test@example.com',
|
|
|
|
|
|
),
|
|
|
|
|
|
])
|
|
|
|
|
|
def test_search_recipient_form(
|
|
|
|
|
|
logged_in_client,
|
|
|
|
|
|
mock_get_notifications,
|
2018-05-09 13:53:02 +01:00
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2017-06-13 10:32:36 +01:00
|
|
|
|
initial_query_arguments,
|
2017-06-13 11:05:57 +01:00
|
|
|
|
form_post_data,
|
2018-08-07 14:44:09 +01:00
|
|
|
|
expected_search_box_label,
|
2017-06-13 10:32:36 +01:00
|
|
|
|
expected_search_box_contents,
|
|
|
|
|
|
):
|
2017-06-13 11:05:57 +01:00
|
|
|
|
response = logged_in_client.post(
|
|
|
|
|
|
url_for(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
**initial_query_arguments
|
|
|
|
|
|
),
|
|
|
|
|
|
data=form_post_data
|
|
|
|
|
|
)
|
2017-06-13 10:32:36 +01:00
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
|
|
|
|
|
2017-06-13 11:05:57 +01:00
|
|
|
|
assert page.find("form")['method'] == 'post'
|
2017-06-13 10:32:36 +01:00
|
|
|
|
action_url = page.find("form")['action']
|
|
|
|
|
|
url = urlparse(action_url)
|
|
|
|
|
|
assert url.path == '/services/{}/notifications/{}'.format(
|
|
|
|
|
|
SERVICE_ONE_ID,
|
2018-08-07 14:44:09 +01:00
|
|
|
|
initial_query_arguments.get('message_type', '')
|
|
|
|
|
|
).rstrip('/')
|
2017-06-13 10:32:36 +01:00
|
|
|
|
query_dict = parse_qs(url.query)
|
|
|
|
|
|
assert query_dict == {}
|
|
|
|
|
|
|
2018-08-07 14:44:09 +01:00
|
|
|
|
assert page.select_one('label[for=to]').text.strip() == expected_search_box_label
|
|
|
|
|
|
|
2017-06-14 16:25:20 +01:00
|
|
|
|
recipient_inputs = page.select("input[name=to]")
|
|
|
|
|
|
assert(len(recipient_inputs) == 2)
|
|
|
|
|
|
|
|
|
|
|
|
for field in recipient_inputs:
|
|
|
|
|
|
assert field['value'] == expected_search_box_contents
|
2017-06-13 10:32:36 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_should_show_notifications_for_a_service_with_next_previous(
|
|
|
|
|
|
logged_in_client,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
mock_get_notifications_with_previous_next,
|
2018-05-09 13:53:02 +01:00
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2017-06-13 10:32:36 +01:00
|
|
|
|
mocker,
|
|
|
|
|
|
):
|
|
|
|
|
|
response = logged_in_client.get(url_for(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=service_one['id'],
|
|
|
|
|
|
message_type='sms',
|
|
|
|
|
|
page=2
|
|
|
|
|
|
))
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
|
|
|
|
next_page_link = page.find('a', {'rel': 'next'})
|
|
|
|
|
|
prev_page_link = page.find('a', {'rel': 'previous'})
|
|
|
|
|
|
assert (
|
|
|
|
|
|
url_for('main.view_notifications', service_id=service_one['id'], message_type='sms', page=3) in
|
|
|
|
|
|
next_page_link['href']
|
|
|
|
|
|
)
|
|
|
|
|
|
assert 'Next page' in next_page_link.text.strip()
|
|
|
|
|
|
assert 'page 3' in next_page_link.text.strip()
|
|
|
|
|
|
assert (
|
|
|
|
|
|
url_for('main.view_notifications', service_id=service_one['id'], message_type='sms', page=1) in
|
|
|
|
|
|
prev_page_link['href']
|
|
|
|
|
|
)
|
|
|
|
|
|
assert 'Previous page' in prev_page_link.text.strip()
|
|
|
|
|
|
assert 'page 1' in prev_page_link.text.strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
|
"job_created_at, expected_message", [
|
|
|
|
|
|
("2016-01-10 11:09:00.000000+00:00", "Data available for 7 days"),
|
|
|
|
|
|
("2016-01-04 11:09:00.000000+00:00", "Data available for 1 day"),
|
2018-11-26 15:15:06 +00:00
|
|
|
|
("2016-01-03 11:09:00.000000+00:00", "Data available for 12 hours"),
|
2017-06-13 10:32:36 +01:00
|
|
|
|
("2016-01-02 23:59:59.000000+00:00", "Data no longer available")
|
|
|
|
|
|
]
|
|
|
|
|
|
)
|
|
|
|
|
|
@freeze_time("2016-01-10 12:00:00.000000")
|
|
|
|
|
|
def test_time_left(job_created_at, expected_message):
|
|
|
|
|
|
assert get_time_left(job_created_at) == expected_message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
STATISTICS = {
|
|
|
|
|
|
'sms': {
|
|
|
|
|
|
'requested': 6,
|
|
|
|
|
|
'failed': 2,
|
|
|
|
|
|
'delivered': 1
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_status_filters_calculates_stats(client):
|
2018-10-26 12:13:04 +01:00
|
|
|
|
ret = get_status_filters(Service({'id': 'foo'}), 'sms', STATISTICS)
|
2017-06-13 10:32:36 +01:00
|
|
|
|
|
|
|
|
|
|
assert {label: count for label, _option, _link, count in ret} == {
|
|
|
|
|
|
'total': 6,
|
|
|
|
|
|
'sending': 3,
|
|
|
|
|
|
'failed': 2,
|
|
|
|
|
|
'delivered': 1
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_status_filters_in_right_order(client):
|
2018-10-26 12:13:04 +01:00
|
|
|
|
ret = get_status_filters(Service({'id': 'foo'}), 'sms', STATISTICS)
|
2017-06-13 10:32:36 +01:00
|
|
|
|
|
|
|
|
|
|
assert [label for label, _option, _link, _count in ret] == [
|
|
|
|
|
|
'total', 'sending', 'delivered', 'failed'
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_status_filters_constructs_links(client):
|
2018-10-26 12:13:04 +01:00
|
|
|
|
ret = get_status_filters(Service({'id': 'foo'}), 'sms', STATISTICS)
|
2017-06-13 10:32:36 +01:00
|
|
|
|
|
|
|
|
|
|
link = ret[0][2]
|
|
|
|
|
|
assert link == '/services/foo/notifications/sms?status={}'.format(quote('sending,delivered,failed'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_html_contains_notification_id(
|
|
|
|
|
|
logged_in_client,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
mock_get_notifications,
|
2018-05-09 13:53:02 +01:00
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2017-06-13 10:32:36 +01:00
|
|
|
|
mocker,
|
|
|
|
|
|
):
|
|
|
|
|
|
response = logged_in_client.get(url_for(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=service_one['id'],
|
|
|
|
|
|
message_type='sms',
|
|
|
|
|
|
status='')
|
|
|
|
|
|
)
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
|
|
|
|
notifications = page.tbody.find_all('tr')
|
|
|
|
|
|
for tr in notifications:
|
|
|
|
|
|
assert uuid.UUID(tr.attrs['id'])
|
2017-06-24 17:29:28 +01:00
|
|
|
|
|
|
|
|
|
|
|
2018-10-30 11:36:42 +00:00
|
|
|
|
def test_html_contains_links_for_failed_notifications(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2018-10-30 11:36:42 +00:00
|
|
|
|
mocker,
|
|
|
|
|
|
):
|
|
|
|
|
|
mock_get_notifications(mocker, active_user_with_permissions, noti_status='technical-failure')
|
|
|
|
|
|
response = client_request.get(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
message_type='sms',
|
|
|
|
|
|
status='sending%2Cdelivered%2Cfailed'
|
|
|
|
|
|
)
|
|
|
|
|
|
notifications = response.tbody.find_all('tr')
|
|
|
|
|
|
for tr in notifications:
|
|
|
|
|
|
link_text = tr.find('div', class_='table-field-status-error').find('a').text
|
|
|
|
|
|
assert normalize_spaces(link_text) == 'Technical failure'
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-06-24 17:29:28 +01:00
|
|
|
|
def test_redacts_templates_that_should_be_redacted(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
active_user_with_permissions,
|
2018-05-09 13:53:02 +01:00
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2017-06-24 17:29:28 +01:00
|
|
|
|
):
|
2017-10-18 14:51:26 +01:00
|
|
|
|
mock_get_notifications(
|
2017-06-24 17:29:28 +01:00
|
|
|
|
mocker,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
template_content="hello ((name))",
|
|
|
|
|
|
personalisation={'name': 'Jo'},
|
|
|
|
|
|
redact_personalisation=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
message_type='sms',
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert normalize_spaces(page.select('tbody tr th')[0].text) == (
|
|
|
|
|
|
'07123456789 hello hidden'
|
|
|
|
|
|
)
|
2017-10-02 12:34:10 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
|
"message_type, tablist_visible, search_bar_visible", [
|
|
|
|
|
|
('email', True, True),
|
|
|
|
|
|
('sms', True, True),
|
|
|
|
|
|
('letter', False, False)
|
|
|
|
|
|
]
|
|
|
|
|
|
)
|
|
|
|
|
|
def test_big_numbers_and_search_dont_show_for_letters(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_notifications,
|
|
|
|
|
|
active_user_with_permissions,
|
2018-05-09 13:53:02 +01:00
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2017-10-02 12:34:10 +01:00
|
|
|
|
message_type,
|
|
|
|
|
|
tablist_visible,
|
|
|
|
|
|
search_bar_visible
|
|
|
|
|
|
):
|
|
|
|
|
|
page = client_request.get(
|
2017-10-18 14:51:26 +01:00
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=service_one['id'],
|
|
|
|
|
|
message_type=message_type,
|
|
|
|
|
|
status='',
|
|
|
|
|
|
page=1,
|
|
|
|
|
|
)
|
2017-10-02 12:34:10 +01:00
|
|
|
|
|
|
|
|
|
|
assert (len(page.select("[role=tablist]")) > 0) == tablist_visible
|
|
|
|
|
|
assert (len(page.select("[type=search]")) > 0) == search_bar_visible
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@freeze_time("2017-09-27 16:30:00.000000")
|
|
|
|
|
|
@pytest.mark.parametrize(
|
2018-10-11 10:54:39 +01:00
|
|
|
|
"message_type, status, expected_hint_status, single_line", [
|
2019-01-15 13:46:57 +00:00
|
|
|
|
('email', 'created', 'Sending since 27 September at 5:30pm', True),
|
|
|
|
|
|
('email', 'sending', 'Sending since 27 September at 5:30pm', True),
|
|
|
|
|
|
('email', 'temporary-failure', 'Inbox not accepting messages right now 27 September at 5:31pm', False),
|
|
|
|
|
|
('email', 'permanent-failure', 'Email address doesn’t exist 27 September at 5:31pm', False),
|
2018-10-11 10:54:39 +01:00
|
|
|
|
('email', 'delivered', 'Delivered 27 September at 5:31pm', True),
|
2019-01-15 13:46:57 +00:00
|
|
|
|
('sms', 'created', 'Sending since 27 September at 5:30pm', True),
|
|
|
|
|
|
('sms', 'sending', 'Sending since 27 September at 5:30pm', True),
|
|
|
|
|
|
('sms', 'temporary-failure', 'Phone not accepting messages right now 27 September at 5:31pm', False),
|
|
|
|
|
|
('sms', 'permanent-failure', 'Phone number doesn’t exist 27 September at 5:31pm', False),
|
2018-10-11 10:54:39 +01:00
|
|
|
|
('sms', 'delivered', 'Delivered 27 September at 5:31pm', True),
|
2019-01-10 17:23:03 +00:00
|
|
|
|
('letter', 'created', '27 September at 5:30pm', True),
|
2019-01-15 13:46:57 +00:00
|
|
|
|
('letter', 'pending-virus-check', '27 September at 5:30pm', True),
|
2019-01-10 17:23:03 +00:00
|
|
|
|
('letter', 'sending', '27 September at 5:30pm', True),
|
2018-10-11 10:54:39 +01:00
|
|
|
|
('letter', 'delivered', '27 September at 5:30pm', True),
|
2019-01-10 17:23:03 +00:00
|
|
|
|
('letter', 'received', '27 September at 5:30pm', True),
|
|
|
|
|
|
('letter', 'accepted', '27 September at 5:30pm', True),
|
2019-01-15 13:46:57 +00:00
|
|
|
|
('letter', 'cancelled', '27 September at 5:30pm', False), # The API won’t return cancelled letters
|
|
|
|
|
|
('letter', 'permanent-failure', '27 September at 5:31pm', False), # Deprecated for ‘cancelled’
|
|
|
|
|
|
('letter', 'temporary-failure', '27 September at 5:30pm', False), # Not currently a real letter status
|
2019-01-10 17:23:03 +00:00
|
|
|
|
('letter', 'virus-scan-failed', 'Virus detected 27 September at 5:30pm', False),
|
2019-01-07 12:02:24 +00:00
|
|
|
|
('letter', 'validation-failed', 'Validation failed 27 September at 5:30pm', False),
|
2019-01-10 17:23:03 +00:00
|
|
|
|
('letter', 'technical-failure', 'Technical failure 27 September at 5:30pm', False),
|
2017-10-02 12:34:10 +01:00
|
|
|
|
]
|
|
|
|
|
|
)
|
2019-01-07 12:02:24 +00:00
|
|
|
|
def test_sending_status_hint_displays_correctly_on_notifications_page(
|
2017-10-02 12:34:10 +01:00
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
2018-05-09 13:53:02 +01:00
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2017-10-02 12:34:10 +01:00
|
|
|
|
message_type,
|
2018-10-11 10:54:39 +01:00
|
|
|
|
status,
|
|
|
|
|
|
expected_hint_status,
|
|
|
|
|
|
single_line,
|
2017-10-02 12:34:10 +01:00
|
|
|
|
mocker
|
|
|
|
|
|
):
|
2018-10-11 10:54:39 +01:00
|
|
|
|
mock_get_notifications(mocker, True, diff_template_type=message_type, noti_status=status)
|
2017-10-02 12:34:10 +01:00
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2017-10-18 14:51:26 +01:00
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=service_one['id'],
|
|
|
|
|
|
message_type=message_type
|
|
|
|
|
|
)
|
2017-10-02 12:34:10 +01:00
|
|
|
|
|
2018-10-11 10:54:39 +01:00
|
|
|
|
assert normalize_spaces(page.select(".table-field-right-aligned")[0].text) == expected_hint_status
|
|
|
|
|
|
assert bool(page.select('.align-with-message-body')) is single_line
|
2018-03-09 12:32:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("is_precompiled_letter,expected_hint", [
|
|
|
|
|
|
(True, "Provided as PDF"),
|
|
|
|
|
|
(False, "template subject")
|
|
|
|
|
|
])
|
|
|
|
|
|
def test_should_expected_hint_for_letters(
|
|
|
|
|
|
logged_in_client,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
2018-05-09 13:53:02 +01:00
|
|
|
|
mock_get_service_statistics,
|
2018-12-03 17:19:38 +00:00
|
|
|
|
mock_get_service_data_retention,
|
2018-03-09 12:32:36 +00:00
|
|
|
|
mocker,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
is_precompiled_letter,
|
|
|
|
|
|
expected_hint
|
|
|
|
|
|
):
|
|
|
|
|
|
mock_get_notifications(
|
|
|
|
|
|
mocker, active_user_with_permissions, is_precompiled_letter=is_precompiled_letter)
|
|
|
|
|
|
|
|
|
|
|
|
response = logged_in_client.get(url_for(
|
|
|
|
|
|
'main.view_notifications',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
message_type='letter'
|
|
|
|
|
|
))
|
|
|
|
|
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
|
|
|
|
assert page.find('p', {'class': 'file-list-hint'}).text.strip() == expected_hint
|