diff --git a/app/main/views/notifications.py b/app/main/views/notifications.py index 77113cb42..af887b48b 100644 --- a/app/main/views/notifications.py +++ b/app/main/views/notifications.py @@ -17,7 +17,7 @@ from flask import ( stream_with_context, url_for, ) -from notifications_python_client.errors import APIError +from notifications_python_client.errors import APIError, HTTPError from notifications_utils.letter_timings import ( get_letter_timings, letter_can_be_cancelled, @@ -185,7 +185,14 @@ def view_notification(service_id, notification_id): def cancel_letter(service_id, notification_id): if request.method == 'POST': - notification_api_client.update_notification_to_cancelled(current_service.id, notification_id) + try: + notification_api_client.update_notification_to_cancelled(current_service.id, notification_id) + except HTTPError as e: + message_fragments = ["already been cancelled", "too late to cancel"] + if e.status_code == 400 and any(fragment in e.message for fragment in message_fragments): + flash(e.message) + else: + raise e return redirect(url_for('main.view_notification', service_id=service_id, notification_id=notification_id)) flash("Are you sure you want to cancel sending this letter?", 'cancel') diff --git a/tests/app/main/views/test_notifications.py b/tests/app/main/views/test_notifications.py index dd74d1723..069b34d78 100644 --- a/tests/app/main/views/test_notifications.py +++ b/tests/app/main/views/test_notifications.py @@ -1,11 +1,11 @@ import base64 from functools import partial -from unittest.mock import mock_open +from unittest.mock import Mock, mock_open import pytest from flask import url_for from freezegun import freeze_time -from notifications_python_client.errors import APIError +from notifications_python_client.errors import APIError, HTTPError from PyPDF2.utils import PdfReadError from tests.conftest import ( @@ -958,6 +958,45 @@ def test_cancelling_a_letter_calls_the_api( assert cancel_endpoint.called +@freeze_time('2016-01-01 15:00') +@pytest.mark.parametrize('error_message', [ + "It’s too late to cancel this letter. Printing started on 1 January at 5.30pm", + "This letter has already been cancelled", + pytest.param("other message", marks=pytest.mark.xfail()) +]) +def test_cancel_letter_catches_errors_from_API( + client_request, + mocker, + fake_uuid, + error_message +): + notification = create_notification(template_type='letter', notification_status='created') + mocker.patch('app.notification_api_client.get_notification', return_value=notification) + mocker.patch( + 'app.main.views.notifications.get_page_count_for_letter', + return_value=1 + ) + mocker.patch( + 'app.main.views.notifications.notification_api_client.update_notification_to_cancelled', + side_effect=HTTPError(response=Mock( + status_code=400, + json=Mock( + return_value={'message': error_message} + ) + )) + ) + + page = client_request.post( + 'main.cancel_letter', + service_id=SERVICE_ONE_ID, + notification_id=fake_uuid, + _follow_redirects=True, + ) + + assert page.find('h1').text.strip() == "Letter" + assert page.select_one('div.banner-dangerous').text.strip() == error_message + + @pytest.mark.parametrize('notification_type', ['sms', 'email']) def test_should_show_reply_to_from_notification( mocker,