From 2b95d3ad2af73ceba16fb3aa60864a57fc325932 Mon Sep 17 00:00:00 2001 From: Hamzah Ullah Date: Tue, 8 Sep 2026 12:43:56 -0400 Subject: [PATCH] feat: replace enterprise support contact-tag import with filter call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Swaps the direct openedx.features.enterprise_support import in the support contact-us view for a call to the new SupportContactContextRequested openedx-filter. Per pwnage101's review feedback on the filter itself, run_filter now returns a tuple of all its inputs (tags, user) and no longer takes request — pipeline steps that need it fetch it via crum internally. No settings changes here: OPEN_EDX_FILTERS_CONFIG registration for the pipeline step lives in edx-enterprise's own plugin_settings() (enterprise/settings/common.py), per the ENT-11830 ownership handoff. The test now mocks the filter call at the view layer; the enterprise-specific pipeline step behavior is covered by edx-enterprise's own test suite. Also bumps openedx-filters (3.9.0 -> 3.10.0) and edx-enterprise (8.9.4 -> 8.10.0) in pyproject.toml's uv_constraints and uv.lock / the compiled requirements files, via `make upgrade-package package=edx-enterprise,openedx-filters`, now that both releases carrying this filter and its enterprise-side pipeline step are published on PyPI. Without this bump the import above raises ImportError, since SupportContactContextRequested doesn't exist in the previously-pinned openedx-filters 3.9.0. ENT-11574 --- lms/djangoapps/support/tests/test_views.py | 44 ++++++++++++++++++++++ lms/djangoapps/support/views/contact_us.py | 6 +-- pyproject.toml | 4 +- requirements/edx/base.txt | 4 +- requirements/edx/development.txt | 4 +- uv.lock | 14 +++---- 6 files changed, 59 insertions(+), 17 deletions(-) diff --git a/lms/djangoapps/support/tests/test_views.py b/lms/djangoapps/support/tests/test_views.py index 7e2e04ea1f68..4576cc39bda8 100644 --- a/lms/djangoapps/support/tests/test_views.py +++ b/lms/djangoapps/support/tests/test_views.py @@ -96,6 +96,50 @@ def setUp(self): assert success, 'Could not log in' +class ContactUsViewTests(SupportViewTestCase): + """ + Tests for ContactUsView. + """ + + @override_settings(ZENDESK_URL='https://example.zendesk.com') + @patch('lms.djangoapps.support.views.contact_us.SupportContactContextRequested.run_filter') + def test_tags_run_through_filter_for_authenticated_user(self, mock_run_filter): + """ + For an authenticated user, the tags list is passed through the + SupportContactContextRequested filter, and the filter's return value is used + as the final tags list in the rendered context. + + The behavior of the filter's pipeline step (edx-enterprise's SupportContactEnterpriseTagStep) + is covered by edx-enterprise's own test suite. This view only needs to verify it wires + the filter's return value through correctly. + """ + mock_run_filter.return_value = (['LMS', 'enterprise_learner'], self.user) + + response = self.client.get(reverse('support:contact_us')) + + assert response.status_code == 200 + mock_run_filter.assert_called_once() + _, call_kwargs = mock_run_filter.call_args + assert call_kwargs['tags'] == ['LMS'] + assert call_kwargs['user'] == self.user + assert 'request' not in call_kwargs + assert b'enterprise_learner' in response.content + + def test_filter_not_called_for_anonymous_user(self): + """ + Anonymous users never reach the enterprise-tagging branch. + """ + self.client.logout() + with override_settings(ZENDESK_URL='https://example.zendesk.com'): + with patch( + 'lms.djangoapps.support.views.contact_us.SupportContactContextRequested.run_filter' + ) as mock_run_filter: + response = self.client.get(reverse('support:contact_us')) + + assert response.status_code == 200 + mock_run_filter.assert_not_called() + + class SupportViewManageUserTests(SupportViewTestCase): """ Base class for support view tests. diff --git a/lms/djangoapps/support/views/contact_us.py b/lms/djangoapps/support/views/contact_us.py index acb1dc122e62..3f3d6fd356fe 100644 --- a/lms/djangoapps/support/views/contact_us.py +++ b/lms/djangoapps/support/views/contact_us.py @@ -7,11 +7,11 @@ from django.http import Http404 from django.shortcuts import redirect from django.views.generic import View +from openedx_filters.learning.filters import SupportContactContextRequested from common.djangoapps.edxmako.shortcuts import marketing_link, render_to_response from common.djangoapps.student.models import CourseEnrollment from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.features.enterprise_support import api as enterprise_api class ContactUsView(View): @@ -47,9 +47,7 @@ def get(self, request): # pylint: disable=missing-function-docstring if request.user.is_authenticated: context['course_id'] = request.session.get('course_id', '') context['user_enrollments'] = CourseEnrollment.enrollments_for_user_with_overviews_preload(request.user) - enterprise_customer = enterprise_api.enterprise_customer_for_request(request) - if enterprise_customer: - tags.append('enterprise_learner') + tags, _ = SupportContactContextRequested.run_filter(tags=tags, user=request.user) context['tags'] = tags diff --git a/pyproject.toml b/pyproject.toml index 29b214f7ccd3..9cbf0362d7e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -290,7 +290,7 @@ constraint-dependencies = [ "sphinx-autoapi<3.6.1", "setuptools<82", "astroid==4.0.4", - "edx-enterprise==8.9.4", + "edx-enterprise==8.10.0", "djangorestframework<3.18", ] [tool.edx_lint] @@ -407,7 +407,7 @@ uv_constraints = [ # The team that owns this package will manually bump this package rather than # having it pulled in automatically. This is to allow them to better control its # deployment and to do it in a process that works better for them. - "edx-enterprise==8.9.4", + "edx-enterprise==8.10.0", # Date: 2026-08-31 # DRF 3.18.0 changes many=True validation errors from a list to a dict keyed by # item index, which breaks the error response shape of several write endpoints. diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index aafbc395d366..d70799329b85 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -480,7 +480,7 @@ edx-drf-extensions==10.8.0 # openedx-authz # openedx-core # openedx-platform -edx-enterprise==8.9.4 +edx-enterprise==8.10.0 # via openedx-platform edx-event-bus-kafka==6.1.0 # via openedx-platform @@ -845,7 +845,7 @@ openedx-events==11.2.0 # openedx-core # openedx-platform # ora2 -openedx-filters==3.9.0 +openedx-filters==3.10.0 # via # edx-enterprise # lti-consumer-xblock diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index 9fb980ed12e9..9b4d0d8b1c42 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -533,7 +533,7 @@ edx-drf-extensions==10.8.0 # openedx-authz # openedx-core # openedx-platform -edx-enterprise==8.9.4 +edx-enterprise==8.10.0 # via openedx-platform edx-event-bus-kafka==6.1.0 # via openedx-platform @@ -947,7 +947,7 @@ openedx-events==11.2.0 # openedx-core # openedx-platform # ora2 -openedx-filters==3.9.0 +openedx-filters==3.10.0 # via # edx-enterprise # lti-consumer-xblock diff --git a/uv.lock b/uv.lock index d9e58461dc59..ef9da2c98524 100644 --- a/uv.lock +++ b/uv.lock @@ -20,7 +20,7 @@ constraints = [ { name = "django-oauth-toolkit", specifier = "==1.7.1" }, { name = "django-stubs", specifier = "<6" }, { name = "djangorestframework", specifier = "<3.18" }, - { name = "edx-enterprise", specifier = "==8.9.4" }, + { name = "edx-enterprise", specifier = "==8.10.0" }, { name = "elasticsearch", specifier = "==7.9.1" }, { name = "libsass", specifier = "==0.10.0" }, { name = "lxml", specifier = "==5.3.2" }, @@ -2044,7 +2044,7 @@ wheels = [ [[package]] name = "edx-enterprise" -version = "8.9.4" +version = "8.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "bleach" }, @@ -2098,9 +2098,9 @@ dependencies = [ { name = "tincan" }, { name = "unicodecsv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3e/3a/7b57ce0e6781268bab6035b0a85b769a01e13fdfd231de7a447e51eaf7c0/edx_enterprise-8.9.4.tar.gz", hash = "sha256:22ff6461888a496bdeaba57623cb58ea6114cefa4479d7bf821a281be75a4db1", size = 5166016, upload-time = "2026-08-28T13:08:06.996Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/17/f84016daad23b0e7f3ad5fc716a25fd60eaaa304cc249e6e0b2d4fdd07b6/edx_enterprise-8.10.0.tar.gz", hash = "sha256:64e84e3c05f4db6ffae57fccc7acbe76c34b7592146d63631d9aeb15f4cc39f5", size = 5166582, upload-time = "2026-09-09T18:07:14.962Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fa/ac/a44afffd844843be1241faa1a8de145e83d9cb284da026c7b248268fcfa0/edx_enterprise-8.9.4-py3-none-any.whl", hash = "sha256:ab81432141cc106e9319e76be9da9516f7acb3f577635016355f58b6ad8d2ce8", size = 5559792, upload-time = "2026-08-28T13:08:03.667Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f8/16e13fa2c3a7f585ee66a1aad753ea9cc68cb9660a33cff66437c90f7eb9/edx_enterprise-8.10.0-py3-none-any.whl", hash = "sha256:d18a19d5de9b495bd20f164100aacf717f022499a0ae15515d26ae5ea7415178", size = 5560569, upload-time = "2026-09-09T18:07:11.061Z" }, ] [[package]] @@ -4370,7 +4370,7 @@ wheels = [ [[package]] name = "openedx-filters" -version = "3.9.0" +version = "3.10.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "django", version = "4.2.30", source = { registry = "https://pypi.org/simple" }, marker = "extra == 'group-16-openedx-platform-django42'" }, @@ -4378,9 +4378,9 @@ dependencies = [ { name = "edx-opaque-keys" }, { name = "setuptools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ed/54/34ff71ff7ac30feff9b76f4961b1ad1561010d2b218afb30c44ac2e81361/openedx_filters-3.9.0.tar.gz", hash = "sha256:928c159c9d215172f82cc894a06ada805b7a0c53a3ab1d148efefa1209efe4d5", size = 51210, upload-time = "2026-08-07T00:39:07.819Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/a3/4af57a5388acbb6c9f830646d372f7da3e42944c6579a0bb6df9af75b171/openedx_filters-3.10.0.tar.gz", hash = "sha256:eda139c5ab0b9d08995d93cb2532f71f291c2ce2b272dd780fb9bfc3009be132", size = 51490, upload-time = "2026-09-09T16:50:38.612Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a1/98/eccd5dd4e25996209ddb623c74c219f0961c92cd6fed1b630483bc872039/openedx_filters-3.9.0-py2.py3-none-any.whl", hash = "sha256:a29bfd0c897d53f5567bf6205ffbb3ea2688aacbbb9c3f5071010d3ab3534412", size = 50085, upload-time = "2026-08-07T00:39:06.47Z" }, + { url = "https://files.pythonhosted.org/packages/91/32/4eaf0404f757dd3deb4c35297d2af3427fadc97aac06900d96025061892a/openedx_filters-3.10.0-py2.py3-none-any.whl", hash = "sha256:6a549334bd6f376f6c09c7f7e76625a8c00dbfb5fc5930923c6fcc784423561d", size = 50537, upload-time = "2026-09-09T16:50:37.456Z" }, ] [[package]]