remove components related to MOU and agreement (#476)

Co-authored-by: Kenneth Kehl <@kkehl@flexion.us>
This commit is contained in:
Kenneth Kehl
2023-04-28 11:08:12 -07:00
committed by GitHub
parent f5f666884c
commit 54abfb3a4d
27 changed files with 15 additions and 1315 deletions

View File

@@ -1,12 +1,9 @@
from unittest import mock
import pytest
from flask import url_for
from freezegun import freeze_time
from notifications_python_client.errors import HTTPError
from tests import organisation_json, service_json
from tests.app.main.views.test_agreement import MockS3Object
from tests.conftest import (
ORGANISATION_ID,
SERVICE_ONE_ID,
@@ -144,7 +141,6 @@ def test_create_new_organisation(
mock_create_organisation.assert_called_once_with(
name='new name',
organisation_type='federal',
agreement_signed=False,
)
@@ -360,16 +356,11 @@ def test_gps_can_name_their_organisation(
service_id=SERVICE_ONE_ID,
_data=data,
_expected_status=302,
_expected_redirect=url_for(
'main.service_agreement',
service_id=SERVICE_ONE_ID,
)
)
mock_create_organisation.assert_called_once_with(
name=expected_service_name,
organisation_type='nhs_gp',
agreement_signed=False,
)
mock_update_service_organisation.assert_called_once_with(SERVICE_ONE_ID, ORGANISATION_ID)
@@ -430,10 +421,6 @@ def test_nhs_local_assigns_to_selected_organisation(
'organisations': ORGANISATION_ID,
},
_expected_status=302,
_expected_redirect=url_for(
'main.service_agreement',
service_id=SERVICE_ONE_ID,
)
)
mock_update_service_organisation.assert_called_once_with(SERVICE_ONE_ID, ORGANISATION_ID)
@@ -918,10 +905,6 @@ def test_organisation_settings_for_platform_admin(
'Label Value Action',
'Name Test organisation Change organization name',
'Sector Federal government Change sector for the organization',
(
'Data sharing and financial agreement '
'Not signed Change data sharing and financial agreement for the organization'
),
'Request to go live notes None Change go live notes for the organization',
'Billing details None Change billing details for the organization',
'Notes None Change the notes for the organization',
@@ -950,27 +933,6 @@ def test_organisation_settings_for_platform_admin(
),
'federal',
),
(
'.edit_organisation_agreement',
(
{
'value': 'yes',
'label': 'Yes',
'hint': 'Users will be told their organization has already signed the agreement'
},
{
'value': 'no',
'label': 'No',
'hint': 'Users will be prompted to sign the agreement before they can go live'
},
{
'value': 'unknown',
'label': 'No (but we have some service-specific agreements in place)',
'hint': 'Users will not be prompted to sign the agreement'
},
),
'no',
),
))
@pytest.mark.parametrize('user', (
pytest.param(
@@ -1024,21 +986,6 @@ def test_view_organisation_settings(
{'organisation_type': 'state'},
{'cached_service_ids': [], 'organisation_type': 'state'},
),
(
'.edit_organisation_agreement',
{'agreement_signed': 'yes'},
{'agreement_signed': True},
),
(
'.edit_organisation_agreement',
{'agreement_signed': 'no'},
{'agreement_signed': False},
),
(
'.edit_organisation_agreement',
{'agreement_signed': 'unknown'},
{'agreement_signed': None},
),
))
@pytest.mark.parametrize('user', (
pytest.param(
@@ -1582,137 +1529,3 @@ def test_organisation_billing_page_not_accessible_if_not_platform_admin(
org_id=ORGANISATION_ID,
_expected_status=403
)
@pytest.mark.parametrize('signed_by_id, signed_by_name, expected_signatory', [
('1234', None, 'Test User'),
(None, 'The Org Manager', 'The Org Manager'),
('1234', 'The Org Manager', 'The Org Manager'),
])
def test_organisation_billing_page_when_the_agreement_is_signed_by_a_known_person(
organisation_one,
client_request,
api_user_active,
mocker,
platform_admin_user,
signed_by_id,
signed_by_name,
expected_signatory,
):
api_user_active['id'] = '1234'
organisation_one['agreement_signed'] = True
organisation_one['agreement_signed_version'] = 2.5
organisation_one['agreement_signed_by_id'] = signed_by_id
organisation_one['agreement_signed_on_behalf_of_name'] = signed_by_name
organisation_one['agreement_signed_at'] = 'Thu, 20 Feb 2020 06:00:00 GMT'
mocker.patch('app.organisations_client.get_organisation', return_value=organisation_one)
client_request.login(platform_admin_user)
mocker.patch('app.user_api_client.get_user', side_effect=[api_user_active])
page = client_request.get(
'.organisation_billing',
org_id=ORGANISATION_ID,
)
assert page.h1.string == 'Billing'
assert '2.5 of the U.S. Notify data sharing and financial agreement on 20 February 2020' in normalize_spaces(
page.text)
assert f'{expected_signatory} signed' in page.text
# assert page.select_one('main a')['href'] == url_for('.organisation_download_agreement', org_id=ORGANISATION_ID)
def test_organisation_billing_page_when_the_agreement_is_signed_by_an_unknown_person(
organisation_one,
client_request,
platform_admin_user,
mocker,
):
organisation_one['agreement_signed'] = True
mocker.patch('app.organisations_client.get_organisation', return_value=organisation_one)
client_request.login(platform_admin_user)
page = client_request.get(
'.organisation_billing',
org_id=ORGANISATION_ID,
)
assert page.h1.string == 'Billing'
assert (f'{organisation_one["name"]} has accepted the U.S. Notify data '
'sharing and financial agreement.') in page.text
# assert page.select_one('main a')['href'] == url_for('.organisation_download_agreement', org_id=ORGANISATION_ID)
@pytest.mark.parametrize('agreement_signed, expected_content', [
(False, 'needs to accept'),
(None, 'has not accepted'),
])
def test_organisation_billing_page_when_the_agreement_is_not_signed(
organisation_one,
client_request,
platform_admin_user,
mocker,
agreement_signed,
expected_content,
):
organisation_one['agreement_signed'] = agreement_signed
mocker.patch('app.organisations_client.get_organisation', return_value=organisation_one)
client_request.login(platform_admin_user)
page = client_request.get(
'.organisation_billing',
org_id=ORGANISATION_ID,
)
assert page.h1.string == 'Billing'
assert f'{organisation_one["name"]} {expected_content}' in page.text
@pytest.mark.parametrize('expected_status, expected_file_fetched, expected_file_served', (
(
200, 'agreement.pdf',
'U.S. Notify data sharing and financial agreement.pdf',
),
))
@mock.patch('app.s3_client.s3_mou_client.current_app')
def test_download_organisation_agreement(
mock_flask_current_app,
client_request,
platform_admin_user,
mocker,
expected_status,
expected_file_fetched,
expected_file_served,
):
mock_flask_current_app.config['MOU_BUCKET_NAME'] = 'test-mou'
mocker.patch(
'app.models.organisation.organisations_client.get_organisation',
return_value=organisation_json(
)
)
mock_get_s3_object = mocker.patch(
'app.s3_client.s3_mou_client.get_s3_object',
return_value=MockS3Object(b'foo')
)
client_request.login(platform_admin_user)
response = client_request.get_response(
'main.organisation_download_agreement',
org_id=ORGANISATION_ID,
_expected_status=expected_status,
)
if expected_file_served:
assert response.get_data() == b'foo'
assert response.headers['Content-Type'] == 'application/pdf'
assert response.headers['Content-Disposition'] == (
f'attachment; filename="{expected_file_served}"'
)
# mock_get_s3_object.assert_called_once_with('test-mou', expected_file_fetched)
mock_get_s3_object.assert_called_once()
else:
assert not expected_file_fetched
assert mock_get_s3_object.called is False

View File

@@ -760,12 +760,10 @@ def test_should_check_for_sending_things_right(
mock_get_invites.assert_called_once_with(SERVICE_ONE_ID)
@pytest.mark.parametrize('checklist_completed, agreement_signed, expected_button', (
(True, True, True),
(True, None, True),
(True, False, False),
(False, True, False),
(False, None, False),
@pytest.mark.parametrize('checklist_completed, expected_button', (
(True, True),
(True, True),
(False, False),
))
def test_should_not_show_go_live_button_if_checklist_not_complete(
client_request,
@@ -776,7 +774,6 @@ def test_should_not_show_go_live_button_if_checklist_not_complete(
mock_get_invites_for_service,
single_sms_sender,
checklist_completed,
agreement_signed,
expected_button,
):
mocker.patch(
@@ -784,12 +781,6 @@ def test_should_not_show_go_live_button_if_checklist_not_complete(
new_callable=PropertyMock,
return_value=checklist_completed,
)
mocker.patch(
'app.models.organisation.Organisation.agreement_signed',
new_callable=PropertyMock,
return_value=agreement_signed,
create=True,
)
for channel in ('email', 'sms'):
mocker.patch(
@@ -963,68 +954,6 @@ def test_should_check_for_sms_sender_on_go_live(
mock_get_sms_senders.assert_called_once_with(SERVICE_ONE_ID)
@pytest.mark.parametrize('agreement_signed, expected_item', (
pytest.param(
None,
'',
marks=pytest.mark.xfail(raises=IndexError)
),
(
True,
'Accept our data sharing and financial agreement Completed',
),
(
False,
'Accept our data sharing and financial agreement Not completed',
),
))
def test_should_check_for_mou_on_request_to_go_live(
client_request,
service_one,
mocker,
agreement_signed,
mock_get_invites_for_service,
mock_get_service_organisation,
expected_item,
):
mocker.patch(
'app.models.service.Service.has_team_members',
return_value=False,
)
mocker.patch(
'app.models.service.Service.all_templates',
new_callable=PropertyMock,
return_value=[],
)
mocker.patch(
'app.main.views.service_settings.service_api_client.get_sms_senders',
return_value=[],
)
mocker.patch(
'app.main.views.service_settings.service_api_client.get_reply_to_email_addresses',
return_value=[],
)
for channel in {'email', 'sms'}:
mocker.patch(
'app.models.service.Service.volume_{}'.format(channel),
create=True,
new_callable=PropertyMock,
return_value=None,
)
mocker.patch(
'app.organisations_client.get_organisation',
return_value=organisation_json(agreement_signed=agreement_signed)
)
page = client_request.get(
'main.request_to_go_live', service_id=SERVICE_ONE_ID
)
assert page.h1.text == 'Before you request to go live'
checklist_items = page.select('.task-list .task-list-item')
assert normalize_spaces(checklist_items[3].text) == expected_item
def test_non_gov_user_is_told_they_cant_go_live(
client_request,
api_nongov_user_active,
@@ -1316,8 +1245,7 @@ def test_should_redirect_after_request_to_go_live(
'http://localhost/services/{service_id}\n'
'\n'
'---\n'
'Organisation type: Federal government\n'
'Agreement signed: Cant tell (domain is user.gsa.gov).\n'
'Organisation type: Federal government (domain is user.gsa.gov).\n'
'\n'
'{formatted_displayed_volumes}'
'\n'
@@ -1400,8 +1328,7 @@ def test_request_to_go_live_displays_go_live_notes_in_zendesk_ticket(
'http://localhost/services/{service_id}\n'
'\n'
'---\n'
'Organisation type: Federal government\n'
'Agreement signed: No (organisation is Org 1). {go_live_note}\n'
'Organisation type: Federal government (organisation is Org 1). {go_live_note}\n'
'\n'
'Emails in next year: 111,111\n'
'Text messages in next year: 222,222\n'
@@ -1472,11 +1399,10 @@ def test_request_to_go_live_displays_mou_signatories(
)
assert (
'Organisation type: Federal government\n'
'Agreement signed: Yes, for Org 1.\n'
'Agreement signed by: test@user.gsa.gov\n'
'Agreement signed on behalf of: bigdog@example.gsa.gov\n'
'\n'
'Organisation type: Federal government'
) in mock_create_ticket.call_args[1]['message']
assert (
'Emails in next year: 111,111\n'
) in mock_create_ticket.call_args[1]['message']

View File

@@ -1,481 +0,0 @@
from functools import partial
from io import BytesIO
from unittest import mock
from unittest.mock import call
import pytest
from flask import url_for
from freezegun import freeze_time
from tests import organisation_json
from tests.conftest import ORGANISATION_ID, SERVICE_ONE_ID, normalize_spaces
class MockS3Object():
def __init__(self, data=None):
self.data = data or b''
def get(self):
return {'Body': BytesIO(self.data)}
@pytest.mark.parametrize('agreement_signed, expected_back_link, expected_other_links', [
(
True,
partial(url_for, 'main.request_to_go_live', service_id=SERVICE_ONE_ID),
[]
),
(
False,
partial(url_for, 'main.request_to_go_live', service_id=SERVICE_ONE_ID),
[
(
['govuk-button'],
partial(url_for, 'main.service_accept_agreement', service_id=SERVICE_ONE_ID),
),
]
),
(
False,
partial(url_for, 'main.request_to_go_live', service_id=SERVICE_ONE_ID),
[
(
['govuk-button'],
partial(url_for, 'main.service_accept_agreement', service_id=SERVICE_ONE_ID),
),
]
),
])
def test_show_agreement_page(
client_request,
mocker,
fake_uuid,
mock_get_service_organisation,
mock_has_jobs,
agreement_signed,
expected_back_link,
expected_other_links,
):
org = organisation_json(
agreement_signed=agreement_signed
)
mocker.patch('app.organisations_client.get_organisation', return_value=org)
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]
assert link.get('class', []) == classes
assert link['href'] == url()
@pytest.mark.parametrize('org_type, expected_endpoint', (
('nhs_gp', 'main.add_organisation_from_gp_service'),
('nhs_local', 'main.add_organisation_from_nhs_local_service'),
))
@pytest.mark.skip(reason='Update for TTS')
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,
),
)
@pytest.mark.parametrize('expected_status, expected_file_fetched, expected_file_served', (
(
200, 'agreement.pdf',
'U.S. Notify data sharing and financial agreement.pdf',
),
))
@mock.patch('app.s3_client.s3_mou_client.current_app')
def test_download_service_agreement(
mock_flask_current_app,
client_request,
mocker,
mock_get_service_organisation,
expected_status,
expected_file_fetched,
expected_file_served,
):
mock_flask_current_app.config['MOU_BUCKET_NAME'] = 'test-mou'
mocker.patch(
'app.models.organisation.organisations_client.get_organisation',
return_value=organisation_json(
)
)
mock_get_s3_object = mocker.patch(
'app.s3_client.s3_mou_client.get_s3_object',
return_value=MockS3Object(b'foo')
)
response = client_request.get_response(
'main.service_download_agreement',
service_id=SERVICE_ONE_ID,
_expected_status=expected_status,
)
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()
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,
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'),
('text', 'version', 'version'),
('hidden', 'csrf_token', None),
]
assert normalize_spaces(page.select_one('label[for=version]').text) == (
'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'
)
assert page.select_one('input[name=version]').get('value') is None
assert normalize_spaces(page.select_one('#who legend').text) == (
'Who are you accepting the agreement for?'
)
assert normalize_spaces(page.select_one('label[for=who-0]').text) == (
'Yourself'
)
assert page.select('input[name=who]')[0]['value'] == 'me'
assert 'checked' not in page.select('input[name=who]')[0]
assert 'data-target' not in page.select('.multiple-choice')[0]
assert normalize_spaces(page.select_one('label[for=who-1]').text) == (
'Someone else'
)
assert page.select('input[name=who]')[1]['value'] == 'someone-else'
assert 'checked' not in page.select('input[name=who]')[1]
assert page.select('.multiple-choice')[1]['data-target'] == 'on-behalf-of'
assert [
field['name']
for field in page.select('#on-behalf-of.conditional-radios-panel input')
] == [
'on_behalf_of_name', 'on_behalf_of_email'
]
assert normalize_spaces(page.select_one('label[for=on_behalf_of_name]').text) == (
'Whats their name?'
)
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?'
)
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,
):
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'),
('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',
'Error: Must be a number',
],
),
(
{
'version': 'one point two',
'who': 'me',
'on_behalf_of_name': '',
'on_behalf_of_email': '',
},
[
'Error: Must be a number',
],
),
(
{
'version': '1.2',
'who': 'someone-else',
'on_behalf_of_name': '',
'on_behalf_of_email': '',
},
[
'Error: Cannot be empty',
'Error: Cannot be empty',
],
),
(
{
'version': '1.2',
'who': 'someone-else',
'on_behalf_of_name': 'Firstname Lastname',
'on_behalf_of_email': '',
},
[
'Error: Cannot be empty',
],
),
(
{
'version': '1.2',
'who': 'someone-else',
'on_behalf_of_name': '',
'on_behalf_of_email': 'test@example.com',
},
[
'Error: Cannot be empty',
],
),
))
def test_accept_agreement_page_validates(
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(
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(
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(
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(
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,
),
)
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 '
'U.S. 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 '
'U.S. 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,
):
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,
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,
):
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,
),
)
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', (
('foo', 404),
))
def test_show_public_agreement_page(
client_request,
mocker,
endpoint,
variant,
expected_status,
):
mocker.patch(
'app.s3_client.s3_mou_client.get_s3_object',
return_value=MockS3Object()
)
client_request.logout()
client_request.get_response(
endpoint,
variant=variant,
_expected_status=expected_status,
)