From e145e209659b87b46c971f4859a790d9e2a9a028 Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Thu, 28 Mar 2024 23:12:56 +0000 Subject: [PATCH] feat(enrollment): view handler for re-enrollment error --- benefits/enrollment/urls.py | 1 + benefits/enrollment/views.py | 28 +++++++++++++---- tests/pytest/conftest.py | 1 + tests/pytest/enrollment/test_views.py | 43 +++++++++++++++++++++++---- 4 files changed, 61 insertions(+), 12 deletions(-) diff --git a/benefits/enrollment/urls.py b/benefits/enrollment/urls.py index 22398bc988..f74eb2452f 100644 --- a/benefits/enrollment/urls.py +++ b/benefits/enrollment/urls.py @@ -12,6 +12,7 @@ # /enrollment path("", views.index, name="index"), path("token", views.token, name="token"), + path("reenrollment-error", views.reenrollment_error, name="reenrollment-error"), path("retry", views.retry, name="retry"), path("success", views.success, name="success"), ] diff --git a/benefits/enrollment/views.py b/benefits/enrollment/views.py index 9b3eaa76f8..b434c9cdc7 100644 --- a/benefits/enrollment/views.py +++ b/benefits/enrollment/views.py @@ -12,16 +12,13 @@ from requests.exceptions import HTTPError from benefits.core import session -from benefits.core.middleware import ( - EligibleSessionRequired, - VerifierSessionRequired, - pageview_decorator, -) +from benefits.core.middleware import EligibleSessionRequired, VerifierSessionRequired, pageview_decorator from benefits.core.views import ROUTE_LOGGED_OUT -from . import analytics, forms +from . import analytics, forms ROUTE_INDEX = "enrollment:index" +ROUTE_REENROLLMENT_ERROR = "enrollment:reenrollment-error" ROUTE_RETRY = "enrollment:retry" ROUTE_SUCCESS = "enrollment:success" ROUTE_TOKEN = "enrollment:token" @@ -122,6 +119,25 @@ def index(request): return TemplateResponse(request, eligibility.enrollment_index_template, context) +@decorator_from_middleware(EligibleSessionRequired) +def reenrollment_error(request): + """View handler for a re-enrollment attempt that is not yet within the re-enrollment window.""" + eligibility = session.eligibility(request) + verifier = session.verifier(request) + + if eligibility.reenrollment_error_template is None: + raise Exception(f"Re-enrollment error with null template on: {eligibility.label}") + + if session.logged_in(request) and verifier.auth_provider.supports_sign_out: + # overwrite origin for a logged in user + # if they click the logout button, they are taken to the new route + session.update(request, origin=reverse(ROUTE_LOGGED_OUT)) + + analytics.returned_error(request, "Re-enrollment error.") + + return TemplateResponse(request, eligibility.reenrollment_error_template) + + @decorator_from_middleware(EligibleSessionRequired) def retry(request): """View handler for a recoverable failure condition.""" diff --git a/tests/pytest/conftest.py b/tests/pytest/conftest.py index c10093d6df..2dfb4aa48a 100644 --- a/tests/pytest/conftest.py +++ b/tests/pytest/conftest.py @@ -139,6 +139,7 @@ def model_EligibilityType_supports_expiration(model_EligibilityType): model_EligibilityType.supports_expiration = True model_EligibilityType.expiration_days = 365 model_EligibilityType.expiration_reenrollment_days = 14 + model_EligibilityType.reenrollment_error_template = "enrollment/reenrollment-error--calfresh.html" model_EligibilityType.save() return model_EligibilityType diff --git a/tests/pytest/enrollment/test_views.py b/tests/pytest/enrollment/test_views.py index c2643262c9..187c4811d0 100644 --- a/tests/pytest/enrollment/test_views.py +++ b/tests/pytest/enrollment/test_views.py @@ -1,24 +1,23 @@ import time +import pytest from django.urls import reverse - from littlepay.api.funding_sources import FundingSourceResponse from requests import HTTPError -import pytest +import benefits.enrollment.views from benefits.core.middleware import TEMPLATE_USER_ERROR from benefits.core.views import ROUTE_LOGGED_OUT from benefits.enrollment.views import ( ROUTE_INDEX, - ROUTE_TOKEN, - ROUTE_SUCCESS, + ROUTE_REENROLLMENT_ERROR, ROUTE_RETRY, + ROUTE_SUCCESS, + ROUTE_TOKEN, TEMPLATE_SUCCESS, TEMPLATE_RETRY, ) -import benefits.enrollment.views - @pytest.fixture def card_tokenize_form_data(): @@ -211,6 +210,38 @@ def test_index_ineligible(client): assert response.template_name == TEMPLATE_USER_ERROR +@pytest.mark.django_db +def test_reenrollment_error_ineligible(client): + path = reverse(ROUTE_REENROLLMENT_ERROR) + + response = client.get(path) + + assert response.status_code == 200 + assert response.template_name == TEMPLATE_USER_ERROR + + +@pytest.mark.django_db +@pytest.mark.usefixtures("mocked_session_agency", "mocked_session_verifier", "mocked_session_eligibility") +def test_reenrollment_error_eligibility_no_error_template(client): + path = reverse(ROUTE_REENROLLMENT_ERROR) + + with pytest.raises(Exception, match="Re-enrollment error with null template"): + client.get(path) + + +@pytest.mark.django_db +@pytest.mark.usefixtures("mocked_session_agency", "mocked_session_verifier") +def test_reenrollment_error(client, model_EligibilityType_supports_expiration, mocked_session_eligibility): + mocked_session_eligibility.return_value = model_EligibilityType_supports_expiration + + path = reverse(ROUTE_REENROLLMENT_ERROR) + + response = client.get(path) + + assert response.status_code == 200 + assert response.template_name == model_EligibilityType_supports_expiration.reenrollment_error_template + + @pytest.mark.django_db def test_retry_ineligible(client): path = reverse(ROUTE_RETRY)