diff --git a/feedback/extensions/filters.py b/feedback/extensions/filters.py index 2813907..88a3c44 100644 --- a/feedback/extensions/filters.py +++ b/feedback/extensions/filters.py @@ -9,7 +9,7 @@ from web_fragments.fragment import Fragment try: - from cms.djangoapps.contentstore.utils import get_lms_link_for_item + from feedback.utils import get_lms_link_for_item from lms.djangoapps.courseware.block_render import (get_block_by_usage_id, load_single_xblock) from openedx.core.djangoapps.enrollments.data import get_user_enrollments diff --git a/feedback/settings/test.py b/feedback/settings/test.py index 1277001..9f8c731 100644 --- a/feedback/settings/test.py +++ b/feedback/settings/test.py @@ -22,3 +22,5 @@ } SECRET_KEY = 'fake-key' + +LMS_ROOT_URL = "https://example.com" diff --git a/feedback/utils.py b/feedback/utils.py index 6b01fe2..4168f29 100644 --- a/feedback/utils.py +++ b/feedback/utils.py @@ -1,6 +1,44 @@ """Utilities for feedback app""" +# feedbackblock/feedback/utils.py +from urllib.parse import urlencode, urlparse, urlunparse +from opaque_keys.edx.keys import UsageKey +from django.conf import settings + def _(text): """Dummy `gettext` replacement to make string extraction tools scrape strings marked for translation""" return text + + +def get_lms_link_for_item(location, preview=False): + """ + Returns an LMS link to the course with a jump_to to the provided location. + """ + assert isinstance(location, UsageKey) + + try: + # pylint: disable=import-outside-toplevel + from openedx.core.djangoapps.site_configuration.models import SiteConfiguration + + except ImportError: + return None + + lms_base = SiteConfiguration.get_value_for_org( + location.org, + "LMS_ROOT_URL", + settings.LMS_ROOT_URL + ) + + if lms_base is None: + return None + + query_string = '' + if preview: + query_string = urlencode({'preview': '1'}) + + url_parts = list(urlparse(lms_base)) + url_parts[2] = f'/courses/{location.course_key}/jump_to/{location}' + url_parts[4] = query_string + + return urlunparse(url_parts) diff --git a/feedbacktests/test_utils.py b/feedbacktests/test_utils.py new file mode 100644 index 0000000..05fc503 --- /dev/null +++ b/feedbacktests/test_utils.py @@ -0,0 +1,62 @@ +from feedback.utils import get_lms_link_for_item +from opaque_keys.edx.keys import UsageKey +from unittest.mock import Mock +import sys +import types + + +def test_get_lms_link_importerror(monkeypatch): + location = Mock(spec=UsageKey) + location.org = "edX" + location.course_key = "course-v1:edX+DemoX+2024" + location.__str__ = lambda self=location: "dummy" + + if "openedx.core.djangoapps.site_configuration.models" in sys.modules: + del sys.modules["openedx.core.djangoapps.site_configuration.models"] + + monkeypatch.setattr("feedback.utils.settings", types.SimpleNamespace(LMS_ROOT_URL="https://example.com")) + + result = get_lms_link_for_item(location) + assert result is None + +def test_get_lms_link_with_null_lms_base(monkeypatch): + location = Mock(spec=UsageKey) + location.org = "edX" + location.course_key = "dummy" + location.__str__ = lambda self=location: "dummy" + + class MockSiteConfiguration: + @staticmethod + def get_value_for_org(org, key, default): + return None # simulate LMS base not set + + monkeypatch.setitem( + sys.modules, + "openedx.core.djangoapps.site_configuration.models", + types.SimpleNamespace(SiteConfiguration=MockSiteConfiguration) + ) + + result = get_lms_link_for_item(location) + assert result is None + + +def test_get_lms_link_with_preview(monkeypatch): + location = Mock(spec=UsageKey) + location.org = "edX" + location.course_key = "course-v1:edX+DemoX+2024" + location.__str__ = lambda self=location: "dummy" + + class MockSiteConfiguration: + @staticmethod + def get_value_for_org(org, key, default): + return "https://fallback.com" + + monkeypatch.setitem( + sys.modules, + "openedx.core.djangoapps.site_configuration.models", + types.SimpleNamespace(SiteConfiguration=MockSiteConfiguration) + ) + + result = get_lms_link_for_item(location, preview=True) + assert result == "https://fallback.com/courses/course-v1:edX+DemoX+2024/jump_to/dummy?preview=1" +