diff --git a/common/lib/xmodule/xmodule/html_module.py b/common/lib/xmodule/xmodule/html_module.py index b0571fba9fb4..822ca902ceee 100644 --- a/common/lib/xmodule/xmodule/html_module.py +++ b/common/lib/xmodule/xmodule/html_module.py @@ -76,6 +76,17 @@ def student_view(self, _context): """ return Fragment(self.get_html()) + def student_view_data(self): + """ + Returns a JSON representation of the student_view of this XBlock, + retrievable from the Course Block API. + Since this data is not user-specific, fields like `html` may contain + placeholders like %%USER_ID%%. + """ + return { + 'html': self.data + } + def get_html(self): """ Returns html required for rendering XModule. """ diff --git a/common/lib/xmodule/xmodule/tests/test_html_module.py b/common/lib/xmodule/xmodule/tests/test_html_module.py index 2b272487ff13..b0f00432e51e 100644 --- a/common/lib/xmodule/xmodule/tests/test_html_module.py +++ b/common/lib/xmodule/xmodule/tests/test_html_module.py @@ -1,5 +1,5 @@ import unittest - +import ddt from mock import Mock from opaque_keys.edx.locations import SlashSeparatedCourseKey from xblock.field_data import DictFieldData @@ -24,6 +24,30 @@ def instantiate_descriptor(**field_data): ) +@ddt.ddt +class HtmlModuleCourseApiTestCase(unittest.TestCase): + """ + Ensure that student_view_data can handle likely input, + and doesn't modify the HTML in any way. + This means that it does NOT protect against XSS, escape HTML tags, etc. + """ + @ddt.data( + '

Some content

', # Valid HTML + '', + None, + '

Some contentalert()', # Does not escape tags + '', # Images allowed + 'short string ' * 100, # May contain long strings + ) + def test_common_values(self, html): + descriptor = Mock() + field_data = DictFieldData({'data': html}) + module_system = get_test_system() + module = HtmlModule(descriptor, module_system, field_data, Mock()) + self.assertEqual(module.student_view_data(), {'html': html}) + + class HtmlModuleSubstitutionTestCase(unittest.TestCase): descriptor = Mock() diff --git a/lms/djangoapps/course_api/blocks/tests/test_views.py b/lms/djangoapps/course_api/blocks/tests/test_views.py index 5c518fa7e27a..70a6e4918201 100644 --- a/lms/djangoapps/course_api/blocks/tests/test_views.py +++ b/lms/djangoapps/course_api/blocks/tests/test_views.py @@ -22,7 +22,7 @@ class TestBlocksView(SharedModuleStoreTestCase): Test class for BlocksView """ requested_fields = ['graded', 'format', 'student_view_multi_device', 'children', 'not_a_field', 'due'] - BLOCK_TYPES_WITH_STUDENT_VIEW_DATA = ['video', 'discussion'] + BLOCK_TYPES_WITH_STUDENT_VIEW_DATA = ['video', 'discussion', 'html'] @classmethod def setUpClass(cls): diff --git a/lms/djangoapps/course_api/blocks/transformers/tests/test_student_view.py b/lms/djangoapps/course_api/blocks/transformers/tests/test_student_view.py index b37ec88e80f4..f20e76c40a3d 100644 --- a/lms/djangoapps/course_api/blocks/transformers/tests/test_student_view.py +++ b/lms/djangoapps/course_api/blocks/transformers/tests/test_student_view.py @@ -44,7 +44,7 @@ def test_transform(self): # verify html data html_block_key = self.course_key.make_usage_key('html', 'toyhtml') - self.assertIsNone( + self.assertIsNotNone( self.block_structure.get_transformer_block_field( html_block_key, StudentViewTransformer, StudentViewTransformer.STUDENT_VIEW_DATA, )