diff --git a/benefits/enrollment/templates/enrollment/reenrollment-error.html b/benefits/enrollment/templates/enrollment/reenrollment-error.html deleted file mode 100644 index e69de29bb..000000000 diff --git a/benefits/enrollment/views.py b/benefits/enrollment/views.py index 0d27ea3d2..6ea2edf29 100644 --- a/benefits/enrollment/views.py +++ b/benefits/enrollment/views.py @@ -3,12 +3,10 @@ """ import logging -from datetime import timedelta from django.http import JsonResponse from django.template.response import TemplateResponse from django.urls import reverse -from django.utils import timezone from django.utils.decorators import decorator_from_middleware from littlepay.api.client import Client from requests.exceptions import HTTPError @@ -28,7 +26,6 @@ ROUTE_SUCCESS = "enrollment:success" ROUTE_TOKEN = "enrollment:token" -TEMPLATE_REENROLLMENT_ERROR = "enrollment/reenrollment-error.html" TEMPLATE_RETRY = "enrollment/retry.html" TEMPLATE_SUCCESS = "enrollment/success.html" @@ -72,6 +69,7 @@ def index(request): if not form.is_valid(): raise Exception("Invalid card token form") + logger.debug("Read tokenized card") card_token = form.cleaned_data.get("card_token") client = Client( @@ -83,73 +81,25 @@ def index(request): client.oauth.ensure_active_token(client.token) funding_source = client.get_funding_source_by_token(card_token) - group_id = eligibility.group_id try: - group_funding_source = _get_group_funding_source( - client=client, group_id=group_id, funding_source_id=funding_source.id - ) - - already_enrolled = group_funding_source is not None - - if eligibility.supports_expiration: - # set expiry on session - if already_enrolled and group_funding_source.expiry_date is not None: - session.update(request, enrollment_expiry=group_funding_source.expiry_date) - else: - session.update(request, enrollment_expiry=_calculate_expiry(eligibility.expiration_days)) - - if not already_enrolled: - # enroll user with an expiration date, return success - client.link_concession_group_funding_source( - group_id=group_id, funding_source_id=funding_source.id, expiry=session.enrollment_expiry(request) - ) - return success(request) - else: # already_enrolled - if group_funding_source.expiry_date is None: - # update expiration of existing enrollment, return success - client.update_concession_group_funding_source_expiry( - group_id=group_id, - funding_source_id=funding_source.id, - expiry=session.enrollment_expiry(request), - ) - return success(request) - else: - is_expired = _is_expired(group_funding_source.expiry_date) - is_within_reenrollment_window = _is_within_reenrollment_window( - group_funding_source.expiry_date, session.enrollment_reenrollment(request) - ) - - if is_expired or is_within_reenrollment_window: - # update expiration of existing enrollment, return success - client.update_concession_group_funding_source_expiry( - group_id=group_id, - funding_source_id=funding_source.id, - expiry=session.enrollment_expiry(request), - ) - return success(request) - else: - # re-enrollment error, return enrollment error with expiration and reenrollment_date - return reenrollment_error(request) - else: # eligibility does not support expiration - if not already_enrolled: - # enroll user with no expiration date, return success - client.link_concession_group_funding_source(group_id=group_id, funding_source_id=funding_source.id) - return success(request) - else: # already_enrolled - if group_funding_source.expiry_date is None: - # no action, return success - return success(request) - else: - # remove expiration date, return success - raise NotImplementedError("Removing expiration date is currently not supported") - + client.link_concession_group_funding_source(funding_source_id=funding_source.id, group_id=eligibility.group_id) except HTTPError as e: - analytics.returned_error(request, str(e)) - raise Exception(f"{e}: {e.response.json()}") + # 409 means that customer already belongs to a concession group. + # the response JSON will look like: + # {"errors":[{"detail":"Conflict (409) - Customer already belongs to a concession group."}]} + if e.response.status_code == 409: + analytics.returned_success(request, eligibility.group_id) + return success(request) + else: + analytics.returned_error(request, str(e)) + raise Exception(f"{e}: {e.response.json()}") except Exception as e: analytics.returned_error(request, str(e)) raise e + else: + analytics.returned_success(request, eligibility.group_id) + return success(request) # GET enrollment index else: @@ -172,43 +122,6 @@ def index(request): return TemplateResponse(request, eligibility.enrollment_index_template, context) -def _get_group_funding_source(client: Client, group_id, funding_source_id): - group_funding_sources = client.get_concession_group_linked_funding_sources(group_id) - matching_group_funding_source = None - for group_funding_source in group_funding_sources: - if group_funding_source.id == funding_source_id: - matching_group_funding_source = group_funding_source - break - - return matching_group_funding_source - - -def _is_expired(expiry_date): - """Returns whether the passed in datetime is expired or not.""" - return expiry_date <= timezone.now() - - -def _is_within_reenrollment_window(expiry_date, enrollment_reenrollment_date): - """Returns if we are currently within the reenrollment window.""" - return enrollment_reenrollment_date <= timezone.now() < expiry_date - - -def _calculate_expiry(expiration_days): - """Returns the expiry datetime, which should be midnight in our configured timezone of the (N + 1)th day from now, - where N is expiration_days.""" - default_time_zone = timezone.get_default_timezone() - expiry_date = timezone.localtime(timezone=default_time_zone) + timedelta(days=expiration_days + 1) - expiry_datetime = expiry_date.replace(hour=0, minute=0, second=0, microsecond=0) - - return expiry_datetime - - -def reenrollment_error(request): - """View handler for a re-enrollment attempt that is not yet within the re-enrollment window.""" - analytics.returned_error(request, "Re-enrollment error") - return TemplateResponse(request, TEMPLATE_REENROLLMENT_ERROR) - - @decorator_from_middleware(EligibleSessionRequired) def retry(request): """View handler for a recoverable failure condition.""" @@ -217,7 +130,6 @@ def retry(request): @pageview_decorator -@decorator_from_middleware(EligibleSessionRequired) @decorator_from_middleware(VerifierSessionRequired) def success(request): """View handler for the final success page.""" @@ -226,12 +138,10 @@ def success(request): agency = session.agency(request) verifier = session.verifier(request) - eligibility = session.eligibility(request) 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_success(request, eligibility.group_id) return TemplateResponse(request, agency.enrollment_success_template) diff --git a/benefits/settings.py b/benefits/settings.py index da5f947d9..c1ad706c0 100644 --- a/benefits/settings.py +++ b/benefits/settings.py @@ -204,11 +204,7 @@ def RUNTIME_ENVIRONMENT(): USE_I18N = True -# See https://docs.djangoproject.com/en/5.0/ref/settings/#std-setting-TIME_ZONE -# > Note that this isn’t necessarily the time zone of the server. -# > When USE_TZ is True, this is the default time zone that Django will use to display datetimes in templates -# > and to interpret datetimes entered in forms. -TIME_ZONE = "America/Los_Angeles" +TIME_ZONE = "UTC" USE_TZ = True # Static files (CSS, JavaScript, Images) diff --git a/tests/pytest/conftest.py b/tests/pytest/conftest.py index aea5920b3..c10093d6d 100644 --- a/tests/pytest/conftest.py +++ b/tests/pytest/conftest.py @@ -1,7 +1,6 @@ from unittest.mock import create_autospec from django.contrib.sessions.middleware import SessionMiddleware from django.middleware.locale import LocaleMiddleware -from django.utils import timezone import pytest from pytest_socket import disable_socket @@ -257,15 +256,6 @@ def mocked_session_oauth_token(mocker): return mocker.patch("benefits.core.session.oauth_token", autospec=True, return_value="token") -@pytest.fixture -def mocked_session_enrollment_expiry(mocker): - return mocker.patch( - "benefits.core.session.enrollment_expiry", - autospec=True, - return_value=timezone.make_aware(timezone.datetime(2024, 1, 1), timezone=timezone.get_default_timezone()), - ) - - @pytest.fixture def mocked_session_verifier(mocker, model_EligibilityVerifier): return mocker.patch("benefits.core.session.verifier", autospec=True, return_value=model_EligibilityVerifier) diff --git a/tests/pytest/enrollment/test_views.py b/tests/pytest/enrollment/test_views.py index 1770f842b..fba0b7c53 100644 --- a/tests/pytest/enrollment/test_views.py +++ b/tests/pytest/enrollment/test_views.py @@ -1,11 +1,8 @@ -from datetime import timedelta import time from django.urls import reverse -from django.utils import timezone from littlepay.api.funding_sources import FundingSourceResponse -from littlepay.api.groups import GroupFundingSourceResponse from requests import HTTPError import pytest @@ -16,13 +13,8 @@ ROUTE_TOKEN, ROUTE_SUCCESS, ROUTE_RETRY, - TEMPLATE_REENROLLMENT_ERROR, TEMPLATE_SUCCESS, TEMPLATE_RETRY, - _get_group_funding_source, - _calculate_expiry, - _is_expired, - _is_within_reenrollment_window, ) import benefits.enrollment.views @@ -59,26 +51,6 @@ def mocked_funding_source(): ) -@pytest.fixture -def mocked_group_funding_source_no_expiry(mocked_funding_source): - return GroupFundingSourceResponse( - id=mocked_funding_source.id, - created_date=None, - updated_date=None, - expiry_date=None, - ) - - -@pytest.fixture -def mocked_group_funding_source_with_expiry(mocked_funding_source): - return GroupFundingSourceResponse( - id=mocked_funding_source.id, - created_date="2023-01-01T00:00:00Z", - updated_date="2021-01-01T00:00:00Z", - expiry_date="2021-01-01T00:00:00Z", - ) - - @pytest.mark.django_db def test_token_ineligible(client): path = reverse(ROUTE_TOKEN) @@ -159,6 +131,7 @@ def test_index_eligible_post_valid_form_http_error(mocker, client, card_tokenize 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 mock_error = {"message": "Mock error message"} mock_error_response = mocker.Mock(status_code=400, **mock_error) mock_error_response.json.return_value = mock_error @@ -184,122 +157,33 @@ def test_index_eligible_post_valid_form_failure(mocker, client, card_tokenize_fo client.post(path, card_tokenize_form_data) -@pytest.mark.django_db -@pytest.mark.usefixtures("model_EligibilityType") -def test_get_group_funding_sources_funding_source_not_enrolled_yet(mocker, mocked_funding_source): - mock_client = mocker.Mock() - mock_client.get_concession_group_linked_funding_sources.return_value = [] - - matching_group_funding_source = _get_group_funding_source(mock_client, "group123", mocked_funding_source.id) - - assert matching_group_funding_source is None - - -@pytest.mark.django_db -@pytest.mark.usefixtures("model_EligibilityType") -def test_get_group_funding_sources_funding_source_already_enrolled( - mocker, mocked_funding_source, mocked_group_funding_source_no_expiry -): - mock_client = mocker.Mock() - mock_client.get_concession_group_linked_funding_sources.return_value = [mocked_group_funding_source_no_expiry] - - matching_group_funding_source = _get_group_funding_source(mock_client, "group123", mocked_funding_source.id) - - assert matching_group_funding_source == mocked_group_funding_source_no_expiry - - -@pytest.mark.django_db -@pytest.mark.usefixtures("mocked_session_agency", "mocked_session_verifier", "mocked_session_eligibility") -def test_index_eligible_post_valid_form_success_does_not_support_expiration_customer_already_enrolled_no_expiry( - mocker, - client, - card_tokenize_form_data, - mocked_analytics_module, - model_EligibilityType_does_not_support_expiration, - mocked_funding_source, - mocked_group_funding_source_no_expiry, -): - mock_client_cls = mocker.patch("benefits.enrollment.views.Client") - mock_client = mock_client_cls.return_value - mock_client.get_funding_source_by_token.return_value = mocked_funding_source - - mocker.patch("benefits.enrollment.views._get_group_funding_source", return_value=mocked_group_funding_source_no_expiry) - - path = reverse(ROUTE_INDEX) - response = client.post(path, card_tokenize_form_data) - - assert response.status_code == 200 - assert response.template_name == TEMPLATE_SUCCESS - mocked_analytics_module.returned_success.assert_called_once() - assert ( - model_EligibilityType_does_not_support_expiration.group_id in mocked_analytics_module.returned_success.call_args.args - ) - - @pytest.mark.django_db @pytest.mark.usefixtures("mocked_session_agency", "mocked_session_verifier", "mocked_session_eligibility") -def test_index_eligible_post_valid_form_success_does_not_support_expiration_no_expiry( - mocker, - client, - card_tokenize_form_data, - mocked_analytics_module, - model_EligibilityType_does_not_support_expiration, - mocked_funding_source, +def test_index_eligible_post_valid_form_customer_already_enrolled( + mocker, client, card_tokenize_form_data, mocked_analytics_module, model_EligibilityType, mocked_funding_source ): mock_client_cls = mocker.patch("benefits.enrollment.views.Client") mock_client = mock_client_cls.return_value mock_client.get_funding_source_by_token.return_value = mocked_funding_source + mock_error_response = mocker.Mock(status_code=409) + 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) mock_client.link_concession_group_funding_source.assert_called_once_with( - funding_source_id=mocked_funding_source.id, group_id=model_EligibilityType_does_not_support_expiration.group_id + funding_source_id=mocked_funding_source.id, group_id=model_EligibilityType.group_id ) assert response.status_code == 200 assert response.template_name == TEMPLATE_SUCCESS mocked_analytics_module.returned_success.assert_called_once() - assert ( - model_EligibilityType_does_not_support_expiration.group_id in mocked_analytics_module.returned_success.call_args.args - ) - - -def test_calculate_expiry(): - expiration_days = 365 - - expiry_date = _calculate_expiry(expiration_days) - - assert expiry_date == ( - timezone.localtime(timezone=timezone.get_default_timezone()) + timedelta(days=expiration_days + 1) - ).replace(hour=0, minute=0, second=0, microsecond=0) - - -def test_calculate_expiry_specific_date(mocker): - expiration_days = 14 - mocker.patch( - "benefits.enrollment.views.timezone.now", - return_value=timezone.make_aware( - value=timezone.datetime(2024, 3, 1, 13, 37, 11, 5), timezone=timezone.get_fixed_timezone(offset=0) - ), - ) - - expiry_date = _calculate_expiry(expiration_days) - - assert expiry_date == timezone.make_aware( - value=timezone.datetime(2024, 3, 16, 0, 0, 0, 0), timezone=timezone.get_default_timezone() - ) + assert model_EligibilityType.group_id in mocked_analytics_module.returned_success.call_args.args @pytest.mark.django_db @pytest.mark.usefixtures("mocked_session_agency", "mocked_session_verifier", "mocked_session_eligibility") -def test_index_eligible_post_valid_form_success_supports_expiration( - mocker, - client, - card_tokenize_form_data, - mocked_analytics_module, - model_EligibilityType_supports_expiration, - mocked_funding_source, - mocked_session_enrollment_expiry, +def test_index_eligible_post_valid_form_success( + mocker, client, card_tokenize_form_data, mocked_analytics_module, model_EligibilityType, mocked_funding_source ): mock_client_cls = mocker.patch("benefits.enrollment.views.Client") mock_client = mock_client_cls.return_value @@ -309,297 +193,12 @@ def test_index_eligible_post_valid_form_success_supports_expiration( response = client.post(path, card_tokenize_form_data) mock_client.link_concession_group_funding_source.assert_called_once_with( - funding_source_id=mocked_funding_source.id, - group_id=model_EligibilityType_supports_expiration.group_id, - expiry=mocked_session_enrollment_expiry.return_value, - ) - assert response.status_code == 200 - assert response.template_name == TEMPLATE_SUCCESS - mocked_analytics_module.returned_success.assert_called_once() - assert model_EligibilityType_supports_expiration.group_id in mocked_analytics_module.returned_success.call_args.args - - -@pytest.mark.django_db -@pytest.mark.usefixtures("mocked_session_agency", "mocked_session_verifier", "mocked_session_eligibility") -def test_index_eligible_post_valid_form_success_supports_expiration_no_expiry( - mocker, - client, - card_tokenize_form_data, - mocked_analytics_module, - model_EligibilityType_supports_expiration, - mocked_funding_source, - mocked_group_funding_source_no_expiry, - mocked_session_enrollment_expiry, -): - mock_client_cls = mocker.patch("benefits.enrollment.views.Client") - mock_client = mock_client_cls.return_value - mock_client.get_funding_source_by_token.return_value = mocked_funding_source - - mocker.patch("benefits.enrollment.views._get_group_funding_source", return_value=mocked_group_funding_source_no_expiry) - - path = reverse(ROUTE_INDEX) - response = client.post(path, card_tokenize_form_data) - - mock_client.update_concession_group_funding_source_expiry.assert_called_once_with( - funding_source_id=mocked_funding_source.id, - group_id=model_EligibilityType_supports_expiration.group_id, - expiry=mocked_session_enrollment_expiry.return_value, - ) - assert response.status_code == 200 - assert response.template_name == TEMPLATE_SUCCESS - mocked_analytics_module.returned_success.assert_called_once() - assert model_EligibilityType_supports_expiration.group_id in mocked_analytics_module.returned_success.call_args.args - - -def test_is_expired_expiry_date_is_in_the_past(mocker): - expiry_date = timezone.make_aware(timezone.datetime(2023, 12, 31), timezone.get_default_timezone()) - - # mock datetime of "now" to be specific date for testing - mocker.patch( - "benefits.enrollment.views.timezone.now", - return_value=timezone.make_aware(timezone.datetime(2024, 1, 1, 10, 30), timezone.get_default_timezone()), - ) - - assert _is_expired(expiry_date) - - -def test_is_expired_expiry_date_is_in_the_future(mocker): - expiry_date = timezone.make_aware(timezone.datetime(2024, 1, 1, 17, 34), timezone.get_default_timezone()) - - # mock datetime of "now" to be specific date for testing - mocker.patch( - "benefits.enrollment.views.timezone.now", - return_value=timezone.make_aware(timezone.datetime(2024, 1, 1, 11, 5), timezone.get_default_timezone()), - ) - - assert not _is_expired(expiry_date) - - -def test_is_expired_expiry_date_equals_now(mocker): - expiry_date = timezone.make_aware(timezone.datetime(2024, 1, 1, 13, 37), timezone.get_default_timezone()) - - # mock datetime of "now" to be specific date for testing - mocker.patch( - "benefits.enrollment.views.timezone.now", - return_value=timezone.make_aware(timezone.datetime(2024, 1, 1, 13, 37), timezone.get_default_timezone()), - ) - - assert _is_expired(expiry_date) - - -@pytest.mark.django_db -@pytest.mark.usefixtures("mocked_session_agency", "mocked_session_verifier", "mocked_session_eligibility") -def test_index_eligible_post_valid_form_success_supports_expiration_is_expired( - mocker, - client, - card_tokenize_form_data, - mocked_analytics_module, - model_EligibilityType_supports_expiration, - mocked_funding_source, - mocked_group_funding_source_with_expiry, - mocked_session_enrollment_expiry, -): - mock_client_cls = mocker.patch("benefits.enrollment.views.Client") - mock_client = mock_client_cls.return_value - mock_client.get_funding_source_by_token.return_value = mocked_funding_source - - # mock that a funding source already exists, doesn't matter what expiry_date is - mocker.patch("benefits.enrollment.views._get_group_funding_source", return_value=mocked_group_funding_source_with_expiry) - - mocker.patch("benefits.enrollment.views._is_expired", return_value=True) - - path = reverse(ROUTE_INDEX) - response = client.post(path, card_tokenize_form_data) - - mock_client.update_concession_group_funding_source_expiry.assert_called_once_with( - funding_source_id=mocked_funding_source.id, - group_id=model_EligibilityType_supports_expiration.group_id, - expiry=mocked_session_enrollment_expiry.return_value, - ) - assert response.status_code == 200 - assert response.template_name == TEMPLATE_SUCCESS - mocked_analytics_module.returned_success.assert_called_once() - assert model_EligibilityType_supports_expiration.group_id in mocked_analytics_module.returned_success.call_args.args - - -def test_is_within_enrollment_window_True(mocker): - enrollment_reenrollment_date = timezone.make_aware(timezone.datetime(2023, 2, 1), timezone=timezone.get_default_timezone()) - expiry_date = timezone.make_aware(timezone.datetime(2023, 3, 1), timezone=timezone.get_default_timezone()) - - # mock datetime of "now" to be specific date for testing - mocker.patch( - "benefits.enrollment.views.timezone.now", - return_value=timezone.make_aware(timezone.datetime(2023, 2, 15, 15, 30), timezone=timezone.get_default_timezone()), - ) - - is_within_reenrollment_window = _is_within_reenrollment_window(expiry_date, enrollment_reenrollment_date) - - assert is_within_reenrollment_window - - -def test_is_within_enrollment_window_before_window(mocker): - enrollment_reenrollment_date = timezone.make_aware(timezone.datetime(2023, 2, 1), timezone=timezone.get_default_timezone()) - expiry_date = timezone.make_aware(timezone.datetime(2023, 3, 1), timezone=timezone.get_default_timezone()) - - # mock datetime of "now" to be specific date for testing - mocker.patch( - "benefits.enrollment.views.timezone.now", - return_value=timezone.make_aware(timezone.datetime(2023, 1, 15, 15, 30), timezone=timezone.get_default_timezone()), - ) - - is_within_reenrollment_window = _is_within_reenrollment_window(expiry_date, enrollment_reenrollment_date) - - assert not is_within_reenrollment_window - - -def test_is_within_enrollment_window_after_window(mocker): - enrollment_reenrollment_date = timezone.make_aware(timezone.datetime(2023, 2, 1), timezone=timezone.get_default_timezone()) - expiry_date = timezone.make_aware(timezone.datetime(2023, 3, 1), timezone=timezone.get_default_timezone()) - - # mock datetime of "now" to be specific date for testing - mocker.patch( - "benefits.enrollment.views.timezone.now", - return_value=timezone.make_aware(timezone.datetime(2023, 3, 15, 15, 30), timezone=timezone.get_default_timezone()), - ) - - is_within_reenrollment_window = _is_within_reenrollment_window(expiry_date, enrollment_reenrollment_date) - - assert not is_within_reenrollment_window - - -def test_is_within_enrollment_window_equal_reenrollment_date(mocker): - enrollment_reenrollment_date = timezone.make_aware(timezone.datetime(2023, 2, 1), timezone=timezone.get_default_timezone()) - expiry_date = timezone.make_aware(timezone.datetime(2023, 3, 1), timezone=timezone.get_default_timezone()) - - # mock datetime of "now" to be specific date for testing - mocker.patch( - "benefits.enrollment.views.timezone.now", - return_value=enrollment_reenrollment_date, - ) - - is_within_reenrollment_window = _is_within_reenrollment_window(expiry_date, enrollment_reenrollment_date) - - assert is_within_reenrollment_window - - -def test_is_within_enrollment_window_equal_expiry_date(mocker): - enrollment_reenrollment_date = timezone.make_aware(timezone.datetime(2023, 2, 1), timezone=timezone.get_default_timezone()) - expiry_date = timezone.make_aware(timezone.datetime(2023, 3, 1), timezone=timezone.get_default_timezone()) - - # mock datetime of "now" to be specific date for testing - mocker.patch( - "benefits.enrollment.views.timezone.now", - return_value=expiry_date, - ) - - is_within_reenrollment_window = _is_within_reenrollment_window(expiry_date, enrollment_reenrollment_date) - - assert not is_within_reenrollment_window - - -@pytest.mark.django_db -@pytest.mark.usefixtures("mocked_session_agency", "mocked_session_verifier", "mocked_session_eligibility") -def test_index_eligible_post_valid_form_success_supports_expiration_is_within_reenrollment_window( - mocker, - client, - card_tokenize_form_data, - mocked_analytics_module, - model_EligibilityType_supports_expiration, - mocked_funding_source, - mocked_group_funding_source_with_expiry, - mocked_session_enrollment_expiry, -): - mock_client_cls = mocker.patch("benefits.enrollment.views.Client") - mock_client = mock_client_cls.return_value - mock_client.get_funding_source_by_token.return_value = mocked_funding_source - - # mock that a funding source already exists, doesn't matter what expiry_date is - mocker.patch("benefits.enrollment.views._get_group_funding_source", return_value=mocked_group_funding_source_with_expiry) - - mocker.patch("benefits.enrollment.views._is_within_reenrollment_window", return_value=True) - - path = reverse(ROUTE_INDEX) - response = client.post(path, card_tokenize_form_data) - - mock_client.update_concession_group_funding_source_expiry.assert_called_once_with( - funding_source_id=mocked_funding_source.id, - group_id=model_EligibilityType_supports_expiration.group_id, - expiry=mocked_session_enrollment_expiry.return_value, + funding_source_id=mocked_funding_source.id, group_id=model_EligibilityType.group_id ) assert response.status_code == 200 assert response.template_name == TEMPLATE_SUCCESS mocked_analytics_module.returned_success.assert_called_once() - assert model_EligibilityType_supports_expiration.group_id in mocked_analytics_module.returned_success.call_args.args - - -@pytest.mark.django_db -@pytest.mark.usefixtures( - "mocked_session_agency", - "mocked_session_verifier", - "mocked_session_eligibility", - "model_EligibilityType_supports_expiration", -) -def test_index_eligible_post_valid_form_success_supports_expiration_is_not_expired_yet( - mocker, - client, - card_tokenize_form_data, - mocked_analytics_module, - mocked_funding_source, - mocked_group_funding_source_with_expiry, -): - mock_client_cls = mocker.patch("benefits.enrollment.views.Client") - mock_client = mock_client_cls.return_value - mock_client.get_funding_source_by_token.return_value = mocked_funding_source - - # mock that a funding source already exists, doesn't matter what expiry_date is - mocker.patch("benefits.enrollment.views._get_group_funding_source", return_value=mocked_group_funding_source_with_expiry) - - mocker.patch("benefits.enrollment.views._is_expired", return_value=False) - mocker.patch("benefits.enrollment.views._is_within_reenrollment_window", return_value=False) - - path = reverse(ROUTE_INDEX) - response = client.post(path, card_tokenize_form_data) - - assert response.status_code == 200 - assert response.template_name == TEMPLATE_REENROLLMENT_ERROR - mocked_analytics_module.returned_error.assert_called_once() - - -@pytest.mark.django_db -@pytest.mark.usefixtures("mocked_session_agency", "mocked_session_verifier", "mocked_session_eligibility") -def test_index_eligible_post_valid_form_success_does_not_support_expiration_has_expiration_date( - mocker, - client, - card_tokenize_form_data, - mocked_analytics_module, - model_EligibilityType_does_not_support_expiration, - mocked_funding_source, - mocked_group_funding_source_with_expiry, -): - mock_client_cls = mocker.patch("benefits.enrollment.views.Client") - mock_client = mock_client_cls.return_value - mock_client.get_funding_source_by_token.return_value = mocked_funding_source - - # mock that a funding source already exists, doesn't matter what expiry_date is - mocker.patch("benefits.enrollment.views._get_group_funding_source", return_value=mocked_group_funding_source_with_expiry) - - path = reverse(ROUTE_INDEX) - with pytest.raises(NotImplementedError): - client.post(path, card_tokenize_form_data) - - # this is what we would assert if removing expiration were supported - # - # mock_client.link_concession_group_funding_source.assert_called_once_with( - # funding_source_id=mocked_funding_source.id, - # group_id=model_EligibilityType_does_not_support_expiration.group_id, - # expiry_date=None, - # ) - # assert response.status_code == 200 - # assert response.template_name == TEMPLATE_SUCCESS - # mocked_analytics_module.returned_success.assert_called_once() - # assert ( - # model_EligibilityType_does_not_support_expiration.group_id in mocked_analytics_module.returned_success.call_args.args - # ) + assert model_EligibilityType.group_id in mocked_analytics_module.returned_success.call_args.args @pytest.mark.django_db @@ -655,8 +254,8 @@ def test_success_no_verifier(client): @pytest.mark.django_db -@pytest.mark.usefixtures("mocked_session_verifier_auth_required", "mocked_session_eligibility") -def test_success_authentication_logged_in(mocker, client, model_TransitAgency, mocked_analytics_module): +@pytest.mark.usefixtures("mocked_session_verifier_auth_required") +def test_success_authentication_logged_in(mocker, client, model_TransitAgency): mock_session = mocker.patch("benefits.enrollment.views.session") mock_session.logged_in.return_value = True mock_session.agency.return_value = model_TransitAgency @@ -667,12 +266,11 @@ def test_success_authentication_logged_in(mocker, client, model_TransitAgency, m assert response.status_code == 200 assert response.template_name == TEMPLATE_SUCCESS assert {"origin": reverse(ROUTE_LOGGED_OUT)} in mock_session.update.call_args - mocked_analytics_module.returned_success.assert_called_once() @pytest.mark.django_db -@pytest.mark.usefixtures("mocked_session_verifier_auth_required", "mocked_session_eligibility") -def test_success_authentication_not_logged_in(mocker, client, model_TransitAgency, mocked_analytics_module): +@pytest.mark.usefixtures("mocked_session_verifier_auth_required") +def test_success_authentication_not_logged_in(mocker, client, model_TransitAgency): mock_session = mocker.patch("benefits.enrollment.views.session") mock_session.logged_in.return_value = False mock_session.agency.return_value = model_TransitAgency @@ -682,15 +280,13 @@ def test_success_authentication_not_logged_in(mocker, client, model_TransitAgenc assert response.status_code == 200 assert response.template_name == TEMPLATE_SUCCESS - mocked_analytics_module.returned_success.assert_called_once() @pytest.mark.django_db -@pytest.mark.usefixtures("mocked_session_agency", "mocked_session_verifier_auth_not_required", "mocked_session_eligibility") -def test_success_no_authentication(client, mocked_analytics_module): +@pytest.mark.usefixtures("mocked_session_agency", "mocked_session_verifier_auth_not_required") +def test_success_no_authentication(client): path = reverse(ROUTE_SUCCESS) response = client.get(path) assert response.status_code == 200 assert response.template_name == TEMPLATE_SUCCESS - mocked_analytics_module.returned_success.assert_called_once()