diff --git a/lms/djangoapps/courseware/tests/helpers.py b/lms/djangoapps/courseware/tests/helpers.py index 91212dcd4b09..4e325690cccd 100644 --- a/lms/djangoapps/courseware/tests/helpers.py +++ b/lms/djangoapps/courseware/tests/helpers.py @@ -3,8 +3,6 @@ """ -import ast -import re import json from collections import OrderedDict from datetime import timedelta @@ -444,17 +442,27 @@ def get_expiration_banner_text(user, course, language='en'): # lint-amnesty, py return bannerText -def get_context_dict_from_string(data): +def get_context_from_dict(data): """ - Retrieve dictionary from string. + Retrieve validated dictionary from template's contextual data. + + Args: + data: The context dictionary to validate + + Returns: + dict: context dictionary """ - # Replace tuple and un-necessary info from inside string and get the dictionary. - cleaned_data = data.split('((\'video.html\',')[1].replace("),\n {})", '').strip() + # Make a copy to avoid modifying the original dict + validated_data = data.copy() + # Omit user_id validation - cleaned_data_without_user = re.sub(".*user_id.*\n?", '', cleaned_data) + validated_data.pop('user_id', None) + + # Handle metadata field - parse and sort to ensure consistent ordering + if 'metadata' in validated_data and validated_data['metadata'] is not None: + metadata_dict = json.loads(validated_data['metadata']) + validated_data['metadata'] = OrderedDict( + sorted(metadata_dict.items(), key=lambda t: t[0]) + ) - validated_data = ast.literal_eval(cleaned_data_without_user) - validated_data['metadata'] = OrderedDict( - sorted(json.loads(validated_data['metadata']).items(), key=lambda t: t[0]) - ) return validated_data diff --git a/lms/djangoapps/courseware/tests/test_video_mongo.py b/lms/djangoapps/courseware/tests/test_video_mongo.py index 753eb2e5d462..f01bfad49432 100644 --- a/lms/djangoapps/courseware/tests/test_video_mongo.py +++ b/lms/djangoapps/courseware/tests/test_video_mongo.py @@ -46,7 +46,7 @@ from xmodule.modulestore.inheritance import own_metadata from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE # noinspection PyUnresolvedReferences -from xmodule.tests.helpers import override_descriptor_system # pylint: disable=unused-import +from xmodule.tests.helpers import mock_render_template, override_descriptor_system # pylint: disable=unused-import from xmodule.tests.test_import import DummyModuleStoreRuntime from xmodule.tests.test_video import VideoBlockTestBase from xmodule.video_block import VideoBlock, bumper_utils, video_utils @@ -55,7 +55,7 @@ from xmodule.x_module import PUBLIC_VIEW, STUDENT_VIEW from common.djangoapps.xblock_django.constants import ATTR_KEY_REQUEST_COUNTRY_CODE -from lms.djangoapps.courseware.tests.helpers import get_context_dict_from_string +from lms.djangoapps.courseware.tests.helpers import get_context_from_dict from openedx.core.djangoapps.video_config.toggles import PUBLIC_VIDEO_SHARE from openedx.core.djangoapps.video_config import sharing from openedx.core.djangoapps.video_pipeline.config.waffle import DEPRECATE_YOUTUBE @@ -82,9 +82,10 @@ class TestVideoYouTube(TestVideo): # lint-amnesty, pylint: disable=missing-class-docstring, test-inherits-tests METADATA = {} - def test_video_constructor(self): + @patch('xblock.utils.resources.ResourceLoader.render_django_template', side_effect=mock_render_template) + def test_video_constructor(self, mock_render_django_template): """Make sure that all parameters extracted correctly from xml""" - context = self.block.student_view(None).content + self.block.student_view(None) sources = ['example.mp4', 'example.webm'] expected_context = { @@ -145,9 +146,11 @@ def test_video_constructor(self): 'video_id': '', } - mako_service = self.block.runtime.service(self.block, 'mako') - assert get_context_dict_from_string(context) ==\ - get_context_dict_from_string(mako_service.render_lms_template('video.html', expected_context)) + # Get the actual context that was passed to render_django_template + actual_context = mock_render_django_template.call_args.args[1] + + # Validate and compare contexts + assert get_context_from_dict(actual_context) == get_context_from_dict(expected_context) class TestVideoNonYouTube(TestVideo): # pylint: disable=test-inherits-tests @@ -168,11 +171,12 @@ class TestVideoNonYouTube(TestVideo): # pylint: disable=test-inherits-tests } METADATA = {} - def test_video_constructor(self): + @patch('xblock.utils.resources.ResourceLoader.render_django_template', side_effect=mock_render_template) + def test_video_constructor(self, mock_render_django_template): """Make sure that if the 'youtube' attribute is omitted in XML, then the template generates an empty string for the YouTube streams. """ - context = self.block.student_view(None).content + self.block.student_view(None) sources = ['example.mp4', 'example.webm'] expected_context = { @@ -233,13 +237,17 @@ def test_video_constructor(self): 'video_id': '', } - mako_service = self.block.runtime.service(self.block, 'mako') - expected_result = get_context_dict_from_string( - mako_service.render_lms_template('video.html', expected_context) - ) - assert get_context_dict_from_string(context) == expected_result - assert expected_result['download_video_link'] == 'example.mp4' - assert expected_result['display_name'] == 'A Name' + # Get the actual context that was passed to render_django_template + actual_context = mock_render_django_template.call_args.args[1] + + # Validate and compare contexts + validated_actual = get_context_from_dict(actual_context) + validated_expected = get_context_from_dict(expected_context) + assert validated_actual == validated_expected + + # Verify specific fields + assert validated_actual['download_video_link'] == 'example.mp4' + assert validated_actual['display_name'] == 'A Name' @ddt.ddt @@ -323,15 +331,19 @@ def test_is_public_sharing_course_not_found(self, mock_get_course): self.assertEqual(self.block.public_access, is_public_sharing_enabled) @ddt.data(False, True) - def test_context(self, is_public_sharing_enabled): + @patch('xblock.utils.resources.ResourceLoader.render_django_template', side_effect=mock_render_template) + def test_context(self, is_public_sharing_enabled, mock_render_django_template): with self.mock_feature_toggle(): with patch.object( sharing, 'is_public_sharing_enabled', return_value=is_public_sharing_enabled ): - content = self.block.student_view(None).content - context = get_context_dict_from_string(content) + self.block.student_view(None) + + # Get the actual context that was passed to render_django_template + context = mock_render_django_template.call_args.args[1] + assert ('public_sharing_enabled' in context) == is_public_sharing_enabled assert ('public_video_url' in context) == is_public_sharing_enabled @@ -391,7 +403,8 @@ def get_handler_url(self, handler, suffix): self.block, handler, suffix ).rstrip('/?') - def test_get_html_track(self): + @patch('xblock.utils.resources.ResourceLoader.render_django_template', side_effect=mock_render_template) + def test_get_html_track(self, mock_render_django_template): # pylint: disable=invalid-name # lint-amnesty, pylint: disable=redefined-outer-name SOURCE_XML = """ @@ -493,7 +506,7 @@ def test_get_html_track(self): self.initialize_block(data=DATA) track_url = self.get_handler_url('transcript', 'download') - context = self.block.student_view(None).content + self.block.student_view(None) metadata.update({ 'transcriptLanguages': {"en": "English"} if not data['transcripts'] else {"uk": 'Українська'}, 'transcriptLanguage': 'en' if not data['transcripts'] or data.get('sub') else 'uk', @@ -516,11 +529,14 @@ def test_get_html_track(self): 'metadata': json.dumps(metadata) }) - mako_service = self.block.runtime.service(self.block, 'mako') - assert get_context_dict_from_string(context) ==\ - get_context_dict_from_string(mako_service.render_lms_template('video.html', expected_context)) + # Get the actual context that was passed to render_django_template + actual_context = mock_render_django_template.call_args.args[1] - def test_get_html_source(self): + # Validate and compare contexts + assert get_context_from_dict(actual_context) == get_context_from_dict(expected_context) + + @patch('xblock.utils.resources.ResourceLoader.render_django_template', side_effect=mock_render_template) + def test_get_html_source(self, mock_render_django_template): # lint-amnesty, pylint: disable=invalid-name, redefined-outer-name SOURCE_XML = """