From 23e08b2744e1f146f265d2e5f76d8f667f8b581b Mon Sep 17 00:00:00 2001 From: Syed Hassan Raza Date: Tue, 7 Apr 2015 16:58:47 +0500 Subject: [PATCH] Split courses drafts import issue --- .../modulestore/split_mongo/split_draft.py | 4 ++ .../tests/test_mixed_modulestore.py | 55 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py index 7d84e56124..5fb612ca4d 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split_draft.py @@ -498,6 +498,10 @@ class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPubli draft_course = course_key.for_branch(ModuleStoreEnum.BranchName.draft) with self.branch_setting(ModuleStoreEnum.Branch.draft_preferred, draft_course): draft_block = self.import_xblock(user_id, draft_course, block_type, block_id, fields, runtime) + # if block was published once and now it is in draft state then return draft version + # as current state of block is draft state + if self.has_published_version(draft_block) and block_type not in DIRECT_ONLY_CATEGORIES: + return draft_block return self.publish(draft_block.location.version_agnostic(), user_id, blacklist=EXCLUDE_ALL, **kwargs) # do the import diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py index cbd6c6762e..2c9b3dfb80 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py @@ -10,6 +10,8 @@ import itertools import mimetypes from unittest import skip from uuid import uuid4 +from shutil import rmtree +from tempfile import mkdtemp # Mixed modulestore depends on django, so we'll manually configure some django settings # before importing the module @@ -26,6 +28,7 @@ from xmodule.modulestore.tests.test_cross_modulestore_import_export import Mongo from xmodule.contentstore.content import StaticContent from opaque_keys.edx.keys import CourseKey from xmodule.modulestore.xml_importer import import_course_from_xml +from xmodule.modulestore.xml_exporter import export_course_to_xml from xmodule.modulestore.django import SignalHandler if not settings.configured: @@ -151,6 +154,8 @@ class TestMixedModuleStore(CourseComparisonTest): self.course_locations = {} self.user_id = ModuleStoreEnum.UserID.test + self.export_dir = mkdtemp() + self.addCleanup(rmtree, self.export_dir, ignore_errors=True) # pylint: disable=invalid-name def _create_course(self, course_key): @@ -504,6 +509,56 @@ class TestMixedModuleStore(CourseComparisonTest): component = self.store.publish(component.location, self.user_id) self.assertFalse(self.store.has_changes(component)) + @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) + def test_has_changes_before_export_and_after_import(self, default_ms): + """ + Tests that an unpublished unit remains with no changes across export and re-import. + """ + with MongoContentstoreBuilder().build() as contentstore: + # initialize the mixed modulestore + self._initialize_mixed(contentstore=contentstore, mappings={}) + + with self.store.default_store(default_ms): + + source_course_key = self.store.make_course_key("org.source", "course.source", "run.source") + self._create_course(source_course_key) + + # Create a dummy component to test against + xblock = self.store.create_item( + self.user_id, + self.course.id, + 'vertical', + block_id='test_vertical' + ) + + # Not yet published, so changes are present + self.assertTrue(self.store.has_changes(xblock)) + + export_course_to_xml( + self.store, + contentstore, + source_course_key, + self.export_dir, + 'exported_source_course', + ) + + import_course_from_xml( + self.store, + 'test_user', + self.export_dir, + source_dirs=['exported_source_course'], + static_content_store=contentstore, + target_id=source_course_key, + create_if_not_present=True, + raise_on_failure=True, + ) + + # Get the xblock from the imported course. + component = self.store.get_item(xblock.location) + + # Verify that it still is a draft, i.e. has changes. + self.assertTrue(self.store.has_changes(component)) + def _has_changes(self, location): """ Helper function that loads the item before calling has_changes