From 59170aa6270fd7f1ade4a2122123162715fdc8a3 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Thu, 25 May 2023 14:30:54 -0700 Subject: [PATCH 1/7] get rid of test skips --- .../views/organisations/test_organisations.py | 2 +- .../test_email_branding_requests.py | 46 ------------------- tests/app/main/views/test_index.py | 3 +- 3 files changed, 2 insertions(+), 49 deletions(-) diff --git a/tests/app/main/views/organisations/test_organisations.py b/tests/app/main/views/organisations/test_organisations.py index 497954970..4c7b03834 100644 --- a/tests/app/main/views/organisations/test_organisations.py +++ b/tests/app/main/views/organisations/test_organisations.py @@ -398,7 +398,7 @@ def test_validation_of_gps_creating_organisations( assert expected_error in page.select_one('.govuk-error-message, .error-message').text -@pytest.mark.skip(reason='Update for TTS') +@pytest.mark.g(reason='Update for TTS') def test_nhs_local_assigns_to_selected_organisation( client_request, mocker, diff --git a/tests/app/main/views/service_settings/test_email_branding_requests.py b/tests/app/main/views/service_settings/test_email_branding_requests.py index ca3c1467c..f0dba939a 100644 --- a/tests/app/main/views/service_settings/test_email_branding_requests.py +++ b/tests/app/main/views/service_settings/test_email_branding_requests.py @@ -6,7 +6,6 @@ from notifications_utils.clients.zendesk.zendesk_client import ( NotifySupportTicket, ) -from app.utils.branding import NHS_EMAIL_BRANDING_ID from tests import sample_uuid from tests.conftest import ORGANISATION_ID, SERVICE_ONE_ID, normalize_spaces @@ -77,7 +76,6 @@ def test_email_branding_request_page_shows_branding_if_set( assert page.find('iframe')['src'] == url_for('main.email_template', branding_style='some-random-branding') -@pytest.mark.skip(reason='Update for TTS') def test_email_branding_request_page_back_link( client_request, ): @@ -104,13 +102,6 @@ def test_email_branding_request_page_back_link( 'federal', 'main.email_branding_govuk_and_org', ), - ( - { - 'options': 'organisation', - }, - 'federal', - 'main.email_branding_organisation', - ), ( { 'options': 'something_else', @@ -119,7 +110,6 @@ def test_email_branding_request_page_back_link( 'main.email_branding_something_else', ), )) -@pytest.mark.skip(reason='Update for TTS') def test_email_branding_request_submit( client_request, service_one, @@ -151,7 +141,6 @@ def test_email_branding_request_submit( ) -@pytest.mark.skip(reason='Update for TTS') def test_email_branding_request_submit_when_no_radio_button_is_selected( client_request, service_one, @@ -170,9 +159,7 @@ def test_email_branding_request_submit_when_no_radio_button_is_selected( @pytest.mark.parametrize('endpoint, expected_heading', [ ('main.email_branding_govuk_and_org', 'Before you request new branding'), - ('main.email_branding_organisation', 'When you request new branding'), ]) -@pytest.mark.skip(reason='Update for TTS') def test_email_branding_description_pages_for_org_branding( client_request, mocker, @@ -250,7 +237,6 @@ def test_email_branding_something_else_page(client_request, service_one): ) -@pytest.mark.skip(reason='Update for TTS') def test_get_email_branding_something_else_page_is_only_option(client_request, service_one): # should only have a "something else" option # so back button goes back to settings page @@ -268,7 +254,6 @@ def test_get_email_branding_something_else_page_is_only_option(client_request, s @pytest.mark.parametrize('endpoint', [ ('main.email_branding_govuk'), ('main.email_branding_govuk_and_org'), - # ('main.email_branding_nhs'), ('main.email_branding_organisation'), ]) def test_email_branding_pages_give_404_if_selected_branding_not_allowed( @@ -284,7 +269,6 @@ def test_email_branding_pages_give_404_if_selected_branding_not_allowed( ) -@pytest.mark.skip(reason='Update for TTS') def test_email_branding_govuk_submit( mocker, client_request, @@ -379,34 +363,6 @@ def test_email_branding_govuk_and_org_submit( ) -@pytest.mark.skip(reason='Update for TTS') -def test_email_branding_nhs_submit( - mocker, - client_request, - service_one, - organisation_one, - no_reply_to_email_addresses, - mock_get_email_branding, - single_sms_sender, - mock_update_service, -): - service_one['email_branding'] = sample_uuid() - service_one['organisation_type'] = 'nhs_local' - - page = client_request.post( - '.email_branding_nhs', - service_id=SERVICE_ONE_ID, - _follow_redirects=True, - ) - - mock_update_service.assert_called_once_with( - SERVICE_ONE_ID, - email_branding=NHS_EMAIL_BRANDING_ID, - ) - assert page.h1.text == 'Settings' - assert normalize_spaces(page.select_one('.banner-default').text) == 'You’ve updated your email branding' - - @pytest.mark.skip(reason='Update for TTS') def test_email_branding_organisation_submit( mocker, @@ -466,7 +422,6 @@ def test_email_branding_organisation_submit( ) -@pytest.mark.skip(reason='Update for TTS') def test_email_branding_something_else_submit( client_request, mocker, @@ -518,7 +473,6 @@ def test_email_branding_something_else_submit( ) -@pytest.mark.skip(reason='Update for TTS') def test_email_branding_something_else_submit_shows_error_if_textbox_is_empty( client_request, ): diff --git a/tests/app/main/views/test_index.py b/tests/app/main/views/test_index.py index 519218758..d9f0e1825 100644 --- a/tests/app/main/views/test_index.py +++ b/tests/app/main/views/test_index.py @@ -239,14 +239,13 @@ def test_css_is_served_from_correct_path(client_request): ][index]) -@pytest.mark.skip(reason="Update for TTS") def test_resources_that_use_asset_path_variable_have_correct_path(client_request): page = client_request.get('main.documentation') # easy static page logo_svg_fallback = page.select_one('.govuk-header__logotype-fallback-image') - assert logo_svg_fallback['src'].startswith('https://static.example.com/images/govuk-logotype.png') + assert logo_svg_fallback['src'].startswith('https://static.example.com/images/email-template/us-flag.png') @pytest.mark.parametrize('extra_args, email_branding_retrieved', ( From d69dffa67794813829e645810ec5864e9747feb7 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Fri, 26 May 2023 07:35:59 -0700 Subject: [PATCH 2/7] remove nhs test --- .../views/organisations/test_organisations.py | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/tests/app/main/views/organisations/test_organisations.py b/tests/app/main/views/organisations/test_organisations.py index 4c7b03834..6fb404aab 100644 --- a/tests/app/main/views/organisations/test_organisations.py +++ b/tests/app/main/views/organisations/test_organisations.py @@ -398,33 +398,6 @@ def test_validation_of_gps_creating_organisations( assert expected_error in page.select_one('.govuk-error-message, .error-message').text -@pytest.mark.g(reason='Update for TTS') -def test_nhs_local_assigns_to_selected_organisation( - client_request, - mocker, - service_one, - mock_get_organisation, - mock_update_service_organisation, -): - mocker.patch( - 'app.models.organisation.AllOrganisations.client_method', - return_value=[ - organisation_json(ORGANISATION_ID, 'Trust 1', organisation_type='nhs_local'), - ], - ) - service_one['organisation_type'] = 'nhs_local' - - client_request.post( - '.add_organisation_from_nhs_local_service', - service_id=SERVICE_ONE_ID, - _data={ - 'organisations': ORGANISATION_ID, - }, - _expected_status=302, - ) - mock_update_service_organisation.assert_called_once_with(SERVICE_ONE_ID, ORGANISATION_ID) - - @freeze_time("2020-02-20 20:20") def test_organisation_services_shows_live_services_and_usage( client_request, From 618c2eb6bb83ffa9eeff0d11336385a62fdce16e Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Fri, 26 May 2023 12:35:48 -0700 Subject: [PATCH 3/7] fix skips and xfails --- .../views/organisations/test_organisations.py | 85 +++++-- .../test_email_branding_requests.py | 7 +- .../service_settings/test_service_settings.py | 233 +++++++++++++++--- tests/app/main/views/test_jobs.py | 14 +- tests/app/main/views/test_send.py | 47 +++- tests/app/main/views/test_template_folders.py | 45 +++- tests/app/test_navigation.py | 4 +- tests/app/utils/test_user.py | 30 ++- 8 files changed, 388 insertions(+), 77 deletions(-) diff --git a/tests/app/main/views/organisations/test_organisations.py b/tests/app/main/views/organisations/test_organisations.py index 6fb404aab..f4b99d723 100644 --- a/tests/app/main/views/organisations/test_organisations.py +++ b/tests/app/main/views/organisations/test_organisations.py @@ -768,8 +768,8 @@ def test_manage_org_users_shows_no_link_for_cancelled_users( @pytest.mark.parametrize('number_of_users', ( - pytest.param(7, marks=pytest.mark.xfail), pytest.param(8), + pytest.param(800), )) def test_manage_org_users_should_show_live_search_if_more_than_7_users( client_request, @@ -812,6 +812,37 @@ def test_manage_org_users_should_show_live_search_if_more_than_7_users( ) == 'Search by name or email address' +@pytest.mark.parametrize('number_of_users', ( + pytest.param(3), + pytest.param(7), +)) +def test_manage_org_users_should_show_live_search_if_7_users_or_less( + client_request, + mocker, + mock_get_organisation, + active_user_with_permissions, + number_of_users, +): + mocker.patch( + 'app.models.user.OrganisationInvitedUsers.client_method', + return_value=[], + ) + mocker.patch( + 'app.models.user.OrganisationUsers.client_method', + return_value=[active_user_with_permissions] * number_of_users, + ) + + page = client_request.get( + '.manage_org_users', + org_id=ORGANISATION_ID, + ) + + with pytest.raises(expected_exception=TypeError): + assert page.select_one('div[data-module=live-search]')['data-targets'] == ( + ".user-list-item" + ) + + def test_edit_organisation_user_shows_the_delete_confirmation_banner( client_request, mock_get_organisation, @@ -966,7 +997,6 @@ def test_view_organisation_settings( ), pytest.param( create_active_user_with_permissions(), - marks=pytest.mark.xfail ), )) def test_update_organisation_settings( @@ -984,21 +1014,28 @@ def test_update_organisation_settings( mocker.patch('app.organisations_client.get_organisation_services', return_value=[]) client_request.login(user) + if user['email_address'] == 'platform@admin.gsa.gov': + expected_status = 302 + expected_redirect = url_for( + 'main.organisation_settings', + org_id=organisation_one['id'], + ) + else: + expected_status = 403 + expected_redirect = None client_request.post( endpoint, org_id=organisation_one['id'], _data=post_data, - _expected_status=302, - _expected_redirect=url_for( - 'main.organisation_settings', - org_id=organisation_one['id'], - ), + _expected_status=expected_status, + _expected_redirect=expected_redirect, ) - mock_update_organisation.assert_called_once_with( - organisation_one['id'], - **expected_persisted, - ) + if user['email_address'] == 'platform@admin.gsa.gov': + mock_update_organisation.assert_called_once_with( + organisation_one['id'], + **expected_persisted, + ) def test_update_organisation_sector_sends_service_id_data_to_api_client( @@ -1116,7 +1153,6 @@ def test_view_organisation_domains( ), pytest.param( create_active_user_with_permissions(), - marks=pytest.mark.xfail ), )) def test_update_organisation_domains( @@ -1130,22 +1166,29 @@ def test_update_organisation_domains( user, ): client_request.login(user) + if user['email_address'] == 'platform@admin.gsa.gov': + expected_status = 302 + expected_redirect = url_for( + 'main.organisation_settings', + org_id=organisation_one['id'], + ) + else: + expected_status = 403 + expected_redirect = None client_request.post( 'main.edit_organisation_domains', org_id=ORGANISATION_ID, _data=post_data, - _expected_status=302, - _expected_redirect=url_for( - 'main.organisation_settings', - org_id=organisation_one['id'], - ), + _expected_status=expected_status, + _expected_redirect=expected_redirect, ) - mock_update_organisation.assert_called_once_with( - ORGANISATION_ID, - **expected_persisted, - ) + if user['email_address'] == 'platform@admin.gsa.gov': + mock_update_organisation.assert_called_once_with( + ORGANISATION_ID, + **expected_persisted, + ) def test_update_organisation_domains_when_domain_already_exists( diff --git a/tests/app/main/views/service_settings/test_email_branding_requests.py b/tests/app/main/views/service_settings/test_email_branding_requests.py index f0dba939a..305337e66 100644 --- a/tests/app/main/views/service_settings/test_email_branding_requests.py +++ b/tests/app/main/views/service_settings/test_email_branding_requests.py @@ -11,15 +11,10 @@ from tests.conftest import ORGANISATION_ID, SERVICE_ONE_ID, normalize_spaces @pytest.mark.parametrize('organisation_type, expected_options', ( - ('nhs_central', [ - ('nhs', 'NHS'), - ('something_else', 'Something else'), - ]), ('other', [ ('something_else', 'Something else'), - ]) + ]), )) -@pytest.mark.skip(reason='Update for TTS') def test_email_branding_request_page_when_no_branding_is_set( service_one, client_request, diff --git a/tests/app/main/views/service_settings/test_service_settings.py b/tests/app/main/views/service_settings/test_service_settings.py index 3d3ba51cd..9b2c57e2c 100644 --- a/tests/app/main/views/service_settings/test_service_settings.py +++ b/tests/app/main/views/service_settings/test_service_settings.py @@ -619,8 +619,6 @@ def test_should_check_if_estimated_volumes_provided( 'reply_to_email_addresses,' 'expected_reply_to_checklist_item' ), [ - pytest.param(None, 0, [], '', marks=pytest.mark.xfail(raises=IndexError)), - pytest.param(0, 0, [], '', marks=pytest.mark.xfail(raises=IndexError)), (None, 1, [], 'Add a reply-to email address Not completed'), (None, 1, [{}], 'Add a reply-to email address Completed'), (1, 1, [], 'Add a reply-to email address Not completed'), @@ -674,6 +672,59 @@ def test_should_check_for_reply_to_on_go_live( mock_get_reply_to_email_addresses.assert_called_once_with(SERVICE_ONE_ID) +@pytest.mark.parametrize(( + 'volume_email,' + 'count_of_email_templates,' + 'reply_to_email_addresses,' + 'expected_reply_to_checklist_item' +), [ + (None, 0, [], ''), + (0, 0, [], ''), +]) +def test_should_check_for_reply_to_on_go_live_index_error( + client_request, + mocker, + service_one, + fake_uuid, + single_sms_sender, + volume_email, + count_of_email_templates, + reply_to_email_addresses, + expected_reply_to_checklist_item, + mock_get_invites_for_service, + mock_get_users_by_service, +): + mocker.patch( + 'app.service_api_client.get_service_templates', + return_value={'data': [ + create_template(template_type='email') + for _ in range(0, count_of_email_templates) + ]} + ) + + mocker.patch( + 'app.main.views.service_settings.service_api_client.get_reply_to_email_addresses', + return_value=reply_to_email_addresses + ) + + for channel, volume in (('email', volume_email), ('sms', 0)): + mocker.patch( + 'app.models.service.Service.volume_{}'.format(channel), + create=True, + new_callable=PropertyMock, + return_value=volume, + ) + + with pytest.raises(expected_exception=IndexError): + 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_reply_to_checklist_item + + @pytest.mark.parametrize(( 'count_of_users_with_manage_service,' 'count_of_invites_with_manage_service,' @@ -835,55 +886,49 @@ def test_request_to_go_live_redirects_if_service_already_live( 'sms_senders,' 'expected_sms_sender_checklist_item' ), [ - pytest.param( + ( 0, 'state', 0, [], '', - marks=pytest.mark.xfail(raises=IndexError) ), - pytest.param( + ( None, 'state', 0, [{'is_default': True, 'sms_sender': 'GOVUK'}], '', - marks=pytest.mark.xfail(raises=IndexError) ), - pytest.param( + ( 1, 'federal', 99, [{'is_default': True, 'sms_sender': 'GOVUK'}], '', - marks=pytest.mark.xfail(raises=IndexError) ), - pytest.param( + ( None, 'federal', 99, [{'is_default': True, 'sms_sender': 'GOVUK'}], '', - marks=pytest.mark.xfail(raises=IndexError) ), - pytest.param( + ( 1, 'federal', 99, [{'is_default': True, 'sms_sender': 'GOVUK'}], '', - marks=pytest.mark.xfail(raises=IndexError) ), - pytest.param( + ( 1, 'state', 1, [], 'Change your text message sender name Not completed', - marks=pytest.mark.xfail(raises=IndexError), ), - pytest.param( + ( 1, 'state', 1, @@ -892,7 +937,6 @@ def test_request_to_go_live_redirects_if_service_already_live( {'is_default': True, 'sms_sender': 'KUVOG'}, ], 'Change your text message sender name Completed', - marks=pytest.mark.xfail(raises=IndexError), ), ]) def test_should_check_for_sms_sender_on_go_live( @@ -935,15 +979,16 @@ def test_should_check_for_sms_sender_on_go_live( return_value=volume, ) - page = client_request.get( - 'main.request_to_go_live', service_id=SERVICE_ONE_ID - ) - assert page.h1.text == 'Before you request to go live' + with pytest.raises(expected_exception=IndexError): + 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_sms_sender_checklist_item + checklist_items = page.select('.task-list .task-list-item') + assert normalize_spaces(checklist_items[3].text) == expected_sms_sender_checklist_item - mock_get_sms_senders.assert_called_once_with(SERVICE_ONE_ID) + mock_get_sms_senders.assert_called_once_with(SERVICE_ONE_ID) def test_non_gov_user_is_told_they_cant_go_live( @@ -2899,7 +2944,6 @@ def test_should_show_page_to_set_sms_allowance( ('0', 0), ('1', 1), ('250000', 250000), - pytest.param('foo', 'foo', marks=pytest.mark.xfail), ]) def test_should_set_sms_allowance( client_request, @@ -2929,6 +2973,34 @@ def test_should_set_sms_allowance( ) +@freeze_time("2017-04-01 11:09:00.061258") +@pytest.mark.parametrize('given_allowance, expected_api_argument', [ + pytest.param('foo', 'foo'), +]) +def test_should_set_sms_allowance_fails( + client_request, + platform_admin_user, + given_allowance, + expected_api_argument, + mock_get_free_sms_fragment_limit, + mock_create_or_update_free_sms_fragment_limit, +): + + with pytest.raises(expected_exception=AssertionError): + client_request.login(platform_admin_user) + client_request.post( + 'main.set_free_sms_allowance', + service_id=SERVICE_ONE_ID, + _data={ + 'free_sms_allowance': given_allowance, + }, + _expected_redirect=url_for( + 'main.service_settings', + service_id=SERVICE_ONE_ID, + ), + ) + + def test_should_show_page_to_set_message_limit( client_request, platform_admin_user, @@ -3147,8 +3219,6 @@ def test_switch_service_enable_international_sms( [create_platform_admin_user(), True], [create_platform_admin_user(), False], [create_active_user_with_permissions(), True], - pytest.param(create_active_user_with_permissions(), False, marks=pytest.mark.xfail), - pytest.param(create_active_user_no_settings_permission(), True, marks=pytest.mark.xfail), )) def test_archive_service_after_confirm( client_request, @@ -3186,12 +3256,51 @@ def test_archive_service_after_confirm( assert call(f"user-{sample_uuid()}") in redis_delete_mock.call_args_list +@pytest.mark.parametrize('user, is_trial_service', ( + pytest.param(create_active_user_with_permissions(), False), + pytest.param(create_active_user_no_settings_permission(), True), +)) +def test_archive_service_after_confirm_error( + client_request, + mocker, + mock_get_organisations, + mock_get_service_and_organisation_counts, + mock_get_organisations_and_services_for_user, + mock_get_users_by_service, + mock_get_service_templates, + service_one, + user, + is_trial_service, +): + service_one['restricted'] = is_trial_service + mocker.patch('app.service_api_client.post') + mocker.patch('app.main.views.service_settings.create_archive_service_event') + mocker.patch('app.notify_client.service_api_client.redis_client.delete') + mocker.patch('app.notify_client.service_api_client.redis_client.delete_by_pattern') + + with pytest.raises(expected_exception=AssertionError): + client_request.login(user) + client_request.post( + 'main.archive_service', + service_id=SERVICE_ONE_ID, + _follow_redirects=True, + ) + + # mock_api.assert_called_once_with('/service/{}/archive'.format(SERVICE_ONE_ID), data=None) + # mock_event.assert_called_once_with(service_id=SERVICE_ONE_ID, archived_by_id=user['id']) + + # assert normalize_spaces(page.select_one('h1').text) == 'Choose service' + # assert normalize_spaces(page.select_one('.banner-default-with-tick').text) == ( + # '‘service one’ was deleted' + # ) + # The one user which is part of this service has the sample_uuid as it's user ID + # assert call(f"user-{sample_uuid()}") in redis_delete_mock.call_args_list + + @pytest.mark.parametrize('user, is_trial_service', ( [create_platform_admin_user(), True], [create_platform_admin_user(), False], [create_active_user_with_permissions(), True], - pytest.param(create_active_user_with_permissions(), False, marks=pytest.mark.xfail), - pytest.param(create_active_user_no_settings_permission(), True, marks=pytest.mark.xfail), )) def test_archive_service_prompts_user( client_request, @@ -3230,6 +3339,48 @@ def test_archive_service_prompts_user( assert mock_api.called is False +@pytest.mark.parametrize('user, is_trial_service', ( + pytest.param(create_active_user_with_permissions(), False), + pytest.param(create_active_user_no_settings_permission(), True), +)) +def test_archive_service_prompts_user_error( + client_request, + mocker, + single_reply_to_email_address, + service_one, + single_sms_sender, + mock_get_service_settings_page_common, + user, + is_trial_service, +): + mocker.patch('app.service_api_client.post') + service_one['restricted'] = is_trial_service + client_request.login(user) + + with pytest.raises(expected_exception=AssertionError): + client_request.get( + 'main.archive_service', + service_id=SERVICE_ONE_ID + ) + # delete_link = settings_page.select('.page-footer-link a')[0] + # assert normalize_spaces(delete_link.text) == 'Delete this service' + # assert delete_link['href'] == url_for( + # 'main.archive_service', + # service_id=SERVICE_ONE_ID, + # ) + # + # delete_page = client_request.get( + # 'main.archive_service', + # service_id=SERVICE_ONE_ID, + # ) + # assert normalize_spaces(delete_page.select_one('.banner-dangerous').text) == ( + # 'Are you sure you want to delete ‘service one’? ' + # 'There’s no way to undo this. ' + # 'Yes, delete' + # ) + # assert mock_api.called is False + + def test_cant_archive_inactive_service( client_request, platform_admin_user, @@ -3251,7 +3402,6 @@ def test_cant_archive_inactive_service( @pytest.mark.parametrize('user', ( create_platform_admin_user(), - pytest.param(create_active_user_with_permissions(), marks=pytest.mark.xfail), )) def test_suspend_service_after_confirm( client_request, @@ -3275,6 +3425,31 @@ def test_suspend_service_after_confirm( mock_event.assert_called_once_with(service_id=SERVICE_ONE_ID, suspended_by_id=user['id']) +@pytest.mark.parametrize('user', ( + pytest.param(create_active_user_with_permissions()), +)) +def test_suspend_service_after_confirm_error( + client_request, + user, + mocker, +): + mocker.patch('app.service_api_client.post') + mocker.patch('app.main.views.service_settings.create_suspend_service_event') + with pytest.raises(expected_exception=AssertionError): + client_request.login(user) + client_request.post( + 'main.suspend_service', + service_id=SERVICE_ONE_ID, + _expected_redirect=url_for( + 'main.service_settings', + service_id=SERVICE_ONE_ID, + ), + ) + + # mock_api.assert_called_once_with('/service/{}/suspend'.format(SERVICE_ONE_ID), data=None) + # mock_event.assert_called_once_with(service_id=SERVICE_ONE_ID, suspended_by_id=user['id']) + + @pytest.mark.parametrize('user', ( create_platform_admin_user(), pytest.param(create_active_user_with_permissions(), marks=pytest.mark.xfail), diff --git a/tests/app/main/views/test_jobs.py b/tests/app/main/views/test_jobs.py index a792e0880..8c67b3b8e 100644 --- a/tests/app/main/views/test_jobs.py +++ b/tests/app/main/views/test_jobs.py @@ -245,16 +245,20 @@ def test_should_show_job_with_sending_limit_exceeded_status( )), # Just started (datetime(2020, 1, 10, 0, 0, 0), datetime(2020, 1, 10, 0, 0, 1), ( - 'No messages to show yet…' + 'No messages to show yet…' )), # Created a while ago, just started (datetime(2020, 1, 1, 0, 0, 0), datetime(2020, 1, 10, 0, 0, 1), ( - 'No messages to show yet…' + 'No messages to show yet…' )), # Created a while ago, started just within the last 24h - (datetime(2020, 1, 1, 0, 0, 0), datetime(2020, 1, 9, 6, 0, 1), ( - 'No messages to show yet…' - )), + # TODO -- should pass, tech debt due to timezone changes, re-evaluate after UTC changes + pytest.param( + datetime(2020, 1, 1, 0, 0, 0), + datetime(2020, 1, 9, 6, 0, 1), + ('No messages to show yet…'), + marks=pytest.mark.xfail(raises=AssertionError), + ), # Created a while ago, started exactly 24h ago # --- # It doesn’t matter that 24h (1 day) and 7 days (the service’s data diff --git a/tests/app/main/views/test_send.py b/tests/app/main/views/test_send.py index 467a5c149..6f087dbbc 100644 --- a/tests/app/main/views/test_send.py +++ b/tests/app/main/views/test_send.py @@ -2172,9 +2172,7 @@ def test_check_messages_shows_trial_mode_error( @pytest.mark.parametrize('uploaded_file_name', ( pytest.param('applicants.ods'), # normal job - pytest.param('thisisatest.csv', marks=pytest.mark.xfail), # different template version pytest.param('send_me_later.csv'), # should look at scheduled job - pytest.param('full_of_regret.csv', marks=pytest.mark.xfail), # job is cancelled )) def test_warns_if_file_sent_already( client_request, @@ -2215,6 +2213,51 @@ def test_warns_if_file_sent_already( mock_get_jobs.assert_called_once_with(SERVICE_ONE_ID, limit_days=0) +@pytest.mark.parametrize('uploaded_file_name', ( + pytest.param('thisisatest.csv'), # different template version + pytest.param('full_of_regret.csv'), # job is cancelled +)) +def test_warns_if_file_sent_already_errors( + client_request, + mock_get_users_by_service, + mock_get_live_service, + mock_get_service_template, + mock_has_permissions, + mock_get_service_statistics, + mock_get_job_doesnt_exist, + mock_get_jobs, + fake_uuid, + mocker, + uploaded_file_name, +): + mocker.patch('app.main.views.send.s3download', return_value=( + 'phone number,\n2028675209' + )) + mocker.patch( + 'app.main.views.send.get_csv_metadata', + return_value={'original_file_name': uploaded_file_name}, + ) + # Should be botocore.errorfactory.NoSuchKey but for some reason can't use that + with pytest.raises(expected_exception=Exception): + page = client_request.get( + 'main.check_messages', + service_id=SERVICE_ONE_ID, + template_id="5d729fbd-239c-44ab-b498-75a985f3198f", + upload_id=fake_uuid, + original_file_name=uploaded_file_name, + _test_page_title=False, + ) + + assert normalize_spaces( + page.select_one('.banner-dangerous').text + ) == ( + 'These messages have already been sent today ' + 'If you need to resend them, rename the file and upload it again.' + ) + + mock_get_jobs.assert_called_once_with(SERVICE_ONE_ID, limit_days=0) + + def test_check_messages_column_error_doesnt_show_optional_columns( mocker, client_request, diff --git a/tests/app/main/views/test_template_folders.py b/tests/app/main/views/test_template_folders.py index 0eff0016e..bbc8d089d 100644 --- a/tests/app/main/views/test_template_folders.py +++ b/tests/app/main/views/test_template_folders.py @@ -985,14 +985,6 @@ def test_delete_folder( pytest.param( create_active_user_with_permissions() ), - pytest.param( - create_active_user_view_permissions(), - marks=pytest.mark.xfail(raises=AssertionError) - ), - pytest.param( - create_active_caseworking_user(), - marks=pytest.mark.xfail(raises=AssertionError) - ), ]) def test_should_show_checkboxes_for_selecting_templates( client_request, @@ -1022,6 +1014,43 @@ def test_should_show_checkboxes_for_selecting_templates( assert TEMPLATE_ONE_ID not in checkboxes[index]['id'] +@pytest.mark.parametrize('user', [ + pytest.param( + create_active_user_view_permissions(), + ), + pytest.param( + create_active_caseworking_user(), + ), +]) +def test_should_show_checkboxes_for_selecting_templates_assertion_error( + client_request, + mocker, + service_one, + mock_get_service_templates, + mock_get_template_folders, + mock_has_no_jobs, + mock_get_no_api_keys, + user, +): + with pytest.raises(expected_exception=AssertionError): + client_request.login(user) + + page = client_request.get( + 'main.choose_template', + service_id=SERVICE_ONE_ID, + ) + checkboxes = page.select('input[name=templates_and_folders]') + + assert len(checkboxes) == 4 + + assert checkboxes[0]['value'] == TEMPLATE_ONE_ID + assert checkboxes[0]['id'] == 'templates-or-folder-{}'.format(TEMPLATE_ONE_ID) + + for index in (1, 2, 3): + assert checkboxes[index]['value'] != TEMPLATE_ONE_ID + assert TEMPLATE_ONE_ID not in checkboxes[index]['id'] + + @pytest.mark.parametrize('user', [ create_active_user_view_permissions(), create_active_caseworking_user(), diff --git a/tests/app/test_navigation.py b/tests/app/test_navigation.py index 87ffd25c2..f234e99ca 100644 --- a/tests/app/test_navigation.py +++ b/tests/app/test_navigation.py @@ -352,11 +352,11 @@ def test_all_endpoints_are_covered(navigation_instance): navigation_instances, ids=(x.__class__.__name__ for x in navigation_instances) ) -@pytest.mark.xfail(raises=KeyError) def test_raises_on_invalid_navigation_item( client_request, navigation_instance ): - navigation_instance.is_selected('foo') + with pytest.raises(expected_exception=KeyError): + navigation_instance.is_selected('foo') @pytest.mark.parametrize('endpoint, selected_nav_item', [ diff --git a/tests/app/utils/test_user.py b/tests/app/utils/test_user.py index 6a6378911..ed4d9c1ae 100644 --- a/tests/app/utils/test_user.py +++ b/tests/app/utils/test_user.py @@ -6,10 +6,6 @@ from app.utils.user import user_has_permissions @pytest.mark.parametrize('permissions', ( - pytest.param([ - # Route has a permission which the user doesn’t have - 'send_messages' - ], marks=pytest.mark.xfail(raises=Forbidden)), [ # Route has one of the permissions which the user has 'manage_service' @@ -45,6 +41,32 @@ def test_permissions( index() +@pytest.mark.parametrize('permissions', ( + [ + # Route has a permission which the user doesn’t have + 'send_messages' + ], +)) +def test_permissions_forbidden( + client_request, + permissions, + api_user_active, +): + request.view_args.update({'service_id': 'foo'}) + + api_user_active['permissions'] = {'foo': ['manage_users', 'manage_templates', 'manage_settings']} + api_user_active['services'] = ['foo', 'bar'] + + client_request.login(api_user_active) + + @user_has_permissions(*permissions) + def index(): + pass + + with pytest.raises(expected_exception=Forbidden): + index() + + def test_restrict_admin_usage( client_request, platform_admin_user, From 02d5cfc62bcd6a929cce482a18bed0c4e2305c7a Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Fri, 26 May 2023 13:01:34 -0700 Subject: [PATCH 4/7] fix test --- tests/app/main/views/test_jobs.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/app/main/views/test_jobs.py b/tests/app/main/views/test_jobs.py index 8c67b3b8e..c6e43071d 100644 --- a/tests/app/main/views/test_jobs.py +++ b/tests/app/main/views/test_jobs.py @@ -252,12 +252,11 @@ def test_should_show_job_with_sending_limit_exceeded_status( 'No messages to show yet…' )), # Created a while ago, started just within the last 24h - # TODO -- should pass, tech debt due to timezone changes, re-evaluate after UTC changes + # TODO -- fails locally, should pass, tech debt due to timezone changes, re-evaluate after UTC changes pytest.param( datetime(2020, 1, 1, 0, 0, 0), datetime(2020, 1, 9, 6, 0, 1), ('No messages to show yet…'), - marks=pytest.mark.xfail(raises=AssertionError), ), # Created a while ago, started exactly 24h ago # --- From 647c7a91d5b232ab2598d01c46bd643f9fb90c74 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Fri, 26 May 2023 14:52:33 -0700 Subject: [PATCH 5/7] more tests --- .../views/accounts/test_choose_accounts.py | 7 ++++-- .../test_service_setting_permissions.py | 24 +++++++++++++++---- .../service_settings/test_service_settings.py | 8 ++++++- tests/app/main/views/test_manage_users.py | 9 ++++++- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/tests/app/main/views/accounts/test_choose_accounts.py b/tests/app/main/views/accounts/test_choose_accounts.py index e789f7f5e..da12a9e8c 100644 --- a/tests/app/main/views/accounts/test_choose_accounts.py +++ b/tests/app/main/views/accounts/test_choose_accounts.py @@ -267,7 +267,7 @@ def test_choose_account_should_not_show_back_to_service_link_if_not_signed_in( @pytest.mark.parametrize('active', ( False, - pytest.param(True, marks=pytest.mark.xfail(raises=AssertionError)), + pytest.param(True), )) def test_choose_account_should_not_show_back_to_service_link_if_service_archived( client_request, @@ -283,7 +283,10 @@ def test_choose_account_should_not_show_back_to_service_link_if_service_archived page = client_request.get('main.choose_account') assert normalize_spaces(page.select_one('h1').text) == 'Choose service' - assert page.select_one('.navigation-service a') is None + if active: + assert page.select_one('.navigation-service a') is not None + else: + assert page.select_one('.navigation-service a') is None def test_should_not_show_back_to_service_if_user_doesnt_belong_to_service( diff --git a/tests/app/main/views/service_settings/test_service_setting_permissions.py b/tests/app/main/views/service_settings/test_service_setting_permissions.py index 1b3502674..276dd973b 100644 --- a/tests/app/main/views/service_settings/test_service_setting_permissions.py +++ b/tests/app/main/views/service_settings/test_service_setting_permissions.py @@ -122,10 +122,6 @@ def test_service_setting_toggles_show( ({'active': True}, '.history', 2, 'Service history'), ({'active': False}, '.resume_service', 0, 'Resume service'), ({'active': False}, '.history', 1, 'Service history'), - pytest.param( - {'active': False}, '.archive_service', 2, 'Resume service', - marks=pytest.mark.xfail(raises=IndexError) - ) ]) def test_service_setting_link_toggles( get_service_settings_page, @@ -143,6 +139,26 @@ def test_service_setting_link_toggles( assert link['href'] == link_url +@pytest.mark.parametrize('service_fields, endpoint, index, text', [ + pytest.param( + {'active': False}, '.archive_service', 2, 'Resume service', + ) +]) +def test_service_setting_link_toggles_index_error( + get_service_settings_page, + service_one, + service_fields, + endpoint, + index, + text, +): + with pytest.raises(expected_exception=IndexError): + url_for(endpoint, service_id=service_one['id']) + service_one.update(service_fields) + page = get_service_settings_page() + page.select('.page-footer-link a')[index] + + @pytest.mark.parametrize('permissions,permissions_text,visible', [ ('sms', 'inbound SMS', True), ('inbound_sms', 'inbound SMS', False), # no sms parent permission diff --git a/tests/app/main/views/service_settings/test_service_settings.py b/tests/app/main/views/service_settings/test_service_settings.py index 9b2c57e2c..a9b5effb3 100644 --- a/tests/app/main/views/service_settings/test_service_settings.py +++ b/tests/app/main/views/service_settings/test_service_settings.py @@ -3452,7 +3452,7 @@ def test_suspend_service_after_confirm_error( @pytest.mark.parametrize('user', ( create_platform_admin_user(), - pytest.param(create_active_user_with_permissions(), marks=pytest.mark.xfail), + pytest.param(create_active_user_with_permissions()), )) def test_suspend_service_prompts_user( client_request, @@ -3466,6 +3466,12 @@ def test_suspend_service_prompts_user( mock_api = mocker.patch('app.service_api_client.post') client_request.login(user) + + if user['email_address'] != 'platform@admin.gsa.gov': + with pytest.raises(expected_exception=AssertionError): + client_request.get('main.suspend_service', service_id=service_one['id']) + return + page = client_request.get('main.suspend_service', service_id=service_one['id']) assert 'This will suspend the service and revoke all api keys. Are you sure you want to suspend this service?' in \ diff --git a/tests/app/main/views/test_manage_users.py b/tests/app/main/views/test_manage_users.py index 0987e85e5..8ade6f3c9 100644 --- a/tests/app/main/views/test_manage_users.py +++ b/tests/app/main/views/test_manage_users.py @@ -191,7 +191,7 @@ def test_should_show_change_details_link( @pytest.mark.parametrize('number_of_users', ( - pytest.param(7, marks=pytest.mark.xfail), + pytest.param(7), pytest.param(8), )) def test_should_show_live_search_if_more_than_7_users( @@ -213,6 +213,13 @@ def test_should_show_live_search_if_more_than_7_users( page = client_request.get('main.manage_users', service_id=SERVICE_ONE_ID) + if number_of_users == 7: + with pytest.raises(expected_exception=TypeError): + assert page.select_one('div[data-module=live-search]')['data-targets'] == ( + ".user-list-item" + ) + return + assert page.select_one('div[data-module=live-search]')['data-targets'] == ( ".user-list-item" ) From f277dd1289d0d11a0bf632894583e82fa1081629 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Mon, 29 May 2023 07:01:35 -0700 Subject: [PATCH 6/7] more skips and xfails --- .../views/organisations/test_organisations.py | 58 ------------------- .../service_settings/test_service_settings.py | 10 +++- 2 files changed, 9 insertions(+), 59 deletions(-) diff --git a/tests/app/main/views/organisations/test_organisations.py b/tests/app/main/views/organisations/test_organisations.py index f4b99d723..2bb0eca14 100644 --- a/tests/app/main/views/organisations/test_organisations.py +++ b/tests/app/main/views/organisations/test_organisations.py @@ -262,64 +262,6 @@ def test_gps_can_create_own_organisations( ) -@pytest.mark.parametrize('organisation_type, organisation, expected_status', ( - ('nhs_local', None, 200), - ('nhs_gp', None, 403), - ('central', None, 403), - ('nhs_local', organisation_json(organisation_type='nhs_local'), 403), -)) -@pytest.mark.skip(reason='Update for TTS') -def test_nhs_local_can_create_own_organisations( - client_request, - mocker, - mock_get_service_organisation, - service_one, - organisation_type, - organisation, - expected_status, -): - mocker.patch('app.organisations_client.get_organisation', return_value=organisation) - mocker.patch( - 'app.models.organisation.AllOrganisations.client_method', - return_value=[ - organisation_json('t2', 'Trust 2', organisation_type='nhs_local'), - organisation_json('t1', 'Trust 1', organisation_type='nhs_local'), - organisation_json('gp1', 'GP 1', organisation_type='nhs_gp'), - organisation_json('c1', 'Central 1'), - ], - ) - service_one['organisation_type'] = organisation_type - - page = client_request.get( - '.add_organisation_from_nhs_local_service', - service_id=SERVICE_ONE_ID, - _expected_status=expected_status, - ) - - if expected_status == 403: - return - - assert normalize_spaces(page.select_one('main p').text) == ( - 'Which NHS Trust or Clinical Commissioning Group do you work for?' - ) - assert page.select_one('[data-module=live-search]')['data-targets'] == ( - '.govuk-radios__item' - ) - assert [ - ( - normalize_spaces(radio.select_one('label').text), - radio.select_one('input')['value'] - ) - for radio in page.select('.govuk-radios__item') - ] == [ - ('Trust 1', 't1'), - ('Trust 2', 't2'), - ] - assert normalize_spaces(page.select_one('.js-stick-at-bottom-when-scrolling button').text) == ( - 'Continue' - ) - - @pytest.mark.parametrize('data, expected_service_name', ( ( { diff --git a/tests/app/main/views/service_settings/test_service_settings.py b/tests/app/main/views/service_settings/test_service_settings.py index a9b5effb3..944e17f24 100644 --- a/tests/app/main/views/service_settings/test_service_settings.py +++ b/tests/app/main/views/service_settings/test_service_settings.py @@ -3500,7 +3500,7 @@ def test_cant_suspend_inactive_service( @pytest.mark.parametrize('user', ( create_platform_admin_user(), - pytest.param(create_active_user_with_permissions(), marks=pytest.mark.xfail), + create_active_user_with_permissions(), )) def test_resume_service_after_confirm( mocker, @@ -3513,6 +3513,14 @@ def test_resume_service_after_confirm( mock_event = mocker.patch('app.main.views.service_settings.create_resume_service_event') client_request.login(user) + if user['email_address'] != "platform@admin.gsa.gov": + client_request.post( + 'main.resume_service', + service_id=SERVICE_ONE_ID, + _expected_status=403, + ) + return + client_request.post( 'main.resume_service', service_id=SERVICE_ONE_ID, From 2c981a431b762e8f959e98a704c4989ca8536bb8 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Wed, 31 May 2023 12:03:16 -0700 Subject: [PATCH 7/7] code review feedback --- .../service_settings/test_service_settings.py | 75 ------------------- 1 file changed, 75 deletions(-) diff --git a/tests/app/main/views/service_settings/test_service_settings.py b/tests/app/main/views/service_settings/test_service_settings.py index 944e17f24..5bc60db20 100644 --- a/tests/app/main/views/service_settings/test_service_settings.py +++ b/tests/app/main/views/service_settings/test_service_settings.py @@ -61,12 +61,6 @@ def mock_get_service_settings_page_common( 'Start text messages with service name On Change your settings for starting text messages with service name', 'Send international text messages Off Change your settings for sending international text messages', - # 'Label Value Action', - # 'Send emails On Change your settings for sending emails', - # 'Reply-to email addresses Not set Manage reply-to email addresses', - # 'Email branding GOV.UK Change email branding', - # 'Send files by email contact_us@gsa.gov Manage sending files by email', - # 'Receive text messages Off Change your settings for receiving text messages', ]), (create_platform_admin_user(), [ @@ -78,12 +72,6 @@ def mock_get_service_settings_page_common( 'Start text messages with service name On Change your settings for starting text messages with service name', 'Send international text messages Off Change your settings for sending international text messages', - # 'Label Value Action', - # 'Send emails On Change your settings for sending emails', - # 'Reply-to email addresses Not set Manage reply-to email addresses', - # 'Email branding GOV.UK Change email branding', - # 'Send files by email contact_us@gsa.gov Manage sending files by email', - # 'Receive text messages Off Change your settings for receiving text messages', 'Label Value Action', 'Live Off Change service status', @@ -221,12 +209,6 @@ def test_send_files_by_email_row_on_settings_page( 'Start text messages with service name On Change your settings for starting text messages with service name', 'Send international text messages On Change your settings for sending international text messages', - # 'Label Value Action', - # 'Send emails On Change your settings for sending emails', - # 'Reply-to email addresses test@example.com Manage reply-to email addresses', - # 'Email branding Organisation name Change email branding', - # 'Send files by email Not set up Manage sending files by email', - # 'Receive text messages On Change your settings for receiving text messages', ]), (['email', 'sms', 'email_auth'], [ @@ -238,12 +220,6 @@ def test_send_files_by_email_row_on_settings_page( 'Start text messages with service name On Change your settings for starting text messages with service name', 'Send international text messages Off Change your settings for sending international text messages', - # 'Label Value Action', - # 'Send emails On Change your settings for sending emails', - # 'Reply-to email addresses test@example.com Manage reply-to email addresses', - # 'Email branding Organisation name Change email branding', - # 'Send files by email Not set up Manage sending files by email' - # 'Receive text messages Off Change your settings for receiving text messages', ]), ]) @@ -1747,8 +1723,6 @@ def test_and_more_hint_appears_on_settings_with_more_than_just_a_single_sender( "Reply-to email addresses test@example.com …and 2 more Manage reply-to email addresses" assert get_row(page, 'Text message senders') == \ "Text message senders Example …and 2 more Manage text message senders" - # assert get_row(page, 'Sender addresses') == \ - # "Sender addresses 1 Example Street …and 2 more Manage sender addresses" @pytest.mark.parametrize('sender_list_page, index, expected_output', [ @@ -3286,16 +3260,6 @@ def test_archive_service_after_confirm_error( _follow_redirects=True, ) - # mock_api.assert_called_once_with('/service/{}/archive'.format(SERVICE_ONE_ID), data=None) - # mock_event.assert_called_once_with(service_id=SERVICE_ONE_ID, archived_by_id=user['id']) - - # assert normalize_spaces(page.select_one('h1').text) == 'Choose service' - # assert normalize_spaces(page.select_one('.banner-default-with-tick').text) == ( - # '‘service one’ was deleted' - # ) - # The one user which is part of this service has the sample_uuid as it's user ID - # assert call(f"user-{sample_uuid()}") in redis_delete_mock.call_args_list - @pytest.mark.parametrize('user, is_trial_service', ( [create_platform_admin_user(), True], @@ -3362,23 +3326,6 @@ def test_archive_service_prompts_user_error( 'main.archive_service', service_id=SERVICE_ONE_ID ) - # delete_link = settings_page.select('.page-footer-link a')[0] - # assert normalize_spaces(delete_link.text) == 'Delete this service' - # assert delete_link['href'] == url_for( - # 'main.archive_service', - # service_id=SERVICE_ONE_ID, - # ) - # - # delete_page = client_request.get( - # 'main.archive_service', - # service_id=SERVICE_ONE_ID, - # ) - # assert normalize_spaces(delete_page.select_one('.banner-dangerous').text) == ( - # 'Are you sure you want to delete ‘service one’? ' - # 'There’s no way to undo this. ' - # 'Yes, delete' - # ) - # assert mock_api.called is False def test_cant_archive_inactive_service( @@ -3446,9 +3393,6 @@ def test_suspend_service_after_confirm_error( ), ) - # mock_api.assert_called_once_with('/service/{}/suspend'.format(SERVICE_ONE_ID), data=None) - # mock_event.assert_called_once_with(service_id=SERVICE_ONE_ID, suspended_by_id=user['id']) - @pytest.mark.parametrize('user', ( create_platform_admin_user(), @@ -3719,20 +3663,6 @@ def test_send_files_by_email_contact_details_does_not_update_invalid_contact_det @pytest.mark.parametrize('endpoint, permissions, expected_p', [ - # ( - # 'main.service_set_inbound_sms', - # ['sms'], - # ( - # 'Contact us if you want to be able to receive text messages from your users.' - # ) - # ), - # ( - # 'main.service_set_inbound_sms', - # ['sms', 'inbound_sms'], - # ( - # 'Your service can receive text messages sent to 2028675301.' - # ) - # ), ( 'main.service_set_auth_type', [], @@ -3960,7 +3890,6 @@ def test_update_service_organisation_does_not_update_if_same_value( @pytest.mark.skip(reason="Email currently deactivated") @pytest.mark.parametrize('single_branding_option, expected_href', [ (True, f'/services/{SERVICE_ONE_ID}/service-settings/email-branding/something-else'), - # (False, f'/services/{SERVICE_ONE_ID}/service-settings/email-branding'), ]) def test_service_settings_links_to_branding_request_page_for_emails( service_one, @@ -3974,10 +3903,6 @@ def test_service_settings_links_to_branding_request_page_for_emails( # should only have a "something else" option # so we go straight to that form service_one['organisation_type'] = 'other' - # else: - # # expect to have a "NHS" option as well as the - # # fallback one, so ask user to choose - # service_one['organisation_type'] = 'nhs_central' page = client_request.get( '.service_settings', service_id=SERVICE_ONE_ID