mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-30 11:19:44 -04:00
Merge with master
This commit is contained in:
79
tests/app/main/test_errors_for_csv.py
Normal file
79
tests/app/main/test_errors_for_csv.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from collections import namedtuple
|
||||
|
||||
import pytest
|
||||
|
||||
from app.utils import get_errors_for_csv
|
||||
|
||||
|
||||
MockRecipients = namedtuple(
|
||||
'RecipientCSV',
|
||||
[
|
||||
'missing_column_headers',
|
||||
'rows_with_bad_recipients',
|
||||
'rows_with_missing_data'
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"missing_column_headers,rows_with_bad_recipients,rows_with_missing_data,template_type,expected_errors",
|
||||
[
|
||||
(
|
||||
[], [], [],
|
||||
'sms',
|
||||
[]
|
||||
),
|
||||
(
|
||||
[], {2}, [],
|
||||
'sms',
|
||||
['fix 1 phone number']
|
||||
),
|
||||
(
|
||||
[], {2, 4, 6}, [],
|
||||
'sms',
|
||||
['fix 3 phone numbers']
|
||||
),
|
||||
(
|
||||
[], {1}, [],
|
||||
'email',
|
||||
['fix 1 email address']
|
||||
),
|
||||
(
|
||||
[], {2, 4, 6}, [],
|
||||
'email',
|
||||
['fix 3 email addresses']
|
||||
),
|
||||
(
|
||||
['name'], {2}, {3},
|
||||
'sms',
|
||||
[
|
||||
'add a column called ‘name’',
|
||||
'fix 1 phone number',
|
||||
'fill in 1 empty cell'
|
||||
]
|
||||
),
|
||||
(
|
||||
['name', 'date'], [], [],
|
||||
'sms',
|
||||
['add 2 columns, ‘name’ and ‘date’']
|
||||
),
|
||||
(
|
||||
['name', 'date', 'time'], {2, 4, 6, 8}, {3, 6, 9, 12},
|
||||
'sms',
|
||||
[
|
||||
'add columns called ‘name’, ‘date’, and ‘time’',
|
||||
'fix 4 phone numbers',
|
||||
'fill in 4 empty cells'
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
def test_get_errors_for_csv(
|
||||
missing_column_headers, rows_with_bad_recipients, rows_with_missing_data,
|
||||
template_type,
|
||||
expected_errors
|
||||
):
|
||||
assert get_errors_for_csv(
|
||||
MockRecipients(missing_column_headers, rows_with_bad_recipients, rows_with_missing_data),
|
||||
template_type
|
||||
) == expected_errors
|
||||
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
from flask import url_for
|
||||
|
||||
from app.utils import user_has_permissions, validate_header_row, validate_recipient, InvalidHeaderError
|
||||
from app.utils import user_has_permissions
|
||||
from app.main.views.index import index
|
||||
from werkzeug.exceptions import Forbidden
|
||||
|
||||
@@ -58,9 +58,13 @@ def test_user_has_permissions_multiple(app_,
|
||||
response = decorated_index()
|
||||
|
||||
|
||||
def test_validate_header_row():
|
||||
row = {'bad': '+44 7700 900981'}
|
||||
try:
|
||||
validate_header_row(row, 'sms')
|
||||
except InvalidHeaderError as e:
|
||||
assert e.message == 'Invalid header name, should be phone number'
|
||||
def test_exact_permissions(app_,
|
||||
api_user_active,
|
||||
mock_login,
|
||||
mock_get_user_with_permissions):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
client.login(api_user_active)
|
||||
decorator = user_has_permissions('manage_users', 'manage_templates', 'manage_settings')
|
||||
decorated_index = decorator(index)
|
||||
response = decorated_index()
|
||||
@@ -1,75 +0,0 @@
|
||||
import pytest
|
||||
from wtforms import Form
|
||||
from app.main.forms import UKMobileNumber
|
||||
|
||||
|
||||
class FormExample(Form):
|
||||
phone_number = UKMobileNumber()
|
||||
|
||||
invalid_phone_numbers = sum([
|
||||
[
|
||||
(phone_number, error) for phone_number in group
|
||||
] for error, group in [
|
||||
('Too many digits', (
|
||||
'0712345678910',
|
||||
'0044712345678910',
|
||||
'0044712345678910',
|
||||
'+44 (0)7123 456 789 10',
|
||||
)),
|
||||
('Not enough digits', (
|
||||
'0712345678',
|
||||
'004471234567',
|
||||
'00447123456',
|
||||
'+44 (0)7123 456 78',
|
||||
)),
|
||||
('Must be a UK mobile number (eg 07700 900460)', (
|
||||
'08081 570364',
|
||||
'+44 8081 570364',
|
||||
'0117 496 0860',
|
||||
'+44 117 496 0860',
|
||||
'020 7946 0991',
|
||||
'+44 20 7946 0991',
|
||||
'71234567890',
|
||||
)),
|
||||
('Must not contain letters or symbols', (
|
||||
'07890x32109',
|
||||
'07123 456789...',
|
||||
'07123 ☟☜⬇⬆☞☝',
|
||||
'07123☟☜⬇⬆☞☝',
|
||||
'07";DROP TABLE;"',
|
||||
'+44 07ab cde fgh',
|
||||
))
|
||||
]
|
||||
], [])
|
||||
|
||||
valid_phone_numbers = [
|
||||
'07123456789',
|
||||
'07123 456789',
|
||||
'07123-456-789',
|
||||
'00447123456789',
|
||||
'00 44 7123456789',
|
||||
'+447123456789',
|
||||
'+44 7123 456 789',
|
||||
'+44 (0)7123 456 789'
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("phone_number", valid_phone_numbers)
|
||||
def test_phone_number_accepts_valid_values(phone_number):
|
||||
form = FormExample(phone_number=phone_number)
|
||||
form.validate()
|
||||
assert form.errors == {}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("phone_number, error_message", invalid_phone_numbers)
|
||||
def test_phone_number_rejects_invalid_values(phone_number, error_message):
|
||||
form = FormExample(phone_number=phone_number)
|
||||
form.validate()
|
||||
assert form.phone_number.errors[0] == error_message
|
||||
|
||||
|
||||
@pytest.mark.parametrize("phone_number", valid_phone_numbers)
|
||||
def test_phone_number_outputs_in_correct_format(phone_number):
|
||||
form = FormExample(phone_number=phone_number)
|
||||
form.validate()
|
||||
assert form.phone_number.data == '+447123456789'
|
||||
@@ -1,68 +0,0 @@
|
||||
from app.utils import (
|
||||
validate_phone_number,
|
||||
InvalidPhoneError
|
||||
)
|
||||
|
||||
import pytest
|
||||
|
||||
valid_phone_numbers = [
|
||||
'07123456789',
|
||||
'07123 456789',
|
||||
'07123-456-789',
|
||||
'00447123456789',
|
||||
'00 44 7123456789',
|
||||
'+447123456789',
|
||||
'+44 7123 456 789',
|
||||
'+44 (0)7123 456 789'
|
||||
]
|
||||
|
||||
invalid_phone_numbers = sum([
|
||||
[
|
||||
(phone_number, error) for phone_number in group
|
||||
] for error, group in [
|
||||
('Too many digits', (
|
||||
'0712345678910',
|
||||
'0044712345678910',
|
||||
'0044712345678910',
|
||||
'+44 (0)7123 456 789 10',
|
||||
)),
|
||||
('Not enough digits', (
|
||||
'0712345678',
|
||||
'004471234567',
|
||||
'00447123456',
|
||||
'+44 (0)7123 456 78',
|
||||
)),
|
||||
('Must be a UK mobile number (eg 07700 900460)', (
|
||||
'08081 570364',
|
||||
'+44 8081 570364',
|
||||
'0117 496 0860',
|
||||
'+44 117 496 0860',
|
||||
'020 7946 0991',
|
||||
'+44 20 7946 0991',
|
||||
'71234567890',
|
||||
)),
|
||||
('Must not contain letters or symbols', (
|
||||
'07890x32109',
|
||||
'07123 456789...',
|
||||
'07123 ☟☜⬇⬆☞☝',
|
||||
'07123☟☜⬇⬆☞☝',
|
||||
'07";DROP TABLE;"',
|
||||
'+44 07ab cde fgh',
|
||||
))
|
||||
]
|
||||
], [])
|
||||
|
||||
|
||||
@pytest.mark.parametrize("phone_number", valid_phone_numbers)
|
||||
def test_phone_number_accepts_valid_values(phone_number):
|
||||
try:
|
||||
validate_phone_number(phone_number)
|
||||
except InvalidPhoneError:
|
||||
pytest.fail('Unexpected InvalidPhoneError')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("phone_number, error_message", invalid_phone_numbers)
|
||||
def test_phone_number_rejects_invalid_values(phone_number, error_message):
|
||||
with pytest.raises(InvalidPhoneError) as e:
|
||||
validate_phone_number(phone_number)
|
||||
assert error_message == str(e.value)
|
||||
@@ -58,6 +58,10 @@ def test_existing_signed_out_user_accept_invite_redirects_to_sign_in(app_,
|
||||
assert response.status_code == 200
|
||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||
assert page.h1.string.strip() == 'Sign in'
|
||||
flash_banners = page.find_all('div', class_='banner-default')
|
||||
assert len(flash_banners) == 2
|
||||
assert flash_banners[0].text.strip() == 'Please log in to access this page.'
|
||||
assert flash_banners[1].text.strip() == 'You already have an account with GOV.UK Notify. Sign in to your account to accept this invitation.' # noqa
|
||||
|
||||
|
||||
def test_new_user_accept_invite_calls_api_and_redirects_to_registration(app_,
|
||||
@@ -100,14 +104,17 @@ def test_new_user_accept_invite_calls_api_and_views_registration_page(app_,
|
||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||
assert page.h1.string.strip() == 'Create an account'
|
||||
|
||||
email_in_page = page.find('p')
|
||||
assert email_in_page.text.strip() == 'Your account will be created with this email: invited_user@test.gov.uk' # noqa
|
||||
|
||||
form = page.find('form')
|
||||
email = form.find('input', id='email_address')
|
||||
name = form.find('input', id='name')
|
||||
password = form.find('input', id='password')
|
||||
service = form.find('input', type='hidden', id='service')
|
||||
email = form.find('input', type='hidden', id='email_address')
|
||||
|
||||
assert email
|
||||
assert email.attrs['disabled']
|
||||
assert email.attrs['value'] == 'invited_user@test.gov.uk'
|
||||
assert name
|
||||
assert password
|
||||
assert service
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from flask import url_for
|
||||
|
||||
import app
|
||||
|
||||
|
||||
def test_should_render_forgot_password(app_):
|
||||
with app_.test_request_context():
|
||||
@@ -9,14 +11,12 @@ def test_should_render_forgot_password(app_):
|
||||
in response.get_data(as_text=True)
|
||||
|
||||
|
||||
def test_should_redirect_to_password_reset_sent_and_state_updated(
|
||||
app_,
|
||||
api_user_active,
|
||||
mock_get_user_by_email,
|
||||
mock_update_user,
|
||||
mock_send_email
|
||||
):
|
||||
def test_should_redirect_to_password_reset_sent_for_valid_email(
|
||||
app_,
|
||||
api_user_active,
|
||||
mocker):
|
||||
with app_.test_request_context():
|
||||
mocker.patch('app.user_api_client.send_reset_password_url', return_value=None)
|
||||
response = app_.test_client().post(
|
||||
url_for('.forgot_password'),
|
||||
data={'email_address': api_user_active.email_address})
|
||||
@@ -24,23 +24,4 @@ def test_should_redirect_to_password_reset_sent_and_state_updated(
|
||||
assert (
|
||||
'You have been sent an email containing a link'
|
||||
' to reset your password.') in response.get_data(as_text=True)
|
||||
assert mock_send_email.call_count == 1
|
||||
|
||||
|
||||
def test_should_redirect_to_password_reset_sent_for_non_existant_email_address(
|
||||
app_,
|
||||
api_user_active,
|
||||
mock_dont_get_user_by_email,
|
||||
mock_update_user,
|
||||
mock_send_email
|
||||
):
|
||||
with app_.test_request_context():
|
||||
response = app_.test_client().post(
|
||||
url_for('.forgot_password'),
|
||||
data={'email_address': 'nope@example.gov.uk'})
|
||||
assert response.status_code == 200
|
||||
assert (
|
||||
'You have been sent an email containing a link'
|
||||
' to reset your password.') in response.get_data(as_text=True)
|
||||
mock_dont_get_user_by_email.assert_called_once_with('nope@example.gov.uk')
|
||||
assert not mock_send_email.called
|
||||
app.user_api_client.send_reset_password_url.assert_called_once_with(api_user_active.email_address)
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
from flask import url_for
|
||||
|
||||
from app.main.dao import users_dao
|
||||
from app.main.encryption import check_hash
|
||||
from app.notify_client.sender import generate_token
|
||||
|
||||
import pytest
|
||||
from utils.url_safe_token import generate_token
|
||||
|
||||
|
||||
def test_should_render_new_password_template(app_,
|
||||
@@ -14,59 +12,62 @@ def test_should_render_new_password_template(app_,
|
||||
mock_get_user_by_email_request_password_reset):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
token = generate_token(api_user_active.email_address)
|
||||
data = json.dumps({'email': api_user_active.email_address, 'created_at': str(datetime.now())})
|
||||
token = generate_token(data, app_.config['SECRET_KEY'],
|
||||
app_.config['DANGEROUS_SALT'])
|
||||
response = client.get(url_for('.new_password', token=token))
|
||||
assert response.status_code == 200
|
||||
assert 'You can now create a new password for your account.' in response.get_data(as_text=True)
|
||||
|
||||
|
||||
@pytest.mark.skipif(True, reason='Password reset no implemented')
|
||||
def test_should_render_new_password_template_with_message_of_bad_token(app_,
|
||||
mock_get_user_by_email):
|
||||
def test_should_return_404_when_email_address_does_not_exist(app_, mock_get_user_by_email_not_found):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
token = generate_token('no_user@d.gov.uk')
|
||||
data = json.dumps({'email': 'no_user@d.gov.uk', 'created_at': str(datetime.now())})
|
||||
token = generate_token(data, app_.config['SECRET_KEY'], app_.config['DANGEROUS_SALT'])
|
||||
response = client.get(url_for('.new_password', token=token))
|
||||
assert response.status_code == 200
|
||||
assert 'Message about email address does not exist. Some one needs to figure out the words here.' in \
|
||||
response.get_data(as_text=True)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
@pytest.mark.skipif(True, reason='Password reset no implemented')
|
||||
def test_should_redirect_to_two_factor_when_password_reset_is_successful(app_,
|
||||
mock_get_user_by_email_request_password_reset,
|
||||
mock_login):
|
||||
mock_login,
|
||||
mock_send_verify_code):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
user = mock_get_user_by_email_request_password_reset.return_value
|
||||
token = generate_token(user.email_address)
|
||||
data = json.dumps({'email': user.email_address, 'created_at': str(datetime.now())})
|
||||
token = generate_token(data, app_.config['SECRET_KEY'], app_.config['DANGEROUS_SALT'])
|
||||
response = client.post(url_for('.new_password', token=token), data={'new_password': 'a-new_password'})
|
||||
assert response.status_code == 302
|
||||
assert response.location == url_for('.two_factor', _external=True)
|
||||
mock_get_user_by_email_request_password_reset.assert_called_once_with(user.email_address)
|
||||
|
||||
|
||||
def test_should_redirect_index_if_user_has_already_changed_password(app_,
|
||||
mock_get_user_by_email_user_changed_password,
|
||||
mock_login,
|
||||
mock_send_verify_code):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
user = mock_get_user_by_email_user_changed_password.return_value
|
||||
data = json.dumps({'email': user.email_address, 'created_at': str(datetime.now())})
|
||||
token = generate_token(data, app_.config['SECRET_KEY'], app_.config['DANGEROUS_SALT'])
|
||||
response = client.post(url_for('.new_password', token=token), data={'new_password': 'a-new_password'})
|
||||
assert response.status_code == 302
|
||||
assert response.location == url_for('.index', _external=True)
|
||||
mock_get_user_by_email_user_changed_password.assert_called_once_with(user.email_address)
|
||||
|
||||
|
||||
def test_should_redirect_to_forgot_password_with_flash_message_when_token_is_expired(
|
||||
app_, mock_get_user_by_email_request_password_reset, mock_login
|
||||
app_, mock_get_user_by_email_request_password_reset, mock_login
|
||||
):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
app_.config['TOKEN_MAX_AGE_SECONDS'] = -1000
|
||||
user = mock_get_user_by_email_request_password_reset.return_value
|
||||
token = generate_token(user.email_address)
|
||||
token = generate_token(user.email_address, app_.config['SECRET_KEY'], app_.config['DANGEROUS_SALT'])
|
||||
response = client.post(url_for('.new_password', token=token), data={'new_password': 'a-new_password'})
|
||||
assert response.status_code == 302
|
||||
assert response.location == url_for('.forgot_password', _external=True)
|
||||
app_.config['TOKEN_MAX_AGE_SECONDS'] = 3600
|
||||
|
||||
|
||||
@pytest.mark.skipif(True, reason='Password reset no implemented')
|
||||
def test_should_redirect_to_forgot_pass_when_user_active_should_be_request_passw_reset(
|
||||
app_, mock_get_user_by_email_request_password_reset, mock_login
|
||||
):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
user = mock_get_user_by_email_request_password_reset.return_value
|
||||
token = generate_token(user.email_address)
|
||||
response = client.post(url_for('.new_password', token=token), data={'new_password': 'a-new_password'})
|
||||
assert response.status_code == 302
|
||||
assert response.location == url_for('.index', _external=True)
|
||||
|
||||
@@ -55,7 +55,7 @@ def test_process_register_returns_400_when_mobile_number_is_invalid(app_,
|
||||
'password': 'validPassword!'})
|
||||
|
||||
assert response.status_code == 200
|
||||
assert 'Must be a UK mobile number (eg 07700 900460)' in response.get_data(as_text=True)
|
||||
assert 'Must not contain letters or symbols' in response.get_data(as_text=True)
|
||||
|
||||
|
||||
def test_should_return_400_when_email_is_not_gov_uk(app_,
|
||||
|
||||
@@ -34,33 +34,7 @@ def test_choose_template(
|
||||
assert '{} template two content'.format(template_type) in content
|
||||
|
||||
|
||||
def test_upload_empty_csvfile_returns_to_upload_page(
|
||||
app_,
|
||||
api_user_active,
|
||||
mock_login,
|
||||
mock_get_user,
|
||||
mock_get_service,
|
||||
mock_get_service_templates,
|
||||
mock_check_verify_code,
|
||||
mock_get_service_template,
|
||||
mock_has_permissions
|
||||
):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
client.login(api_user_active)
|
||||
upload_data = {'file': (BytesIO(''.encode('utf-8')), 'emtpy.csv')}
|
||||
response = client.post(
|
||||
url_for('main.send_messages', service_id=12345, template_id=54321),
|
||||
data=upload_data,
|
||||
follow_redirects=True
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
content = response.get_data(as_text=True)
|
||||
assert 'The file emtpy.csv contained no data' in content
|
||||
|
||||
|
||||
def test_upload_csvfile_with_invalid_phone_shows_check_page_with_errors(
|
||||
def test_upload_csvfile_with_errors_shows_check_page_with_errors(
|
||||
app_,
|
||||
api_user_active,
|
||||
mocker,
|
||||
@@ -86,43 +60,11 @@ def test_upload_csvfile_with_invalid_phone_shows_check_page_with_errors(
|
||||
)
|
||||
assert response.status_code == 200
|
||||
content = response.get_data(as_text=True)
|
||||
assert 'Your CSV file contained missing or invalid data' in content
|
||||
assert 'There was a problem with invalid.csv' in content
|
||||
assert '+44 123' in content
|
||||
assert '+44 456' in content
|
||||
assert 'Upload a CSV file' in content
|
||||
|
||||
|
||||
def test_upload_csvfile_removes_empty_lines_and_trailing_commas(
|
||||
app_,
|
||||
api_user_active,
|
||||
mocker,
|
||||
mock_login,
|
||||
mock_get_service,
|
||||
mock_get_service_template,
|
||||
mock_s3_upload,
|
||||
mock_has_permissions
|
||||
):
|
||||
|
||||
contents = 'phone number,name,,,\n++44 7700 900981,test1,,,\n+44 7700 900981,test2,,,\n ,,, \n ,,, \t \t \n'
|
||||
file_data = (BytesIO(contents.encode('utf-8')), 'invalid.csv')
|
||||
|
||||
expected_data = {'data': ['phone number,name', '++44 7700 900981,test1', '+44 7700 900981,test2'],
|
||||
'file_name': 'invalid.csv'}
|
||||
|
||||
mocker.patch('app.main.views.send.s3download',
|
||||
return_value='phone number,name\n++44 7700 900981,test1\n+44 7700 900981,test2')
|
||||
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
client.login(api_user_active)
|
||||
upload_data = {'file': file_data}
|
||||
response = client.post(
|
||||
url_for('main.send_messages', service_id=12345, template_id=54321),
|
||||
data=upload_data,
|
||||
follow_redirects=True
|
||||
)
|
||||
assert response.status_code == 200
|
||||
mock_s3_upload.assert_called_with(ANY, '12345', expected_data, 'eu-west-1')
|
||||
assert 'Not a UK mobile number' in content
|
||||
assert 'Re-upload your file' in content
|
||||
|
||||
|
||||
def test_send_test_message_to_self(
|
||||
@@ -161,7 +103,7 @@ def test_send_test_message_to_self(
|
||||
mock_has_permissions
|
||||
):
|
||||
|
||||
expected_data = {'data': ['email address', 'test@user.gov.uk'], 'file_name': 'Test run'}
|
||||
expected_data = {'data': 'email address\r\ntest@user.gov.uk\r\n', 'file_name': 'Test run'}
|
||||
mocker.patch('app.main.views.send.s3download', return_value='email address\r\ntest@user.gov.uk')
|
||||
|
||||
with app_.test_request_context():
|
||||
@@ -208,31 +150,32 @@ def test_upload_csvfile_with_valid_phone_shows_all_numbers(
|
||||
mock_has_permissions
|
||||
):
|
||||
|
||||
contents = 'phone number\n+44 7700 900981\n+44 7700 900982\n+44 7700 900983\n+44 7700 900984\n+44 7700 900985\n+44 7700 900986' # noqa
|
||||
file_data = (BytesIO(contents.encode('utf-8')), 'valid.csv')
|
||||
mocker.patch('app.main.views.send.s3download', return_value=contents)
|
||||
mocker.patch(
|
||||
'app.main.views.send.s3download',
|
||||
return_value='phone number\n+44 7700 900981\n+44 7700 900982\n+44 7700 900983\n+44 7700 900984\n+44 7700 900985\n+44 7700 900986' # noqa
|
||||
)
|
||||
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
client.login(api_user_active)
|
||||
upload_data = {'file': file_data}
|
||||
response = client.post(url_for('main.send_messages', service_id=12345, template_id=54321),
|
||||
data=upload_data,
|
||||
follow_redirects=True)
|
||||
response = client.post(
|
||||
url_for('main.send_messages', service_id=12345, template_id=54321),
|
||||
data={'file': (BytesIO(), 'valid.csv')},
|
||||
follow_redirects=True
|
||||
)
|
||||
with client.session_transaction() as sess:
|
||||
assert int(sess['upload_data']['template_id']) == 54321
|
||||
assert sess['upload_data']['original_file_name'] == 'valid.csv'
|
||||
assert sess['upload_data']['notification_count'] == 6
|
||||
|
||||
content = response.get_data(as_text=True)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert '+44 7700 900981' in content
|
||||
assert '+44 7700 900982' in content
|
||||
assert '+44 7700 900983' in content
|
||||
assert '+44 7700 900984' in content
|
||||
assert '+44 7700 900985' in content
|
||||
assert '+44 7700 900986' in content
|
||||
assert '1 more row not shown' in content
|
||||
|
||||
|
||||
def test_create_job_should_call_api(
|
||||
@@ -261,8 +204,9 @@ def test_create_job_should_call_api(
|
||||
with client.session_transaction() as session:
|
||||
session['upload_data'] = {'original_file_name': original_file_name,
|
||||
'template_id': template_id,
|
||||
'notification_count': notification_count}
|
||||
url = url_for('main.check_messages', service_id=service_one['id'], upload_id=job_id)
|
||||
'notification_count': notification_count,
|
||||
'valid': True}
|
||||
url = url_for('main.start_job', service_id=service_one['id'], upload_id=job_id)
|
||||
response = client.post(url, data=job_data, follow_redirects=True)
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -285,11 +229,11 @@ def test_check_messages_should_revalidate_file_when_uploading_file(
|
||||
):
|
||||
|
||||
service_id = service_one['id']
|
||||
contents = 'phone number,name,,,\n++44 7700 900981,test1,,,\n+44 7700 900981,test2,,,\n ,,, \n ,,, \t \t \n'
|
||||
file_data = (BytesIO(contents.encode('utf-8')), 'invalid.csv')
|
||||
upload_data = {'file': file_data}
|
||||
|
||||
mocker.patch('app.main.views.send.s3download', return_value=contents)
|
||||
mocker.patch(
|
||||
'app.main.views.send.s3download',
|
||||
return_value='phone number,name,,,\n++44 7700 900981,test1,,,\n+44 7700 900981,test2,,,\n ,,, \n ,,, \t \t \n'
|
||||
)
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
client.login(api_user_active)
|
||||
@@ -297,10 +241,13 @@ def test_check_messages_should_revalidate_file_when_uploading_file(
|
||||
session['upload_data'] = {'original_file_name': 'invalid.csv',
|
||||
'template_id': job_data['template'],
|
||||
'notification_count': job_data['notification_count']}
|
||||
url = url_for('main.check_messages', service_id=service_id, upload_id=job_data['id'])
|
||||
response = client.post(url, data=upload_data, follow_redirects=True)
|
||||
response = client.post(
|
||||
url_for('main.check_messages', service_id=service_id, upload_id=job_data['id']),
|
||||
data={'file': (BytesIO(), 'invalid.csv')},
|
||||
follow_redirects=True
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert 'Your CSV file contained missing or invalid data' in response.get_data(as_text=True)
|
||||
assert 'There was a problem with invalid.csv' in response.get_data(as_text=True)
|
||||
|
||||
|
||||
def test_route_permissions(mocker,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from flask import url_for
|
||||
|
||||
from tests import create_test_user
|
||||
from tests.conftest import SERVICE_ONE_ID
|
||||
|
||||
|
||||
def test_should_render_two_factor_page(app_,
|
||||
@@ -33,11 +32,10 @@ def test_should_login_user_and_redirect_to_service_dashboard(app_,
|
||||
'email': api_user_active.email_address}
|
||||
response = client.post(url_for('main.two_factor'),
|
||||
data={'sms_code': '12345'})
|
||||
|
||||
assert response.status_code == 302
|
||||
assert response.location == url_for(
|
||||
'main.service_dashboard',
|
||||
service_id="596364a0-858e-42c8-9062-a8fe822260eb",
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_external=True
|
||||
)
|
||||
|
||||
@@ -109,3 +107,29 @@ def test_remember_me_set(app_,
|
||||
response = client.post(url_for('main.two_factor'),
|
||||
data={'sms_code': '23456', 'remember_me': True})
|
||||
assert response.status_code == 302
|
||||
|
||||
|
||||
def test_two_factor_should_set_password_when_new_password_exists_in_session(app_,
|
||||
api_user_active,
|
||||
mock_get_user,
|
||||
mock_check_verify_code,
|
||||
mock_get_services_with_one_service,
|
||||
mock_update_user):
|
||||
with app_.test_request_context():
|
||||
with app_.test_client() as client:
|
||||
with client.session_transaction() as session:
|
||||
session['user_details'] = {
|
||||
'id': api_user_active.id,
|
||||
'email': api_user_active.email_address,
|
||||
'password': 'changedpassword'}
|
||||
|
||||
response = client.post(url_for('main.two_factor'),
|
||||
data={'sms_code': '12345'})
|
||||
assert response.status_code == 302
|
||||
assert response.location == url_for(
|
||||
'main.service_dashboard',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
_external=True
|
||||
)
|
||||
api_user_active.password = 'changedpassword'
|
||||
mock_update_user.assert_called_once_with(api_user_active)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import uuid
|
||||
from datetime import date
|
||||
from datetime import date, datetime, timedelta
|
||||
import pytest
|
||||
|
||||
from app import create_app
|
||||
@@ -90,17 +90,20 @@ def mock_update_service(mocker):
|
||||
'app.notifications_api_client.update_service', side_effect=_update)
|
||||
|
||||
|
||||
SERVICE_ONE_ID = "596364a0-858e-42c8-9062-a8fe822260eb"
|
||||
SERVICE_TWO_ID = "147ad62a-2951-4fa1-9ca0-093cd1a52c52"
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def mock_get_services(mocker, user=None):
|
||||
if user is None:
|
||||
user = api_user_active()
|
||||
|
||||
def _create(user_id=None):
|
||||
import uuid
|
||||
service_one = service_json(
|
||||
"596364a0-858e-42c8-9062-a8fe822260eb", "service_one", [user.id], 1000, True, False)
|
||||
SERVICE_ONE_ID, "service_one", [user.id], 1000, True, False)
|
||||
service_two = service_json(
|
||||
"147ad62a-2951-4fa1-9ca0-093cd1a52c52", "service_two", [user.id], 1000, True, False)
|
||||
SERVICE_TWO_ID, "service_two", [user.id], 1000, True, False)
|
||||
return {'data': [service_one, service_two]}
|
||||
|
||||
return mocker.patch(
|
||||
@@ -113,9 +116,8 @@ def mock_get_services_with_one_service(mocker, user=None):
|
||||
user = api_user_active()
|
||||
|
||||
def _create(user_id=None):
|
||||
import uuid
|
||||
return {'data': [service_json(
|
||||
"596364a0-858e-42c8-9062-a8fe822260eb", "service_one", [user.id], 1000, True, False
|
||||
SERVICE_ONE_ID, "service_one", [user.id], 1000, True, False
|
||||
)]}
|
||||
|
||||
return mocker.patch(
|
||||
@@ -268,9 +270,27 @@ def api_user_request_password_reset():
|
||||
'password': 'somepassword',
|
||||
'email_address': 'test@user.gov.uk',
|
||||
'mobile_number': '+4412341234',
|
||||
'state': 'request_password_reset',
|
||||
'state': 'active',
|
||||
'failed_login_count': 5,
|
||||
'permissions': {}
|
||||
'permissions': {},
|
||||
'password_changed_at': None
|
||||
}
|
||||
user = User(user_data)
|
||||
return user
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def api_user_changed_password():
|
||||
from app.notify_client.user_api_client import User
|
||||
user_data = {'id': 555,
|
||||
'name': 'Test User',
|
||||
'password': 'somepassword',
|
||||
'email_address': 'test@user.gov.uk',
|
||||
'mobile_number': '+4412341234',
|
||||
'state': 'active',
|
||||
'failed_login_count': 5,
|
||||
'permissions': {},
|
||||
'password_changed_at': str(datetime.now() + timedelta(minutes=1))
|
||||
}
|
||||
user = User(user_data)
|
||||
return user
|
||||
@@ -345,6 +365,13 @@ def mock_get_user_by_email_request_password_reset(mocker, api_user_request_passw
|
||||
return_value=api_user_request_password_reset)
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def mock_get_user_by_email_user_changed_password(mocker, api_user_changed_password):
|
||||
return mocker.patch(
|
||||
'app.user_api_client.get_user_by_email',
|
||||
return_value=api_user_changed_password)
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def mock_get_user_by_email_locked(mocker, api_user_locked):
|
||||
return mocker.patch(
|
||||
@@ -382,14 +409,6 @@ def mock_verify_password(mocker):
|
||||
side_effect=_verify_password)
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def mock_password_reset(mocker, api_user_active):
|
||||
|
||||
def _reset(email):
|
||||
api_user_active.state = 'request_password_reset'
|
||||
return mocker.patch('app.main.dao.users_dao.request_password_reset', side_effect=_reset)
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def mock_update_user(mocker):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user