mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-10 18:22:37 -04:00
Merge branch 'master' into flask-login-again
This commit is contained in:
@@ -44,6 +44,16 @@ MockRecipients = namedtuple(
|
||||
'email',
|
||||
['fix 3 email addresses']
|
||||
),
|
||||
(
|
||||
{2}, [], [], [],
|
||||
'letter',
|
||||
['fix 1 address']
|
||||
),
|
||||
(
|
||||
{2, 4}, [], [], [],
|
||||
'letter',
|
||||
['fix 2 addresses']
|
||||
),
|
||||
(
|
||||
{2}, {3}, [], [],
|
||||
'sms',
|
||||
|
||||
@@ -384,6 +384,7 @@ def test_service_navigation_for_org_user(
|
||||
(
|
||||
'Templates',
|
||||
'Sent messages',
|
||||
'Uploads',
|
||||
'Team members',
|
||||
),
|
||||
403,
|
||||
@@ -393,6 +394,7 @@ def test_service_navigation_for_org_user(
|
||||
(
|
||||
'Templates',
|
||||
'Sent messages',
|
||||
'Uploads',
|
||||
'Team members',
|
||||
'Usage',
|
||||
),
|
||||
|
||||
@@ -36,7 +36,7 @@ def test_valid_email_not_in_valid_domains(
|
||||
):
|
||||
form = RegisterUserForm(email_address="test@test.com", mobile_number='441231231231')
|
||||
assert not form.validate()
|
||||
assert "Enter a government email address" in form.errors['email_address'][0]
|
||||
assert "Enter a public sector email address" in form.errors['email_address'][0]
|
||||
|
||||
|
||||
def test_valid_email_in_valid_domains(
|
||||
|
||||
@@ -149,7 +149,7 @@ def test_accepting_invite_removes_invite_from_session(
|
||||
mock_get_billable_units,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
fake_uuid,
|
||||
user,
|
||||
landing_page_title,
|
||||
@@ -477,7 +477,7 @@ def test_new_invited_user_verifies_and_added_to_service(
|
||||
mock_get_service_statistics,
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
mock_create_event,
|
||||
mocker,
|
||||
):
|
||||
|
||||
@@ -272,12 +272,11 @@ def test_accept_agreement_page_populates(
|
||||
(
|
||||
{
|
||||
'version': '',
|
||||
'who': '',
|
||||
'on_behalf_of_name': '',
|
||||
'on_behalf_of_email': '',
|
||||
},
|
||||
[
|
||||
'This field is required.',
|
||||
'Not a valid choice',
|
||||
'Must be a number',
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import copy
|
||||
import json
|
||||
from datetime import datetime
|
||||
from unittest.mock import call
|
||||
|
||||
import pytest
|
||||
from bs4 import BeautifulSoup
|
||||
@@ -144,7 +143,7 @@ def test_get_started(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.template_statistics_client.get_template_statistics_for_service',
|
||||
@@ -169,7 +168,7 @@ def test_get_started_is_hidden_once_templates_exist(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.template_statistics_client.get_template_statistics_for_service',
|
||||
@@ -195,7 +194,7 @@ def test_inbound_messages_not_visible_to_service_without_permissions(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
|
||||
service_one['permissions'] = []
|
||||
@@ -220,7 +219,7 @@ def test_inbound_messages_shows_count_of_messages_when_there_are_messages(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
service_one['permissions'] = ['inbound_sms']
|
||||
page = client_request.get(
|
||||
@@ -247,7 +246,7 @@ def test_inbound_messages_shows_count_of_messages_when_there_are_no_messages(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary_with_no_messages,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
service_one['permissions'] = ['inbound_sms']
|
||||
page = client_request.get(
|
||||
@@ -489,7 +488,7 @@ def test_returned_letters_not_visible_if_service_has_no_returned_letters(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
page = client_request.get(
|
||||
'main.service_dashboard',
|
||||
@@ -512,21 +511,11 @@ def test_returned_letters_shows_count_of_recently_returned_letters(
|
||||
mock_get_inbound_sms_summary,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.service_api_client.get_returned_letter_summary',
|
||||
return_value=[
|
||||
# Today (should be counted)
|
||||
{
|
||||
'returned_letter_count': 1000, 'reported_at': '2020-01-10'
|
||||
},
|
||||
# Just within the last 7 days (should be counted)
|
||||
{
|
||||
'returned_letter_count': 3000, 'reported_at': '2020-01-3'
|
||||
},
|
||||
# Just after the last 7 days (should not be counted)
|
||||
{
|
||||
'returned_letter_count': 2000, 'reported_at': '2020-01-2'
|
||||
},
|
||||
],
|
||||
'app.service_api_client.get_returned_letter_statistics',
|
||||
return_value={
|
||||
'returned_letter_count': 4000,
|
||||
'most_recent_report': '2020-01-10',
|
||||
},
|
||||
)
|
||||
page = client_request.get(
|
||||
'main.service_dashboard',
|
||||
@@ -541,29 +530,29 @@ def test_returned_letters_shows_count_of_recently_returned_letters(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('reporting_date, expected_message', (
|
||||
('2020-02-02', (
|
||||
@pytest.mark.parametrize('reporting_date, count, expected_message', (
|
||||
('2020-02-02', 1, (
|
||||
'1 returned letter latest report today'
|
||||
)),
|
||||
('2020-02-01', (
|
||||
('2020-02-01', 1, (
|
||||
'1 returned letter latest report yesterday'
|
||||
)),
|
||||
('2020-01-31', (
|
||||
('2020-01-31', 1, (
|
||||
'1 returned letter latest report 2 days ago'
|
||||
)),
|
||||
('2020-01-26', (
|
||||
('2020-01-26', 1, (
|
||||
'1 returned letter latest report 7 days ago'
|
||||
)),
|
||||
('2020-01-25', (
|
||||
('2020-01-25', 0, (
|
||||
'0 returned letters latest report 8 days ago'
|
||||
)),
|
||||
('2020-01-01', (
|
||||
('2020-01-01', 0, (
|
||||
'0 returned letters latest report 1 month ago'
|
||||
)),
|
||||
('2019-09-09', (
|
||||
('2019-09-09', 0, (
|
||||
'0 returned letters latest report 4 months ago'
|
||||
)),
|
||||
('2010-10-10', (
|
||||
('2010-10-10', 0, (
|
||||
'0 returned letters latest report 9 years ago'
|
||||
)),
|
||||
))
|
||||
@@ -580,15 +569,15 @@ def test_returned_letters_only_counts_recently_returned_letters(
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary_with_no_messages,
|
||||
reporting_date,
|
||||
count,
|
||||
expected_message,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.service_api_client.get_returned_letter_summary',
|
||||
return_value=[
|
||||
{
|
||||
'returned_letter_count': 1, 'reported_at': reporting_date
|
||||
},
|
||||
],
|
||||
'app.service_api_client.get_returned_letter_statistics',
|
||||
return_value={
|
||||
'returned_letter_count': count,
|
||||
'most_recent_report': reporting_date,
|
||||
},
|
||||
)
|
||||
page = client_request.get(
|
||||
'main.service_dashboard',
|
||||
@@ -610,7 +599,7 @@ def test_should_show_recent_templates_on_dashboard(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
mock_template_stats = mocker.patch('app.template_statistics_client.get_template_statistics_for_service',
|
||||
return_value=copy.deepcopy(stub_template_stats))
|
||||
@@ -664,7 +653,7 @@ def test_should_not_show_recent_templates_on_dashboard_if_only_one_template_used
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
stats,
|
||||
):
|
||||
mock_template_stats = mocker.patch(
|
||||
@@ -819,7 +808,7 @@ def test_should_show_upcoming_jobs_on_dashboard(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
page = client_request.get(
|
||||
'main.service_dashboard',
|
||||
@@ -876,7 +865,7 @@ def test_correct_font_size_for_big_numbers(
|
||||
mock_get_jobs,
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
service_one,
|
||||
permissions,
|
||||
totals,
|
||||
@@ -903,56 +892,6 @@ def test_correct_font_size_for_big_numbers(
|
||||
) == 3
|
||||
|
||||
|
||||
@freeze_time("2016-01-01 11:09:00.061258")
|
||||
def test_should_show_recent_jobs_on_dashboard(
|
||||
client_request,
|
||||
mock_get_service_templates,
|
||||
mock_get_template_statistics,
|
||||
mock_get_service_statistics,
|
||||
mock_get_jobs,
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
):
|
||||
page = client_request.get(
|
||||
'main.service_dashboard',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
)
|
||||
|
||||
third_call = mock_get_jobs.call_args_list[2]
|
||||
assert third_call[0] == (SERVICE_ONE_ID,)
|
||||
assert third_call[1]['limit_days'] == 7
|
||||
assert 'scheduled' not in third_call[1]['statuses']
|
||||
|
||||
table_rows = page.select_one('tbody').select('tr')
|
||||
|
||||
assert len(table_rows) == 4
|
||||
|
||||
for index, filename in enumerate((
|
||||
"export 1/1/2016.xls",
|
||||
"all email addresses.xlsx",
|
||||
"applicants.ods",
|
||||
"thisisatest.csv",
|
||||
)):
|
||||
assert filename in table_rows[index].find_all('th')[0].text
|
||||
assert 'Sent today at 11:09' in table_rows[index].find_all('th')[0].text
|
||||
assert normalize_spaces(
|
||||
table_rows[index].select_one('td').text
|
||||
) == (
|
||||
'1 sending 0 delivered 0 failed'
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('extra_permissions', (
|
||||
pytest.param(
|
||||
[],
|
||||
marks=pytest.mark.xfail(raises=AssertionError),
|
||||
),
|
||||
pytest.param(
|
||||
['upload_letters']
|
||||
),
|
||||
))
|
||||
def test_should_not_show_jobs_on_dashboard_for_users_with_uploads_page(
|
||||
client_request,
|
||||
service_one,
|
||||
@@ -963,10 +902,8 @@ def test_should_not_show_jobs_on_dashboard_for_users_with_uploads_page(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
extra_permissions,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
service_one['permissions'] += extra_permissions
|
||||
page = client_request.get(
|
||||
'main.service_dashboard',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
@@ -1160,7 +1097,7 @@ def test_menu_send_messages(
|
||||
mock_get_usage,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
service_one['permissions'] = ['email', 'sms', 'letter', 'upload_letters']
|
||||
|
||||
@@ -1196,7 +1133,7 @@ def test_menu_send_messages_when_service_does_not_have_upload_letters_permission
|
||||
mock_get_usage,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
with app_.test_request_context():
|
||||
resp = _test_dashboard_menu(
|
||||
@@ -1221,7 +1158,7 @@ def test_menu_manage_service(
|
||||
mock_get_service_statistics,
|
||||
mock_get_usage,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
):
|
||||
with app_.test_request_context():
|
||||
@@ -1253,7 +1190,7 @@ def test_menu_manage_api_keys(
|
||||
mock_get_service_statistics,
|
||||
mock_get_usage,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
):
|
||||
with app_.test_request_context():
|
||||
@@ -1283,7 +1220,7 @@ def test_menu_all_services_for_platform_admin_user(
|
||||
mock_get_service_statistics,
|
||||
mock_get_usage,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
):
|
||||
with app_.test_request_context():
|
||||
@@ -1316,7 +1253,7 @@ def test_route_for_service_permissions(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
with app_.test_request_context():
|
||||
validate_route_permission(
|
||||
@@ -1370,7 +1307,7 @@ def test_service_dashboard_updates_gets_dashboard_totals(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
mocker.patch('app.main.views.dashboard.get_dashboard_totals', return_value={
|
||||
'email': {'requested': 123, 'delivered': 0, 'failed': 0},
|
||||
@@ -1546,38 +1483,6 @@ def test_get_tuples_of_financial_years_defaults_to_2015():
|
||||
))[0]
|
||||
|
||||
|
||||
@freeze_time("2016-01-01 11:09:00.061258")
|
||||
def test_should_show_all_jobs_with_valid_statuses(
|
||||
logged_in_client,
|
||||
mock_get_template_statistics,
|
||||
mock_get_service_statistics,
|
||||
mock_get_service_templates_when_no_templates_exist,
|
||||
mock_get_jobs,
|
||||
mock_get_usage,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
):
|
||||
logged_in_client.get(url_for('main.service_dashboard', service_id=SERVICE_ONE_ID))
|
||||
|
||||
first_call = mock_get_jobs.call_args_list[0]
|
||||
# first call - checking for any jobs
|
||||
assert first_call == call(SERVICE_ONE_ID)
|
||||
second_call = mock_get_jobs.call_args_list[1]
|
||||
# second call - scheduled jobs only
|
||||
assert second_call == call(SERVICE_ONE_ID, statuses=['scheduled'])
|
||||
# third call - everything but scheduled and cancelled
|
||||
third_call = mock_get_jobs.call_args_list[2]
|
||||
assert third_call == call(SERVICE_ONE_ID, limit_days=7, statuses={
|
||||
'pending',
|
||||
'in progress',
|
||||
'finished',
|
||||
'sending limits exceeded',
|
||||
'ready to send',
|
||||
'sent to dvla'
|
||||
})
|
||||
|
||||
|
||||
def test_org_breadcrumbs_do_not_show_if_service_has_no_org(
|
||||
client_request,
|
||||
mock_get_template_statistics,
|
||||
@@ -1585,7 +1490,7 @@ def test_org_breadcrumbs_do_not_show_if_service_has_no_org(
|
||||
mock_get_jobs,
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
page = client_request.get('main.service_dashboard', service_id=SERVICE_ONE_ID)
|
||||
|
||||
@@ -1600,7 +1505,7 @@ def test_org_breadcrumbs_do_not_show_if_user_is_not_an_org_member(
|
||||
active_caseworking_user,
|
||||
client_request,
|
||||
mock_get_template_folders,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
):
|
||||
# active_caseworking_user is not an org member
|
||||
|
||||
@@ -1623,7 +1528,7 @@ def test_org_breadcrumbs_show_if_user_is_a_member_of_the_services_org(
|
||||
mock_get_jobs,
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
active_user_with_permissions,
|
||||
client_request,
|
||||
):
|
||||
@@ -1651,7 +1556,7 @@ def test_org_breadcrumbs_do_not_show_if_user_is_a_member_of_the_services_org_but
|
||||
mock_get_jobs,
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
active_user_with_permissions,
|
||||
client_request,
|
||||
):
|
||||
@@ -1676,7 +1581,7 @@ def test_org_breadcrumbs_show_if_user_is_platform_admin(
|
||||
mock_get_jobs,
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
platform_admin_user,
|
||||
platform_admin_client,
|
||||
):
|
||||
@@ -1708,7 +1613,7 @@ def test_should_show_usage_on_dashboard(
|
||||
mock_get_jobs,
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters,
|
||||
permissions,
|
||||
):
|
||||
service_one['permissions'] = permissions
|
||||
|
||||
@@ -6,11 +6,11 @@ from bs4 import BeautifulSoup, element
|
||||
from flask import url_for
|
||||
from freezegun import freeze_time
|
||||
|
||||
from app.main.views.feedback import (
|
||||
from app.main.views.feedback import has_live_services, in_business_hours
|
||||
from app.models.feedback import (
|
||||
GENERAL_TICKET_TYPE,
|
||||
PROBLEM_TICKET_TYPE,
|
||||
QUESTION_TICKET_TYPE,
|
||||
has_live_services,
|
||||
in_business_hours,
|
||||
)
|
||||
from tests.conftest import normalize_spaces
|
||||
|
||||
@@ -19,18 +19,48 @@ def no_redirect():
|
||||
return lambda _external=True: None
|
||||
|
||||
|
||||
@pytest.mark.parametrize('endpoint', [
|
||||
'main.old_feedback',
|
||||
'main.support',
|
||||
])
|
||||
def test_get_support_index_page(
|
||||
client,
|
||||
endpoint,
|
||||
client_request,
|
||||
):
|
||||
response = client.get(url_for('main.support'), follow_redirects=True)
|
||||
assert response.status_code == 200
|
||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||
assert page.h1.string.strip() == 'Support'
|
||||
page = client_request.get('.support')
|
||||
assert page.select_one('form')['method'] == 'post'
|
||||
assert 'action' not in page.select_one('form')
|
||||
assert normalize_spaces(page.select_one('h1').text) == 'Support'
|
||||
assert normalize_spaces(
|
||||
page.select_one('form label[for=support_type-0]').text
|
||||
) == 'Report a problem'
|
||||
assert page.select_one('form input#support_type-0')['value'] == 'report-problem'
|
||||
assert normalize_spaces(
|
||||
page.select_one('form label[for=support_type-1]').text
|
||||
) == 'Ask a question or give feedback'
|
||||
assert page.select_one('form input#support_type-1')['value'] == 'ask-question-give-feedback'
|
||||
assert normalize_spaces(
|
||||
page.select_one('form button[type=submit]').text
|
||||
) == 'Continue'
|
||||
|
||||
|
||||
def test_get_support_index_page_when_signed_out(
|
||||
client_request,
|
||||
):
|
||||
client_request.logout()
|
||||
page = client_request.get('.support')
|
||||
assert page.select_one('form')['method'] == 'post'
|
||||
assert 'action' not in page.select_one('form')
|
||||
assert normalize_spaces(
|
||||
page.select_one('form label[for=who-0]').text
|
||||
) == (
|
||||
'I work in the public sector and need to send emails, text messages or letters'
|
||||
)
|
||||
assert page.select_one('form input#who-0')['value'] == 'public-sector'
|
||||
assert normalize_spaces(
|
||||
page.select_one('form label[for=who-1]').text
|
||||
) == (
|
||||
'I’m a member of the public with a question for the government'
|
||||
)
|
||||
assert page.select_one('form input#who-1')['value'] == 'public'
|
||||
assert normalize_spaces(
|
||||
page.select_one('form button[type=submit]').text
|
||||
) == 'Continue'
|
||||
|
||||
|
||||
@freeze_time('2016-12-12 12:00:00.000000')
|
||||
@@ -38,34 +68,59 @@ def test_get_support_index_page(
|
||||
(PROBLEM_TICKET_TYPE, 'Report a problem'),
|
||||
(QUESTION_TICKET_TYPE, 'Ask a question or give feedback'),
|
||||
])
|
||||
@pytest.mark.parametrize('logged_in, expected_form_field, expected_contact_details', [
|
||||
(True, type(None), 'We’ll reply to test@user.gov.uk'),
|
||||
(False, element.Tag, None),
|
||||
])
|
||||
def test_choose_support_type(
|
||||
client,
|
||||
api_user_active,
|
||||
mock_get_user,
|
||||
mock_get_services,
|
||||
logged_in,
|
||||
expected_form_field,
|
||||
expected_contact_details,
|
||||
client_request,
|
||||
support_type,
|
||||
expected_h1
|
||||
):
|
||||
if logged_in:
|
||||
client.login(api_user_active)
|
||||
response = client.post(
|
||||
url_for('main.support'),
|
||||
data={'support_type': support_type}, follow_redirects=True
|
||||
page = client_request.post(
|
||||
'main.support',
|
||||
_data={'support_type': support_type},
|
||||
_follow_redirects=True,
|
||||
)
|
||||
assert response.status_code == 200
|
||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||
assert page.h1.string.strip() == expected_h1
|
||||
assert isinstance(page.find('input', {'name': 'name'}), expected_form_field)
|
||||
assert isinstance(page.find('input', {'name': 'email_address'}), expected_form_field)
|
||||
if expected_contact_details:
|
||||
assert page.find('form').find('p').text.strip() == expected_contact_details
|
||||
assert not page.select_one('input[name=name]')
|
||||
assert not page.select_one('input[name=email_address]')
|
||||
assert page.find('form').find('p').text.strip() == (
|
||||
'We’ll reply to test@user.gov.uk'
|
||||
)
|
||||
|
||||
|
||||
@freeze_time('2016-12-12 12:00:00.000000')
|
||||
def test_get_support_as_someone_in_the_public_sector(
|
||||
client_request,
|
||||
):
|
||||
client_request.logout()
|
||||
page = client_request.post(
|
||||
'main.support',
|
||||
_data={'who': 'public-sector'},
|
||||
_follow_redirects=True,
|
||||
)
|
||||
assert normalize_spaces(page.select('h1')) == (
|
||||
'Contact GOV.UK Notify support'
|
||||
)
|
||||
assert page.select_one('form textarea[name=feedback]')
|
||||
assert page.select_one('form input[name=name]')
|
||||
assert page.select_one('form input[name=email_address]')
|
||||
assert page.select_one('form button[type=submit]')
|
||||
|
||||
|
||||
def test_get_support_as_member_of_public(
|
||||
client_request,
|
||||
):
|
||||
client_request.logout()
|
||||
page = client_request.post(
|
||||
'main.support',
|
||||
_data={'who': 'public'},
|
||||
_follow_redirects=True,
|
||||
)
|
||||
assert normalize_spaces(page.select('h1')) == (
|
||||
'The GOV.UK Notify service is for people who work in the government'
|
||||
)
|
||||
assert len(page.select('h2 a')) == 3
|
||||
assert not page.select('form')
|
||||
assert not page.select('input')
|
||||
assert not page.select('form [type=submit]')
|
||||
|
||||
|
||||
@freeze_time('2016-12-12 12:00:00.000000')
|
||||
@@ -79,50 +134,6 @@ def test_get_feedback_page(client, ticket_type, expected_status_code):
|
||||
assert response.status_code == expected_status_code
|
||||
|
||||
|
||||
@pytest.mark.parametrize('prefilled_body, expected_textarea', [
|
||||
(
|
||||
'agreement',
|
||||
(
|
||||
'Please can you tell me if there’s an agreement in place '
|
||||
'between GOV.UK Notify and my organisation?'
|
||||
)
|
||||
),
|
||||
(
|
||||
'foo',
|
||||
''
|
||||
),
|
||||
])
|
||||
@freeze_time('2016-12-12 12:00:00.000000')
|
||||
def test_get_feedback_page_with_prefilled_body(
|
||||
client_request,
|
||||
mocker,
|
||||
fake_uuid,
|
||||
prefilled_body,
|
||||
expected_textarea,
|
||||
active_user_with_permissions,
|
||||
):
|
||||
active_user_with_permissions['email_address'] = 'test@marinemanagement.org.uk'
|
||||
mocker.patch('app.user_api_client.get_user', return_value=active_user_with_permissions)
|
||||
mock_post = mocker.patch('app.main.views.feedback.zendesk_client.create_ticket')
|
||||
page = client_request.get(
|
||||
'main.feedback',
|
||||
ticket_type=QUESTION_TICKET_TYPE,
|
||||
body=prefilled_body,
|
||||
)
|
||||
assert page.select_one('textarea').text == (
|
||||
expected_textarea
|
||||
)
|
||||
client_request.post(
|
||||
'main.feedback',
|
||||
ticket_type=QUESTION_TICKET_TYPE,
|
||||
body='agreement',
|
||||
_data={'feedback': 'blah', 'name': 'Example', 'email_address': 'test@example.com'}
|
||||
)
|
||||
message = mock_post.call_args[1]['message']
|
||||
assert message.startswith('blah')
|
||||
assert 'Please send' not in message
|
||||
|
||||
|
||||
@freeze_time('2016-12-12 12:00:00.000000')
|
||||
@pytest.mark.parametrize('ticket_type', [PROBLEM_TICKET_TYPE, QUESTION_TICKET_TYPE])
|
||||
def test_passed_non_logged_in_user_details_through_flow(client, mocker, ticket_type):
|
||||
@@ -204,34 +215,15 @@ def test_passes_user_details_through_flow(
|
||||
{'feedback': 'blah', 'name': 'Fred'},
|
||||
{'feedback': 'blah'},
|
||||
])
|
||||
@pytest.mark.parametrize('ticket_type, expected_response, expected_redirect, expected_error', [
|
||||
(
|
||||
PROBLEM_TICKET_TYPE,
|
||||
200,
|
||||
lambda: None,
|
||||
element.Tag,
|
||||
),
|
||||
(
|
||||
QUESTION_TICKET_TYPE,
|
||||
302,
|
||||
partial(
|
||||
url_for,
|
||||
'.thanks',
|
||||
email_address_provided=False,
|
||||
out_of_hours_emergency=False,
|
||||
_external=True,
|
||||
),
|
||||
type(None),
|
||||
),
|
||||
@pytest.mark.parametrize('ticket_type', [
|
||||
PROBLEM_TICKET_TYPE,
|
||||
QUESTION_TICKET_TYPE,
|
||||
])
|
||||
def test_email_address_required_for_problems(
|
||||
def test_email_address_required_for_problems_and_questions(
|
||||
client_request,
|
||||
mocker,
|
||||
data,
|
||||
ticket_type,
|
||||
expected_response,
|
||||
expected_redirect,
|
||||
expected_error
|
||||
):
|
||||
mocker.patch('app.main.views.feedback.zendesk_client')
|
||||
client_request.logout()
|
||||
@@ -239,10 +231,9 @@ def test_email_address_required_for_problems(
|
||||
'main.feedback',
|
||||
ticket_type=ticket_type,
|
||||
_data=data,
|
||||
_expected_status=expected_response,
|
||||
_expected_redirect=expected_redirect(),
|
||||
_expected_status=200
|
||||
)
|
||||
assert isinstance(page.find('span', {'class': 'error-message'}), expected_error)
|
||||
assert isinstance(page.find('span', {'class': 'error-message'}), element.Tag)
|
||||
|
||||
|
||||
@freeze_time('2016-12-12 12:00:00.000000')
|
||||
@@ -314,8 +305,8 @@ def test_urgency(
|
||||
|
||||
ids, params = zip(*[
|
||||
('non-logged in users always have to triage', (
|
||||
PROBLEM_TICKET_TYPE, False, False, True,
|
||||
302, partial(url_for, 'main.triage')
|
||||
GENERAL_TICKET_TYPE, False, False, True,
|
||||
302, partial(url_for, 'main.triage', ticket_type=GENERAL_TICKET_TYPE)
|
||||
)),
|
||||
('trial services are never high priority', (
|
||||
PROBLEM_TICKET_TYPE, False, True, False,
|
||||
@@ -331,7 +322,7 @@ ids, params = zip(*[
|
||||
)),
|
||||
('should triage out of hours', (
|
||||
PROBLEM_TICKET_TYPE, False, True, True,
|
||||
302, partial(url_for, 'main.triage')
|
||||
302, partial(url_for, 'main.triage', ticket_type=PROBLEM_TICKET_TYPE)
|
||||
))
|
||||
])
|
||||
|
||||
@@ -365,6 +356,21 @@ def test_redirects_to_triage(
|
||||
assert response.location == expected_redirect(_external=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('ticket_type, expected_h1', (
|
||||
(PROBLEM_TICKET_TYPE, 'Report a problem'),
|
||||
(GENERAL_TICKET_TYPE, 'Contact GOV.UK Notify support'),
|
||||
))
|
||||
def test_options_on_triage_page(
|
||||
client_request,
|
||||
ticket_type,
|
||||
expected_h1,
|
||||
):
|
||||
page = client_request.get('main.triage', ticket_type=ticket_type)
|
||||
assert normalize_spaces(page.select_one('h1').text) == expected_h1
|
||||
assert page.select('form input[type=radio]')[0]['value'] == 'yes'
|
||||
assert page.select('form input[type=radio]')[1]['value'] == 'no'
|
||||
|
||||
|
||||
def test_doesnt_lose_message_if_post_across_closing(
|
||||
client_request,
|
||||
mocker,
|
||||
@@ -378,7 +384,7 @@ def test_doesnt_lose_message_if_post_across_closing(
|
||||
ticket_type=PROBLEM_TICKET_TYPE,
|
||||
_data={'feedback': 'foo'},
|
||||
_expected_status=302,
|
||||
_expected_redirect=url_for('.triage', _external=True),
|
||||
_expected_redirect=url_for('.triage', ticket_type=PROBLEM_TICKET_TYPE, _external=True),
|
||||
)
|
||||
with client_request.session_transaction() as session:
|
||||
assert session['feedback_message'] == 'foo'
|
||||
@@ -428,19 +434,64 @@ def test_in_business_hours(when, is_in_business_hours):
|
||||
assert in_business_hours() == is_in_business_hours
|
||||
|
||||
|
||||
@pytest.mark.parametrize('ticket_type', (
|
||||
GENERAL_TICKET_TYPE,
|
||||
PROBLEM_TICKET_TYPE,
|
||||
))
|
||||
@pytest.mark.parametrize('choice, expected_redirect_param', [
|
||||
('yes', 'yes'),
|
||||
('no', 'no'),
|
||||
])
|
||||
def test_triage_redirects_to_correct_url(client, choice, expected_redirect_param):
|
||||
response = client.post(url_for('main.triage'), data={'severe': choice})
|
||||
assert response.status_code == 302
|
||||
assert response.location == url_for(
|
||||
def test_triage_redirects_to_correct_url(
|
||||
client_request,
|
||||
ticket_type,
|
||||
choice,
|
||||
expected_redirect_param,
|
||||
):
|
||||
client_request.post(
|
||||
'main.triage',
|
||||
ticket_type=ticket_type,
|
||||
_data={'severe': choice},
|
||||
_expected_status=302,
|
||||
_expected_redirect=url_for(
|
||||
'main.feedback',
|
||||
ticket_type=ticket_type,
|
||||
severe=expected_redirect_param,
|
||||
_external=True,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('extra_args, expected_back_link', [
|
||||
(
|
||||
{'severe': 'yes'},
|
||||
partial(url_for, 'main.triage', ticket_type=PROBLEM_TICKET_TYPE)
|
||||
),
|
||||
(
|
||||
{'severe': 'no'},
|
||||
partial(url_for, 'main.triage', ticket_type=PROBLEM_TICKET_TYPE)
|
||||
),
|
||||
(
|
||||
{'severe': 'foo'}, # hacking the URL
|
||||
partial(url_for, 'main.support')
|
||||
),
|
||||
(
|
||||
{},
|
||||
partial(url_for, 'main.support')
|
||||
),
|
||||
])
|
||||
def test_back_link_from_form(
|
||||
client_request,
|
||||
extra_args,
|
||||
expected_back_link,
|
||||
):
|
||||
page = client_request.get(
|
||||
'main.feedback',
|
||||
ticket_type=PROBLEM_TICKET_TYPE,
|
||||
severe=expected_redirect_param,
|
||||
_external=True,
|
||||
**extra_args
|
||||
)
|
||||
assert page.select_one('.govuk-back-link')['href'] == expected_back_link()
|
||||
assert normalize_spaces(page.select_one('h1').text) == 'Report a problem'
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -469,15 +520,15 @@ def test_triage_redirects_to_correct_url(client, choice, expected_redirect_param
|
||||
# Treat empty query param as mangled URL – ask question again
|
||||
(
|
||||
False, '',
|
||||
302, partial(url_for, 'main.triage'),
|
||||
302, partial(url_for, 'main.triage'),
|
||||
302, partial(url_for, 'main.triage', ticket_type=PROBLEM_TICKET_TYPE),
|
||||
302, partial(url_for, 'main.triage', ticket_type=PROBLEM_TICKET_TYPE),
|
||||
),
|
||||
|
||||
# User hasn’t answered the triage question
|
||||
(
|
||||
False, None,
|
||||
302, partial(url_for, 'main.triage'),
|
||||
302, partial(url_for, 'main.triage'),
|
||||
302, partial(url_for, 'main.triage', ticket_type=PROBLEM_TICKET_TYPE),
|
||||
302, partial(url_for, 'main.triage', ticket_type=PROBLEM_TICKET_TYPE),
|
||||
),
|
||||
|
||||
# Escalation is needed for non-logged-in users
|
||||
@@ -518,6 +569,57 @@ def test_should_be_shown_the_bat_email(
|
||||
assert logged_in_response.location == expected_redirect_when_logged_in(_external=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
(
|
||||
'severe,'
|
||||
'expected_status_code, expected_redirect,'
|
||||
'expected_status_code_when_logged_in, expected_redirect_when_logged_in'
|
||||
),
|
||||
[
|
||||
# User hasn’t answered the triage question
|
||||
(
|
||||
None,
|
||||
302, partial(url_for, 'main.triage', ticket_type=GENERAL_TICKET_TYPE),
|
||||
302, partial(url_for, 'main.triage', ticket_type=GENERAL_TICKET_TYPE),
|
||||
),
|
||||
|
||||
# Escalation is needed for non-logged-in users
|
||||
(
|
||||
'yes',
|
||||
302, partial(url_for, 'main.bat_phone'),
|
||||
200, no_redirect(),
|
||||
),
|
||||
]
|
||||
)
|
||||
def test_should_be_shown_the_bat_email_for_general_questions(
|
||||
client,
|
||||
active_user_with_permissions,
|
||||
mocker,
|
||||
service_one,
|
||||
mock_get_services,
|
||||
severe,
|
||||
expected_status_code,
|
||||
expected_redirect,
|
||||
expected_status_code_when_logged_in,
|
||||
expected_redirect_when_logged_in,
|
||||
):
|
||||
|
||||
mocker.patch('app.main.views.feedback.in_business_hours', return_value=False)
|
||||
|
||||
feedback_page = url_for('main.feedback', ticket_type=GENERAL_TICKET_TYPE, severe=severe)
|
||||
|
||||
response = client.get(feedback_page)
|
||||
|
||||
assert response.status_code == expected_status_code
|
||||
assert response.location == expected_redirect(_external=True)
|
||||
|
||||
# logged in users should never be redirected to the bat email page
|
||||
client.login(active_user_with_permissions, mocker, service_one)
|
||||
logged_in_response = client.get(feedback_page)
|
||||
assert logged_in_response.status_code == expected_status_code_when_logged_in
|
||||
assert logged_in_response.location == expected_redirect_when_logged_in(_external=True)
|
||||
|
||||
|
||||
def test_bat_email_page(
|
||||
client,
|
||||
active_user_with_permissions,
|
||||
@@ -530,9 +632,11 @@ def test_bat_email_page(
|
||||
assert response.status_code == 200
|
||||
|
||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||
assert page.select('main a')[1].text == 'Fill in this form'
|
||||
assert page.select('main a')[1]['href'] == url_for('main.feedback', ticket_type=PROBLEM_TICKET_TYPE, severe='no')
|
||||
next_page_response = client.get(page.select('main a')[1]['href'])
|
||||
assert page.select('main a')[0].text == 'Back'
|
||||
assert page.select('main a')[0]['href'] == url_for('main.support')
|
||||
assert page.select('main a')[2].text == 'Fill in this form'
|
||||
assert page.select('main a')[2]['href'] == url_for('main.feedback', ticket_type=PROBLEM_TICKET_TYPE, severe='no')
|
||||
next_page_response = client.get(page.select('main a')[2]['href'])
|
||||
next_page = BeautifulSoup(next_page_response.data.decode('utf-8'), 'html.parser')
|
||||
assert next_page.h1.text.strip() == 'Report a problem'
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ def test_robots(client):
|
||||
'features_letters', 'how_to_pay', 'get_started',
|
||||
'guidance_index', 'branding_and_customisation',
|
||||
'create_and_send_messages', 'edit_and_format_messages',
|
||||
'send_files_by_email', 'upload_a_letter',
|
||||
'send_files_by_email', 'upload_a_letter', 'who_its_for',
|
||||
])
|
||||
def test_static_pages(
|
||||
client_request,
|
||||
|
||||
@@ -18,131 +18,19 @@ from tests.conftest import (
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('user, expected_rows', [
|
||||
(create_active_user_with_permissions(), (
|
||||
(
|
||||
'File Status'
|
||||
),
|
||||
(
|
||||
'export 1/1/2016.xls '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'all email addresses.xlsx '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'applicants.ods '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'thisisatest.csv '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
)),
|
||||
(create_active_caseworking_user(), (
|
||||
(
|
||||
'File Messages to be sent'
|
||||
),
|
||||
(
|
||||
'even_later.csv '
|
||||
'Sending 1 January 2016 at 11:09pm 1'
|
||||
),
|
||||
(
|
||||
'send_me_later.csv '
|
||||
'Sending 1 January 2016 at 11:09am 1'
|
||||
),
|
||||
(
|
||||
'File Status'
|
||||
),
|
||||
(
|
||||
'export 1/1/2016.xls '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'all email addresses.xlsx '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'applicants.ods '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'thisisatest.csv '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
)),
|
||||
])
|
||||
@freeze_time("2012-12-12 12:12")
|
||||
def test_jobs_page_shows_scheduled_jobs_if_user_doesnt_have_dashboard(
|
||||
def test_old_jobs_hub_redirects(
|
||||
client_request,
|
||||
service_one,
|
||||
active_user_with_permissions,
|
||||
mock_get_jobs,
|
||||
user,
|
||||
expected_rows,
|
||||
):
|
||||
client_request.login(user)
|
||||
page = client_request.get('main.view_jobs', service_id=service_one['id'])
|
||||
|
||||
for index, row in enumerate(expected_rows):
|
||||
assert normalize_spaces(page.select('tr')[index].text) == row
|
||||
|
||||
|
||||
@pytest.mark.parametrize('user', [
|
||||
create_active_user_with_permissions(),
|
||||
create_active_caseworking_user(),
|
||||
])
|
||||
def test_get_jobs_shows_page_links(
|
||||
client_request,
|
||||
active_user_with_permissions,
|
||||
mock_get_jobs,
|
||||
user,
|
||||
):
|
||||
client_request.login(user)
|
||||
page = client_request.get('main.view_jobs', service_id=SERVICE_ONE_ID)
|
||||
|
||||
assert 'Next page' in page.find('li', {'class': 'next-page'}).text
|
||||
assert 'Previous page' in page.find('li', {'class': 'previous-page'}).text
|
||||
|
||||
|
||||
@pytest.mark.parametrize('user', [
|
||||
create_active_user_with_permissions(),
|
||||
create_active_caseworking_user(),
|
||||
])
|
||||
@freeze_time("2012-12-12 12:12")
|
||||
def test_jobs_page_doesnt_show_scheduled_on_page_2(
|
||||
client_request,
|
||||
service_one,
|
||||
active_user_with_permissions,
|
||||
mock_get_jobs,
|
||||
user,
|
||||
):
|
||||
client_request.login(user)
|
||||
page = client_request.get('main.view_jobs', service_id=service_one['id'], page=2)
|
||||
|
||||
for index, row in enumerate((
|
||||
(
|
||||
'File Status'
|
||||
),
|
||||
(
|
||||
'export 1/1/2016.xls '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'all email addresses.xlsx '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'applicants.ods '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'thisisatest.csv '
|
||||
'Sent today at 12:12pm 1 sending 0 delivered 0 failed'
|
||||
),
|
||||
)):
|
||||
assert normalize_spaces(page.select('tr')[index].text) == row
|
||||
client_request.get(
|
||||
'main.view_jobs',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_expected_status=302,
|
||||
_expected_redirect=url_for(
|
||||
'main.uploads',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_external=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('user', [
|
||||
|
||||
@@ -1192,7 +1192,7 @@ def test_edit_user_email_cannot_change_a_gov_email_address_to_a_non_gov_email_ad
|
||||
},
|
||||
_expected_status=200,
|
||||
)
|
||||
assert 'Enter a government email address.' in page.find('span', class_='error-message').text
|
||||
assert 'Enter a public sector email address' in page.select_one('.error-message').text
|
||||
with client_request.session_transaction() as session:
|
||||
assert 'team_member_email_change-'.format(active_user_with_permissions['id']) not in session
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ def test_should_redirect_if_not_logged_in(
|
||||
|
||||
@pytest.mark.parametrize('endpoint', [
|
||||
'main.platform_admin',
|
||||
'main.platform_admin_splash_page',
|
||||
'main.live_services',
|
||||
'main.trial_services',
|
||||
])
|
||||
@@ -589,6 +590,20 @@ def test_get_tech_failure_status_box_data_removes_percentage_data():
|
||||
assert 'percentage' not in tech_failure_data
|
||||
|
||||
|
||||
def test_platform_admin_splash_doesnt_talk_to_api(
|
||||
client_request,
|
||||
platform_admin_user,
|
||||
):
|
||||
|
||||
client_request.login(platform_admin_user)
|
||||
|
||||
page = client_request.get('main.platform_admin_splash_page')
|
||||
|
||||
assert page.select_one('main .govuk-body a')['href'] == url_for(
|
||||
'main.platform_admin',
|
||||
)
|
||||
|
||||
|
||||
def test_platform_admin_with_start_and_end_dates_provided(mocker, platform_admin_client):
|
||||
start_date = '2018-01-01'
|
||||
end_date = '2018-06-01'
|
||||
@@ -691,9 +706,10 @@ def test_platform_admin_submit_returned_letters(mocker, platform_admin_client):
|
||||
)
|
||||
|
||||
mock_client.assert_called_once_with(['REF1', 'REF2'])
|
||||
redis.delete_cache_keys_by_pattern.assert_called_once_with(
|
||||
'service-????????-????-????-????-????????????-returned-letters-summary'
|
||||
)
|
||||
assert redis.delete_cache_keys_by_pattern.call_args_list == [
|
||||
call('service-????????-????-????-????-????????????-returned-letters-statistics'),
|
||||
call('service-????????-????-????-????-????????????-returned-letters-summary'),
|
||||
]
|
||||
assert response.status_code == 302
|
||||
assert response.location == url_for('main.platform_admin_returned_letters', _external=True)
|
||||
|
||||
@@ -734,6 +750,15 @@ def test_clear_cache_shows_form(client_request, platform_admin_user, mocker):
|
||||
call('template-????????-????-????-????-????????????-version-*'),
|
||||
call('template-????????-????-????-????-????????????-versions'),
|
||||
], 'Removed 3 template objects from redis'),
|
||||
('service', [
|
||||
call('has_jobs-????????-????-????-????-????????????'),
|
||||
call('service-????????-????-????-????-????????????'),
|
||||
call('service-????????-????-????-????-????????????-templates'),
|
||||
call('service-????????-????-????-????-????????????-data-retention'),
|
||||
call('service-????????-????-????-????-????????????-template-folders'),
|
||||
call('service-????????-????-????-????-????????????-returned-letters-statistics'),
|
||||
call('service-????????-????-????-????-????????????-returned-letters-summary'),
|
||||
], 'Removed 3 service objects from redis'),
|
||||
('organisation', [
|
||||
call('organisations'),
|
||||
call('domains'),
|
||||
@@ -749,7 +774,7 @@ def test_clear_cache_submits_and_tells_you_how_many_things_were_deleted(
|
||||
expected_confirmation,
|
||||
):
|
||||
redis = mocker.patch('app.main.views.platform_admin.redis_client')
|
||||
redis.delete_cache_keys_by_pattern.side_effect = [0, 3, 1]
|
||||
redis.delete_cache_keys_by_pattern.side_effect = [0, 3, 1, 0, 0, 0, 0, 0]
|
||||
client_request.login(platform_admin_user)
|
||||
|
||||
page = client_request.post('main.clear_cache', _data={'model_type': model_type}, _expected_status=200)
|
||||
|
||||
@@ -7,6 +7,7 @@ from flask import session, url_for
|
||||
from flask_login import current_user
|
||||
|
||||
from app.models.user import InvitedUser
|
||||
from tests.conftest import normalize_spaces
|
||||
|
||||
|
||||
def test_render_register_returns_template_with_form(client):
|
||||
@@ -97,20 +98,27 @@ def test_process_register_returns_200_when_mobile_number_is_invalid(
|
||||
|
||||
|
||||
def test_should_return_200_when_email_is_not_gov_uk(
|
||||
client,
|
||||
mock_send_verify_code,
|
||||
mock_get_user_by_email,
|
||||
client_request,
|
||||
mock_get_organisations,
|
||||
mock_login,
|
||||
):
|
||||
response = client.post(url_for('main.register'),
|
||||
data={'name': 'Bad Mobile',
|
||||
'email_address': 'bad_mobile@example.not.right',
|
||||
'mobile_number': '+44123412345',
|
||||
'password': 'validPassword!'})
|
||||
client_request.logout()
|
||||
page = client_request.post(
|
||||
'main.register',
|
||||
_data={
|
||||
'name': 'Firstname Lastname',
|
||||
'email_address': 'bad_mobile@example.not.right',
|
||||
'mobile_number': '07900900123',
|
||||
'password': 'validPassword!'
|
||||
},
|
||||
_expected_status=200,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert 'Enter a government email address' in response.get_data(as_text=True)
|
||||
assert normalize_spaces(page.select_one('.error-message').text) == (
|
||||
'Enter a public sector email address or find out who can use Notify'
|
||||
)
|
||||
assert page.select_one('.error-message a')['href'] == url_for(
|
||||
'main.who_its_for'
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('email_address', (
|
||||
|
||||
@@ -6,12 +6,14 @@ from glob import glob
|
||||
from io import BytesIO
|
||||
from itertools import repeat
|
||||
from os import path
|
||||
from unittest.mock import ANY
|
||||
from uuid import uuid4
|
||||
from zipfile import BadZipFile
|
||||
|
||||
import pytest
|
||||
from bs4 import BeautifulSoup
|
||||
from flask import url_for
|
||||
from freezegun import freeze_time
|
||||
from notifications_python_client.errors import HTTPError
|
||||
from notifications_utils.recipients import RecipientCSV
|
||||
from notifications_utils.template import (
|
||||
@@ -36,6 +38,7 @@ from tests.conftest import (
|
||||
create_active_user_with_permissions,
|
||||
create_multiple_email_reply_to_addresses,
|
||||
create_multiple_sms_senders,
|
||||
create_platform_admin_user,
|
||||
create_template,
|
||||
mock_get_service_email_template,
|
||||
mock_get_service_letter_template,
|
||||
@@ -776,6 +779,7 @@ def test_upload_valid_csv_only_sets_meta_if_filename_known(
|
||||
mock_get_job_doesnt_exist,
|
||||
mock_get_jobs,
|
||||
mock_s3_set_metadata,
|
||||
mock_template_preview,
|
||||
fake_uuid,
|
||||
):
|
||||
|
||||
@@ -787,10 +791,6 @@ def test_upload_valid_csv_only_sets_meta_if_filename_known(
|
||||
'app.main.views.send.get_page_count_for_letter',
|
||||
return_value=5,
|
||||
)
|
||||
mocker.patch(
|
||||
'app.main.views.send.TemplatePreview.from_utils_template',
|
||||
return_value='foo'
|
||||
)
|
||||
|
||||
client_request.get(
|
||||
'no_cookie.check_messages_preview',
|
||||
@@ -1063,6 +1063,7 @@ def test_send_test_step_redirects_if_session_not_setup(
|
||||
mock_get_service_statistics,
|
||||
mock_get_users_by_service,
|
||||
mock_has_no_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
fake_uuid,
|
||||
user,
|
||||
endpoint,
|
||||
@@ -1177,6 +1178,7 @@ def test_send_one_off_or_test_has_correct_page_titles(
|
||||
logged_in_client,
|
||||
service_one,
|
||||
mock_has_no_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
fake_uuid,
|
||||
mocker,
|
||||
template_type,
|
||||
@@ -1238,6 +1240,7 @@ def test_send_one_off_or_test_shows_placeholders_in_correct_order(
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_has_no_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
mock_get_service_template_with_multiple_placeholders,
|
||||
endpoint,
|
||||
step_index,
|
||||
@@ -1289,6 +1292,7 @@ def test_send_one_off_has_skip_link(
|
||||
fake_uuid,
|
||||
mock_get_service_email_template,
|
||||
mock_has_no_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
mocker,
|
||||
template_type,
|
||||
expected_link_text,
|
||||
@@ -1308,32 +1312,34 @@ def test_send_one_off_has_skip_link(
|
||||
_follow_redirects=True,
|
||||
)
|
||||
|
||||
skip_links = page.select('a.top-gutter-4-3')
|
||||
skip_links = page.select('form a')
|
||||
|
||||
if expected_link_text and expected_link_url:
|
||||
assert skip_links[0].text.strip() == expected_link_text
|
||||
assert skip_links[0]['href'] == expected_link_url(
|
||||
assert skip_links[1].text.strip() == expected_link_text
|
||||
assert skip_links[1]['href'] == expected_link_url(
|
||||
service_id=service_one['id'],
|
||||
template_id=fake_uuid,
|
||||
)
|
||||
else:
|
||||
assert not skip_links
|
||||
with pytest.raises(IndexError):
|
||||
skip_links[1]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('template_type, expected_sticky', [
|
||||
('sms', False),
|
||||
('email', True),
|
||||
('letter', True),
|
||||
('letter', False),
|
||||
])
|
||||
def test_send_one_off_has_sticky_header_for_email_and_letter(
|
||||
def test_send_one_off_has_sticky_header_for_email(
|
||||
mocker,
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_has_no_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
template_type,
|
||||
expected_sticky,
|
||||
):
|
||||
template_data = create_template(template_type=template_type)
|
||||
template_data = create_template(template_type=template_type, content='((body))')
|
||||
mocker.patch('app.service_api_client.get_service_template', return_value={'data': template_data})
|
||||
mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=9)
|
||||
|
||||
@@ -1348,6 +1354,39 @@ def test_send_one_off_has_sticky_header_for_email_and_letter(
|
||||
assert bool(page.select('.js-stick-at-top-when-scrolling')) == expected_sticky
|
||||
|
||||
|
||||
def test_send_one_off_has_sticky_header_for_letter_on_non_address_placeholders(
|
||||
mocker,
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_get_live_service,
|
||||
):
|
||||
template_data = create_template(template_type='letter', content='((body))')
|
||||
mocker.patch('app.service_api_client.get_service_template', return_value={'data': template_data})
|
||||
mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=9)
|
||||
|
||||
with client_request.session_transaction() as session:
|
||||
session['send_test_letter_page_count'] = 1
|
||||
session['recipient'] = ''
|
||||
session['placeholders'] = {
|
||||
'address line 1': 'foo',
|
||||
'address line 2': 'bar',
|
||||
'address line 3': '',
|
||||
'address line 4': '',
|
||||
'address line 5': '',
|
||||
'address line 6': '',
|
||||
'postcode': 'SW1 1AA',
|
||||
}
|
||||
|
||||
page = client_request.get(
|
||||
'main.send_one_off_step',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
step_index=7, # letter template has 7 placeholders – we’re at the end
|
||||
_follow_redirects=True,
|
||||
)
|
||||
assert page.select('.js-stick-at-top-when-scrolling')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('user', (
|
||||
create_active_user_with_permissions(),
|
||||
create_active_caseworking_user(),
|
||||
@@ -1358,6 +1397,7 @@ def test_skip_link_will_not_show_on_sms_one_off_if_service_has_no_mobile_number(
|
||||
fake_uuid,
|
||||
mock_get_service_template,
|
||||
mock_has_no_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
mocker,
|
||||
user,
|
||||
):
|
||||
@@ -1374,17 +1414,17 @@ def test_skip_link_will_not_show_on_sms_one_off_if_service_has_no_mobile_number(
|
||||
assert not skip_links
|
||||
|
||||
|
||||
@pytest.mark.parametrize('user, link_index', (
|
||||
(create_active_user_with_permissions(), 2),
|
||||
(create_active_caseworking_user(), 1),
|
||||
@pytest.mark.parametrize('user', (
|
||||
create_active_user_with_permissions(),
|
||||
create_active_caseworking_user(),
|
||||
))
|
||||
def test_send_one_off_offers_link_to_upload(
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_get_service_template,
|
||||
mock_has_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
user,
|
||||
link_index,
|
||||
):
|
||||
client_request.login(user)
|
||||
|
||||
@@ -1396,7 +1436,7 @@ def test_send_one_off_offers_link_to_upload(
|
||||
)
|
||||
|
||||
back_link = page.select('main a')[0]
|
||||
link = page.select('main a')[link_index]
|
||||
link = page.select_one('form a')
|
||||
|
||||
assert back_link.text.strip() == 'Back'
|
||||
|
||||
@@ -1408,6 +1448,76 @@ def test_send_one_off_offers_link_to_upload(
|
||||
)
|
||||
|
||||
|
||||
def test_send_one_off_has_link_to_use_existing_list(
|
||||
client_request,
|
||||
mock_get_service_template,
|
||||
mock_has_jobs,
|
||||
mock_get_contact_lists,
|
||||
fake_uuid,
|
||||
):
|
||||
page = client_request.get(
|
||||
'main.send_one_off',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
_follow_redirects=True,
|
||||
)
|
||||
|
||||
assert [
|
||||
(link.text, link['href']) for link in page.select('form a')
|
||||
] == [
|
||||
(
|
||||
'Upload a list of phone numbers',
|
||||
url_for(
|
||||
'main.send_messages',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
),
|
||||
),
|
||||
(
|
||||
'Use a saved list',
|
||||
url_for(
|
||||
'main.choose_from_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
),
|
||||
),
|
||||
(
|
||||
'Use my phone number',
|
||||
url_for(
|
||||
'main.send_test',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def test_no_link_to_use_existing_list_for_service_without_lists(
|
||||
mocker,
|
||||
client_request,
|
||||
mock_get_service_template,
|
||||
mock_has_jobs,
|
||||
fake_uuid,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.models.contact_list.ContactLists.client_method',
|
||||
return_value=[],
|
||||
)
|
||||
client_request.login(create_platform_admin_user())
|
||||
page = client_request.get(
|
||||
'main.send_one_off',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
_follow_redirects=True,
|
||||
)
|
||||
assert [
|
||||
link.text for link in page.select('form a')
|
||||
] == [
|
||||
'Upload a list of phone numbers',
|
||||
'Use my phone number',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('user', (
|
||||
create_active_user_with_permissions(),
|
||||
create_active_caseworking_user(),
|
||||
@@ -2066,6 +2176,180 @@ def test_send_test_clears_session(
|
||||
assert session['placeholders'] == {}
|
||||
|
||||
|
||||
def test_send_one_off_redirects_to_letter_address(client_request, fake_uuid, mock_get_service_letter_template):
|
||||
with client_request.session_transaction() as session:
|
||||
session['placeholders'] = {'foo': 'some old data that we dont care about'}
|
||||
|
||||
client_request.get(
|
||||
'main.send_one_off',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
_expected_redirect=url_for(
|
||||
'main.send_one_off_letter_address',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
_external=True,
|
||||
)
|
||||
)
|
||||
# make sure it cleared session first
|
||||
with client_request.session_transaction() as session:
|
||||
assert session['recipient'] is None
|
||||
assert session['placeholders'] == {}
|
||||
|
||||
|
||||
def test_send_one_off_letter_address_shows_form(
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_get_service_letter_template,
|
||||
mock_template_preview,
|
||||
):
|
||||
with client_request.session_transaction() as session:
|
||||
session['recipient'] = None
|
||||
session['placeholders'] = {}
|
||||
|
||||
page = client_request.get(
|
||||
'main.send_one_off_letter_address',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid
|
||||
)
|
||||
|
||||
assert page.select_one('h1').text.strip() == 'Send ‘Two week reminder’'
|
||||
|
||||
form = page.select_one('form')
|
||||
|
||||
assert form.select_one('label').text.strip() == 'Address'
|
||||
assert form.select_one('textarea').attrs['name'] == 'address'
|
||||
|
||||
upload_link = form.select_one('a')
|
||||
|
||||
assert upload_link.text.strip() == 'Upload a list of addresses'
|
||||
assert upload_link['href'] == url_for(
|
||||
'main.send_messages',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
)
|
||||
|
||||
assert (
|
||||
page.find_all('a', {'class': 'govuk-back-link'})[0]['href']
|
||||
) == url_for('main.view_template', service_id=SERVICE_ONE_ID, template_id=fake_uuid)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(['form_data', 'expected_placeholders'], [
|
||||
# minimal
|
||||
('\n'.join(['a', 'b', 'c']), {
|
||||
'address line 1': 'a',
|
||||
'address line 2': 'b',
|
||||
'address line 3': '',
|
||||
'address line 4': '',
|
||||
'address line 5': '',
|
||||
'address line 6': '',
|
||||
'postcode': 'c',
|
||||
}),
|
||||
# maximal
|
||||
('\n'.join(['a', 'b', 'c', 'd', 'e', 'f', 'g']), {
|
||||
'address line 1': 'a',
|
||||
'address line 2': 'b',
|
||||
'address line 3': 'c',
|
||||
'address line 4': 'd',
|
||||
'address line 5': 'e',
|
||||
'address line 6': 'f',
|
||||
'postcode': 'g',
|
||||
}),
|
||||
# it ignores empty lines and strips whitespace from each line.
|
||||
# It also strips extra whitespace from the middle of lines.
|
||||
('\n a\ta \n\n\n \n\n\n\nb b \r\nc', {
|
||||
'address line 1': 'a\ta',
|
||||
'address line 2': 'b b',
|
||||
'address line 3': '',
|
||||
'address line 4': '',
|
||||
'address line 5': '',
|
||||
'address line 6': '',
|
||||
'postcode': 'c',
|
||||
}),
|
||||
])
|
||||
def test_send_one_off_letter_address_populates_address_fields_in_session(
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_get_service_letter_template,
|
||||
mock_template_preview,
|
||||
form_data,
|
||||
expected_placeholders
|
||||
):
|
||||
with client_request.session_transaction() as session:
|
||||
session['recipient'] = None
|
||||
session['placeholders'] = {}
|
||||
|
||||
client_request.post(
|
||||
'main.send_one_off_letter_address',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
_data={'address': form_data},
|
||||
# there are no additional placeholders so go straight to the check page
|
||||
_expected_redirect=url_for(
|
||||
'main.check_notification',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
_external=True,
|
||||
),
|
||||
)
|
||||
with client_request.session_transaction() as session:
|
||||
assert session['placeholders'] == expected_placeholders
|
||||
|
||||
|
||||
@pytest.mark.parametrize(['form_data', 'expected_error_message'], [
|
||||
('', 'Cannot be empty'),
|
||||
('a\n\n\n\nb', 'Address must be at least 3 lines long'),
|
||||
('\n'.join(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']), 'Address must be no more than 7 lines long'),
|
||||
])
|
||||
def test_send_one_off_letter_address_rejects_bad_addresses(
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_get_service_letter_template,
|
||||
mock_template_preview,
|
||||
form_data,
|
||||
expected_error_message
|
||||
):
|
||||
with client_request.session_transaction() as session:
|
||||
session['recipient'] = None
|
||||
session['placeholders'] = {}
|
||||
|
||||
page = client_request.post(
|
||||
'main.send_one_off_letter_address',
|
||||
_data={'address': form_data},
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
_expected_status=200
|
||||
)
|
||||
|
||||
error = page.select('form .error-message')
|
||||
assert normalize_spaces(error[0].text) == expected_error_message
|
||||
|
||||
|
||||
def test_send_one_off_letter_address_goes_to_next_placeholder(client_request, mock_template_preview, mocker):
|
||||
with client_request.session_transaction() as session:
|
||||
session['recipient'] = None
|
||||
session['placeholders'] = {}
|
||||
|
||||
template_data = create_template(template_type='letter', content='((foo))')
|
||||
|
||||
mocker.patch('app.service_api_client.get_service_template', return_value={'data': template_data})
|
||||
|
||||
client_request.post(
|
||||
'main.send_one_off_letter_address',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=template_data['id'],
|
||||
_data={'address': 'a\nb\nc'},
|
||||
# step 0-6 represent address line 1-6 and postcode. step 7 is the first non address placeholder
|
||||
_expected_redirect=url_for(
|
||||
'main.send_one_off_step',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=template_data['id'],
|
||||
step_index=7,
|
||||
_external=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_download_example_csv(
|
||||
logged_in_client,
|
||||
mocker,
|
||||
@@ -2180,6 +2464,31 @@ def test_upload_csvfile_with_international_validates(
|
||||
assert mock_recipients.call_args[1]['international_sms'] == should_allow_international
|
||||
|
||||
|
||||
def test_job_from_contact_list_knows_where_its_come_from(
|
||||
client_request,
|
||||
mocker,
|
||||
service_one,
|
||||
mock_get_service_template,
|
||||
mock_s3_download,
|
||||
mock_get_users_by_service,
|
||||
mock_get_service_statistics,
|
||||
mock_get_job_doesnt_exist,
|
||||
mock_get_jobs,
|
||||
mock_s3_set_metadata,
|
||||
fake_uuid
|
||||
):
|
||||
page = client_request.get(
|
||||
'main.check_messages',
|
||||
service_id=service_one['id'],
|
||||
upload_id=fake_uuid,
|
||||
template_id=fake_uuid,
|
||||
contact_list_id=unchanging_fake_uuid,
|
||||
)
|
||||
assert page.select_one(
|
||||
'form input[type=hidden][name=contact_list_id]'
|
||||
)['value'] == str(unchanging_fake_uuid)
|
||||
|
||||
|
||||
def test_test_message_can_only_be_sent_now(
|
||||
client_request,
|
||||
mocker,
|
||||
@@ -2216,7 +2525,10 @@ def test_letter_can_only_be_sent_now(
|
||||
mock_get_jobs,
|
||||
fake_uuid,
|
||||
):
|
||||
mocker.patch('app.main.views.send.s3download', return_value="addressline1, addressline2, postcode\na,b,c")
|
||||
mocker.patch(
|
||||
'app.main.views.send.s3download',
|
||||
return_value="addressline1, addressline2, postcode\na,b,sw1 1aa"
|
||||
)
|
||||
mocker.patch('app.main.views.send.set_metadata_on_csv_upload')
|
||||
mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=1)
|
||||
|
||||
@@ -2268,6 +2580,9 @@ def test_send_button_is_correctly_labelled(
|
||||
@pytest.mark.parametrize('when', [
|
||||
'', '2016-08-25T13:04:21.767198'
|
||||
])
|
||||
@pytest.mark.parametrize('contact_list_id', [
|
||||
'', unchanging_fake_uuid,
|
||||
])
|
||||
def test_create_job_should_call_api(
|
||||
client_request,
|
||||
mock_create_job,
|
||||
@@ -2277,7 +2592,8 @@ def test_create_job_should_call_api(
|
||||
mock_get_service_data_retention,
|
||||
mocker,
|
||||
fake_uuid,
|
||||
when
|
||||
when,
|
||||
contact_list_id,
|
||||
):
|
||||
data = mock_get_job(SERVICE_ONE_ID, fake_uuid)['data']
|
||||
job_id = data['id']
|
||||
@@ -2298,7 +2614,10 @@ def test_create_job_should_call_api(
|
||||
service_id=SERVICE_ONE_ID,
|
||||
upload_id=job_id,
|
||||
original_file_name=original_file_name,
|
||||
_data={'scheduled_for': when},
|
||||
_data={
|
||||
'scheduled_for': when,
|
||||
'contact_list_id': contact_list_id,
|
||||
},
|
||||
_follow_redirects=True,
|
||||
_expected_status=200,
|
||||
)
|
||||
@@ -2309,6 +2628,7 @@ def test_create_job_should_call_api(
|
||||
job_id,
|
||||
SERVICE_ONE_ID,
|
||||
scheduled_for=when,
|
||||
contact_list_id=str(contact_list_id),
|
||||
)
|
||||
|
||||
|
||||
@@ -2908,8 +3228,8 @@ def test_check_messages_shows_data_errors_before_trial_mode_errors_for_letters(
|
||||
|
||||
mocker.patch('app.main.views.send.s3download', return_value='\n'.join(
|
||||
['address_line_1,address_line_2,postcode,'] +
|
||||
[' , ,11SW1 1AA'] +
|
||||
[' , ,11SW1 1AA']
|
||||
[' , ,SW1 1AA'] +
|
||||
[' , ,SW1 1AA']
|
||||
))
|
||||
|
||||
mocker.patch(
|
||||
@@ -3670,6 +3990,7 @@ def test_reply_to_is_previewed_if_chosen(
|
||||
mock_get_service_statistics,
|
||||
mock_get_job_doesnt_exist,
|
||||
mock_get_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
get_default_reply_to_email_address,
|
||||
fake_uuid,
|
||||
endpoint,
|
||||
@@ -3721,6 +4042,7 @@ def test_sms_sender_is_previewed(
|
||||
mock_get_service_statistics,
|
||||
mock_get_job_doesnt_exist,
|
||||
mock_get_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
get_default_sms_sender,
|
||||
fake_uuid,
|
||||
endpoint,
|
||||
@@ -3780,3 +4102,164 @@ def test_redirects_to_template_if_job_exists_already(
|
||||
_external=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize((
|
||||
'template_type, '
|
||||
'expected_list_id, '
|
||||
'expected_filename, '
|
||||
'expected_time, '
|
||||
'expected_count'
|
||||
), (
|
||||
(
|
||||
'email',
|
||||
'6ce466d0-fd6a-11e5-82f5-e0accb9d11a6',
|
||||
'EmergencyContactList.xls',
|
||||
'Uploaded today at 10:59am',
|
||||
'100 email addresses',
|
||||
),
|
||||
(
|
||||
'sms',
|
||||
'd7b0bd1a-d1c7-4621-be5c-3c1b4278a2ad',
|
||||
'phone number list.csv',
|
||||
'Uploaded today at 1:00pm',
|
||||
'123 phone numbers',
|
||||
),
|
||||
))
|
||||
@freeze_time('2020-03-13 13:00')
|
||||
def test_choose_from_contact_list(
|
||||
mocker,
|
||||
client_request,
|
||||
mock_get_contact_lists,
|
||||
fake_uuid,
|
||||
template_type,
|
||||
expected_list_id,
|
||||
expected_filename,
|
||||
expected_time,
|
||||
expected_count,
|
||||
):
|
||||
template = create_template(template_type=template_type)
|
||||
mocker.patch(
|
||||
'app.service_api_client.get_service_template',
|
||||
return_value={'data': template},
|
||||
)
|
||||
page = client_request.get(
|
||||
'main.choose_from_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
)
|
||||
assert len(page.select('.file-list-filename-large')) == 1
|
||||
assert normalize_spaces(page.select_one('.file-list-filename-large').text) == (
|
||||
expected_filename
|
||||
)
|
||||
assert page.select_one('a.file-list-filename-large')['href'] == url_for(
|
||||
'main.send_from_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=template['id'],
|
||||
contact_list_id=expected_list_id,
|
||||
)
|
||||
assert normalize_spaces(page.select_one('.file-list-hint-large').text) == (
|
||||
expected_time
|
||||
)
|
||||
assert normalize_spaces(page.select_one('.big-number-smallest').text) == (
|
||||
expected_count
|
||||
)
|
||||
|
||||
|
||||
def test_choose_from_contact_list_with_personalised_template(
|
||||
mocker,
|
||||
client_request,
|
||||
mock_get_contact_lists,
|
||||
fake_uuid,
|
||||
):
|
||||
template = create_template(
|
||||
content="Hey ((name)) ((thing)) is happening"
|
||||
)
|
||||
mocker.patch(
|
||||
'app.service_api_client.get_service_template',
|
||||
return_value={'data': template},
|
||||
)
|
||||
page = client_request.get(
|
||||
'main.choose_from_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
)
|
||||
assert [
|
||||
normalize_spaces(p.text) for p in page.select('main p')
|
||||
] == [
|
||||
'You cannot use a saved contact list with this template because '
|
||||
'it is personalised with ((name)) and ((thing)).',
|
||||
'Saved contact lists can only store email addresses or phone numbers.',
|
||||
]
|
||||
assert not page.select('table')
|
||||
|
||||
|
||||
def test_choose_from_contact_list_with_no_lists(
|
||||
mocker,
|
||||
client_request,
|
||||
mock_get_service_template,
|
||||
fake_uuid,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.models.contact_list.ContactLists.client_method',
|
||||
return_value=[],
|
||||
)
|
||||
page = client_request.get(
|
||||
'main.choose_from_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
)
|
||||
assert [
|
||||
normalize_spaces(p.text) for p in page.select('main p')
|
||||
] == [
|
||||
'You have not saved any lists of phone numbers yet.',
|
||||
'To upload and save a new contact list, go to the uploads page.',
|
||||
]
|
||||
assert page.select_one('main p a')['href'] == url_for(
|
||||
'main.uploads',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
)
|
||||
assert not page.select('table')
|
||||
|
||||
|
||||
def test_send_from_contact_list(
|
||||
mocker,
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_get_contact_list,
|
||||
):
|
||||
new_uuid = uuid.uuid4()
|
||||
mock_download = mocker.patch('app.models.contact_list.s3download', return_value='contents')
|
||||
mock_get_metadata = mocker.patch('app.models.contact_list.get_csv_metadata', return_value={
|
||||
'example_key': 'example value',
|
||||
})
|
||||
mock_upload = mocker.patch('app.models.contact_list.s3upload', return_value=new_uuid)
|
||||
mock_set_metadata = mocker.patch('app.models.contact_list.set_metadata_on_csv_upload')
|
||||
client_request.get(
|
||||
'main.send_from_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
contact_list_id=fake_uuid,
|
||||
_expected_status=302,
|
||||
_expected_redirect=url_for(
|
||||
'main.check_messages',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
upload_id=new_uuid,
|
||||
original_file_name='EmergencyContactList.xls',
|
||||
contact_list_id=fake_uuid,
|
||||
_external=True,
|
||||
)
|
||||
)
|
||||
mock_download.assert_called_once_with(
|
||||
SERVICE_ONE_ID, fake_uuid, bucket='test-contact-list'
|
||||
)
|
||||
mock_get_metadata.assert_called_once_with(
|
||||
SERVICE_ONE_ID, fake_uuid, bucket='test-contact-list'
|
||||
)
|
||||
mock_upload.assert_called_once_with(
|
||||
SERVICE_ONE_ID, {'data': 'contents'}, ANY
|
||||
)
|
||||
mock_set_metadata.assert_called_once_with(
|
||||
SERVICE_ONE_ID, new_uuid, example_key='example value'
|
||||
)
|
||||
|
||||
@@ -31,7 +31,7 @@ def test_sign_out_user(
|
||||
mock_get_usage,
|
||||
mock_get_free_sms_fragment_limit,
|
||||
mock_get_inbound_sms_summary,
|
||||
mock_get_returned_letter_summary_with_no_returned_letters,
|
||||
mock_get_returned_letter_statistics_with_no_returned_letters
|
||||
):
|
||||
with client_request.session_transaction() as session:
|
||||
assert session.get('user_id') is not None
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import pytest
|
||||
from bs4 import BeautifulSoup
|
||||
from flask import url_for
|
||||
from freezegun import freeze_time
|
||||
@@ -107,6 +108,9 @@ def test_should_login_user_and_not_redirect_to_external_url(
|
||||
assert response.location == url_for('main.show_accounts_or_dashboard', _external=True)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('platform_admin', (
|
||||
True, False,
|
||||
))
|
||||
@freeze_time('2020-01-27T12:00:00')
|
||||
def test_should_login_user_and_redirect_to_show_accounts(
|
||||
client,
|
||||
@@ -115,12 +119,14 @@ def test_should_login_user_and_redirect_to_show_accounts(
|
||||
mock_get_user_by_email,
|
||||
mock_check_verify_code,
|
||||
mock_create_event,
|
||||
platform_admin,
|
||||
):
|
||||
with client.session_transaction() as session:
|
||||
session['user_details'] = {
|
||||
'id': api_user_active['id'],
|
||||
'email': api_user_active['email_address']}
|
||||
api_user_active['email_access_validated_at'] = '2020-01-23T11:35:21.726132Z'
|
||||
api_user_active['platform_admin'] = platform_admin
|
||||
|
||||
response = client.post(url_for('main.two_factor'),
|
||||
data={'sms_code': '12345'})
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import re
|
||||
import urllib
|
||||
from unittest.mock import Mock
|
||||
import uuid
|
||||
from io import BytesIO
|
||||
from unittest.mock import ANY, Mock
|
||||
|
||||
import pytest
|
||||
from flask import make_response, url_for
|
||||
@@ -13,36 +15,61 @@ from tests.conftest import (
|
||||
SERVICE_ONE_ID,
|
||||
create_active_caseworking_user,
|
||||
create_active_user_with_permissions,
|
||||
create_platform_admin_user,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('extra_permissions', (
|
||||
[],
|
||||
['letter'],
|
||||
['upload_letters'],
|
||||
pytest.param(
|
||||
['letter', 'upload_letters'],
|
||||
[],
|
||||
marks=pytest.mark.xfail(raises=AssertionError),
|
||||
),
|
||||
pytest.param(
|
||||
['upload_letters'],
|
||||
marks=pytest.mark.xfail(raises=AssertionError),
|
||||
),
|
||||
['letter'],
|
||||
['letter', 'upload_letters'],
|
||||
))
|
||||
def test_no_upload_letters_button_without_permission(
|
||||
def test_upload_letters_button_only_with_letters_permission(
|
||||
client_request,
|
||||
service_one,
|
||||
mock_get_uploads,
|
||||
mock_get_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
extra_permissions,
|
||||
):
|
||||
service_one['permissions'] += extra_permissions
|
||||
page = client_request.get('main.uploads', service_id=SERVICE_ONE_ID)
|
||||
assert not page.find('a', text=re.compile('Upload a letter'))
|
||||
assert page.find('a', text=re.compile('Upload a letter'))
|
||||
|
||||
|
||||
@pytest.mark.parametrize('user', (
|
||||
create_platform_admin_user(),
|
||||
create_active_user_with_permissions(),
|
||||
))
|
||||
def test_all_users_have_upload_contact_list(
|
||||
client_request,
|
||||
mock_get_uploads,
|
||||
mock_get_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
user,
|
||||
):
|
||||
client_request.login(user)
|
||||
page = client_request.get('main.uploads', service_id=SERVICE_ONE_ID)
|
||||
button = page.find('a', text=re.compile('Upload an emergency contact list'))
|
||||
assert button
|
||||
assert button['href'] == url_for(
|
||||
'main.upload_contact_list', service_id=SERVICE_ONE_ID,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('extra_permissions, expected_empty_message', (
|
||||
(['letter'], (
|
||||
([], (
|
||||
'You have not uploaded any files recently. '
|
||||
'To upload a list of contact details, first choose a template.'
|
||||
)),
|
||||
(['letter', 'upload_letters'], (
|
||||
(['letter'], (
|
||||
'You have not uploaded any files recently. '
|
||||
'Upload a letter and Notify will print, pack and post it for you. '
|
||||
'To upload a list of contact details, first choose a template.'
|
||||
@@ -53,6 +80,7 @@ def test_get_upload_hub_with_no_uploads(
|
||||
client_request,
|
||||
service_one,
|
||||
mock_get_no_uploads,
|
||||
mock_get_no_contact_lists,
|
||||
extra_permissions,
|
||||
expected_empty_message,
|
||||
):
|
||||
@@ -70,6 +98,7 @@ def test_get_upload_hub_page(
|
||||
client_request,
|
||||
service_one,
|
||||
mock_get_uploads,
|
||||
mock_get_no_contact_lists,
|
||||
):
|
||||
mocker.patch('app.job_api_client.get_jobs', return_value={'data': []})
|
||||
service_one['permissions'] += ['letter', 'upload_letters']
|
||||
@@ -97,7 +126,7 @@ def test_get_upload_hub_page(
|
||||
'123 Example Street'
|
||||
)
|
||||
assert normalize_spaces(str(uploads[1].select_one('.govuk-body'))) == (
|
||||
'<p class="govuk-body govuk-!-margin-bottom-1"> '
|
||||
'<p class="govuk-body letter-recipient-summary"> '
|
||||
'Firstname Lastname<br/> '
|
||||
'123 Example Street<br/> '
|
||||
'</p>'
|
||||
@@ -656,6 +685,7 @@ def test_uploads_page_shows_scheduled_jobs(
|
||||
client_request,
|
||||
mock_get_no_uploads,
|
||||
mock_get_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
user,
|
||||
):
|
||||
client_request.login(user)
|
||||
@@ -681,11 +711,56 @@ def test_uploads_page_shows_scheduled_jobs(
|
||||
assert not page.select('.table-empty-message')
|
||||
|
||||
|
||||
@freeze_time('2020-03-15')
|
||||
def test_uploads_page_shows_contact_lists_first(
|
||||
mocker,
|
||||
client_request,
|
||||
mock_get_no_uploads,
|
||||
mock_get_jobs,
|
||||
mock_get_contact_lists,
|
||||
):
|
||||
page = client_request.get('main.uploads', service_id=SERVICE_ONE_ID)
|
||||
|
||||
assert [
|
||||
normalize_spaces(row.text) for row in page.select('tr')
|
||||
] == [
|
||||
(
|
||||
'File Status'
|
||||
),
|
||||
(
|
||||
'phone number list.csv '
|
||||
'Uploaded 13 March at 1:00pm '
|
||||
'123 saved phone numbers'
|
||||
),
|
||||
(
|
||||
'EmergencyContactList.xls '
|
||||
'Uploaded 13 March at 10:59am '
|
||||
'100 saved email addresses'
|
||||
),
|
||||
(
|
||||
'even_later.csv '
|
||||
'Sending 1 January 2016 at 11:09pm '
|
||||
'1 text message waiting to send'
|
||||
),
|
||||
(
|
||||
'send_me_later.csv '
|
||||
'Sending 1 January 2016 at 11:09am '
|
||||
'1 text message waiting to send'
|
||||
),
|
||||
]
|
||||
assert page.select_one('.file-list-filename-large')['href'] == url_for(
|
||||
'main.contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id='d7b0bd1a-d1c7-4621-be5c-3c1b4278a2ad',
|
||||
)
|
||||
|
||||
|
||||
def test_get_uploads_shows_pagination(
|
||||
client_request,
|
||||
active_user_with_permissions,
|
||||
mock_get_jobs,
|
||||
mock_get_uploads,
|
||||
mock_get_no_contact_lists,
|
||||
):
|
||||
page = client_request.get('main.uploads', service_id=SERVICE_ONE_ID)
|
||||
|
||||
@@ -697,3 +772,541 @@ def test_get_uploads_shows_pagination(
|
||||
'Previous page '
|
||||
'page 0'
|
||||
)
|
||||
|
||||
|
||||
def test_upload_contact_list_page(client_request):
|
||||
page = client_request.get(
|
||||
'main.upload_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
)
|
||||
assert 'action' not in page.select_one('form')
|
||||
assert page.select_one('form input')['name'] == 'file'
|
||||
assert page.select_one('form input')['type'] == 'file'
|
||||
|
||||
assert normalize_spaces(page.select('.spreadsheet')[0].text) == (
|
||||
'Example A '
|
||||
'1 email address '
|
||||
'2 test@example.gov.uk'
|
||||
)
|
||||
assert normalize_spaces(page.select('.spreadsheet')[1].text) == (
|
||||
'Example A '
|
||||
'1 phone number '
|
||||
'2 07700 900123'
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('file_contents, expected_error, expected_thead, expected_tbody,', [
|
||||
(
|
||||
"""
|
||||
telephone,name
|
||||
+447700900986
|
||||
""",
|
||||
(
|
||||
'Your file has too many columns '
|
||||
'It needs to have 1 column, called ‘email address’ or ‘phone number’. '
|
||||
'Right now it has 2 columns called ‘telephone’ and ‘name’. '
|
||||
'Skip to file contents'
|
||||
),
|
||||
'Row in file 1 telephone name',
|
||||
'2 +447700900986',
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number, email address
|
||||
+447700900986, test@example.com
|
||||
""",
|
||||
(
|
||||
'Your file has too many columns '
|
||||
'It needs to have 1 column, called ‘email address’ or ‘phone number’. '
|
||||
'Right now it has 2 columns called ‘phone number’ and ‘email address’. '
|
||||
'Skip to file contents'
|
||||
),
|
||||
'Row in file 1 phone number email address',
|
||||
'2 +447700900986 test@example.com',
|
||||
),
|
||||
(
|
||||
"""
|
||||
email address
|
||||
+447700900986
|
||||
""",
|
||||
(
|
||||
'There’s a problem with invalid.csv '
|
||||
'You need to fix 1 email address. '
|
||||
'Skip to file contents'
|
||||
),
|
||||
'Row in file 1 email address',
|
||||
'2 Not a valid email address +447700900986',
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number
|
||||
test@example.com
|
||||
""",
|
||||
(
|
||||
'There’s a problem with invalid.csv '
|
||||
'You need to fix 1 phone number. '
|
||||
'Skip to file contents'
|
||||
),
|
||||
'Row in file 1 phone number',
|
||||
'2 Must not contain letters or symbols test@example.com',
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number, phone number, PHONE_NUMBER
|
||||
+447700900111,+447700900222,+447700900333,
|
||||
""",
|
||||
(
|
||||
'Your file has too many columns '
|
||||
'It needs to have 1 column, called ‘email address’ or ‘phone number’. '
|
||||
'Right now it has 3 columns called ‘phone number’, ‘phone number’ and ‘PHONE_NUMBER’. '
|
||||
'Skip to file contents'
|
||||
),
|
||||
'Row in file 1 phone number phone number PHONE_NUMBER',
|
||||
'2 +447700900333 +447700900333 +447700900333',
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number
|
||||
""",
|
||||
(
|
||||
'Your file is missing some rows '
|
||||
'It needs at least one row of data. '
|
||||
'Skip to file contents'
|
||||
),
|
||||
'Row in file 1 phone number',
|
||||
'',
|
||||
),
|
||||
(
|
||||
"+447700900986",
|
||||
(
|
||||
'Your file is missing some rows '
|
||||
'It needs at least one row of data, in a column called '
|
||||
'‘email address’ or ‘phone number’. '
|
||||
'Skip to file contents'
|
||||
),
|
||||
'Row in file 1 +447700900986',
|
||||
'',
|
||||
),
|
||||
(
|
||||
"",
|
||||
(
|
||||
'Your file is missing some rows '
|
||||
'It needs at least one row of data, in a column called '
|
||||
'‘email address’ or ‘phone number’. '
|
||||
'Skip to file contents'
|
||||
),
|
||||
'Row in file 1',
|
||||
'',
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number
|
||||
+447700900986
|
||||
|
||||
+447700900986
|
||||
""",
|
||||
(
|
||||
'There’s a problem with invalid.csv '
|
||||
'You need to enter missing data in 1 row. '
|
||||
'Skip to file contents'
|
||||
),
|
||||
'Row in file 1 phone number',
|
||||
(
|
||||
'3 Missing'
|
||||
)
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number
|
||||
+447700900
|
||||
""",
|
||||
(
|
||||
'There’s a problem with invalid.csv '
|
||||
'You need to fix 1 phone number. '
|
||||
'Skip to file contents'
|
||||
),
|
||||
'Row in file 1 phone number',
|
||||
'2 Not enough digits +447700900',
|
||||
),
|
||||
(
|
||||
"""
|
||||
email address
|
||||
ok@example.com
|
||||
bad@example1
|
||||
bad@example2
|
||||
""",
|
||||
(
|
||||
'There’s a problem with invalid.csv '
|
||||
'You need to fix 2 email addresses. '
|
||||
'Skip to file contents'
|
||||
),
|
||||
'Row in file 1 email address',
|
||||
(
|
||||
'3 Not a valid email address bad@example1 '
|
||||
'4 Not a valid email address bad@example2'
|
||||
),
|
||||
),
|
||||
])
|
||||
def test_upload_csv_file_shows_error_banner(
|
||||
client_request,
|
||||
mocker,
|
||||
mock_s3_upload,
|
||||
mock_get_job_doesnt_exist,
|
||||
mock_get_users_by_service,
|
||||
fake_uuid,
|
||||
file_contents,
|
||||
expected_error,
|
||||
expected_thead,
|
||||
expected_tbody,
|
||||
):
|
||||
mock_upload = mocker.patch(
|
||||
'app.models.contact_list.s3upload',
|
||||
return_value=fake_uuid,
|
||||
)
|
||||
mock_download = mocker.patch(
|
||||
'app.models.contact_list.s3download',
|
||||
return_value=file_contents,
|
||||
)
|
||||
|
||||
page = client_request.post(
|
||||
'main.upload_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_data={'file': (BytesIO(''.encode('utf-8')), 'invalid.csv')},
|
||||
_follow_redirects=True,
|
||||
)
|
||||
mock_upload.assert_called_once_with(
|
||||
SERVICE_ONE_ID,
|
||||
{'data': '', 'file_name': 'invalid.csv'},
|
||||
ANY,
|
||||
bucket='test-contact-list',
|
||||
)
|
||||
mock_download.assert_called_once_with(
|
||||
SERVICE_ONE_ID,
|
||||
fake_uuid,
|
||||
bucket='test-contact-list',
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select_one('.banner-dangerous').text) == expected_error
|
||||
|
||||
assert page.select_one('form')['action'] == url_for(
|
||||
'main.upload_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
)
|
||||
assert page.select_one('form input')['type'] == 'file'
|
||||
|
||||
assert normalize_spaces(page.select_one('thead').text) == expected_thead
|
||||
assert normalize_spaces(page.select_one('tbody').text) == expected_tbody
|
||||
|
||||
|
||||
def test_upload_csv_file_shows_error_banner_for_too_many_rows(
|
||||
client_request,
|
||||
mocker,
|
||||
mock_s3_upload,
|
||||
mock_get_job_doesnt_exist,
|
||||
mock_get_users_by_service,
|
||||
fake_uuid,
|
||||
):
|
||||
mocker.patch('app.models.contact_list.s3upload', return_value=fake_uuid)
|
||||
mocker.patch('app.models.contact_list.s3download', return_value='\n'.join(
|
||||
['phone number'] + (['07700900986'] * 50001)
|
||||
))
|
||||
|
||||
page = client_request.post(
|
||||
'main.upload_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_data={'file': (BytesIO(''.encode('utf-8')), 'invalid.csv')},
|
||||
_follow_redirects=True,
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select_one('.banner-dangerous').text) == (
|
||||
'Your file has too many rows '
|
||||
'Notify can store files up to 50,000 rows in size. '
|
||||
'Your file has 50,001 rows. '
|
||||
'Skip to file contents'
|
||||
)
|
||||
assert len(page.select('tbody tr')) == 50
|
||||
assert normalize_spaces(page.select_one('.table-show-more-link').text) == (
|
||||
'Only showing the first 50 rows'
|
||||
)
|
||||
|
||||
|
||||
def test_upload_csv_shows_trial_mode_error(
|
||||
client_request,
|
||||
mock_get_users_by_service,
|
||||
mock_get_job_doesnt_exist,
|
||||
fake_uuid,
|
||||
mocker
|
||||
):
|
||||
mocker.patch('app.models.contact_list.s3upload', return_value=fake_uuid)
|
||||
mocker.patch('app.models.contact_list.s3download', return_value=(
|
||||
'phone number\n'
|
||||
'07900900321' # Not in team
|
||||
))
|
||||
|
||||
page = client_request.get(
|
||||
'main.check_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
upload_id=fake_uuid,
|
||||
_test_page_title=False,
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select_one('.banner-dangerous').text) == (
|
||||
'You cannot save this phone number '
|
||||
'In trial mode you can only send to yourself and members of your team '
|
||||
'Skip to file contents'
|
||||
)
|
||||
assert page.select_one('.banner-dangerous a')['href'] == url_for(
|
||||
'main.trial_mode_new'
|
||||
)
|
||||
|
||||
|
||||
def test_upload_csv_shows_ok_page(
|
||||
client_request,
|
||||
mock_get_live_service,
|
||||
mock_get_users_by_service,
|
||||
mock_get_job_doesnt_exist,
|
||||
fake_uuid,
|
||||
mocker
|
||||
):
|
||||
mocker.patch('app.models.contact_list.s3download', return_value='\n'.join(
|
||||
['email address'] + ['test@example.com'] * 51
|
||||
))
|
||||
mock_metadata_set = mocker.patch('app.models.contact_list.set_metadata_on_csv_upload')
|
||||
|
||||
page = client_request.get(
|
||||
'main.check_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
upload_id=fake_uuid,
|
||||
original_file_name='good times.xlsx',
|
||||
_test_page_title=False,
|
||||
)
|
||||
|
||||
mock_metadata_set.assert_called_once_with(
|
||||
SERVICE_ONE_ID,
|
||||
fake_uuid,
|
||||
bucket='test-contact-list',
|
||||
row_count=51,
|
||||
original_file_name='good times.xlsx',
|
||||
template_type='email',
|
||||
valid=True,
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select_one('h1').text) == (
|
||||
'good times.xlsx'
|
||||
)
|
||||
assert normalize_spaces(page.select_one('main p').text) == (
|
||||
'51 email addresses found'
|
||||
)
|
||||
assert page.select_one('form')['action'] == url_for(
|
||||
'main.save_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
upload_id=fake_uuid,
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select_one('form [type=submit]').text) == (
|
||||
'Save contact list'
|
||||
)
|
||||
assert normalize_spaces(page.select_one('thead').text) == (
|
||||
'Row in file 1 email address'
|
||||
)
|
||||
assert len(page.select('tbody tr')) == 50
|
||||
assert normalize_spaces(page.select_one('tbody tr').text) == (
|
||||
'2 test@example.com'
|
||||
)
|
||||
assert normalize_spaces(page.select_one('.table-show-more-link').text) == (
|
||||
'Only showing the first 50 rows'
|
||||
)
|
||||
|
||||
|
||||
def test_save_contact_list(
|
||||
mocker,
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_create_contact_list,
|
||||
):
|
||||
mock_get_metadata = mocker.patch('app.models.contact_list.get_csv_metadata', return_value={
|
||||
'row_count': 999,
|
||||
'valid': True,
|
||||
'original_file_name': 'example.csv',
|
||||
'template_type': 'email'
|
||||
})
|
||||
client_request.post(
|
||||
'main.save_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
upload_id=fake_uuid,
|
||||
_expected_status=302,
|
||||
_expected_redirect=url_for(
|
||||
'main.uploads',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_external=True,
|
||||
)
|
||||
)
|
||||
mock_get_metadata.assert_called_once_with(
|
||||
SERVICE_ONE_ID,
|
||||
fake_uuid,
|
||||
bucket='test-contact-list',
|
||||
)
|
||||
mock_create_contact_list.assert_called_once_with(
|
||||
service_id=SERVICE_ONE_ID,
|
||||
upload_id=fake_uuid,
|
||||
original_file_name='example.csv',
|
||||
row_count=999,
|
||||
template_type='email',
|
||||
)
|
||||
|
||||
|
||||
def test_cant_save_bad_contact_list(
|
||||
mocker,
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_create_contact_list,
|
||||
):
|
||||
mocker.patch('app.models.contact_list.get_csv_metadata', return_value={
|
||||
'row_count': 999,
|
||||
'valid': False,
|
||||
'original_file_name': 'example.csv',
|
||||
'template_type': 'email'
|
||||
})
|
||||
client_request.post(
|
||||
'main.save_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
upload_id=fake_uuid,
|
||||
_expected_status=403,
|
||||
)
|
||||
assert mock_create_contact_list.called is False
|
||||
|
||||
|
||||
@freeze_time('2020-03-13 16:51:56')
|
||||
def test_view_contact_list(
|
||||
mocker,
|
||||
client_request,
|
||||
mock_get_contact_list,
|
||||
fake_uuid,
|
||||
):
|
||||
mocker.patch('app.models.contact_list.s3download', return_value='\n'.join(
|
||||
['email address'] + ['test@example.com'] * 51
|
||||
))
|
||||
page = client_request.get(
|
||||
'main.contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id=fake_uuid,
|
||||
)
|
||||
assert normalize_spaces(page.select_one('h1').text) == (
|
||||
'EmergencyContactList.xls'
|
||||
)
|
||||
assert normalize_spaces(page.select('main p')[0].text) == (
|
||||
'Uploaded by Test User today at 10:59am'
|
||||
)
|
||||
assert normalize_spaces(page.select('main p')[1].text) == (
|
||||
'Download this list 51 email addresses'
|
||||
)
|
||||
assert page.select_one('a[download]')['href'] == url_for(
|
||||
'main.download_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id=fake_uuid,
|
||||
)
|
||||
assert normalize_spaces(page.select_one('table').text).startswith(
|
||||
'Email addresses '
|
||||
'1 email address '
|
||||
'2 test@example.com '
|
||||
'3 test@example.com '
|
||||
)
|
||||
assert normalize_spaces(page.select_one('table').text).endswith(
|
||||
'50 test@example.com '
|
||||
'51 test@example.com'
|
||||
)
|
||||
assert normalize_spaces(page.select_one('.table-show-more-link').text) == (
|
||||
'Only showing the first 50 rows'
|
||||
)
|
||||
|
||||
|
||||
def test_view_contact_list_404s_for_non_existing_list(
|
||||
client_request,
|
||||
mock_get_no_contact_list,
|
||||
fake_uuid,
|
||||
):
|
||||
client_request.get(
|
||||
'main.contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id=uuid.uuid4(),
|
||||
_expected_status=404,
|
||||
)
|
||||
|
||||
|
||||
def test_download_contact_list(
|
||||
mocker,
|
||||
logged_in_client,
|
||||
fake_uuid,
|
||||
mock_get_contact_list,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.models.contact_list.s3download',
|
||||
return_value='phone number\n07900900321'
|
||||
)
|
||||
response = logged_in_client.get(url_for(
|
||||
'main.download_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id=fake_uuid,
|
||||
))
|
||||
assert response.status_code == 200
|
||||
assert response.headers['Content-Type'] == (
|
||||
'text/csv; '
|
||||
'charset=utf-8'
|
||||
)
|
||||
assert response.headers['Content-Disposition'] == (
|
||||
'attachment; '
|
||||
'filename=EmergencyContactList.csv'
|
||||
)
|
||||
assert response.get_data(as_text=True) == (
|
||||
'phone number\n'
|
||||
'07900900321'
|
||||
)
|
||||
|
||||
|
||||
def test_confirm_delete_contact_list(
|
||||
mocker,
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_get_contact_list,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.models.contact_list.s3download',
|
||||
return_value='phone number\n07900900321'
|
||||
)
|
||||
page = client_request.get(
|
||||
'main.delete_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id=fake_uuid,
|
||||
)
|
||||
assert normalize_spaces(page.select_one('.banner-dangerous').text) == (
|
||||
'Are you sure you want to delete ‘EmergencyContactList.xls’? '
|
||||
'Yes, delete'
|
||||
)
|
||||
assert 'action' not in page.select_one('form')
|
||||
assert page.select_one('form')['method'] == 'post'
|
||||
assert page.select_one('form button')['type'] == 'submit'
|
||||
|
||||
|
||||
def test_delete_contact_list(
|
||||
mocker,
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_get_contact_list,
|
||||
):
|
||||
mock_delete = mocker.patch(
|
||||
'app.models.contact_list.contact_list_api_client.delete_contact_list'
|
||||
)
|
||||
client_request.post(
|
||||
'main.delete_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id=fake_uuid,
|
||||
_expected_redirect=url_for(
|
||||
'main.uploads',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_external=True,
|
||||
)
|
||||
)
|
||||
mock_delete.assert_called_once_with(
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id=fake_uuid,
|
||||
)
|
||||
|
||||
@@ -50,6 +50,21 @@ def test_client_schedules_job(mocker, fake_uuid):
|
||||
assert mock_post.call_args[1]['data']['scheduled_for'] == when
|
||||
|
||||
|
||||
def test_client_links_job_to_contact_list(mocker, fake_uuid):
|
||||
|
||||
mocker.patch('app.notify_client.current_user', id='1')
|
||||
|
||||
contact_list_id = uuid.uuid4()
|
||||
|
||||
mock_post = mocker.patch('app.notify_client.job_api_client.JobApiClient.post')
|
||||
|
||||
JobApiClient().create_job(
|
||||
fake_uuid, 1, contact_list_id=contact_list_id
|
||||
)
|
||||
|
||||
assert mock_post.call_args[1]['data']['contact_list_id'] == contact_list_id
|
||||
|
||||
|
||||
def test_client_gets_job_by_service_and_job(mocker):
|
||||
service_id = 'service_id'
|
||||
job_id = 'job_id'
|
||||
|
||||
@@ -335,6 +335,25 @@ def test_client_returns_count_of_service_templates(
|
||||
],
|
||||
{'data_from': 'api'},
|
||||
),
|
||||
(
|
||||
service_api_client.get_returned_letter_statistics,
|
||||
[SERVICE_ONE_ID],
|
||||
[
|
||||
call('service-{}-returned-letters-statistics'.format(SERVICE_ONE_ID))
|
||||
],
|
||||
None,
|
||||
[
|
||||
call('service/{}/returned-letter-statistics'.format(SERVICE_ONE_ID))
|
||||
],
|
||||
[
|
||||
call(
|
||||
'service-{}-returned-letters-statistics'.format(SERVICE_ONE_ID),
|
||||
'{"data_from": "api"}',
|
||||
ex=604800,
|
||||
)
|
||||
],
|
||||
{'data_from': 'api'},
|
||||
),
|
||||
]
|
||||
)
|
||||
def test_returns_value_from_cache(
|
||||
|
||||
@@ -12,7 +12,7 @@ def test_sets_metadata(client, mocker):
|
||||
|
||||
set_metadata_on_csv_upload('1234', '5678', foo='bar', baz=True)
|
||||
|
||||
mocked_get_s3_object.assert_called_once_with('1234', '5678')
|
||||
mocked_get_s3_object.assert_called_once_with('1234', '5678', bucket=None)
|
||||
mocked_s3_object.copy_from.assert_called_once_with(
|
||||
CopySource='test-notifications-csv-upload/service-1234-notify/5678.csv',
|
||||
Metadata={'baz': 'True', 'foo': 'bar'},
|
||||
|
||||
@@ -191,7 +191,7 @@ def test_caseworkers_get_caseworking_navigation(
|
||||
)
|
||||
page = client_request.get('main.choose_template', service_id=SERVICE_ONE_ID)
|
||||
assert normalize_spaces(page.select_one('header + .govuk-width-container nav').text) == (
|
||||
'Templates Sent messages Team members'
|
||||
'Templates Sent messages Uploads Team members'
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user