diff --git a/cms/envs/test.py b/cms/envs/test.py index 3736e76360..cea21fce05 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -267,6 +267,12 @@ TEST_ELASTICSEARCH_USE_SSL = os.environ.get( TEST_ELASTICSEARCH_HOST = os.environ.get('EDXAPP_TEST_ELASTICSEARCH_HOST', 'edx.devstack.elasticsearch710') TEST_ELASTICSEARCH_PORT = int(os.environ.get('EDXAPP_TEST_ELASTICSEARCH_PORT', '9200')) +############################# TEMPLATE CONFIGURATION ############################# +# Adds mako template dirs for content_libraries tests +MAKO_TEMPLATE_DIRS_BASE.append( + COMMON_ROOT / 'lib' / 'capa' / 'capa' / 'templates' +) + ########################## AUTHOR PERMISSION ####################### FEATURES['ENABLE_CREATOR_GROUP'] = False diff --git a/common/test/problem.html b/common/test/problem.html new file mode 100644 index 0000000000..0c63e205e0 --- /dev/null +++ b/common/test/problem.html @@ -0,0 +1,96 @@ + +<%page expression_filter="h"/> +<%! +from django.utils.translation import ngettext, gettext as _ +from openedx.core.djangolib.markup import HTML +%> + +<%namespace name='static' file='static_content.html'/> +

+ ${ problem['name'] } +

+ +
+ +
+ ${ HTML(problem['html']) } +
+ + +
+ % if demand_hint_possible: + + + + % endif + % if save_button: + + + + % endif + % if reset_button: + + + + % endif + % if answer_available: + + + + % endif +
+
+ + + % if submit_disabled_cta: + % if submit_disabled_cta.get('event_data'): + + + + + (${submit_disabled_cta['description']}) + % else: +
+ + % for form_name, form_value in submit_disabled_cta['form_values'].items(): + + % endfor + + + + + (${submit_disabled_cta['description']}) +
+ % endif + % endif +
+ ## When attempts are not 0, the CTA above will contain a message about the number of used attempts + % if attempts_allowed and (not submit_disabled_cta or attempts_used == 0): + ${ngettext("You have used {num_used} of {num_total} attempt", "You have used {num_used} of {num_total} attempts", attempts_allowed).format(num_used=attempts_used, num_total=attempts_allowed)} + % endif + ${_("Some problems have options such as save, reset, hints, or show answer. These options follow the Submit button.")} +
+
+
+
+ + diff --git a/common/test/problem_ajax.html b/common/test/problem_ajax.html new file mode 100644 index 0000000000..bbe365bd92 --- /dev/null +++ b/common/test/problem_ajax.html @@ -0,0 +1,16 @@ + +
+

+ + Loading… +

+
diff --git a/common/test/video.html b/common/test/video.html new file mode 100644 index 0000000000..ea6a54d994 --- /dev/null +++ b/common/test/video.html @@ -0,0 +1,122 @@ + +<%page expression_filter="h"/> + +<%! +from django.utils.translation import ugettext as _ +from openedx.core.djangolib.js_utils import ( + dump_js_escaped_json, js_escaped_string +) +%> +% if display_name is not UNDEFINED and display_name is not None: +

${display_name}

+% endif + +
+
+ +
+
+ + +
+
+
+ + +
+
+
+ +
+
+ +
+ + % if download_video_link or track or handout or branding_info: +

${_('Downloads and transcripts')}

+
+ % if download_video_link: + + % endif + % if track: +
+

${_('Transcripts')}

+ % if transcript_download_format: +
    + % for item in transcript_download_formats_list: +
  • + <% dname = _("Download {file}").format(file=item['display_name']) %> + ${dname} +
  • + % endfor +
+ % else: + ${_('Download transcript')} + % endif +
+ % endif + % if handout: +
+

${_('Handouts')}

+ ${_('Download Handout')} +
+ % endif + % if branding_info: +
+ ${branding_info['logo_tag']} + +
+ % endif +
+ % endif +
+% if cdn_eval: + +% endif; diff --git a/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py b/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py index c23679cb18..599dfd9a60 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py @@ -3,7 +3,9 @@ Tests for Blockstore-based Content Libraries """ from uuid import UUID from unittest.mock import patch +from urllib.parse import urlparse, parse_qsl +import json import ddt from django.conf import settings from django.contrib.auth.models import Group @@ -11,6 +13,9 @@ from django.test.client import Client from django.test.utils import override_settings from organizations.models import Organization from rest_framework.test import APITestCase +from web_fragments.fragment import Fragment +from webob import Response +from xblock.core import XBlock from openedx.core.djangoapps.content_libraries.libraries_index import LibraryBlockIndexer, ContentLibraryIndexer from openedx.core.djangoapps.content_libraries.tests.base import ( @@ -20,6 +25,7 @@ from openedx.core.djangoapps.content_libraries.tests.base import ( URL_BLOCK_RENDER_VIEW, URL_BLOCK_GET_HANDLER_URL, URL_BLOCK_XBLOCK_HANDLER, + URL_LIB_BLOCK_OLX, ) from openedx.core.djangoapps.content_libraries.constants import VIDEO, COMPLEX, PROBLEM, CC_4_BY, ALL_RIGHTS_RESERVED from openedx.core.djangolib.blockstore_cache import cache @@ -903,3 +909,164 @@ class ContentLibraryXBlockValidationTest(APITestCase): self.assertEqual(response.json(), { 'detail': f"XBlock {valid_not_found_key} does not exist, or you don't have permission to view it.", }) + + +class AltBlock(XBlock): + """Class for testing LabXchange XBlock type overrides.""" + @XBlock.handler + def student_view_user_state(self, request, suffix=""): + """ + Returns a JSON response for testing. + """ + view_state = { + "id": str(self.location), + "block_type": str(self.location.block_type), + "override_type": str(self.__class__), + } + return Response( + json.dumps(view_state), + content_type='application/json', + charset='UTF-8', + ) + + def student_view(self, context=None): + """ + Returns an HTML fragment for testing. + """ + return Fragment(f"
" + "
") + + +@ddt.ddt +@elasticsearch_test +class ContentLibrariesXBlockTypeOverrideTest(ContentLibrariesRestApiTest): + """ + Tests for Blockstore-based Content Libraries XBlock API, + where the expected XBlock type returned is overridden in the request. + """ + BLOCK_DATA = ( + ('block-wo-override', {}, 'video'), + ('block-w-override', {'lx_block_types': '1'}, 'alt-block'), + ) + + def setUp(self): + super().setUp() + if settings.ENABLE_ELASTICSEARCH_FOR_TESTS: + ContentLibraryIndexer.remove_all_items() + LibraryBlockIndexer.remove_all_items() + + self.olx = """ +