mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-18 05:29:38 -04:00
Remove contact-list references from code
This commit is contained in:
@@ -6,13 +6,11 @@ from io import BytesIO
|
||||
from itertools import repeat
|
||||
from os import path
|
||||
from random import randbytes
|
||||
from unittest.mock import ANY
|
||||
from uuid import uuid4
|
||||
from zipfile import BadZipFile
|
||||
|
||||
import pytest
|
||||
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 SMSPreviewTemplate
|
||||
@@ -1034,7 +1032,6 @@ def test_send_one_off_step_redirects_to_start_if_session_not_setup(
|
||||
mock_get_service_statistics,
|
||||
mock_get_users_by_service,
|
||||
mock_has_no_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
fake_uuid,
|
||||
template_type,
|
||||
):
|
||||
@@ -1093,7 +1090,6 @@ def test_send_one_off_has_correct_page_title(
|
||||
client_request,
|
||||
service_one,
|
||||
mock_has_no_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
fake_uuid,
|
||||
mocker,
|
||||
user,
|
||||
@@ -1135,7 +1131,6 @@ def test_send_one_off_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,
|
||||
step_index,
|
||||
prefilled,
|
||||
@@ -1180,7 +1175,6 @@ 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,
|
||||
@@ -1221,7 +1215,6 @@ def test_send_one_off_has_sticky_header_for_email(
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_has_no_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
template_type,
|
||||
expected_sticky,
|
||||
):
|
||||
@@ -1249,7 +1242,6 @@ 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,
|
||||
):
|
||||
@@ -1279,7 +1271,6 @@ def test_send_one_off_offers_link_to_upload(
|
||||
fake_uuid,
|
||||
mock_get_service_template,
|
||||
mock_has_jobs,
|
||||
mock_get_no_contact_lists,
|
||||
user,
|
||||
):
|
||||
client_request.login(user)
|
||||
@@ -1307,7 +1298,6 @@ 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(
|
||||
@@ -1328,14 +1318,6 @@ def test_send_one_off_has_link_to_use_existing_list(
|
||||
template_id=fake_uuid,
|
||||
),
|
||||
),
|
||||
(
|
||||
'Use an emergency list',
|
||||
url_for(
|
||||
'main.choose_from_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
template_id=fake_uuid,
|
||||
),
|
||||
),
|
||||
(
|
||||
'Use my phone number',
|
||||
url_for(
|
||||
@@ -1347,33 +1329,6 @@ def test_send_one_off_has_link_to_use_existing_list(
|
||||
]
|
||||
|
||||
|
||||
def test_no_link_to_use_existing_list_for_service_without_lists(
|
||||
mocker,
|
||||
client_request,
|
||||
mock_get_service_template,
|
||||
mock_has_jobs,
|
||||
platform_admin_user,
|
||||
fake_uuid,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.models.contact_list.ContactLists.client_method',
|
||||
return_value=[],
|
||||
)
|
||||
client_request.login(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(),
|
||||
@@ -1590,7 +1545,6 @@ def test_send_one_off_step_0_back_link(
|
||||
mock_get_service,
|
||||
mock_get_service_template_with_placeholders,
|
||||
mock_has_no_jobs,
|
||||
mock_get_contact_lists,
|
||||
permissions,
|
||||
expected_back_link_endpoint,
|
||||
extra_args,
|
||||
@@ -1671,7 +1625,6 @@ def test_send_one_off_sms_message_puts_submitted_data_in_session(
|
||||
mock_get_service_template_with_placeholders,
|
||||
mock_get_users_by_service,
|
||||
mock_get_service_statistics,
|
||||
mock_get_contact_lists,
|
||||
fake_uuid,
|
||||
):
|
||||
with client_request.session_transaction() as session:
|
||||
@@ -1847,32 +1800,6 @@ def test_upload_csvfile_with_international_validates(
|
||||
assert mock_recipients.call_args[1]['allow_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_get_metadata,
|
||||
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,
|
||||
@@ -1932,9 +1859,6 @@ 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,
|
||||
@@ -1945,7 +1869,6 @@ def test_create_job_should_call_api(
|
||||
mocker,
|
||||
fake_uuid,
|
||||
when,
|
||||
contact_list_id,
|
||||
):
|
||||
data = mock_get_job(SERVICE_ONE_ID, fake_uuid)['data']
|
||||
job_id = data['id']
|
||||
@@ -1968,7 +1891,6 @@ def test_create_job_should_call_api(
|
||||
original_file_name=original_file_name,
|
||||
_data={
|
||||
'scheduled_for': when,
|
||||
'contact_list_id': contact_list_id,
|
||||
},
|
||||
_follow_redirects=True,
|
||||
_expected_status=200,
|
||||
@@ -1980,7 +1902,6 @@ def test_create_job_should_call_api(
|
||||
job_id,
|
||||
SERVICE_ONE_ID,
|
||||
scheduled_for=when,
|
||||
contact_list_id=str(contact_list_id),
|
||||
)
|
||||
|
||||
|
||||
@@ -2724,7 +2645,6 @@ 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,
|
||||
@@ -2777,7 +2697,6 @@ 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,
|
||||
@@ -2838,163 +2757,6 @@ def test_redirects_to_template_if_job_exists_already(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize((
|
||||
'template_type, '
|
||||
'expected_list_id, '
|
||||
'expected_filenames, '
|
||||
'expected_time, '
|
||||
'expected_count'
|
||||
), (
|
||||
(
|
||||
'email',
|
||||
'6ce466d0-fd6a-11e5-82f5-e0accb9d11a6',
|
||||
['EmergencyContactList.xls'],
|
||||
'Uploaded today at 5:59am',
|
||||
'100 email addresses',
|
||||
),
|
||||
(
|
||||
'sms',
|
||||
'd7b0bd1a-d1c7-4621-be5c-3c1b4278a2ad',
|
||||
['phone number list.csv', 'UnusedList.tsv'],
|
||||
'Uploaded today at 8:00am',
|
||||
'123 phone numbers',
|
||||
),
|
||||
))
|
||||
@freeze_time('2020-06-13 13:00')
|
||||
def test_choose_from_contact_list(
|
||||
mocker,
|
||||
client_request,
|
||||
mock_get_contact_lists,
|
||||
fake_uuid,
|
||||
template_type,
|
||||
expected_list_id,
|
||||
expected_filenames,
|
||||
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 [
|
||||
normalize_spaces(filename.text)
|
||||
for filename in page.select('.file-list-filename-large')
|
||||
] == expected_filenames
|
||||
|
||||
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 an emergency contact list with this template because '
|
||||
'it is personalized with ((name)) and ((thing)).',
|
||||
'Emergency contact lists can only include 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 an emergency 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')
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="Need to figure out how to handle cross-bucket copies.")
|
||||
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.get_s3_contents', return_value='contents')
|
||||
mock_get_metadata = mocker.patch('app.models.contact_list.get_s3_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,
|
||||
contact_list_id=fake_uuid,
|
||||
)
|
||||
)
|
||||
mock_download.assert_called_once()
|
||||
mock_get_metadata.assert_called_once()
|
||||
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'
|
||||
)
|
||||
|
||||
|
||||
def test_send_to_myself_sets_placeholder_and_redirects_for_email(
|
||||
mocker, client_request, fake_uuid, mock_get_service_email_template
|
||||
):
|
||||
|
||||
@@ -1,714 +0,0 @@
|
||||
import uuid
|
||||
from io import BytesIO
|
||||
from unittest.mock import ANY
|
||||
|
||||
import pytest
|
||||
from flask import url_for
|
||||
from freezegun import freeze_time
|
||||
|
||||
from app.formatters import normalize_spaces
|
||||
from tests import contact_list_json
|
||||
from tests.conftest import SERVICE_ONE_ID
|
||||
|
||||
|
||||
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 page.select_one('form input')['accept'] == '.csv,.xlsx,.xls,.ods,.xlsm,.tsv'
|
||||
|
||||
assert normalize_spaces(page.select('.spreadsheet')[0].text) == (
|
||||
'Example A '
|
||||
'1 email address '
|
||||
'2 test@example.gsa.gov'
|
||||
)
|
||||
assert normalize_spaces(page.select('.spreadsheet')[1].text) == (
|
||||
'Example A '
|
||||
'1 phone number '
|
||||
'2 555-867-5309'
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('file_contents, expected_error, expected_thead, expected_tbody,', [
|
||||
(
|
||||
"""
|
||||
telephone,name
|
||||
+12028675109
|
||||
""",
|
||||
(
|
||||
'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’.'
|
||||
),
|
||||
'Row in file 1 telephone name',
|
||||
'2 +12028675109',
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number, email address
|
||||
+12028675109, 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’.'
|
||||
),
|
||||
'Row in file 1 phone number email address',
|
||||
'2 +12028675109 test@example.com',
|
||||
),
|
||||
(
|
||||
"""
|
||||
email address
|
||||
+12028675109
|
||||
""",
|
||||
(
|
||||
'There’s a problem with invalid.csv '
|
||||
'You need to fix 1 email address.'
|
||||
),
|
||||
'Row in file 1 email address',
|
||||
'2 Not a valid email address +12028675109',
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number
|
||||
test@example.com
|
||||
""",
|
||||
(
|
||||
'There’s a problem with invalid.csv '
|
||||
'You need to fix 1 phone number.'
|
||||
),
|
||||
'Row in file 1 phone number',
|
||||
'2 The string supplied did not seem to be a phone number. test@example.com',
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number, phone number, PHONE_NUMBER
|
||||
+12027900111,+12027900222,+12027900333,
|
||||
""",
|
||||
(
|
||||
'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’.'
|
||||
),
|
||||
'Row in file 1 phone number phone number PHONE_NUMBER',
|
||||
'2 +12027900333 +12027900333 +12027900333',
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number
|
||||
""",
|
||||
(
|
||||
'Your file is missing some rows '
|
||||
'It needs at least one row of data.'
|
||||
),
|
||||
'Row in file 1 phone number',
|
||||
'',
|
||||
),
|
||||
(
|
||||
"+12028675109",
|
||||
(
|
||||
'Your file is missing some rows '
|
||||
'It needs at least one row of data, in a column called '
|
||||
'‘email address’ or ‘phone number’.'
|
||||
),
|
||||
'Row in file 1 +12028675109',
|
||||
'',
|
||||
),
|
||||
(
|
||||
"",
|
||||
(
|
||||
'Your file is missing some rows '
|
||||
'It needs at least one row of data, in a column called '
|
||||
'‘email address’ or ‘phone number’.'
|
||||
),
|
||||
'Row in file 1',
|
||||
'',
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number
|
||||
+12028675109
|
||||
|
||||
+12028675109
|
||||
""",
|
||||
(
|
||||
'There’s a problem with invalid.csv '
|
||||
'You need to enter missing data in 1 row.'
|
||||
),
|
||||
'Row in file 1 phone number',
|
||||
(
|
||||
'3 Missing'
|
||||
)
|
||||
),
|
||||
(
|
||||
"""
|
||||
phone number
|
||||
+12027900
|
||||
""",
|
||||
(
|
||||
'There’s a problem with invalid.csv '
|
||||
'You need to fix 1 phone number.'
|
||||
),
|
||||
'Row in file 1 phone number',
|
||||
'2 Not enough digits +12027900',
|
||||
),
|
||||
(
|
||||
"""
|
||||
email address
|
||||
ok@example.com
|
||||
bad@example1
|
||||
bad@example2
|
||||
""",
|
||||
(
|
||||
'There’s a problem with invalid.csv '
|
||||
'You need to fix 2 email addresses.'
|
||||
),
|
||||
'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,
|
||||
notify_admin,
|
||||
mock_s3_upload,
|
||||
mock_get_job_doesnt_exist,
|
||||
mock_get_users_by_service,
|
||||
fake_uuid,
|
||||
file_contents,
|
||||
expected_error,
|
||||
expected_thead,
|
||||
expected_tbody,
|
||||
):
|
||||
mocker.patch('app.models.contact_list.uuid4', return_value=fake_uuid)
|
||||
mock_upload = mocker.patch('app.models.contact_list.utils_s3upload')
|
||||
mock_download = mocker.patch(
|
||||
'app.models.contact_list.get_s3_contents',
|
||||
return_value=file_contents,
|
||||
)
|
||||
mock_set_metadata = mocker.patch('app.models.contact_list.set_s3_metadata')
|
||||
mock_get_metadata = mocker.patch(
|
||||
'app.models.contact_list.get_s3_metadata',
|
||||
return_value={'original_file_name': 'invalid.csv'},
|
||||
)
|
||||
|
||||
page = client_request.post(
|
||||
'main.upload_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_data={'file': (BytesIO(''.encode('utf-8')), 'invalid.csv')},
|
||||
_follow_redirects=True,
|
||||
)
|
||||
bucket_creds = notify_admin.config['CONTACT_LIST_BUCKET']
|
||||
mock_upload.assert_called_once_with(
|
||||
filedata='',
|
||||
region=bucket_creds['region'],
|
||||
bucket_name=bucket_creds['bucket'],
|
||||
file_location=f"service-{SERVICE_ONE_ID}-notify/{fake_uuid}.csv",
|
||||
access_key=bucket_creds['access_key_id'],
|
||||
secret_key=bucket_creds['secret_access_key'],
|
||||
)
|
||||
mock_set_metadata.assert_called_once_with(
|
||||
ANY,
|
||||
original_file_name='invalid.csv'
|
||||
)
|
||||
mock_download.assert_called_once()
|
||||
mock_get_metadata.assert_called_once()
|
||||
|
||||
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 page.select_one('form input')['accept'] == '.csv,.xlsx,.xls,.ods,.xlsm,.tsv'
|
||||
|
||||
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.utils_s3upload', return_value=fake_uuid)
|
||||
mocker.patch('app.models.contact_list.set_s3_metadata')
|
||||
mocker.patch('app.models.contact_list.get_s3_contents', return_value='\n'.join(
|
||||
['phone number'] + (['2028675309'] * 100_001)
|
||||
))
|
||||
mocker.patch('app.models.contact_list.get_s3_metadata',
|
||||
return_value={'original_file_name': 'invalid.csv'})
|
||||
|
||||
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 100,000 rows in size. '
|
||||
'Your file has 100,001 rows.'
|
||||
)
|
||||
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_error_with_invalid_extension(
|
||||
client_request,
|
||||
):
|
||||
page = client_request.post(
|
||||
'main.upload_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_data={'file': (BytesIO(''.encode('utf-8')), 'invalid.txt')},
|
||||
_follow_redirects=True,
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select_one('.banner-dangerous').text) == (
|
||||
"invalid.txt is not a spreadsheet that Notify can read"
|
||||
)
|
||||
|
||||
|
||||
def test_upload_csv_file_sanitises_and_truncates_file_name_in_metadata(
|
||||
client_request,
|
||||
mocker,
|
||||
mock_s3_upload,
|
||||
mock_get_job_doesnt_exist,
|
||||
mock_get_users_by_service,
|
||||
fake_uuid,
|
||||
):
|
||||
mocker.patch('app.models.contact_list.utils_s3upload', return_value=fake_uuid)
|
||||
mock_set_metadata = mocker.patch('app.models.contact_list.set_s3_metadata')
|
||||
mocker.patch('app.models.contact_list.get_s3_contents', return_value='\n'.join(
|
||||
['phone number'] + (['2028675309'] * 100_001)
|
||||
))
|
||||
|
||||
filename = f"😁{'a' * 2000}.csv"
|
||||
mocker.patch('app.models.contact_list.get_s3_metadata',
|
||||
return_value={'original_file_name': filename})
|
||||
client_request.post(
|
||||
'main.upload_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_data={'file': (BytesIO(''.encode('utf-8')), filename)},
|
||||
_follow_redirects=False
|
||||
)
|
||||
|
||||
assert len(
|
||||
mock_set_metadata.call_args_list[0][1]['original_file_name']
|
||||
) < len(filename)
|
||||
|
||||
assert mock_set_metadata.call_args_list[0][1]['original_file_name'].startswith('?')
|
||||
|
||||
|
||||
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.utils_s3upload', return_value=fake_uuid)
|
||||
mocker.patch('app.models.contact_list.get_s3_contents', return_value=(
|
||||
'phone number\n'
|
||||
'2028675209' # Not in team
|
||||
))
|
||||
mocker.patch('app.models.contact_list.get_s3_metadata',
|
||||
return_value={'original_file_name': 'invalid.csv'})
|
||||
|
||||
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'
|
||||
)
|
||||
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.get_s3_contents', return_value='\n'.join(
|
||||
['email address'] + ['test@example.com'] * 51
|
||||
))
|
||||
mocker.patch('app.models.contact_list.get_s3_metadata',
|
||||
return_value={'original_file_name': 'good times.xlsx'})
|
||||
mock_metadata_set = mocker.patch('app.models.contact_list.set_s3_metadata')
|
||||
|
||||
page = client_request.get(
|
||||
'main.check_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
upload_id=fake_uuid,
|
||||
_test_page_title=False,
|
||||
)
|
||||
|
||||
mock_metadata_set.assert_called_once_with(
|
||||
mocker.ANY,
|
||||
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_s3_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,
|
||||
)
|
||||
)
|
||||
mock_get_metadata.assert_called_once()
|
||||
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_s3_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
|
||||
|
||||
|
||||
@pytest.mark.parametrize('has_jobs, expected_empty_message', [
|
||||
(False, 'Not used yet.'),
|
||||
(True, 'Not used in the last 7 days.'),
|
||||
])
|
||||
@freeze_time('2020-06-13 16:51:56')
|
||||
def test_view_contact_list(
|
||||
mocker,
|
||||
client_request,
|
||||
mock_get_contact_list,
|
||||
mock_get_no_jobs,
|
||||
mock_get_service_data_retention,
|
||||
fake_uuid,
|
||||
has_jobs,
|
||||
expected_empty_message,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.models.contact_list.contact_list_api_client.get_contact_list',
|
||||
return_value=contact_list_json(
|
||||
created_at='2020-03-03T17:12:12.000000Z',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
has_jobs=has_jobs
|
||||
)
|
||||
)
|
||||
mocker.patch('app.models.contact_list.get_s3_contents', return_value='\n'.join(
|
||||
['email address'] + [
|
||||
f'test-{i}@example.com' for i in range(51)
|
||||
]
|
||||
))
|
||||
page = client_request.get(
|
||||
'main.contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id=fake_uuid,
|
||||
)
|
||||
mock_get_no_jobs.assert_called_once_with(
|
||||
SERVICE_ONE_ID,
|
||||
contact_list_id=fake_uuid,
|
||||
limit_days=7,
|
||||
statuses={
|
||||
'finished',
|
||||
'in progress',
|
||||
'pending',
|
||||
'ready to send',
|
||||
'scheduled',
|
||||
'sending limits exceeded',
|
||||
'sent to dvla',
|
||||
},
|
||||
page=1,
|
||||
)
|
||||
assert normalize_spaces(page.select_one('h1').text) == (
|
||||
'EmergencyContactList.xls'
|
||||
)
|
||||
assert normalize_spaces(page.select('main p')[0].text) == (
|
||||
'Uploaded by Test User on 3 March at 12:12pm.'
|
||||
)
|
||||
assert normalize_spaces(page.select('main p')[1].text) == (
|
||||
expected_empty_message
|
||||
)
|
||||
assert normalize_spaces(page.select_one('main h2').text) == (
|
||||
'51 saved email addresses'
|
||||
)
|
||||
assert page.select_one('.js-stick-at-bottom-when-scrolling a[download]')['href'] == url_for(
|
||||
'main.download_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id=fake_uuid,
|
||||
)
|
||||
assert len(page.select('tbody tr')) == 50
|
||||
assert [
|
||||
normalize_spaces(page.select('tbody tr')[0].text),
|
||||
normalize_spaces(page.select('tbody tr')[1].text),
|
||||
|
||||
normalize_spaces(page.select('tbody tr')[48].text),
|
||||
normalize_spaces(page.select('tbody tr')[49].text),
|
||||
] == [
|
||||
'test-0@example.com',
|
||||
'test-1@example.com',
|
||||
|
||||
'test-48@example.com',
|
||||
'test-49@example.com',
|
||||
]
|
||||
assert 'test-50@example.com' not in page.select_one('tbody').text
|
||||
assert normalize_spaces(page.select_one('.table-show-more-link').text) == (
|
||||
'Only showing the first 50 rows'
|
||||
)
|
||||
|
||||
|
||||
@freeze_time('2015-12-31 21:51:56')
|
||||
def test_view_jobs_for_contact_list(
|
||||
mocker,
|
||||
client_request,
|
||||
mock_get_jobs,
|
||||
mock_get_service_data_retention,
|
||||
fake_uuid,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.models.contact_list.contact_list_api_client.get_contact_list',
|
||||
return_value={
|
||||
'created_at': '2015-12-31 17:12:12',
|
||||
'created_by': 'Test User',
|
||||
'id': fake_uuid,
|
||||
'original_file_name': 'EmergencyContactList.xls',
|
||||
'row_count': 100,
|
||||
'recent_job_count': 0,
|
||||
'has_jobs': True,
|
||||
'service_id': SERVICE_ONE_ID,
|
||||
'template_type': 'email',
|
||||
},
|
||||
)
|
||||
mocker.patch('app.models.contact_list.get_s3_contents', 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 12:12pm.'
|
||||
)
|
||||
assert normalize_spaces(page.select('main p')[1].text) == (
|
||||
'Used 6 times in the last 7 days.'
|
||||
)
|
||||
assert [
|
||||
normalize_spaces(row.text)
|
||||
for row in page.select_one('table').select('tr')
|
||||
] == [
|
||||
'Template Status',
|
||||
(
|
||||
'Template Y '
|
||||
'Sending tomorrow at 6:09pm '
|
||||
'1 text message waiting to send'
|
||||
),
|
||||
(
|
||||
'Template Z '
|
||||
'Sending tomorrow at 6:09am '
|
||||
'1 text message waiting to send'
|
||||
),
|
||||
(
|
||||
'Template A '
|
||||
'Sent today at 4:51pm '
|
||||
'1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'Template B '
|
||||
'Sent today at 4:51pm '
|
||||
'1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'Template C '
|
||||
'Sent today at 4:51pm '
|
||||
'1 sending 0 delivered 0 failed'
|
||||
),
|
||||
(
|
||||
'Template D '
|
||||
'Sent today at 4:51pm '
|
||||
'1 sending 0 delivered 0 failed'
|
||||
),
|
||||
]
|
||||
assert page.select_one('table a')['href'] == url_for(
|
||||
'main.view_job',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
job_id=fake_uuid,
|
||||
)
|
||||
|
||||
|
||||
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,
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_get_contact_list,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.models.contact_list.get_s3_contents',
|
||||
return_value='phone number\n2028675209'
|
||||
)
|
||||
response = client_request.get_response(
|
||||
'main.download_contact_list',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id=fake_uuid,
|
||||
)
|
||||
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'
|
||||
'2028675209'
|
||||
)
|
||||
|
||||
|
||||
def test_confirm_delete_contact_list(
|
||||
mocker,
|
||||
client_request,
|
||||
fake_uuid,
|
||||
mock_get_jobs,
|
||||
mock_get_service_data_retention,
|
||||
mock_get_contact_list,
|
||||
):
|
||||
mocker.patch(
|
||||
'app.models.contact_list.get_s3_contents',
|
||||
return_value='phone number\n2028675209'
|
||||
)
|
||||
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,
|
||||
)
|
||||
)
|
||||
mock_delete.assert_called_once_with(
|
||||
service_id=SERVICE_ONE_ID,
|
||||
contact_list_id=fake_uuid,
|
||||
)
|
||||
@@ -1,7 +1,4 @@
|
||||
import re
|
||||
|
||||
import pytest
|
||||
from flask import url_for
|
||||
from freezegun import freeze_time
|
||||
|
||||
from app.formatters import normalize_spaces
|
||||
@@ -9,31 +6,9 @@ from tests.conftest import (
|
||||
SERVICE_ONE_ID,
|
||||
create_active_caseworking_user,
|
||||
create_active_user_with_permissions,
|
||||
create_platform_admin_user,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="Not sure that TTS needs this")
|
||||
@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', (
|
||||
([], (
|
||||
'You have not uploaded any files recently.'
|
||||
@@ -44,7 +19,6 @@ 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,
|
||||
):
|
||||
@@ -63,7 +37,6 @@ 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': []})
|
||||
page = client_request.get('main.uploads', service_id=SERVICE_ONE_ID)
|
||||
@@ -93,7 +66,6 @@ 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)
|
||||
@@ -117,53 +89,3 @@ 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,
|
||||
mock_get_service_data_retention,
|
||||
):
|
||||
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 '
|
||||
'Used twice in the last 7 days '
|
||||
'123 saved phone numbers'
|
||||
),
|
||||
(
|
||||
'EmergencyContactList.xls '
|
||||
'Not used in the last 7 days '
|
||||
'100 saved email addresses'
|
||||
),
|
||||
(
|
||||
'UnusedList.tsv '
|
||||
'Not used yet '
|
||||
'1 saved phone number'
|
||||
),
|
||||
(
|
||||
'even_later.csv '
|
||||
'Sending 1 January 2016 at 6:09pm '
|
||||
'1 text message waiting to send'
|
||||
),
|
||||
(
|
||||
'send_me_later.csv '
|
||||
'Sending 1 January 2016 at 6: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',
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user