From f012ec57c0d95e57a9582ea5272ad210fd2b09bf Mon Sep 17 00:00:00 2001 From: chrisw Date: Mon, 25 Sep 2017 15:14:13 +0100 Subject: [PATCH] Allow user to add multiple reply-to addresses --- app/main/forms.py | 3 +- app/main/views/service_settings.py | 77 ++++-- app/notify_client/service_api_client.py | 36 +++ app/templates/components/table.html | 1 - app/templates/views/service-settings.html | 14 +- .../service-settings/email-reply-to/add.html | 33 +++ .../service-settings/email-reply-to/edit.html | 35 +++ .../service-settings/email_reply_to.html | 45 ++++ package-lock.json | 30 +-- .../test_inbound_sms_setting.py | 1 + tests/app/main/views/test_service_settings.py | 225 +++++++++++++++--- tests/conftest.py | 108 ++++++++- 12 files changed, 533 insertions(+), 75 deletions(-) create mode 100644 app/templates/views/service-settings/email-reply-to/add.html create mode 100644 app/templates/views/service-settings/email-reply-to/edit.html create mode 100644 app/templates/views/service-settings/email_reply_to.html diff --git a/app/main/forms.py b/app/main/forms.py index 74356b0a5..b66950051 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -467,8 +467,9 @@ class ProviderForm(Form): priority = IntegerField('Priority', [validators.NumberRange(min=1, max=100, message="Must be between 1 and 100")]) -class ServiceReplyToEmailFrom(Form): +class ServiceReplyToEmailForm(Form): email_address = email_address(label='Email reply to address') + is_default = BooleanField("Make this address the default") class ServiceSmsSender(Form): diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index da2cb1229..866d19873 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -27,7 +27,7 @@ from app.main.forms import ( ConfirmPasswordForm, ServiceNameForm, RequestToGoLiveForm, - ServiceReplyToEmailFrom, + ServiceReplyToEmailForm, ServiceSmsSender, ServiceLetterContactBlock, ServiceBrandingOrg, @@ -67,7 +67,11 @@ def service_settings(service_id): inbound_number = inbound_number_client.get_inbound_sms_number_for_service(service_id) disp_inbound_number = inbound_number['data'].get('number', '') - + reply_to_email_addresses = service_api_client.get_reply_to_email_addresses(service_id) + reply_to_email_address_count = len(reply_to_email_addresses) + default_reply_to_email_address = next( + (x['email_address'] for x in reply_to_email_addresses if x['is_default']), "None" + ) return render_template( 'views/service-settings.html', organisation=organisation, @@ -77,7 +81,9 @@ def service_settings(service_id): can_receive_inbound=('inbound_sms' in current_service['permissions']), inbound_api_url=inbound_api_url, letter_contact_block=Field(current_service['letter_contact_block'], html='escape'), - inbound_number=disp_inbound_number + inbound_number=disp_inbound_number, + default_reply_to_email_address=default_reply_to_email_address, + reply_to_email_address_count=reply_to_email_address_count ) @@ -308,23 +314,64 @@ def service_set_email(service_id): ) -@main.route("/services//service-settings/set-reply-to-email", methods=['GET', 'POST']) +@main.route("/services//service-settings/set-reply-to-email", methods=['GET']) @login_required @user_has_permissions('manage_settings', admin_override=True) def service_set_reply_to_email(service_id): - form = ServiceReplyToEmailFrom() - if request.method == 'GET': - form.email_address.data = current_service.get('reply_to_email_address') - if form.validate_on_submit(): - service_api_client.update_service( - current_service['id'], - reply_to_email_address=form.email_address.data - ) - return redirect(url_for('.service_settings', service_id=service_id)) + return redirect(url_for('.service_email_reply_to', service_id=service_id)) + +@main.route("/services//service-settings/email-reply-to", methods=['GET']) +@login_required +@user_has_permissions('manage_settings', admin_override=True) +def service_email_reply_to(service_id): + reply_to_email_addresses = service_api_client.get_reply_to_email_addresses(service_id) return render_template( - 'views/service-settings/set-reply-to-email.html', - form=form) + 'views/service-settings/email_reply_to.html', + reply_to_email_addresses=reply_to_email_addresses) + + +@main.route("/services//service-settings/email-reply-to/add", methods=['GET', 'POST']) +@login_required +@user_has_permissions('manage_settings', admin_override=True) +def service_add_email_reply_to(service_id): + form = ServiceReplyToEmailForm() + reply_to_email_address_count = len(service_api_client.get_reply_to_email_addresses(service_id)) + first_email_address = reply_to_email_address_count == 0 + if form.validate_on_submit(): + service_api_client.add_reply_to_email_address( + current_service['id'], + email_address=form.email_address.data, + is_default=first_email_address if first_email_address else form.is_default.data + ) + return redirect(url_for('.service_email_reply_to', service_id=service_id)) + return render_template( + 'views/service-settings/email-reply-to/add.html', + form=form, + first_email_address=first_email_address) + + +@main.route("/services//service-settings/email-reply-to//edit", methods=['GET', 'POST']) +@login_required +@user_has_permissions('manage_settings', admin_override=True) +def service_edit_email_reply_to(service_id, reply_to_email_id): + form = ServiceReplyToEmailForm() + reply_to_email_address = service_api_client.get_reply_to_email_address(service_id, reply_to_email_id) + if request.method == 'GET': + form.email_address.data = reply_to_email_address['email_address'] + form.is_default.data = reply_to_email_address['is_default'] + if form.validate_on_submit(): + service_api_client.update_reply_to_email_address( + current_service['id'], + reply_to_email_id=reply_to_email_id, + email_address=form.email_address.data, + is_default=True if reply_to_email_address['is_default'] else form.is_default.data + ) + return redirect(url_for('.service_email_reply_to', service_id=service_id)) + return render_template( + 'views/service-settings/email-reply-to/edit.html', + form=form, + reply_to_email_address_id=reply_to_email_address['id']) @main.route("/services//service-settings/set-sms-sender", methods=['GET', 'POST']) diff --git a/app/notify_client/service_api_client.py b/app/notify_client/service_api_client.py index ede5ae3c6..39e067032 100644 --- a/app/notify_client/service_api_client.py +++ b/app/notify_client/service_api_client.py @@ -282,6 +282,42 @@ class ServiceAPIClient(NotifyAdminAPIClient): ) )['data'] + def get_reply_to_email_addresses(self, service_id): + return self.get( + "/service/{}/email-reply-to".format( + service_id + ) + ) + + def get_reply_to_email_address(self, service_id, reply_to_email_id): + return self.get( + "/service/{}/email-reply-to/{}".format( + service_id, + reply_to_email_id + ) + ) + + def add_reply_to_email_address(self, service_id, email_address, is_default=False): + return self.post( + "/service/{}/email-reply-to".format(service_id), + data={ + "email_address": email_address, + "is_default": is_default + } + ) + + def update_reply_to_email_address(self, service_id, reply_to_email_id, email_address, is_default=False): + return self.post( + "/service/{}/email-reply-to/{}".format( + service_id, + reply_to_email_id, + ), + data={ + "email_address": email_address, + "is_default": is_default + } + ) + class ServicesBrowsableItem(BrowsableItem): @property diff --git a/app/templates/components/table.html b/app/templates/components/table.html index 57a5d995e..a9f9fa2ec 100644 --- a/app/templates/components/table.html +++ b/app/templates/components/table.html @@ -25,7 +25,6 @@ {%- endmacro %} {% macro list_table(items, caption='', empty_message='', field_headings=[], field_headings_visible=True, caption_visible=True) -%} - {% set parent_caller = caller %} {% call mapping_table(caption, field_headings, field_headings_visible, caption_visible) %} diff --git a/app/templates/views/service-settings.html b/app/templates/views/service-settings.html index 873a590fb..193705cf1 100644 --- a/app/templates/views/service-settings.html +++ b/app/templates/views/service-settings.html @@ -45,11 +45,15 @@ {% call row() %} {{ text_field('Email reply to address') }} - {{ text_field( - current_service.reply_to_email_address, - status='' if current_service.reply_to_email_address else 'default' - ) }} - {{ edit_field('Change', url_for('.service_set_reply_to_email', service_id=current_service.id)) }} + {% call field() %} + {{ default_reply_to_email_address }} + {% if reply_to_email_address_count > 1 %} +
+ {{ '…and %d more' | format(reply_to_email_address_count - 1) }} +
+ {% endif %} + {% endcall %} + {{ edit_field('Change', url_for('.service_email_reply_to', service_id=current_service.id)) }} {% endcall %} {% endif %} diff --git a/app/templates/views/service-settings/email-reply-to/add.html b/app/templates/views/service-settings/email-reply-to/add.html new file mode 100644 index 000000000..d4fe351ce --- /dev/null +++ b/app/templates/views/service-settings/email-reply-to/add.html @@ -0,0 +1,33 @@ +{% extends "withnav_template.html" %} +{% from "components/textbox.html" import textbox %} +{% from "components/checkbox.html" import checkbox %} +{% from "components/page-footer.html" import page_footer %} + +{% block service_page_title %} + Add email reply to address +{% endblock %} + +{% block maincolumn_content %} + +

+ Add email reply to address +

+
+ {{ textbox( + form.email_address, + width='2-3', + safe_error_message=True + ) }} + {% if not first_email_address %} +
+ {{ checkbox(form.is_default) }} +
+ {% endif %} + {{ page_footer( + 'Add', + back_link=url_for('.service_email_reply_to', service_id=current_service.id), + back_link_text='Back' + ) }} +
+ +{% endblock %} \ No newline at end of file diff --git a/app/templates/views/service-settings/email-reply-to/edit.html b/app/templates/views/service-settings/email-reply-to/edit.html new file mode 100644 index 000000000..607171789 --- /dev/null +++ b/app/templates/views/service-settings/email-reply-to/edit.html @@ -0,0 +1,35 @@ +{% extends "withnav_template.html" %} +{% from "components/textbox.html" import textbox %} +{% from "components/checkbox.html" import checkbox %} +{% from "components/page-footer.html" import page_footer %} + +{% block service_page_title %} + Edit email reply to address +{% endblock %} + +{% block maincolumn_content %} + +

+ Edit email reply to address +

+
+ {{ textbox( + form.email_address, + width='2-3', + safe_error_message=True + ) }} + {% if form.is_default.data %} +

This email address is the default

+ {% else %} +
+ {{ checkbox(form.is_default) }} +
+ {% endif %} + {{ page_footer( + 'Save', + back_link=url_for('.service_email_reply_to', service_id=current_service.id), + back_link_text='Back' + ) }} +
+ +{% endblock %} \ No newline at end of file diff --git a/app/templates/views/service-settings/email_reply_to.html b/app/templates/views/service-settings/email_reply_to.html new file mode 100644 index 000000000..baa3f035a --- /dev/null +++ b/app/templates/views/service-settings/email_reply_to.html @@ -0,0 +1,45 @@ +{% extends "withnav_template.html" %} +{% from "components/textbox.html" import textbox %} +{% from "components/page-footer.html" import page_footer %} +{% from "components/table.html" import row_group, row, text_field, edit_field, field, boolean_field, list_table %} + +{% block service_page_title %} + Email reply to addresses +{% endblock %} + +{% block maincolumn_content %} + +
+
+

+ Email reply to addresses +

+
+ +
+
+ {% call(item, row_number) list_table( + reply_to_email_addresses, + empty_message="You haven’t added any email addresses yet.", + caption="Reply to email addresses", + caption_visible=false, + field_headings=[ + 'Email addresses', + 'Action' + ], + field_headings_visible=False + ) %} + {% call field() %} + {{ item.email_address }} + {% if item.is_default %} + + {{ "(default)" }} + + {% endif %} + {% endcall %} + {{ edit_field('Change', url_for('.service_edit_email_reply_to', service_id =current_service.id, reply_to_email_id = item.id)) }} + {% endcall %} +
+{% endblock %} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e36f40553..1a0413b0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2597,6 +2597,16 @@ } } }, + "govuk_frontend_toolkit": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/govuk_frontend_toolkit/-/govuk_frontend_toolkit-5.2.0.tgz", + "integrity": "sha1-9fbFrkjkMey5fYuAix6Nt3gqvH8=" + }, + "govuk_template_jinja": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/govuk_template_jinja/-/govuk_template_jinja-0.19.2.tgz", + "integrity": "sha1-oNCTHJrLnYgtXsRGvocyxWxTarU=" + }, "govuk-elements-sass": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/govuk-elements-sass/-/govuk-elements-sass-3.0.3.tgz", @@ -2612,16 +2622,6 @@ } } }, - "govuk_frontend_toolkit": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/govuk_frontend_toolkit/-/govuk_frontend_toolkit-5.2.0.tgz", - "integrity": "sha1-9fbFrkjkMey5fYuAix6Nt3gqvH8=" - }, - "govuk_template_jinja": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/govuk_template_jinja/-/govuk_template_jinja-0.19.2.tgz", - "integrity": "sha1-oNCTHJrLnYgtXsRGvocyxWxTarU=" - }, "graceful-fs": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", @@ -5782,6 +5782,11 @@ } } }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, "string-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz", @@ -5801,11 +5806,6 @@ "strip-ansi": "3.0.1" } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", diff --git a/tests/app/main/views/service_settings/test_inbound_sms_setting.py b/tests/app/main/views/service_settings/test_inbound_sms_setting.py index feb69e7fc..a27609ae0 100644 --- a/tests/app/main/views/service_settings/test_inbound_sms_setting.py +++ b/tests/app/main/views/service_settings/test_inbound_sms_setting.py @@ -26,6 +26,7 @@ def test_get_inbound_number_in_service_settings( logged_in_client, mock_update_service, mock_get_letter_organisations, + single_reply_to_email_addresses, service_one, mocker ): diff --git a/tests/app/main/views/test_service_settings.py b/tests/app/main/views/test_service_settings.py index a11bcd0ec..ec0eacef4 100644 --- a/tests/app/main/views/test_service_settings.py +++ b/tests/app/main/views/test_service_settings.py @@ -10,8 +10,17 @@ import app from app.main.views.service_settings import dummy_bearer_token from app.utils import email_safe from tests import validate_route_permission, service_json -from tests.conftest import active_user_with_permissions, platform_admin_user -from tests.conftest import normalize_spaces +from tests.conftest import ( + active_user_with_permissions, + platform_admin_user, + normalize_spaces, + no_reply_to_email_addresses, + single_reply_to_email_addresses, + multiple_reply_to_email_addresses, + get_default_reply_to_email_address, + get_non_default_reply_to_email_address, + SERVICE_ONE_ID + ) @pytest.mark.parametrize('user, expected_rows', [ @@ -64,6 +73,7 @@ def test_should_show_overview( service_one, fake_uuid, mock_get_letter_organisations, + no_reply_to_email_addresses, user, expected_rows, mock_get_inbound_number_for_service @@ -115,7 +125,7 @@ def test_should_show_overview( 'Label Value Action', 'Send text messages On Change', - 'Text message sender elevenchars Change', + 'Text message sender GOVUK Change', 'International text messages Off Change', 'Receive text messages Off Change', @@ -128,17 +138,18 @@ def test_should_show_overview_for_service_with_more_things_set( client, active_user_with_permissions, mocker, - service_with_reply_to_addresses, + service_one, + single_reply_to_email_addresses, mock_get_organisation, mock_get_letter_organisations, mock_get_inbound_number_for_service, permissions, expected_rows ): - client.login(active_user_with_permissions, mocker, service_with_reply_to_addresses) - service_with_reply_to_addresses['permissions'] = permissions + client.login(active_user_with_permissions, mocker, service_one) + service_one['permissions'] = permissions response = client.get(url_for( - 'main.service_settings', service_id=service_with_reply_to_addresses['id'] + 'main.service_settings', service_id=service_one['id'] )) page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') for index, row in enumerate(expected_rows): @@ -154,6 +165,7 @@ def test_service_settings_show_elided_api_url_if_needed( logged_in_platform_admin_client, service_one, mock_get_letter_organisations, + single_reply_to_email_addresses, mocker, fake_uuid, url, @@ -198,6 +210,7 @@ def test_if_can_receive_inbound_then_cant_change_sms_sender( logged_in_client, service_one, mock_get_letter_organisations, + single_reply_to_email_addresses, mock_get_inbound_number_for_service ): service_one['permissions'] = ['email', 'sms', 'inbound_sms'] @@ -216,6 +229,7 @@ def test_letter_contact_block_shows_none_if_not_set( logged_in_client, service_one, mocker, + single_reply_to_email_addresses, mock_get_letter_organisations, mock_get_inbound_number_for_service ): @@ -234,6 +248,7 @@ def test_escapes_letter_contact_block( logged_in_client, service_one, mocker, + single_reply_to_email_addresses, mock_get_letter_organisations, mock_get_inbound_number_for_service ): @@ -283,6 +298,7 @@ def test_show_restricted_service( logged_in_client, service_one, mock_get_letter_organisations, + single_reply_to_email_addresses, mock_get_inbound_number_for_service ): response = logged_in_client.get(url_for('main.service_settings', service_id=service_one['id'])) @@ -314,6 +330,7 @@ def test_show_live_service( logged_in_client, service_one, mock_get_live_service, + single_reply_to_email_addresses, mock_get_letter_organisations, mock_get_inbound_number_for_service ): @@ -435,6 +452,7 @@ def test_should_redirect_after_request_to_go_live( active_user_with_permissions, service_one, mocker, + single_reply_to_email_addresses, mock_get_letter_organisations, mock_get_inbound_number_for_service ): @@ -528,6 +546,7 @@ def test_route_permissions( client, api_user_active, service_one, + single_reply_to_email_addresses, mock_get_letter_organisations, route, mock_get_inbound_number_for_service @@ -585,6 +604,7 @@ def test_route_for_platform_admin( client, platform_admin_user, service_one, + single_reply_to_email_addresses, mock_get_letter_organisations, route, mock_get_inbound_number_for_service @@ -652,37 +672,173 @@ def test_enabling_and_disabling_email_and_sms( assert mocked_fn.call_args == call(service_one['id'], {'permissions': permissions_after_switch}) -def test_set_reply_to_email_address( - logged_in_client, - mock_update_service, +def test_reply_to_hint_appears_when_service_has_multiple_reply_to_addresses( + client_request, + multiple_reply_to_email_addresses, service_one, mock_get_letter_organisations, mock_get_inbound_number_for_service ): - service_one['permissions'] = ['email'] - data = {"email_address": "test@someservice.gov.uk"} - response = logged_in_client.post(url_for('main.service_set_reply_to_email', service_id=service_one['id']), - data=data, - follow_redirects=True) - assert response.status_code == 200 - mock_update_service.assert_called_with( - service_one['id'], - reply_to_email_address="test@someservice.gov.uk" + page = client_request.get( + 'main.service_settings', + service_id=service_one['id'] + ) + + assert normalize_spaces( + page.select('tbody tr')[2].text + ) == "Email reply to address test@example.com …and 2 more Change" + + +def test_default_email_reply_to_address_has_default_hint( + client_request, + multiple_reply_to_email_addresses +): + page = client_request.get( + 'main.service_email_reply_to', + service_id=SERVICE_ONE_ID + ) + + assert normalize_spaces(page.select('tbody tr')[0].text) == "test@example.com (default) Change" + assert normalize_spaces(page.select('tbody tr')[1].text) == "test2@example.com Change" + assert normalize_spaces(page.select('tbody tr')[2].text) == "test3@example.com Change" + assert len(page.select('tbody tr')) == 3 + + +def test_no_reply_to_email_addresses_message_shows( + client_request, + no_reply_to_email_addresses +): + page = client_request.get( + 'main.service_email_reply_to', + service_id=SERVICE_ONE_ID + ) + + assert normalize_spaces(page.select('tbody tr')[0].text) == "You haven’t added any email addresses yet." + assert len(page.select('tbody tr')) == 1 + + +@pytest.mark.parametrize('reply_to_input, expected_error', [ + ('', 'Can’t be empty'), + ('testtest', 'Enter a valid email address'), + ('test@hello.com', 'Enter a government email address. If you think you should have access contact us') +]) +def test_incorrect_reply_to_email_address( + reply_to_input, + expected_error, + client_request, + no_reply_to_email_addresses +): + page = client_request.post( + 'main.service_add_email_reply_to', + service_id=SERVICE_ONE_ID, + _data={'email_address': reply_to_input}, + _expected_status=200 + ) + + assert normalize_spaces(page.select_one('.error-message').text) == expected_error + + +@pytest.mark.parametrize('fixture, data, api_default_args', [ + (no_reply_to_email_addresses, {}, True), + (multiple_reply_to_email_addresses, {}, False), + (multiple_reply_to_email_addresses, {"is_default": "y"}, True) +]) +def test_add_reply_to_email_address( + fixture, + data, + api_default_args, + mocker, + client_request, + mock_add_reply_to_email_address +): + fixture(mocker) + data['email_address'] = "test@example.gov.uk" + page = client_request.post( + 'main.service_add_email_reply_to', + service_id=SERVICE_ONE_ID, + _data=data + ) + + mock_add_reply_to_email_address.assert_called_once_with( + SERVICE_ONE_ID, + email_address="test@example.gov.uk", + is_default=api_default_args ) -def test_if_reply_to_email_address_set_then_form_populated( - logged_in_client, - service_one, - mock_get_inbound_number_for_service +@pytest.mark.parametrize('fixture, checkbox_present', [ + (no_reply_to_email_addresses, False), + (multiple_reply_to_email_addresses, True) +]) +def test_default_box_shows_on_first_email_address( + fixture, + mocker, + checkbox_present, + client_request ): - service_one['permissions'] = ['email'] - service_one['reply_to_email_address'] = 'test@service.gov.uk' - response = logged_in_client.get(url_for('main.service_set_reply_to_email', service_id=service_one['id'])) + fixture(mocker) + page = client_request.get( + 'main.service_add_email_reply_to', + service_id=SERVICE_ONE_ID + ) - assert response.status_code == 200 - page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') - assert page.find(id='email_address')['value'] == 'test@service.gov.uk' + assert bool(page.select_one('[name=is_default]')) == checkbox_present + + +@pytest.mark.parametrize('fixture, data, api_default_args', [ + (get_default_reply_to_email_address, {"is_default": "y"}, True), + (get_default_reply_to_email_address, {}, True), + (get_non_default_reply_to_email_address, {}, False), + (get_non_default_reply_to_email_address, {"is_default": "y"}, True) +]) +def test_edit_reply_to_email_address( + fixture, + data, + api_default_args, + mocker, + fake_uuid, + client_request, + mock_update_reply_to_email_address +): + fixture(mocker) + data['email_address'] = "test@example.gov.uk" + page = client_request.post( + 'main.service_edit_email_reply_to', + service_id=SERVICE_ONE_ID, + reply_to_email_id=fake_uuid, + _data=data + ) + + mock_update_reply_to_email_address.assert_called_once_with( + SERVICE_ONE_ID, + reply_to_email_id=fake_uuid, + email_address="test@example.gov.uk", + is_default=api_default_args + ) + + +@pytest.mark.parametrize('fixture, checkbox_present', [ + (get_default_reply_to_email_address, False), + (get_non_default_reply_to_email_address, True) +]) +def test_default_box_shows_on_non_default_email_addresses_while_editing( + fixture, + fake_uuid, + mocker, + checkbox_present, + client_request +): + fixture(mocker) + page = client_request.get( + 'main.service_edit_email_reply_to', + service_id=SERVICE_ONE_ID, + reply_to_email_id=fake_uuid + ) + + if checkbox_present: + assert page.select_one('[name=is_default]') + else: + assert normalize_spaces(page.select_one('form p').text) == "This email address is the default" def test_switch_service_to_research_mode( @@ -731,6 +887,7 @@ def test_shows_research_mode_indicator( service_one, mocker, mock_get_letter_organisations, + single_reply_to_email_addresses, mock_get_inbound_number_for_service ): service_one['research_mode'] = True @@ -748,6 +905,7 @@ def test_does_not_show_research_mode_indicator( logged_in_client, service_one, mock_get_letter_organisations, + single_reply_to_email_addresses, mock_get_inbound_number_for_service ): response = logged_in_client.get(url_for('main.service_settings', service_id=service_one['id'])) @@ -1176,6 +1334,7 @@ def test_archive_service_prompts_user( logged_in_platform_admin_client, service_one, mocker, + single_reply_to_email_addresses, mock_get_letter_organisations, mock_get_inbound_number_for_service ): @@ -1192,6 +1351,7 @@ def test_archive_service_prompts_user( def test_cant_archive_inactive_service( logged_in_platform_admin_client, service_one, + single_reply_to_email_addresses, mock_get_letter_organisations, mock_get_inbound_number_for_service ): @@ -1223,6 +1383,7 @@ def test_suspend_service_prompts_user( logged_in_platform_admin_client, service_one, mocker, + single_reply_to_email_addresses, mock_get_letter_organisations, mock_get_inbound_number_for_service ): @@ -1240,6 +1401,7 @@ def test_suspend_service_prompts_user( def test_cant_suspend_inactive_service( logged_in_platform_admin_client, service_one, + single_reply_to_email_addresses, mock_get_letter_organisations, mock_get_inbound_number_for_service ): @@ -1255,6 +1417,7 @@ def test_cant_suspend_inactive_service( def test_resume_service_after_confirm( logged_in_platform_admin_client, service_one, + single_reply_to_email_addresses, mocker, mock_get_inbound_number_for_service ): @@ -1271,6 +1434,7 @@ def test_resume_service_after_confirm( def test_resume_service_prompts_user( logged_in_platform_admin_client, service_one, + single_reply_to_email_addresses, mocker, mock_get_letter_organisations, mock_get_inbound_number_for_service @@ -1290,6 +1454,7 @@ def test_resume_service_prompts_user( def test_cant_resume_active_service( logged_in_platform_admin_client, service_one, + single_reply_to_email_addresses, mock_get_letter_organisations, mock_get_inbound_number_for_service ): @@ -1365,6 +1530,7 @@ def test_invitation_pages( def test_service_settings_when_inbound_number_is_not_set( logged_in_client, service_one, + single_reply_to_email_addresses, mocker, mock_get_letter_organisations, ): @@ -1379,6 +1545,7 @@ def test_service_settings_when_inbound_number_is_not_set( def test_set_inbound_sms_when_inbound_number_is_not_set( logged_in_client, service_one, + single_reply_to_email_addresses, mocker, mock_get_letter_organisations, ): diff --git a/tests/conftest.py b/tests/conftest.py index 167d2d598..c549519c6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -50,14 +50,105 @@ def service_one(api_user_active): @pytest.fixture(scope='function') -def service_with_reply_to_addresses(api_user_active): - return service_json( - SERVICE_ONE_ID, - 'service one', - [api_user_active.id], - reply_to_email_address='test@example.com', - sms_sender='elevenchars', - ) +def multiple_reply_to_email_addresses(mocker): + def _get(service_id): + return [ + { + 'id': '1234', + 'service_id': service_id, + 'email_address': 'test@example.com', + 'is_default': True, + 'created_at': datetime.utcnow(), + 'updated_at': None + }, { + 'id': '5678', + 'service_id': service_id, + 'email_address': 'test2@example.com', + 'is_default': False, + 'created_at': datetime.utcnow(), + 'updated_at': None + }, { + 'id': '9457', + 'service_id': service_id, + 'email_address': 'test3@example.com', + 'is_default': False, + 'created_at': datetime.utcnow(), + 'updated_at': None + } + ] + + return mocker.patch('app.service_api_client.get_reply_to_email_addresses', side_effect=_get) + + +@pytest.fixture(scope='function') +def no_reply_to_email_addresses(mocker): + def _get(service_id): + return [] + + return mocker.patch('app.service_api_client.get_reply_to_email_addresses', side_effect=_get) + + +@pytest.fixture(scope='function') +def single_reply_to_email_addresses(mocker): + def _get(service_id): + return [ + { + 'id': '1234', + 'service_id': service_id, + 'email_address': 'test@example.com', + 'is_default': True, + 'created_at': datetime.utcnow(), + 'updated_at': None + } + ] + + return mocker.patch('app.service_api_client.get_reply_to_email_addresses', side_effect=_get) + + +@pytest.fixture(scope='function') +def get_default_reply_to_email_address(mocker): + def _get(service_id, reply_to_email_id): + return { + 'id': '1234', + 'service_id': service_id, + 'email_address': 'test@example.com', + 'is_default': True, + 'created_at': datetime.utcnow(), + 'updated_at': None + } + + return mocker.patch('app.service_api_client.get_reply_to_email_address', side_effect=_get) + + +@pytest.fixture(scope='function') +def get_non_default_reply_to_email_address(mocker): + def _get(service_id, reply_to_email_id): + return { + 'id': '1234', + 'service_id': service_id, + 'email_address': 'test@example.com', + 'is_default': False, + 'created_at': datetime.utcnow(), + 'updated_at': None + } + + return mocker.patch('app.service_api_client.get_reply_to_email_address', side_effect=_get) + + +@pytest.fixture(scope='function') +def mock_add_reply_to_email_address(mocker): + def _add_reply_to(service_id, email_address, is_default=False): + return + + return mocker.patch('app.service_api_client.add_reply_to_email_address', side_effect=_add_reply_to) + + +@pytest.fixture(scope='function') +def mock_update_reply_to_email_address(mocker): + def _update_reply_to(service_id, reply_to_email_id, email_address, is_default=False): + return + + return mocker.patch('app.service_api_client.update_reply_to_email_address', side_effect=_update_reply_to) @pytest.fixture(scope='function') @@ -206,7 +297,6 @@ def mock_update_service(mocker): 'active', 'restricted', 'email_from', - 'reply_to_email_address', 'sms_sender', 'permissions' ]}