Skip to content

Commit

Permalink
Feat: system enrollment error - 500 error when linking (#2088)
Browse files Browse the repository at this point in the history
  • Loading branch information
thekaveman authored May 20, 2024
2 parents c07ae69 + 95ec106 commit 1a15409
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 7 deletions.
45 changes: 45 additions & 0 deletions benefits/enrollment/templates/enrollment/system_error.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{% extends "core/base.html" %}
{% load i18n %}

{% block classes %}
{{ block.super | add:" system-enrollment-error" }}
{% endblock classes %}

{% block page-title %}
{% translate "Enrollment system down" %}
{% endblock page-title %}

{% block main-content %}
<div class="container">
<h1 class="h2 text-center">
<span class="icon d-block pb-4">{% include "core/includes/icon.html" with name="bankcardquestion" %}</span>
{% translate "Our enrollment system is not working right now." %}
</h1>

<div class="row justify-content-center">
<div class="col-lg-8 pt-4">
<p>
{% translate "We’re working to solve the problem. Please wait 48 hours and try to enroll again, or contact your transit agency for help." %}
</p>
</div>
</div>

<div class="row justify-content-center">
<div class="col-lg-8">{% include "core/includes/agency-links.html" %}</div>
</div>

<div class="row pt-8 justify-content-center">
<div class="col-lg-3 col-8">
{% if authentication and authentication.sign_out_link_template %}
{% url "oauth:logout" as sign_out_url %}
{% translate "Sign out of" as button_text %}
<a href="{{ sign_out_url }}" class="btn btn-lg btn-primary login">
{{ button_text }} <span class="fallback-text white-logo">Login.gov</span>
</a>
{% else %}
{% include "core/includes/button--origin.html" %}
{% endif %}
</div>
</div>
</div>
{% endblock main-content %}
18 changes: 18 additions & 0 deletions benefits/enrollment/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from django.utils.decorators import decorator_from_middleware
from littlepay.api.client import Client
from requests.exceptions import HTTPError
import sentry_sdk

from benefits.core import session
from benefits.core.middleware import EligibleSessionRequired, VerifierSessionRequired, pageview_decorator
Expand All @@ -24,6 +25,7 @@
ROUTE_TOKEN = "enrollment:token"

TEMPLATE_RETRY = "enrollment/retry.html"
TEMPLATE_SYSTEM_ERROR = "enrollment/system_error.html"


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -87,6 +89,11 @@ def index(request):
if e.response.status_code == 409:
analytics.returned_success(request, eligibility.group_id)
return success(request)
elif e.response.status_code >= 500:
analytics.returned_error(request, str(e))
sentry_sdk.capture_exception(e)

return system_error(request)
else:
analytics.returned_error(request, str(e))
raise Exception(f"{e}: {e.response.json()}")
Expand Down Expand Up @@ -144,6 +151,17 @@ def retry(request):
return TemplateResponse(request, TEMPLATE_RETRY)


@decorator_from_middleware(EligibleSessionRequired)
def system_error(request):
"""View handler for an enrollment system error."""

# overwrite origin so that CTA takes user to agency index
agency = session.agency(request)
session.update(request, origin=agency.index_url)

return TemplateResponse(request, TEMPLATE_SYSTEM_ERROR)


@pageview_decorator
@decorator_from_middleware(VerifierSessionRequired)
def success(request):
Expand Down
16 changes: 15 additions & 1 deletion benefits/locale/en/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: https://github.com/cal-itp/benefits/issues \n"
"POT-Creation-Date: 2024-05-16 19:45+0000\n"
"POT-Creation-Date: 2024-05-20 21:48+0000\n"
"Language: English\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand Down Expand Up @@ -706,6 +706,20 @@ msgstr ""
msgid "If you are on a public or shared computer, don’t forget to sign out of "
msgstr ""

msgid "Enrollment system down"
msgstr ""

msgid "Our enrollment system is not working right now."
msgstr ""

msgid ""
"We’re working to solve the problem. Please wait 48 hours and try to enroll "
"again, or contact your transit agency for help."
msgstr ""

msgid "Sign out of"
msgstr ""

msgid "Start over"
msgstr ""

Expand Down
19 changes: 18 additions & 1 deletion benefits/locale/es/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: https://github.com/cal-itp/benefits/issues \n"
"POT-Creation-Date: 2024-05-16 19:45+0000\n"
"POT-Creation-Date: 2024-05-20 21:48+0000\n"
"Language: Español\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand Down Expand Up @@ -897,6 +897,23 @@ msgid "If you are on a public or shared computer, don’t forget to sign out of
msgstr ""
"Si está en una computadora pública o compartida, no olvide cerrar sesión en "

msgid "Enrollment system down"
msgstr "El sistema de inscripción no funciona"

msgid "Our enrollment system is not working right now."
msgstr "Nuestro sistema de inscripción no está funcionando en este momento."

msgid ""
"We’re working to solve the problem. Please wait 48 hours and try to enroll "
"again, or contact your transit agency for help."
msgstr ""
"Estamos trabajando para resolver el problema. Espere 48 horas e intente "
"inscribirse nuevamente, o contacte a su agencia de tránsito para obtener "
"ayuda."

msgid "Sign out of"
msgstr "Cierre sesión de"

msgid "Start over"
msgstr "Comenzar de nuevo"

Expand Down
5 changes: 3 additions & 2 deletions benefits/static/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -470,9 +470,10 @@ footer .footer-links li a.footer-link:visited {
}
}

/* Sign in with Login.gov (white logo) on Eligibility Start */
/* Sign in with Login.gov (white logo) on Eligibility Start, System Enrollment Error */

.eligibility-start .btn.btn-lg.btn-primary.login {
.eligibility-start .btn.btn-lg.btn-primary.login,
.system-enrollment-error .btn.btn-lg.btn-primary.login {
padding: 10px 0;
}

Expand Down
2 changes: 1 addition & 1 deletion benefits/templates/error.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

{% block main-content %}
<div class="container">
<h1 class="icon-title h2 text-center">
<h1 class="h2 text-center">
<span class="icon d-block pb-4">{% include "core/includes/icon.html" with name="sadbus" %}</span>
{% block headline %}
{% endblock headline %}
Expand Down
45 changes: 43 additions & 2 deletions tests/pytest/enrollment/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
ROUTE_RETRY,
ROUTE_SUCCESS,
ROUTE_TOKEN,
TEMPLATE_SYSTEM_ERROR,
TEMPLATE_RETRY,
)

Expand All @@ -33,6 +34,11 @@ def mocked_analytics_module(mocked_analytics_module):
return mocked_analytics_module(benefits.enrollment.views)


@pytest.fixture
def mocked_sentry_sdk_module(mocker):
return mocker.patch.object(benefits.enrollment.views, "sentry_sdk")


@pytest.fixture
def mocked_funding_source():
return FundingSourceResponse(
Expand Down Expand Up @@ -123,13 +129,48 @@ def test_index_eligible_post_invalid_form(client, invalid_form_data):
client.post(path, invalid_form_data)


@pytest.mark.django_db
@pytest.mark.parametrize("status_code", [500, 501, 502, 503, 504])
@pytest.mark.usefixtures("mocked_session_eligibility")
def test_index_eligible_post_valid_form_http_error_500(
mocker,
client,
mocked_session_agency,
mocked_analytics_module,
mocked_sentry_sdk_module,
card_tokenize_form_data,
status_code,
):
mock_session = mocker.patch("benefits.enrollment.views.session")
mock_session.agency.return_value = mocked_session_agency.return_value

mock_client_cls = mocker.patch("benefits.enrollment.views.Client")
mock_client = mock_client_cls.return_value

mock_error = {"message": "Mock error message"}
mock_error_response = mocker.Mock(status_code=status_code, **mock_error)
mock_error_response.json.return_value = mock_error
mock_client.link_concession_group_funding_source.side_effect = HTTPError(
response=mock_error_response,
)

path = reverse(ROUTE_INDEX)
response = client.post(path, card_tokenize_form_data)

assert response.status_code == 200
assert response.template_name == TEMPLATE_SYSTEM_ERROR
assert {"origin": mocked_session_agency.return_value.index_url} in mock_session.update.call_args
mocked_analytics_module.returned_error.assert_called_once()
mocked_sentry_sdk_module.capture_exception.assert_called_once()


@pytest.mark.django_db
@pytest.mark.usefixtures("mocked_session_agency", "mocked_session_eligibility")
def test_index_eligible_post_valid_form_http_error(mocker, client, card_tokenize_form_data):
def test_index_eligible_post_valid_form_http_error_400(mocker, client, card_tokenize_form_data):
mock_client_cls = mocker.patch("benefits.enrollment.views.Client")
mock_client = mock_client_cls.return_value

# any status_code that isn't 409 is considered an error
# any 400 level status_code that isn't 409 is considered an error
mock_error = {"message": "Mock error message"}
mock_error_response = mocker.Mock(status_code=400, **mock_error)
mock_error_response.json.return_value = mock_error
Expand Down

0 comments on commit 1a15409

Please sign in to comment.