From 84de1c5625d73a204761b2c3ef2d02aec9f78e3d Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Tue, 12 Jun 2018 16:17:20 +0100 Subject: [PATCH] Let caseworkers send one off messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The main task that we think ‘caseworker’ users do is send one off messages. So this commit: - makes sure users who don’t have the `view_activity` permission (ie not ‘admin’ users) can still send messages - adds navigation so that these users have a place to go from which to start the process of sending a one off message --- app/__init__.py | 8 +- app/main/views/notifications.py | 4 +- app/main/views/templates.py | 16 +- app/navigation.py | 219 +++++++++++++++++++++ app/templates/main_nav.html | 54 +---- app/templates/partials/tour.html | 40 ++++ app/templates/views/templates/choose.html | 7 +- tests/app/main/views/test_notifications.py | 9 + tests/app/main/views/test_send.py | 141 +++++++++++-- tests/app/main/views/test_templates.py | 24 +++ tests/app/test_navigation.py | 58 ++++-- 11 files changed, 489 insertions(+), 91 deletions(-) create mode 100644 app/templates/partials/tour.html diff --git a/app/__init__.py b/app/__init__.py index d3f74b9b5..bff65c3b1 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -40,7 +40,12 @@ from werkzeug.local import LocalProxy from app import proxy_fix from app.config import configs from app.asset_fingerprinter import AssetFingerprinter -from app.navigation import HeaderNavigation, MainNavigation, OrgNavigation +from app.navigation import ( + CaseworkNavigation, + HeaderNavigation, + MainNavigation, + OrgNavigation +) from app.notify_client.service_api_client import ServiceAPIClient from app.notify_client.api_key_api_client import ApiKeyApiClient from app.notify_client.invite_api_client import InviteApiClient @@ -96,6 +101,7 @@ current_service = LocalProxy(partial(_lookup_req_object, 'service')) current_organisation = LocalProxy(partial(_lookup_req_object, 'organisation')) navigation = { + 'casework_navigation': CaseworkNavigation(), 'main_navigation': MainNavigation(), 'header_navigation': HeaderNavigation(), 'org_navigation': OrgNavigation(), diff --git a/app/main/views/notifications.py b/app/main/views/notifications.py index 0e1ef62a3..c43cb5fc7 100644 --- a/app/main/views/notifications.py +++ b/app/main/views/notifications.py @@ -42,7 +42,7 @@ from app.utils import ( @main.route("/services//notification/") @login_required -@user_has_permissions('view_activity') +@user_has_permissions('view_activity', 'send_messages') def view_notification(service_id, notification_id): notification = notification_api_client.get_notification(service_id, str(notification_id)) notification['template'].update({'reply_to_text': notification['reply_to_text']}) @@ -126,7 +126,7 @@ def view_letter_notification_as_preview(service_id, notification_id, filetype): @main.route("/services//notification/.json") -@user_has_permissions('view_activity') +@user_has_permissions('view_activity', 'send_messages') def view_notification_updates(service_id, notification_id): return jsonify(**get_single_notification_partials( notification_api_client.get_notification(service_id, notification_id) diff --git a/app/main/views/templates.py b/app/main/views/templates.py index 47b97a8f5..c2776ccd8 100644 --- a/app/main/views/templates.py +++ b/app/main/views/templates.py @@ -41,8 +41,12 @@ page_headings = { @main.route("/services//templates/") @login_required -@user_has_permissions('view_activity') +@user_has_permissions('view_activity', 'send_messages') def view_template(service_id, template_id): + if not current_user.has_permissions('view_activity'): + return redirect(url_for( + '.send_one_off', service_id=service_id, template_id=template_id + )) template = service_api_client.get_service_template(service_id, str(template_id))['data'] if template["template_type"] == "letter": letter_contact_details = service_api_client.get_letter_contacts(service_id) @@ -94,7 +98,7 @@ def start_tour(service_id, template_id): @main.route("/services//templates") @main.route("/services//templates/") @login_required -@user_has_permissions('view_activity') +@user_has_permissions('view_activity', 'send_messages') def choose_template(service_id, template_type='all'): templates = service_api_client.get_service_templates(service_id)['data'] @@ -117,8 +121,14 @@ def choose_template(service_id, template_type='all'): if template_type in ['all', template['template_type']] ] + if current_user.has_permissions('view_activity'): + page_title = 'Templates' + else: + page_title = 'Choose a template' + return render_template( 'views/templates/choose.html', + page_title=page_title, templates=templates_on_page, show_search_box=(len(templates_on_page) > 7), show_template_nav=has_multiple_template_types and (len(templates) > 2), @@ -130,7 +140,7 @@ def choose_template(service_id, template_type='all'): @main.route("/services//templates/.") @login_required -@user_has_permissions('view_activity') +@user_has_permissions('view_activity', 'send_messages') def view_letter_template_preview(service_id, template_id, filetype): if filetype not in ('pdf', 'png'): abort(404) diff --git a/app/navigation.py b/app/navigation.py index 186905a8b..7a85cd378 100644 --- a/app/navigation.py +++ b/app/navigation.py @@ -497,6 +497,225 @@ class MainNavigation(Navigation): } +class CaseworkNavigation(Navigation): + + mapping = { + 'send-one-off': { + 'choose_template', + 'send_one_off', + 'send_one_off_step', + 'send_test', + 'send_test_step', + 'view_notification', + }, + } + + exclude = { + 'accept_invite', + 'accept_org_invite', + 'action_blocked', + 'add_organisation', + 'add_service', + 'add_service_template', + 'add_template_by_type', + 'agreement', + 'api_callbacks', + 'api_documentation', + 'api_integration', + 'api_keys', + 'archive_service', + 'bat_phone', + 'branding_request', + 'callbacks', + 'cancel_invited_org_user', + 'cancel_invited_user', + 'cancel_job', + 'check_and_resend_text_code', + 'check_and_resend_verification_code', + 'check_messages', + 'check_messages_preview', + 'check_notification', + 'choose_account', + 'choose_service', + 'confirm_edit_organisation_name', + 'confirm_redact_template', + 'conversation', + 'conversation_reply', + 'conversation_reply_with_template', + 'conversation_updates', + 'cookies', + 'create_api_key', + 'create_email_branding', + 'delete_service_template', + 'delivery_and_failure', + 'delivery_status_callback', + 'design_content', + 'documentation', + 'download_agreement', + 'download_notifications_csv', + 'edit_organisation_name', + 'edit_provider', + 'edit_service_template', + 'edit_user_org_permissions', + 'edit_user_permissions', + 'email_branding', + 'email_not_received', + 'email_template', + 'error', + 'features', + 'feedback', + 'forgot_password', + 'get_example_csv', + 'get_notifications_as_json', + 'go_to_dashboard_after_tour', + 'inbound_sms_admin', + 'inbox', + 'inbox_download', + 'inbox_updates', + 'index', + 'information_risk_management', + 'information_security', + 'integration_testing', + 'invite_org_user', + 'invite_user', + 'letter_jobs', + 'link_service_to_organisation', + 'live_services', + 'manage_org_users', + 'manage_users', + 'monthly', + 'new_password', + 'old_integration_testing', + 'old_roadmap', + 'old_service_dashboard', + 'old_terms', + 'old_using_notify', + 'organisation_dashboard', + 'organisation_settings', + 'organisations', + 'platform_admin', + 'platform_admin_new', + 'platform_admin_list_complaints', + 'pricing', + 'privacy', + 'public_agreement', + 'public_download_agreement', + 'received_text_messages_callback', + 'redact_template', + 'register', + 'register_from_invite', + 'register_from_org_invite', + 'registration_continue', + 'remove_user_from_organisation', + 'remove_user_from_service', + 'request_to_go_live', + 'resend_email_link', + 'resend_email_verification', + 'resume_service', + 'revoke_api_key', + 'roadmap', + 'security', + 'send_messages', + 'send_notification', + 'send_test_preview', + 'service_add_email_reply_to', + 'service_add_letter_contact', + 'service_add_sms_sender', + 'service_confirm_delete_email_reply_to', + 'service_confirm_delete_sms_sender', + 'service_dashboard', + 'service_dashboard_updates', + 'service_delete_email_reply_to', + 'service_delete_sms_sender', + 'service_edit_email_reply_to', + 'service_edit_letter_contact', + 'service_edit_sms_sender', + 'service_email_reply_to', + 'service_letter_contact_details', + 'service_name_change', + 'service_name_change_confirm', + 'service_set_auth_type', + 'service_set_contact_link', + 'service_set_email', + 'service_set_email_branding', + 'service_set_inbound_number', + 'service_set_inbound_sms', + 'service_set_international_sms', + 'service_set_letter_contact_block', + 'service_set_letters', + 'service_set_reply_to_email', + 'service_set_sms', + 'service_set_sms_prefix', + 'service_settings', + 'service_sms_senders', + 'service_switch_can_send_email', + 'service_switch_can_send_precompiled_letter', + 'service_switch_can_send_sms', + 'service_switch_can_upload_document', + 'service_switch_caseworking', + 'service_switch_email_auth', + 'service_switch_live', + 'service_switch_research_mode', + 'services_or_dashboard', + 'set_free_sms_allowance', + 'set_letter_branding', + 'set_organisation_type', + 'set_sender', + 'set_template_sender', + 'show_accounts_or_dashboard', + 'sign_in', + 'sign_out', + 'start_job', + 'start_tour', + 'styleguide', + 'submit_request_to_go_live', + 'support', + 'suspend_service', + 'temp_service_history', + 'template_history', + 'template_usage', + 'terms', + 'thanks', + 'triage', + 'trial_mode', + 'trial_services', + 'two_factor', + 'two_factor_email', + 'two_factor_email_sent', + 'update_email_branding', + 'usage', + 'user_profile', + 'user_profile_email', + 'user_profile_email_authenticate', + 'user_profile_email_confirm', + 'user_profile_mobile_number', + 'user_profile_mobile_number_authenticate', + 'user_profile_mobile_number_confirm', + 'user_profile_name', + 'user_profile_password', + 'using_notify', + 'verify', + 'verify_email', + 'verify_mobile', + 'view_job', + 'view_job_csv', + 'view_job_updates', + 'view_jobs', + 'view_letter_notification_as_preview', + 'view_letter_template_preview', + 'view_notification_updates', + 'view_notifications', + 'view_notifications_csv', + 'view_provider', + 'view_providers', + 'view_template', + 'view_template_version', + 'view_template_version_preview', + 'view_template_versions', + 'whitelist', + } + + class OrgNavigation(Navigation): mapping = { diff --git a/app/templates/main_nav.html b/app/templates/main_nav.html index 6be863235..623bf3f40 100644 --- a/app/templates/main_nav.html +++ b/app/templates/main_nav.html @@ -1,53 +1,11 @@ -{% from "components/banner.html" import banner_wrapper %} - {% if help %} - {% call banner_wrapper(type='tour') %} -

Try sending yourself this example

-
-
-

1.

-
-
-

- Every message is sent from a template -

-
-
-
-
-

2.

-
-
-

- The template pulls in the data you provide -

-
-
-
-
-

3.

-
-
-

- Notify delivers the message -

- {% if help == '3' %} - - Now go to your dashboard - - {% endif %} -
-
- - {% endcall %} -{% else %} + {% include 'partials/tour.html' %} +{% elif current_user.has_permissions('view_activity') %} +{% else %} + {% endif %} diff --git a/app/templates/partials/tour.html b/app/templates/partials/tour.html new file mode 100644 index 000000000..9fba8b93e --- /dev/null +++ b/app/templates/partials/tour.html @@ -0,0 +1,40 @@ +{% from "components/banner.html" import banner_wrapper %} + +{% call banner_wrapper(type='tour') %} +

Try sending yourself this example

+
+
+

1.

+
+
+

+ Every message is sent from a template +

+
+
+
+
+

2.

+
+
+

+ The template pulls in the data you provide +

+
+
+
+
+

3.

+
+
+

+ Notify delivers the message +

+ {% if help == '3' %} + + Now go to your dashboard + + {% endif %} +
+
+{% endcall %} diff --git a/app/templates/views/templates/choose.html b/app/templates/views/templates/choose.html index 4aa6e71cb..8a5e98a7b 100644 --- a/app/templates/views/templates/choose.html +++ b/app/templates/views/templates/choose.html @@ -5,15 +5,14 @@ {% extends "withnav_template.html" %} {% block service_page_title %} - Templates + {{ page_title }} {% endblock %} {% block maincolumn_content %} {% if not templates %} -

Templates

- +

{{ page_title }}

{% if current_user.has_permissions('manage_templates') %}

You need a template before you can send @@ -39,7 +38,7 @@

-

Templates

+

{{ page_title }}

{% if current_user.has_permissions('manage_templates') %}
diff --git a/tests/app/main/views/test_notifications.py b/tests/app/main/views/test_notifications.py index 167b96157..87a943533 100644 --- a/tests/app/main/views/test_notifications.py +++ b/tests/app/main/views/test_notifications.py @@ -9,6 +9,8 @@ from notifications_python_client.errors import APIError from tests.conftest import ( SERVICE_ONE_ID, + active_caseworking_user, + active_user_with_permissions, mock_get_notification, normalize_spaces, ) @@ -23,16 +25,23 @@ from tests.conftest import ( ('permanent-failure', 'Phone number doesn’t exist'), ('technical-failure', 'Technical failure'), ]) +@pytest.mark.parametrize('user', [ + active_user_with_permissions, + active_caseworking_user, +]) @freeze_time("2016-01-01 11:09:00.061258") def test_notification_status_page_shows_details( client_request, mocker, service_one, fake_uuid, + user, notification_status, expected_status, ): + mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) + _mock_get_notification = mock_get_notification( mocker, fake_uuid, diff --git a/tests/app/main/views/test_send.py b/tests/app/main/views/test_send.py index 881e9fa34..e8b92b4f9 100644 --- a/tests/app/main/views/test_send.py +++ b/tests/app/main/views/test_send.py @@ -31,6 +31,8 @@ from tests import ( ) from tests.conftest import ( SERVICE_ONE_ID, + active_caseworking_user, + active_user_with_permissions, fake_uuid, mock_get_international_service, mock_get_live_service, @@ -50,6 +52,8 @@ from tests.conftest import ( template_types = ['email', 'sms'] +unchanging_fake_uuid = uuid.uuid4() + # The * ignores hidden files, eg .DS_Store test_spreadsheet_files = glob(path.join('tests', 'spreadsheet_files', '*')) test_non_spreadsheet_files = glob(path.join('tests', 'non_spreadsheet_files', '*')) @@ -845,6 +849,10 @@ def test_404_for_previewing_a_row_out_of_range( ) +@pytest.mark.parametrize('user', ( + active_user_with_permissions, + active_caseworking_user, +)) def test_send_test_doesnt_show_file_contents( logged_in_client, mocker, @@ -854,8 +862,9 @@ def test_send_test_doesnt_show_file_contents( mock_get_service_statistics, service_one, fake_uuid, + user, ): - + mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) mocker.patch('app.main.views.send.s3download', return_value=""" phone number 07700 900 986 @@ -874,13 +883,49 @@ def test_send_test_doesnt_show_file_contents( assert page.select_one('button[type=submit]').text.strip() == 'Send 1 text message' -@pytest.mark.parametrize('endpoint, template_mock, expected_recipient', [ - ('main.send_test_step', mock_get_service_template_with_placeholders, '07700 900762'), - ('main.send_test_step', mock_get_service_email_template, 'test@user.gov.uk'), - ('main.send_test_step', mock_get_service_letter_template, None), - ('main.send_one_off_step', mock_get_service_template, None), - ('main.send_one_off_step', mock_get_service_email_template, None), - ('main.send_one_off_step', mock_get_service_letter_template, None), +@pytest.mark.parametrize('user, endpoint, template_mock, expected_recipient', [ + ( + active_user_with_permissions, + 'main.send_test_step', + mock_get_service_template_with_placeholders, + '07700 900762' + ), + ( + active_user_with_permissions, + 'main.send_test_step', + mock_get_service_email_template, + 'test@user.gov.uk' + ), + ( + active_caseworking_user, + 'main.send_test_step', + mock_get_service_email_template, + 'caseworker@example.gov.uk' + ), + ( + active_user_with_permissions, + 'main.send_test_step', + mock_get_service_letter_template, + None + ), + ( + active_user_with_permissions, + 'main.send_one_off_step', + mock_get_service_template, + None + ), + ( + active_user_with_permissions, + 'main.send_one_off_step', + mock_get_service_email_template, + None + ), + ( + active_user_with_permissions, + 'main.send_one_off_step', + mock_get_service_letter_template, + None + ), ]) def test_send_test_step_redirects_if_session_not_setup( mocker, @@ -891,7 +936,9 @@ def test_send_test_step_redirects_if_session_not_setup( endpoint, template_mock, expected_recipient, + user, ): + mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) template_mock(mocker) mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=99) @@ -935,6 +982,10 @@ def test_send_one_off_does_not_send_without_the_correct_permissions( ) +@pytest.mark.parametrize('user', ( + active_user_with_permissions, + active_caseworking_user, +)) @pytest.mark.parametrize('template_mock, partial_url, expected_h1, tour_shown', [ ( mock_get_service_template_with_placeholders, @@ -994,8 +1045,9 @@ def test_send_one_off_or_test_has_correct_page_titles( partial_url, expected_h1, tour_shown, + user, ): - + mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) template_mock(mocker) mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=99) @@ -1011,6 +1063,10 @@ def test_send_one_off_or_test_has_correct_page_titles( assert (len(page.select('.banner-tour')) == 1) == tour_shown +@pytest.mark.parametrize('user', ( + active_user_with_permissions, + active_caseworking_user, +)) @pytest.mark.parametrize('template_mock, expected_link_text, expected_link_url', [ (mock_get_service_template, 'Use my phone number', partial(url_for, 'main.send_test')), (mock_get_service_email_template, 'Use my email address', partial(url_for, 'main.send_test')), @@ -1025,7 +1081,9 @@ def test_send_one_off_has_skip_link( template_mock, expected_link_text, expected_link_url, + user, ): + mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) template_mock(mocker) mocker.patch('app.main.views.send.get_page_count_for_letter', return_value=99) @@ -1048,14 +1106,21 @@ def test_send_one_off_has_skip_link( assert not skip_links +@pytest.mark.parametrize('user', ( + active_user_with_permissions, + active_caseworking_user, +)) def test_skip_link_will_not_show_on_sms_one_off_if_service_has_no_mobile_number( logged_in_client, service_one, fake_uuid, mock_get_service_template, - active_user_with_permissions + mocker, + user, ): - active_user_with_permissions.mobile_number = None + user = user(fake_uuid) + user.mobile_number = None + mocker.patch('app.user_api_client.get_user', return_value=user) response = logged_in_client.get( url_for('main.send_one_off_step', service_id=service_one['id'], template_id=fake_uuid, step_index=0), follow_redirects=True @@ -1065,6 +1130,10 @@ def test_skip_link_will_not_show_on_sms_one_off_if_service_has_no_mobile_number( assert not skip_links +@pytest.mark.parametrize('user', ( + active_user_with_permissions, + active_caseworking_user, +)) @pytest.mark.parametrize('endpoint, expected_redirect, placeholders', [ ( 'main.send_test_step', @@ -1084,7 +1153,10 @@ def test_send_test_redirects_to_end_if_step_out_of_bounds( endpoint, placeholders, expected_redirect, + mocker, + user, ): + mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) with logged_in_client.session_transaction() as session: session['placeholders'] = placeholders @@ -1106,6 +1178,10 @@ def test_send_test_redirects_to_end_if_step_out_of_bounds( assert response.location == expected_url +@pytest.mark.parametrize('user', ( + active_user_with_permissions, + active_caseworking_user, +)) @pytest.mark.parametrize('endpoint, expected_redirect', [ ('main.send_test_step', 'main.send_test'), ('main.send_one_off_step', 'main.send_one_off'), @@ -1121,7 +1197,9 @@ def test_send_test_redirects_to_start_if_you_skip_steps( mocker, endpoint, expected_redirect, + user, ): + mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) with logged_in_platform_admin_client.session_transaction() as session: session['send_test_letter_page_count'] = 1 @@ -1142,6 +1220,10 @@ def test_send_test_redirects_to_start_if_you_skip_steps( ) +@pytest.mark.parametrize('user', ( + active_user_with_permissions, + active_caseworking_user, +)) @pytest.mark.parametrize('endpoint, expected_redirect', [ ('main.send_test_step', 'main.send_test'), ('main.send_one_off_step', 'main.send_one_off'), @@ -1156,8 +1238,10 @@ def test_send_test_redirects_to_start_if_index_out_of_bounds_and_some_placeholde mock_get_service_statistics, endpoint, expected_redirect, + mocker, + user, ): - + mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) with logged_in_client.session_transaction() as session: session['placeholders'] = {'name': 'foo'} @@ -1177,6 +1261,10 @@ def test_send_test_redirects_to_start_if_index_out_of_bounds_and_some_placeholde ) +@pytest.mark.parametrize('user', ( + active_user_with_permissions, + active_caseworking_user, +)) @pytest.mark.parametrize('endpoint, expected_redirect', [ ('main.send_test', 'main.send_test_step'), ('main.send_one_off', 'main.send_one_off_step'), @@ -1188,7 +1276,9 @@ def _redirects_with_help_argument( fake_uuid, endpoint, expected_redirect, + user, ): + mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) template = {'data': {'template_type': 'sms'}} mocker.patch('app.service_api_client.get_service_template', return_value=template) @@ -1206,6 +1296,10 @@ def _redirects_with_help_argument( ) +@pytest.mark.parametrize('user', ( + active_user_with_permissions, + active_caseworking_user, +)) def test_send_test_email_message_without_placeholders_redirects_to_check_page( logged_in_client, mocker, @@ -1215,7 +1309,10 @@ def test_send_test_email_message_without_placeholders_redirects_to_check_page( mock_get_users_by_service, mock_get_service_statistics, fake_uuid, + user, ): + mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) + with logged_in_client.session_transaction() as session: session['recipient'] = 'foo@bar.com' @@ -1228,6 +1325,10 @@ def test_send_test_email_message_without_placeholders_redirects_to_check_page( assert page.select('h1')[0].text.strip() == 'Preview of Two week reminder' +@pytest.mark.parametrize('user, expected_back_link_endpoint, extra_args', ( + (active_user_with_permissions, 'main.view_template', {'template_id': unchanging_fake_uuid}), + (active_caseworking_user, 'main.view_template', {'template_id': unchanging_fake_uuid}), +)) def test_send_test_sms_message_with_placeholders_shows_first_field( logged_in_client, mocker, @@ -1236,7 +1337,11 @@ def test_send_test_sms_message_with_placeholders_shows_first_field( mock_get_service, mock_get_service_template_with_placeholders, fake_uuid, + user, + expected_back_link_endpoint, + extra_args, ): + mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) with logged_in_client.session_transaction() as session: assert 'placeholders' not in session @@ -1245,7 +1350,7 @@ def test_send_test_sms_message_with_placeholders_shows_first_field( url_for( 'main.send_test', service_id=service_one['id'], - template_id=fake_uuid, + template_id=unchanging_fake_uuid, ), follow_redirects=True, ) @@ -1255,9 +1360,9 @@ def test_send_test_sms_message_with_placeholders_shows_first_field( assert page.select('label')[0].text.strip() == 'name' assert page.select('input')[0]['name'] == 'placeholder_value' assert page.select('.page-footer-back-link')[0]['href'] == url_for( - 'main.view_template', + expected_back_link_endpoint, service_id=service_one['id'], - template_id=fake_uuid, + **extra_args ) with logged_in_client.session_transaction() as session: assert session['recipient'] == '07700 900762' @@ -2494,7 +2599,11 @@ def test_check_notification_shows_preview( assert page.h1.text.strip() == 'Preview of Two week reminder' assert ( page.findAll('a', {'class': 'page-footer-back-link'})[0]['href'] - ) == url_for('main.view_template', service_id=service_one['id'], template_id=fake_uuid) + ) == url_for( + 'main.view_template', + service_id=service_one['id'], + template_id=fake_uuid, + ) # assert tour not visible assert not page.select('.banner-tour') diff --git a/tests/app/main/views/test_templates.py b/tests/app/main/views/test_templates.py index a7fbd5009..1054419f0 100644 --- a/tests/app/main/views/test_templates.py +++ b/tests/app/main/views/test_templates.py @@ -18,6 +18,7 @@ from tests import ( ) from tests.conftest import ( SERVICE_ONE_ID, + active_caseworking_user, mock_get_service_email_template, mock_get_service_letter_template, mock_get_service_template, @@ -110,6 +111,29 @@ def test_should_show_page_for_one_template( mock_get_service_template.assert_called_with(service_one['id'], template_id) +def test_caseworker_redirected_to_one_off( + client_request, + mock_get_service_templates, + mocker, + fake_uuid, +): + + mocker.patch('app.user_api_client.get_user', return_value=active_caseworking_user(fake_uuid)) + + client_request.get( + 'main.view_template', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + _expected_status=302, + _expected_redirect=url_for( + 'main.send_one_off', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + _external=True, + ), + ) + + @pytest.mark.parametrize('permissions, links_to_be_shown, permissions_warning_to_be_shown', [ ( ['view_activity'], diff --git a/tests/app/test_navigation.py b/tests/app/test_navigation.py index c2f887259..97f222a04 100644 --- a/tests/app/test_navigation.py +++ b/tests/app/test_navigation.py @@ -1,18 +1,32 @@ import pytest -from app.navigation import HeaderNavigation, MainNavigation, OrgNavigation -from tests.conftest import ORGANISATION_ID, SERVICE_ONE_ID, app_ +from app.navigation import ( + CaseworkNavigation, + HeaderNavigation, + MainNavigation, + OrgNavigation, +) +from tests.conftest import ( + ORGANISATION_ID, + SERVICE_ONE_ID, + active_caseworking_user, + app_, + normalize_spaces, +) all_endpoints = [ rule.endpoint for rule in next(app_(None)).url_map.iter_rules() ] - -@pytest.mark.parametrize('navigation_instance', [ +navigation_instances = ( MainNavigation(), HeaderNavigation(), OrgNavigation(), -]) + CaseworkNavigation(), +) + + +@pytest.mark.parametrize('navigation_instance', navigation_instances) def test_navigation_items_are_properly_defined(navigation_instance): for endpoint in navigation_instance.endpoints_with_navigation: assert ( @@ -36,11 +50,7 @@ def test_navigation_items_are_properly_defined(navigation_instance): ) -@pytest.mark.parametrize('navigation_instance', [ - MainNavigation(), - HeaderNavigation(), - OrgNavigation(), -]) +@pytest.mark.parametrize('navigation_instance', navigation_instances) def test_excluded_navigation_items_are_properly_defined(navigation_instance): for endpoint in navigation_instance.endpoints_without_navigation: assert ( @@ -64,11 +74,7 @@ def test_excluded_navigation_items_are_properly_defined(navigation_instance): ) -@pytest.mark.parametrize('navigation_instance', [ - MainNavigation(), - HeaderNavigation(), - OrgNavigation(), -]) +@pytest.mark.parametrize('navigation_instance', navigation_instances) def test_all_endpoints_are_covered(navigation_instance): for endpoint in all_endpoints: if not endpoint == 'main.monthly_billing_usage': @@ -81,11 +87,7 @@ def test_all_endpoints_are_covered(navigation_instance): ) -@pytest.mark.parametrize('navigation_instance', [ - MainNavigation(), - HeaderNavigation(), - OrgNavigation(), -]) +@pytest.mark.parametrize('navigation_instance', navigation_instances) @pytest.mark.xfail(raises=KeyError) def test_raises_on_invalid_navigation_item( client_request, navigation_instance @@ -143,3 +145,19 @@ def test_a_page_should_nave_selected_org_navigation_item( selected_nav_items = page.select('.navigation a.selected') assert len(selected_nav_items) == 1 assert selected_nav_items[0].text.strip() == selected_nav_item + + +def test_caseworkers_get_caseworking_navigation( + client_request, + mocker, + fake_uuid, + mock_get_service_templates, +): + mocker.patch( + 'app.user_api_client.get_user', + return_value=active_caseworking_user(fake_uuid) + ) + page = client_request.get('main.choose_template', service_id=SERVICE_ONE_ID) + assert normalize_spaces(page.select_one('#content nav').text) == ( + 'Send a message' + )