Files
notifications-admin/tests/app/main/views/test_agreement.py
T

517 lines
15 KiB
Python
Raw Normal View History

from functools import partial
2018-03-16 17:27:47 +00:00
from io import BytesIO
from unittest.mock import call
2018-03-16 17:27:47 +00:00
import pytest
from flask import url_for
from freezegun import freeze_time
2018-04-25 14:12:58 +01:00
from tests import organisation_json
2020-03-20 08:42:33 +00:00
from tests.conftest import ORGANISATION_ID, SERVICE_ONE_ID, normalize_spaces
2018-03-16 17:27:47 +00:00
2021-12-07 13:42:44 +00:00
class MockS3Object():
2018-03-16 17:27:47 +00:00
def __init__(self, data=None):
self.data = data or b''
def get(self):
return {'Body': BytesIO(self.data)}
@pytest.mark.parametrize('agreement_signed, crown, expected_back_link, expected_other_links', [
(
True, True,
partial(url_for, 'main.request_to_go_live', service_id=SERVICE_ONE_ID),
[
2019-07-12 09:03:35 +01:00
(
2020-02-12 16:26:08 +00:00
['govuk-link', 'govuk-link--no-visited-state'],
2019-07-12 09:03:35 +01:00
partial(url_for, 'main.service_download_agreement', service_id=SERVICE_ONE_ID),
),
]
),
(
False, False,
partial(url_for, 'main.request_to_go_live', service_id=SERVICE_ONE_ID),
[
2019-07-12 09:03:35 +01:00
(
2020-02-12 16:26:08 +00:00
['govuk-link', 'govuk-link--no-visited-state'],
2019-07-12 09:03:35 +01:00
partial(url_for, 'main.service_download_agreement', service_id=SERVICE_ONE_ID),
),
(
['govuk-button'],
2019-07-12 09:03:35 +01:00
partial(url_for, 'main.service_accept_agreement', service_id=SERVICE_ONE_ID),
),
]
),
(
False, True,
partial(url_for, 'main.request_to_go_live', service_id=SERVICE_ONE_ID),
[
2019-07-12 09:03:35 +01:00
(
2020-02-12 16:26:08 +00:00
['govuk-link', 'govuk-link--no-visited-state'],
2019-07-12 09:03:35 +01:00
partial(url_for, 'main.service_download_agreement', service_id=SERVICE_ONE_ID),
),
(
['govuk-button'],
2019-07-12 09:03:35 +01:00
partial(url_for, 'main.service_accept_agreement', service_id=SERVICE_ONE_ID),
),
]
),
(
None, None,
partial(url_for, 'main.request_to_go_live', service_id=SERVICE_ONE_ID),
[
2019-07-12 09:03:35 +01:00
(
2020-02-12 16:26:08 +00:00
['govuk-link', 'govuk-link--no-visited-state'],
2019-07-12 09:03:35 +01:00
partial(url_for, 'main.support'),
),
]
),
2018-03-16 17:27:47 +00:00
])
def test_show_agreement_page(
client_request,
mocker,
fake_uuid,
mock_get_service_organisation,
mock_has_jobs,
agreement_signed,
crown,
expected_back_link,
expected_other_links,
2018-03-16 17:27:47 +00:00
):
org = organisation_json(
crown=crown,
agreement_signed=agreement_signed
)
2020-03-20 08:42:33 +00:00
mocker.patch('app.organisations_client.get_organisation', return_value=org)
2019-07-12 09:03:35 +01:00
page = client_request.get('main.service_agreement', service_id=SERVICE_ONE_ID)
back_link = page.select_one('.govuk-back-link')
assert back_link['href'] == expected_back_link()
links = page.select('main .govuk-grid-column-five-sixths a')
assert len(links) == len(expected_other_links)
for index, link in enumerate(links):
classes, url = expected_other_links[index]
2019-07-12 09:03:35 +01:00
assert link.get('class', []) == classes
assert link['href'] == url()
2018-03-16 17:27:47 +00:00
@pytest.mark.parametrize('org_type, expected_endpoint', (
('nhs_gp', 'main.add_organisation_from_gp_service'),
('nhs_local', 'main.add_organisation_from_nhs_local_service'),
))
def test_unknown_gps_and_trusts_are_redirected(
client_request,
mocker,
fake_uuid,
mock_has_jobs,
service_one,
org_type,
expected_endpoint,
):
service_one['organisation_id'] = None
service_one['organisation_type'] = org_type
client_request.get(
'main.service_agreement',
service_id=SERVICE_ONE_ID,
_expected_status=302,
_expected_redirect=url_for(
expected_endpoint,
service_id=SERVICE_ONE_ID,
_external=True,
),
)
@pytest.mark.parametrize('crown, expected_status, expected_file_fetched, expected_file_served', (
(
True, 200, 'crown.pdf',
'GOV.UK Notify data sharing and financial agreement.pdf',
),
(
False, 200, 'non-crown.pdf',
'GOV.UK Notify data sharing and financial agreement (non-crown).pdf',
),
(
None, 404, None,
None,
),
))
def test_download_service_agreement(
2021-12-31 12:08:14 +00:00
client_request,
mocker,
mock_get_service_organisation,
crown,
expected_status,
expected_file_fetched,
expected_file_served,
):
2020-03-20 08:42:33 +00:00
mocker.patch(
'app.models.organisation.organisations_client.get_organisation',
return_value=organisation_json(
crown=crown
)
)
mock_get_s3_object = mocker.patch(
'app.s3_client.s3_mou_client.get_s3_object',
2021-12-07 13:42:44 +00:00
return_value=MockS3Object(b'foo')
)
2021-12-31 12:16:12 +00:00
response = client_request.get_response(
'main.service_download_agreement',
service_id=SERVICE_ONE_ID,
2021-12-31 12:08:14 +00:00
_expected_status=expected_status,
2021-12-31 12:16:12 +00:00
)
if expected_file_served:
assert response.get_data() == b'foo'
assert response.headers['Content-Type'] == 'application/pdf'
assert response.headers['Content-Disposition'] == (
'attachment; filename="{}"'.format(expected_file_served)
)
mock_get_s3_object.assert_called_once_with('test-mou', expected_file_fetched)
else:
assert not expected_file_fetched
assert mock_get_s3_object.called is False
def test_show_accept_agreement_page(
client_request,
mocker,
mock_get_service_organisation,
2020-03-20 08:42:33 +00:00
mock_get_organisation,
):
page = client_request.get('main.service_accept_agreement', service_id=SERVICE_ONE_ID)
assert [
(input['type'], input['name'], input.get('id')) for input in page.select('input')
] == [
('radio', 'who', 'who-0'),
('radio', 'who', 'who-1'),
('text', 'on_behalf_of_name', 'on_behalf_of_name'),
('email', 'on_behalf_of_email', 'on_behalf_of_email'),
2019-07-19 16:20:27 +01:00
('text', 'version', 'version'),
('hidden', 'csrf_token', None),
]
assert normalize_spaces(page.select_one('label[for=version]').text) == (
2020-08-07 15:16:04 +01:00
'Which version of the agreement do you want to accept?'
)
assert normalize_spaces(page.select_one('#version-hint').text) == (
'The version number is on the front page, for example 3.6'
)
2020-08-07 15:16:04 +01:00
assert page.select_one('input[name=version]').get('value') is None
assert normalize_spaces(page.select_one('#who legend').text) == (
2019-07-19 16:20:27 +01:00
'Who are you accepting the agreement for?'
)
assert normalize_spaces(page.select_one('label[for=who-0]').text) == (
2019-07-19 16:20:27 +01:00
'Yourself'
)
assert page.select('input[name=who]')[0]['value'] == 'me'
assert 'checked' not in page.select('input[name=who]')[0]
2019-06-18 16:02:37 +01:00
assert 'data-target' not in page.select('.multiple-choice')[0]
assert normalize_spaces(page.select_one('label[for=who-1]').text) == (
2019-07-19 16:20:27 +01:00
'Someone else'
)
assert page.select('input[name=who]')[1]['value'] == 'someone-else'
assert 'checked' not in page.select('input[name=who]')[1]
2019-06-18 16:02:37 +01:00
assert page.select('.multiple-choice')[1]['data-target'] == 'on-behalf-of'
assert [
field['name']
2019-09-05 12:10:24 +01:00
for field in page.select('#on-behalf-of.conditional-radios-panel input')
2019-06-18 16:02:37 +01:00
] == [
'on_behalf_of_name', 'on_behalf_of_email'
]
assert normalize_spaces(page.select_one('label[for=on_behalf_of_name]').text) == (
2019-07-19 16:20:27 +01:00
'Whats their name?'
)
2020-08-07 15:16:04 +01:00
assert page.select_one('input[name=on_behalf_of_name]').get('value') is None
assert normalize_spaces(page.select_one('label[for=on_behalf_of_email]').text) == (
'Whats their email address?'
)
2020-08-07 15:16:04 +01:00
assert page.select_one('input[name=on_behalf_of_email]').get('value') is None
def test_accept_agreement_page_populates(
client_request,
mocker,
mock_get_service_organisation,
):
2020-03-20 08:42:33 +00:00
mocker.patch(
'app.models.organisation.organisations_client.get_organisation',
return_value=organisation_json(
agreement_signed_version='1.2',
agreement_signed_on_behalf_of_name='Firstname Lastname',
agreement_signed_on_behalf_of_email_address='test@example.com',
)
)
page = client_request.get('main.service_accept_agreement', service_id=SERVICE_ONE_ID)
assert [
(field['name'], field['value']) for field in page.select('input[type=text], input[type=email]')
] == [
('on_behalf_of_name', 'Firstname Lastname'),
('on_behalf_of_email', 'test@example.com'),
2019-07-19 16:20:27 +01:00
('version', '1.2'),
]
assert 'checked' not in page.select('input[name=who]')[0]
assert page.select('input[name=who]')[1]['checked'] == ''
@pytest.mark.parametrize('data, expected_errors', (
(
{
'version': '',
'on_behalf_of_name': '',
'on_behalf_of_email': '',
},
[
'Select an option',
2020-08-07 15:16:04 +01:00
'Error: Must be a number',
],
),
(
{
'version': 'one point two',
'who': 'me',
'on_behalf_of_name': '',
'on_behalf_of_email': '',
},
[
2020-08-07 15:16:04 +01:00
'Error: Must be a number',
],
),
(
{
'version': '1.2',
'who': 'someone-else',
'on_behalf_of_name': '',
'on_behalf_of_email': '',
},
[
2020-08-07 15:16:04 +01:00
'Error: Cannot be empty',
'Error: Cannot be empty',
],
),
(
{
'version': '1.2',
'who': 'someone-else',
'on_behalf_of_name': 'Firstname Lastname',
'on_behalf_of_email': '',
},
[
2020-08-07 15:16:04 +01:00
'Error: Cannot be empty',
],
),
(
{
'version': '1.2',
'who': 'someone-else',
'on_behalf_of_name': '',
'on_behalf_of_email': 'test@example.com',
},
[
2020-08-07 15:16:04 +01:00
'Error: Cannot be empty',
],
),
))
def test_accept_agreement_page_validates(
2020-03-20 08:42:33 +00:00
mocker,
client_request,
mock_get_service_organisation,
data,
expected_errors,
):
page = client_request.post(
'main.service_accept_agreement',
service_id=SERVICE_ONE_ID,
_data=data,
_expected_status=200,
)
assert [
error.text.strip() for error in page.select('.govuk-error-message, .error-message')
] == expected_errors
@pytest.mark.parametrize('data, expected_persisted', (
(
{
'version': '1.2',
'who': 'someone-else',
'on_behalf_of_name': 'Firstname Lastname',
'on_behalf_of_email': 'test@example.com',
},
call(
2020-03-20 08:42:33 +00:00
ORGANISATION_ID,
agreement_signed_version=1.2,
agreement_signed_on_behalf_of_name='Firstname Lastname',
agreement_signed_on_behalf_of_email_address='test@example.com',
cached_service_ids=None,
)
),
(
{
'version': '1.2',
'who': 'me',
'on_behalf_of_name': 'Firstname Lastname',
'on_behalf_of_email': 'test@example.com',
},
call(
2020-03-20 08:42:33 +00:00
ORGANISATION_ID,
agreement_signed_version=1.2,
agreement_signed_on_behalf_of_name='',
agreement_signed_on_behalf_of_email_address='',
cached_service_ids=None,
)
),
(
{
'version': '1.2',
'who': 'me',
'on_behalf_of_name': '',
'on_behalf_of_email': '',
},
call(
2020-03-20 08:42:33 +00:00
ORGANISATION_ID,
agreement_signed_version=1.2,
agreement_signed_on_behalf_of_name='',
agreement_signed_on_behalf_of_email_address='',
cached_service_ids=None,
)
),
))
def test_accept_agreement_page_persists(
2020-03-20 08:42:33 +00:00
mocker,
client_request,
mock_get_service_organisation,
mock_update_organisation,
data,
expected_persisted,
):
client_request.post(
'main.service_accept_agreement',
service_id=SERVICE_ONE_ID,
_data=data,
_expected_status=302,
_expected_redirect=url_for(
'main.service_confirm_agreement',
service_id=SERVICE_ONE_ID,
_external=True,
),
)
assert mock_update_organisation.call_args_list == [expected_persisted]
@pytest.mark.parametrize('name, email, expected_paragraph', (
(None, None, (
'I confirm that I have the legal authority to accept the '
'GOV.UK Notify data sharing and financial agreement (version '
'1.2) and that Test Organisation will be bound by it.'
)),
('Firstname Lastname', 'test@example.com', (
'I confirm that I have the legal authority to accept the '
'GOV.UK Notify data sharing and financial agreement (version '
'1.2) on behalf of Firstname Lastname (test@example.com) and '
'that Test Organisation will be bound by it.'
)),
))
def test_show_confirm_agreement_page(
client_request,
mocker,
mock_get_service_organisation,
name,
email,
expected_paragraph,
):
2020-03-20 08:42:33 +00:00
mocker.patch(
'app.models.organisation.organisations_client.get_organisation',
return_value=organisation_json(
agreement_signed_version='1.2',
agreement_signed_on_behalf_of_name=name,
agreement_signed_on_behalf_of_email_address=email,
)
)
page = client_request.get('main.service_confirm_agreement', service_id=SERVICE_ONE_ID)
assert normalize_spaces(page.select_one('main p').text) == expected_paragraph
@pytest.mark.parametrize('http_method', ('get', 'post'))
def test_confirm_agreement_page_403s_if_previous_step_not_taken(
client_request,
2020-03-20 08:42:33 +00:00
mock_get_organisation,
http_method,
):
getattr(client_request, http_method)(
'main.service_confirm_agreement',
service_id=SERVICE_ONE_ID,
_expected_status=403,
)
@freeze_time("2012-01-01 01:01")
def test_confirm_agreement_page_persists(
client_request,
mocker,
mock_get_service_organisation,
mock_update_organisation,
fake_uuid,
):
2020-03-20 08:42:33 +00:00
mocker.patch(
'app.models.organisation.organisations_client.get_organisation',
return_value=organisation_json(agreement_signed_version='1.2')
)
client_request.post(
'main.service_confirm_agreement',
service_id=SERVICE_ONE_ID,
_expected_redirect=url_for(
'main.request_to_go_live',
service_id=SERVICE_ONE_ID,
_external=True,
),
)
mock_update_organisation.assert_called_once_with(
'1234',
agreement_signed=True,
agreement_signed_at='2012-01-01 01:01:00',
agreement_signed_by_id=fake_uuid,
cached_service_ids=None,
)
@pytest.mark.parametrize('endpoint', (
'main.public_agreement',
'main.public_download_agreement',
))
@pytest.mark.parametrize('variant, expected_status', (
('crown', 200),
('non-crown', 200),
('foo', 404),
))
def test_show_public_agreement_page(
2022-01-04 15:40:42 +00:00
client_request,
mocker,
endpoint,
variant,
expected_status,
):
mocker.patch(
'app.s3_client.s3_mou_client.get_s3_object',
2021-12-07 13:42:44 +00:00
return_value=MockS3Object()
)
2022-01-04 15:40:42 +00:00
client_request.logout()
client_request.get_response(
endpoint,
variant=variant,
2022-01-04 15:40:42 +00:00
_expected_status=expected_status,
)