From e306bc74c00b05fe7ae8828926b1633ef41cde4f Mon Sep 17 00:00:00 2001 From: DawoudSheraz Date: Thu, 31 Oct 2019 13:44:51 +0500 Subject: [PATCH] avoid pretty printing of pre tags in course import --- .../views/tests/test_import_export.py | 90 +++++++++++++++++++ common/lib/xmodule/xmodule/raw_module.py | 10 ++- 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/cms/djangoapps/contentstore/views/tests/test_import_export.py b/cms/djangoapps/contentstore/views/tests/test_import_export.py index a7b23ab19b..dd63e8cda1 100644 --- a/cms/djangoapps/contentstore/views/tests/test_import_export.py +++ b/cms/djangoapps/contentstore/views/tests/test_import_export.py @@ -1021,3 +1021,93 @@ class TestCourseExportImport(LibraryTestCase): dest_course.location, publish_item ) + + +@override_settings(CONTENTSTORE=TEST_DATA_CONTENTSTORE) +class TestCourseExportImportProblem(CourseTestCase): + """ + Tests for importing after exporting the course containing problem with pre tags from XML. + """ + def setUp(self): + super(TestCourseExportImportProblem, self).setUp() + self.export_dir = tempfile.mkdtemp() + self.source_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) + self.addCleanup(shutil.rmtree, self.export_dir, ignore_errors=True) + + def _setup_source_course_with_problem_content(self, publish_item=False): + """ + Sets up course with problem content. + """ + chapter = ItemFactory.create( + parent_location=self.source_course.location, + category='chapter', + display_name='Test Section' + ) + sequential = ItemFactory.create( + parent_location=chapter.location, + category='sequential', + display_name='Test Sequential' + ) + vertical = ItemFactory.create( + category='vertical', + parent_location=sequential.location, + display_name='Test Unit' + ) + + ItemFactory.create( + parent=vertical, + category='problem', + display_name='Test Problem', + publish_item=publish_item, + data='
x=10
', + ) + + def get_problem_content(self, block_location): + """ + Get problem content of course. + """ + if block_location.block_type == 'problem': + return self.store.get_item(block_location).data + + return self.get_problem_content(self.store.get_item(block_location).children[0]) + + def assert_problem_definition(self, course_location): + """ + Asserts that problems' data is as expected with pre-tag content maintained. + """ + expected_problem_content = '\n
x=10
\n' \ + ' \n
\n' + problem_content = self.get_problem_content(course_location) + + self.assertEquals(expected_problem_content, problem_content) + + def test_problem_content_on_course_export_import(self): + """ + Verify that problem content in destination matches expected problem content, + specifically concerned with pre tag data with problem. + """ + self._setup_source_course_with_problem_content() + + dest_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) + + export_course_to_xml( + self.store, + contentstore(), + self.source_course.location.course_key, + self.export_dir, + 'exported_source_course', + ) + + import_course_from_xml( + self.store, + self.user.id, + self.export_dir, + ['exported_source_course'], + static_content_store=contentstore(), + target_id=dest_course.location.course_key, + load_error_modules=False, + raise_on_failure=True, + create_if_not_present=True, + ) + + self.assert_problem_definition(dest_course.location) diff --git a/common/lib/xmodule/xmodule/raw_module.py b/common/lib/xmodule/xmodule/raw_module.py index 7d456b7383..5d9eb65db8 100644 --- a/common/lib/xmodule/xmodule/raw_module.py +++ b/common/lib/xmodule/xmodule/raw_module.py @@ -1,6 +1,7 @@ from __future__ import absolute_import import logging +import re from lxml import etree from xblock.fields import Scope, String @@ -11,6 +12,8 @@ from .exceptions import SerializationError log = logging.getLogger(__name__) +PRE_TAG_REGEX = re.compile(r'
[\s\S]*?
') + class RawMixin(object): """ @@ -22,7 +25,12 @@ class RawMixin(object): @classmethod def definition_from_xml(cls, xml_object, system): - return {'data': etree.tostring(xml_object, pretty_print=True, encoding='unicode')}, [] + pre_tag_data = [etree.tostring(pre_tag_info) for pre_tag_info in xml_object.findall('pre')] + data = etree.tostring(xml_object, pretty_print=True, encoding='unicode') + if pre_tag_data: + for index, pre_tag in enumerate(re.findall(PRE_TAG_REGEX, data)): + data = re.sub(re.escape(pre_tag), pre_tag_data[index].decode(), data) + return {'data': data}, [] def definition_to_xml(self, resource_fs): """