diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index ec46484922..aeb0903632 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -1612,17 +1612,15 @@ class RerunCourseTest(ContentStoreTestCase): self.assertEqual(len(self.get_course_listing_elements(course_listing, course_key)), 0) self.assertEqual(len(self.get_unsucceeded_course_action_elements(course_listing, course_key)), 1) - def test_rerun_course_success(self): - - source_course = CourseFactory.create() - destination_course_key = self.post_rerun_request(source_course.id) - - # Verify the contents of the course rerun action + def verify_rerun_course(self, source_course_key, destination_course_key, destination_display_name): + """ + Verify the contents of the course rerun action + """ rerun_state = CourseRerunState.objects.find_first(course_key=destination_course_key) expected_states = { 'state': CourseRerunUIStateManager.State.SUCCEEDED, - 'display_name': self.destination_course_data['display_name'], - 'source_course_key': source_course.id, + 'display_name': destination_display_name, + 'source_course_key': source_course_key, 'course_key': destination_course_key, 'should_display': True, } @@ -1633,28 +1631,46 @@ class RerunCourseTest(ContentStoreTestCase): self.assertTrue(CourseEnrollment.is_enrolled(self.user, destination_course_key)) # Verify both courses are in the course listing section - self.assertInCourseListing(source_course.id) + self.assertInCourseListing(source_course_key) self.assertInCourseListing(destination_course_key) - @skipIf(not settings.FEATURES.get('ALLOW_COURSE_RERUNS', False), "ALLOW_COURSE_RERUNS are not enabled") + + def test_rerun_course_success(self): + source_course = CourseFactory.create() + destination_course_key = self.post_rerun_request(source_course.id) + self.verify_rerun_course(source_course.id, destination_course_key, self.destination_course_data['display_name']) + + def test_rerun_of_rerun(self): + source_course = CourseFactory.create() + rerun_course_key = self.post_rerun_request(source_course.id) + rerun_of_rerun_data = { + 'org': rerun_course_key.org, + 'number': rerun_course_key.course, + 'display_name': 'rerun of rerun', + 'run': 'rerun2' + } + rerun_of_rerun_course_key = self.post_rerun_request(rerun_course_key, rerun_of_rerun_data) + self.verify_rerun_course(rerun_course_key, rerun_of_rerun_course_key, rerun_of_rerun_data['display_name']) + def test_rerun_course_fail_no_source_course(self): - existent_course_key = CourseFactory.create().id - non_existent_course_key = CourseLocator("org", "non_existent_course", "non_existent_run") - destination_course_key = self.post_rerun_request(non_existent_course_key) + with mock.patch.dict('django.conf.settings.FEATURES', {'ALLOW_COURSE_RERUNS': True}): + existent_course_key = CourseFactory.create().id + non_existent_course_key = CourseLocator("org", "non_existent_course", "non_existent_run") + destination_course_key = self.post_rerun_request(non_existent_course_key) - # Verify that the course rerun action is marked failed - rerun_state = CourseRerunState.objects.find_first(course_key=destination_course_key) - self.assertEquals(rerun_state.state, CourseRerunUIStateManager.State.FAILED) - self.assertIn("Cannot find a course at", rerun_state.message) + # Verify that the course rerun action is marked failed + rerun_state = CourseRerunState.objects.find_first(course_key=destination_course_key) + self.assertEquals(rerun_state.state, CourseRerunUIStateManager.State.FAILED) + self.assertIn("Cannot find a course at", rerun_state.message) - # Verify that the creator is not enrolled in the course. - self.assertFalse(CourseEnrollment.is_enrolled(self.user, non_existent_course_key)) + # Verify that the creator is not enrolled in the course. + self.assertFalse(CourseEnrollment.is_enrolled(self.user, non_existent_course_key)) - # Verify that the existing course continues to be in the course listings - self.assertInCourseListing(existent_course_key) + # Verify that the existing course continues to be in the course listings + self.assertInCourseListing(existent_course_key) - # Verify that the failed course is NOT in the course listings - self.assertInUnsucceededCourseActions(destination_course_key) + # Verify that the failed course is NOT in the course listings + self.assertInUnsucceededCourseActions(destination_course_key) def test_rerun_course_fail_duplicate_course(self): existent_course_key = CourseFactory.create().id diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py index 88551f3f7b..fdd5df6414 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py @@ -168,7 +168,8 @@ class BulkWriteRecord(object): return self.structures.get(self.index.get('versions', {}).get(branch)) def set_structure_for_branch(self, branch, structure): - self.index.get('versions', {})[branch] = structure['_id'] + if self.index is not None: + self.index.setdefault('versions', {})[branch] = structure['_id'] self.structures[structure['_id']] = structure def __repr__(self): diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore_bulk_operations.py b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore_bulk_operations.py index 8c75800f02..313fe988df 100644 --- a/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore_bulk_operations.py +++ b/common/lib/xmodule/xmodule/modulestore/tests/test_split_modulestore_bulk_operations.py @@ -174,6 +174,13 @@ class TestBulkWriteMixinClosed(TestBulkWriteMixin): self.structure['_id'] ) + def test_version_structure_new_course(self): + self.conn.get_course_index.return_value = None + self.bulk._begin_bulk_operation(self.course_key) + version_result = self.bulk.version_structure(self.course_key, self.structure, 'user_id') + get_result = self.bulk.get_structure(self.course_key, version_result['_id']) + self.assertEquals(version_result, get_result) + class TestBulkWriteMixinClosedAfterPrevTransaction(TestBulkWriteMixinClosed, TestBulkWriteMixinPreviousTransaction): """ Test that operations on with a closed transaction aren't affected by a previously executed transaction