From c2a691e6d954b8779be87a6588e646bbc463c19c Mon Sep 17 00:00:00 2001 From: David McDonald Date: Wed, 30 Sep 2020 11:08:05 +0100 Subject: [PATCH] Add view for filling in steps of the tour Note, we choose to start our urls at step-1 rather than step-0 as this is consistent when you would enter the first placeholder (excluding the recipient) for the one off tour. Also note, we expect a service to allow international sms by default when it is first created but we keep the check for if the service does just in case they visit this tour later on. --- app/main/views/tour.py | 71 +++++- tests/app/main/views/test_tour.py | 355 ++++++++++++++++++++++++++++++ 2 files changed, 424 insertions(+), 2 deletions(-) diff --git a/app/main/views/tour.py b/app/main/views/tour.py index 98a8f5871..de4ec63a7 100644 --- a/app/main/views/tour.py +++ b/app/main/views/tour.py @@ -1,7 +1,15 @@ -from flask import abort, render_template +from flask import abort, redirect, render_template, session from app import current_service, current_user, url_for from app.main import main +from app.main.views.send import ( + all_placeholders_in_session, + fields_to_fill_in, + get_normalised_placeholders_from_session, + get_notification_check_endpoint, + get_placeholder_form_instance, + get_recipient_and_placeholders_from_session, +) from app.utils import get_template, user_has_permissions @@ -21,6 +29,8 @@ def begin_tour(service_id, template_id): template.values = {"phone_number": current_user.mobile_number} + session['placeholders'] = {} + return render_template( 'views/templates/start-tour.html', template=template, @@ -35,4 +45,61 @@ def begin_tour(service_id, template_id): ) @user_has_permissions('send_messages', restrict_admin_usage=True) def tour_step(service_id, template_id, step_index): - pass + db_template = current_service.get_template(template_id) + + if db_template['template_type'] != 'sms': + abort(404) + + template = get_template( + db_template, + current_service, + show_recipient=True, + ) + + placeholders = fields_to_fill_in(template, prefill_current_user=True) + try: + # user urls are 1 indexed, so start at step-1 + current_placeholder = placeholders[step_index - 1] + except IndexError: + if all_placeholders_in_session(placeholders): + return get_notification_check_endpoint(service_id, template) + return redirect(url_for( + '.tour_step', service_id=current_service.id, template_id=db_template['id'], step_index=1 + )) + + form = get_placeholder_form_instance( + current_placeholder, + dict_to_populate_from=get_normalised_placeholders_from_session(), + template_type=template.template_type, + allow_international_phone_numbers=current_service.has_permission('international_sms') + ) + + if form.validate_on_submit(): + session['placeholders'][current_placeholder] = form.placeholder_value.data + + if all_placeholders_in_session(placeholders): + return get_notification_check_endpoint(service_id, template) + return redirect(url_for( + '.tour_step', service_id=current_service.id, template_id=db_template['id'], step_index=step_index + 1 + )) + + back_link = _get_tour_step_back_link(service_id, template_id, step_index) + + template.values = get_recipient_and_placeholders_from_session(db_template['template_type']) + template.values[current_placeholder] = None + + return render_template( + 'views/send-test.html', + page_title="Example text message", + template=template, + form=form, + back_link=back_link, + help='2' + ) + + +def _get_tour_step_back_link(service_id, template_id, step_index): + if step_index == 1: + return url_for('.begin_tour', service_id=service_id, template_id=template_id) + + return url_for('.tour_step', service_id=service_id, template_id=template_id, step_index=step_index - 1) diff --git a/tests/app/main/views/test_tour.py b/tests/app/main/views/test_tour.py index 6a9decc81..18cea1813 100644 --- a/tests/app/main/views/test_tour.py +++ b/tests/app/main/views/test_tour.py @@ -44,6 +44,25 @@ def test_should_200_for_tour_start( ) +def test_should_clear_session_on_tour_start( + client_request, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, +): + with client_request.session_transaction() as session: + session['placeholders'] = {'one': 'hello', 'phone number': '07700 900762'} + + client_request.get( + 'main.begin_tour', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + ) + + with client_request.session_transaction() as session: + assert session['placeholders'] == {} + + @pytest.mark.parametrize('template_type', ['email', 'letter', 'broadcast']) def test_should_404_if_non_sms_template_for_tour_start( client_request, @@ -103,3 +122,339 @@ def test_should_403_if_user_does_not_have_send_permissions_for_tour_start( ['view_activity'], api_user_active, service_one) + + +def test_should_200_for_get_tour_step( + client_request, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, +): + with client_request.session_transaction() as session: + session['placeholders'] = {} + + page = client_request.get( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=1 + ) + + assert 'Example text message' in normalize_spaces(page.select_one('title').text) + assert normalize_spaces( + page.select('.banner-tour .heading-medium')[0].text + ) == ( + 'Try sending yourself this example' + ) + selected_hint = page.select('.banner-tour .govuk-grid-row')[1] + selected_hint_text = normalize_spaces(selected_hint.select(".govuk-body")[0].text) + assert "greyed-out-step" not in selected_hint["class"] + assert selected_hint_text == 'The template pulls in the data you provide' + + assert normalize_spaces( + page.select('.sms-message-recipient')[0].text + ) == ( + 'To: 07700 900762' + ) + + assert normalize_spaces( + page.select('.sms-message-wrapper')[0].text + ) == ( + 'service one: ((one)) ((two)) ((three))' + ) + + +def test_should_prefill_answers_for_get_tour_step( + client_request, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, +): + with client_request.session_transaction() as session: + session['placeholders'] = session['placeholders'] = {'one': 'hello', 'phone number': '07700 900762'} + + page = client_request.get( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=1 + ) + + page.select('.govuk-input')[0]['value'] == 'hello' + + +@pytest.mark.parametrize('template_type', ['email', 'letter', 'broadcast']) +@pytest.mark.parametrize('method', ['get', 'post']) +def test_should_404_if_non_sms_template_for_tour_step( + client_request, + fake_uuid, + mocker, + template_type, + method +): + mocker.patch( + 'app.service_api_client.get_service_template', + return_value={'data': create_template(template_type=template_type)} + ) + + getattr(client_request, method)( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=1, + _expected_status=404 + ) + + +@pytest.mark.parametrize('method', ['GET', 'POST']) +def test_should_403_if_user_does_not_have_send_permissions_for_tour_step( + mocker, + app_, + client, + api_user_active, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, + method +): + validate_route_permission( + mocker, + app_, + method, + 403, + url_for( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=1 + ), + ['view_activity'], + api_user_active, + service_one + ) + + +def test_back_link_from_first_get_tour_step_points_to_tour_start( + client_request, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, +): + with client_request.session_transaction() as session: + session['placeholders'] = {} + + page = client_request.get( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=1 + ) + + assert page.select('.govuk-back-link')[0]['href'] == url_for( + "main.begin_tour", + service_id=SERVICE_ONE_ID, + template_id=fake_uuid + ) + + +def test_back_link_from_get_tour_step_points_to_previous_step( + client_request, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, +): + with client_request.session_transaction() as session: + session['placeholders'] = {} + + page = client_request.get( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=2 + ) + + assert page.select('.govuk-back-link')[0]['href'] == url_for( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=1 + ) + + +def test_post_tour_step_saves_data_and_redirects_to_next_step( + client_request, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, +): + with client_request.session_transaction() as session: + session['placeholders'] = {} + + client_request.post( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=1, + _data={'placeholder_value': 'hello'}, + _expected_status=302, + _expected_redirect=url_for( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=2, + _external=True, + ), + ) + + with client_request.session_transaction() as session: + assert session['placeholders'] == {'one': 'hello', 'phone number': '07700 900762'} + + +def test_post_tour_step_adds_data_to_saved_data_and_redirects_to_next_step( + client_request, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, +): + with client_request.session_transaction() as session: + session['placeholders'] = {'one': 'hello', 'phone number': '07700 900762'} + + client_request.post( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=2, + _data={'placeholder_value': 'is it me you are looking for'}, + _expected_status=302, + _expected_redirect=url_for( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=3, + _external=True, + ), + ) + + with client_request.session_transaction() as session: + assert session['placeholders'] == { + 'one': 'hello', 'two': 'is it me you are looking for', 'phone number': '07700 900762' + } + + +def test_post_tour_step_raises_validation_error_for_form_error( + client_request, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, +): + with client_request.session_transaction() as session: + session['placeholders'] = {'one': 'hi', 'phone number': '07700 900762'} + + page = client_request.post( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=2, + _data={'placeholder_value': ''}, + _expected_status=200, # should this be 400 + ) + + assert normalize_spaces( + page.select('.govuk-error-message')[0].text + ) == ( + 'Error: Cannot be empty' + ) + + assert normalize_spaces( + page.select('.sms-message-recipient')[0].text + ) == ( + 'To: 07700 900762' + ) + + assert normalize_spaces( + page.select('.sms-message-wrapper')[0].text + ) == ( + 'service one: hi ((two)) ((three))' + ) + + with client_request.session_transaction() as session: + assert session['placeholders'] == {'one': 'hi', 'phone number': '07700 900762'} + + +def test_post_final_tour_step_saves_data_and_redirects_to_check_notification( + client_request, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, +): + with client_request.session_transaction() as session: + session['placeholders'] = {'one': 'hello', 'two': 'hi', 'phone number': '07700 900762'} + + client_request.post( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=3, + _data={'placeholder_value': 'howdy'}, + _expected_status=302, + _expected_redirect=url_for( + 'main.check_notification', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + help=None, + _external=True + ), # this location needs to change + ) + + with client_request.session_transaction() as session: + session['placeholders'] == {'one': 'hello', 'two': 'hi', 'three': 'howdy', 'phone number': '07700 900762'} + + +def test_get_test_step_out_of_index_redirects_to_first_step( + client_request, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, +): + with client_request.session_transaction() as session: + session['placeholders'] = {} + + client_request.get( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=4, + _expected_status=302, + _expected_redirect=url_for( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=1, + _external=True + ), + ) + + +def test_get_test_step_out_of_index_redirects_to_check_notification_if_all_placeholders_filled( + client_request, + mock_get_service_template_with_multiple_placeholders, + service_one, + fake_uuid, +): + with client_request.session_transaction() as session: + session['placeholders'] = {'one': 'hello', 'two': 'hi', 'three': 'howdy', 'phone number': '07700 900762'} + + client_request.get( + 'main.tour_step', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + step_index=4, + _expected_status=302, + _expected_redirect=url_for( + 'main.check_notification', + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + help=None, + _external=True + ), # this location needs to change + )