diff --git a/cms/djangoapps/contentstore/management/commands/migrate_to_split.py b/cms/djangoapps/contentstore/management/commands/migrate_to_split.py deleted file mode 100644 index 38fed6265c0c..000000000000 --- a/cms/djangoapps/contentstore/management/commands/migrate_to_split.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Django management command to migrate a course from the old Mongo modulestore -to the new split-Mongo modulestore. -""" - - -from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user -from django.core.management.base import BaseCommand, CommandError -from opaque_keys import InvalidKeyError -from opaque_keys.edx.keys import CourseKey - -from cms.djangoapps.contentstore.management.commands.utils import user_from_str -from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.split_migrator import SplitMigrator # lint-amnesty, pylint: disable=wrong-import-order - - -class Command(BaseCommand): - """ - Migrate a course from old-Mongo to split-Mongo. It reuses the old course id except where overridden. - """ - - help = "Migrate a course from old-Mongo to split-Mongo. The new org, course, and run will " \ - "default to the old one unless overridden." - - def add_arguments(self, parser): - parser.add_argument('course_key') - parser.add_argument('email') - parser.add_argument('--org', help='New org to migrate to.') - parser.add_argument('--course', help='New course key to migrate to.') - parser.add_argument('--run', help='New run to migrate to.') - - def parse_args(self, **options): - """ - Return a 5-tuple of passed in values for (course_key, user, org, course, run). - """ - try: - course_key = CourseKey.from_string(options['course_key']) - except InvalidKeyError: - raise CommandError("Invalid location string") # lint-amnesty, pylint: disable=raise-missing-from - - try: - user = user_from_str(options['email']) - except User.DoesNotExist: - raise CommandError("No user found identified by {}".format(options['email'])) # lint-amnesty, pylint: disable=raise-missing-from - - return course_key, user.id, options['org'], options['course'], options['run'] - - def handle(self, *args, **options): - course_key, user, org, course, run = self.parse_args(**options) - - migrator = SplitMigrator( - source_modulestore=modulestore(), - split_modulestore=modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.split), # lint-amnesty, pylint: disable=protected-access - ) - - migrator.migrate_mongo_course(course_key, user, org, course, run) diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_backfill_course_outlines.py b/cms/djangoapps/contentstore/management/commands/tests/test_backfill_course_outlines.py index 1aaa4de9fa1b..12a0eae32c9d 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_backfill_course_outlines.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_backfill_course_outlines.py @@ -6,7 +6,6 @@ from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.content.learning_sequences.api import get_course_keys_with_outlines -from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory # lint-amnesty, pylint: disable=wrong-import-order @@ -40,47 +39,41 @@ def setUpClass(cls): """ super().setUpClass() course_run_ids = [ - "OpenEdX/OutlineCourse/OldMongoRun1", + "course-v1:OpenEdX+OutlineCourse+Run1", "course-v1:OpenEdX+OutlineCourse+Run2", - "course-v1:OpenEdX+OutlineCourse+Run3", ] cls.course_keys = [ CourseKey.from_string(course_run_id) for course_run_id in course_run_ids ] for course_key in cls.course_keys: - if course_key.deprecated: - store_type = ModuleStoreEnum.Type.mongo - else: - store_type = ModuleStoreEnum.Type.split - with cls.store.default_store(store_type): - course = CourseFactory.create( - org=course_key.org, - number=course_key.course, - run=course_key.run, - display_name=f"Outline Backfill Test Course {course_key.run}" + course = CourseFactory.create( + org=course_key.org, + number=course_key.course, + run=course_key.run, + display_name=f"Outline Backfill Test Course {course_key.run}" + ) + with cls.store.bulk_operations(course_key): + section = ItemFactory.create( + parent=course, + category="chapter", + display_name="A Section" + ) + sequence = ItemFactory.create( + parent=section, + category="sequential", + display_name="A Sequence" + ) + unit = ItemFactory.create( + parent=sequence, + category="vertical", + display_name="A Unit" + ) + ItemFactory.create( + parent=unit, + category="html", + display_name="An HTML Module" ) - with cls.store.bulk_operations(course_key): - section = ItemFactory.create( - parent=course, - category="chapter", - display_name="A Section" - ) - sequence = ItemFactory.create( - parent=section, - category="sequential", - display_name="A Sequence" - ) - unit = ItemFactory.create( - parent=sequence, - category="vertical", - display_name="A Unit" - ) - ItemFactory.create( - parent=unit, - category="html", - display_name="An HTML Module" - ) def test_end_to_end(self): """Normal invocation, it should skip only the Old Mongo course.""" @@ -91,8 +84,8 @@ def test_end_to_end(self): call_command("backfill_course_outlines") course_keys_with_outlines = set(get_course_keys_with_outlines()) assert course_keys_with_outlines == { + CourseKey.from_string("course-v1:OpenEdX+OutlineCourse+Run1"), CourseKey.from_string("course-v1:OpenEdX+OutlineCourse+Run2"), - CourseKey.from_string("course-v1:OpenEdX+OutlineCourse+Run3"), } def test_partial(self): @@ -102,16 +95,16 @@ def test_partial(self): # Manually create one update_outline_from_modulestore( - CourseKey.from_string("course-v1:OpenEdX+OutlineCourse+Run2") + CourseKey.from_string("course-v1:OpenEdX+OutlineCourse+Run1") ) assert set(get_course_keys_with_outlines()) == { - CourseKey.from_string("course-v1:OpenEdX+OutlineCourse+Run2") + CourseKey.from_string("course-v1:OpenEdX+OutlineCourse+Run1") } # backfill command should fill in the other call_command("backfill_course_outlines") course_keys_with_outlines = set(get_course_keys_with_outlines()) assert course_keys_with_outlines == { + CourseKey.from_string("course-v1:OpenEdX+OutlineCourse+Run1"), CourseKey.from_string("course-v1:OpenEdX+OutlineCourse+Run2"), - CourseKey.from_string("course-v1:OpenEdX+OutlineCourse+Run3"), } diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_cleanup_assets.py b/cms/djangoapps/contentstore/management/commands/tests/test_cleanup_assets.py index dfed3bb69caa..47698bfeaf84 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_cleanup_assets.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_cleanup_assets.py @@ -4,6 +4,8 @@ """ +from unittest import skip + from django.conf import settings from django.core.management import call_command from opaque_keys.edx.keys import CourseKey @@ -20,6 +22,7 @@ TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT +@skip("OldMongo Deprecation") class ExportAllCourses(ModuleStoreTestCase): """ Tests assets cleanup for all courses. diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_create_course.py b/cms/djangoapps/contentstore/management/commands/tests/test_create_course.py index 40d1493f94b3..a0b216357515 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_create_course.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_create_course.py @@ -46,21 +46,23 @@ class TestCreateCourse(ModuleStoreTestCase): Unit tests for creating a course in either old mongo or split mongo via command line """ - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_all_stores_user_email(self, store): + def test_all_stores_user_email(self): call_command( "create_course", - store, + ModuleStoreEnum.Type.split, str(self.user.email), "org", "course", "run", "dummy-course-name" ) new_key = modulestore().make_course_key("org", "course", "run") self.assertTrue( modulestore().has_course(new_key), - f"Could not find course in {store}" + f"Could not find course in {ModuleStoreEnum.Type.split}" ) # pylint: disable=protected-access - self.assertEqual(store, modulestore()._get_modulestore_for_courselike(new_key).get_modulestore_type()) + self.assertEqual( + ModuleStoreEnum.Type.split, + modulestore()._get_modulestore_for_courselike(new_key).get_modulestore_type() + ) def test_duplicate_course(self): """ @@ -85,8 +87,7 @@ def test_duplicate_course(self): expected = "Course already exists" self.assertIn(out.getvalue().strip(), expected) - @ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo) - def test_get_course_with_different_case(self, default_store): + def test_get_course_with_different_case(self): """ Tests that course can not be accessed with different case. @@ -98,21 +99,20 @@ def test_get_course_with_different_case(self, default_store): org = 'org1' number = 'course1' run = 'run1' - with self.store.default_store(default_store): - lowercase_course_id = self.store.make_course_key(org, number, run) - with self.store.bulk_operations(lowercase_course_id, ignore_case=True): - # Create course with lowercase key & Verify that store returns course. - self.store.create_course( - lowercase_course_id.org, - lowercase_course_id.course, - lowercase_course_id.run, - self.user.id - ) - course = self.store.get_course(lowercase_course_id) - self.assertIsNotNone(course, 'Course not found using lowercase course key.') - self.assertEqual(str(course.id), str(lowercase_course_id)) - - # Verify store does not return course with different case. - uppercase_course_id = self.store.make_course_key(org.upper(), number.upper(), run.upper()) - course = self.store.get_course(uppercase_course_id) - self.assertIsNone(course, 'Course should not be accessed with uppercase course id.') + lowercase_course_id = self.store.make_course_key(org, number, run) + with self.store.bulk_operations(lowercase_course_id, ignore_case=True): + # Create course with lowercase key & Verify that store returns course. + self.store.create_course( + lowercase_course_id.org, + lowercase_course_id.course, + lowercase_course_id.run, + self.user.id + ) + course = self.store.get_course(lowercase_course_id) + self.assertIsNotNone(course, 'Course not found using lowercase course key.') + self.assertEqual(str(course.id), str(lowercase_course_id)) + + # Verify store does not return course with different case. + uppercase_course_id = self.store.make_course_key(org.upper(), number.upper(), run.upper()) + course = self.store.get_course(uppercase_course_id) + self.assertIsNone(course, 'Course should not be accessed with uppercase course id.') diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_delete_orphans.py b/cms/djangoapps/contentstore/management/commands/tests/test_delete_orphans.py index 33ae814a7faf..99f9d9de4324 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_delete_orphans.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_delete_orphans.py @@ -23,26 +23,24 @@ def test_no_args(self): with self.assertRaisesRegex(CommandError, errstring): call_command('delete_orphans') - @ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo) - def test_delete_orphans_no_commit(self, default_store): + def test_delete_orphans_no_commit(self): """ Tests that running the command without a '--commit' argument results in no orphans being deleted """ - course = self.create_course_with_orphans(default_store) + course = self.create_course_with_orphans(ModuleStoreEnum.Type.split) call_command('delete_orphans', str(course.id)) self.assertTrue(self.store.has_item(course.id.make_usage_key('html', 'multi_parent_html'))) self.assertTrue(self.store.has_item(course.id.make_usage_key('vertical', 'OrphanVert'))) self.assertTrue(self.store.has_item(course.id.make_usage_key('chapter', 'OrphanChapter'))) self.assertTrue(self.store.has_item(course.id.make_usage_key('html', 'OrphanHtml'))) - @ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo) - def test_delete_orphans_commit(self, default_store): + def test_delete_orphans_commit(self): """ Tests that running the command WITH the '--commit' argument results in the orphans being deleted """ - course = self.create_course_with_orphans(default_store) + course = self.create_course_with_orphans(ModuleStoreEnum.Type.split) call_command('delete_orphans', str(course.id), '--commit') diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_export.py b/cms/djangoapps/contentstore/management/commands/tests/test_export.py index d73286517dd7..4514d8755db0 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_export.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_export.py @@ -45,16 +45,15 @@ def setUp(self): self.addCleanup(shutil.rmtree, self.temp_dir_1) self.addCleanup(shutil.rmtree, self.temp_dir_2) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_export_course_with_directory_name(self, store): + def test_export_course_with_directory_name(self): """ Create a new course try exporting in a path specified """ - course = CourseFactory.create(default_store=store) + course = CourseFactory.create() course_id = str(course.id) self.assertTrue( modulestore().has_course(course.id), - f"Could not find course in {store}" + f"Could not find course in {ModuleStoreEnum.Type.split}" ) # Test `export` management command with invalid course_id errstring = "Invalid course_key: 'InvalidCourseID'." diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_export_all_courses.py b/cms/djangoapps/contentstore/management/commands/tests/test_export_all_courses.py index 262becacbfe5..086d84301828 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_export_all_courses.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_export_all_courses.py @@ -5,6 +5,7 @@ import shutil from tempfile import mkdtemp +from unittest import skip from cms.djangoapps.contentstore.management.commands.export_all_courses import export_courses_to_output_path from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order @@ -13,6 +14,7 @@ from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order +@skip("OldMongo Deprecation") class ExportAllCourses(ModuleStoreTestCase): """ Tests exporting all courses. diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_export_olx.py b/cms/djangoapps/contentstore/management/commands/tests/test_export_olx.py index 3dea23778535..8d2c2ff5b669 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_export_olx.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_export_olx.py @@ -74,9 +74,8 @@ def check_export_file(self, tar_file, course_key): self.assertIn(f"{dirname}/assets/assets.xml", names) self.assertIn(f"{dirname}/policies", names) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_export_course(self, store_type): - test_course_key = self.create_dummy_course(store_type) + def test_export_course(self): + test_course_key = self.create_dummy_course(ModuleStoreEnum.Type.split) tmp_dir = path(mkdtemp()) self.addCleanup(shutil.rmtree, tmp_dir) filename = tmp_dir / 'test.tar.gz' @@ -91,9 +90,8 @@ def test_export_course(self, store_type): # django this is fixed. Howevere it's not possible to get this test to # pass in Python3 and django 1.11 @unittest.skip("Bug in django 1.11 prevents this from working in python3. Re-enable after django 2.x upgrade.") - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) def test_export_course_stdout(self, store_type): - test_course_key = self.create_dummy_course(store_type) + test_course_key = self.create_dummy_course(ModuleStoreEnum.Type.split) out = StringIO() call_command('export_olx', str(test_course_key), stdout=out) out.seek(0) diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_fix_not_found.py b/cms/djangoapps/contentstore/management/commands/tests/test_fix_not_found.py index c3c016aa1590..042baf89e08f 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_fix_not_found.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_fix_not_found.py @@ -23,14 +23,6 @@ def test_no_args(self): with self.assertRaisesRegex(CommandError, msg): call_command('fix_not_found') - def test_fix_not_found_non_split(self): - """ - The management command doesn't work on non split courses - """ - course = CourseFactory.create(default_store=ModuleStoreEnum.Type.mongo) - with self.assertRaisesRegex(CommandError, "The owning modulestore does not support this command."): - call_command("fix_not_found", str(course.id)) - def test_fix_not_found(self): course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) ItemFactory.create(category='chapter', parent_location=course.location) diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_force_publish.py b/cms/djangoapps/contentstore/management/commands/tests/test_force_publish.py index b6c78b60232e..8baecc954a4e 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_force_publish.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_force_publish.py @@ -58,15 +58,6 @@ def test_course_key_not_found(self): with self.assertRaisesRegex(CommandError, errstring): call_command('force_publish', 'course-v1:org+course+run') - def test_force_publish_non_split(self): - """ - Test 'force_publish' command doesn't work on non split courses - """ - course = CourseFactory.create(default_store=ModuleStoreEnum.Type.mongo) - errstring = 'The owning modulestore does not support this command.' - with self.assertRaisesRegex(CommandError, errstring): - call_command('force_publish', str(course.id)) - class TestForcePublishModifications(ModuleStoreTestCase): """ diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_git_export.py b/cms/djangoapps/contentstore/management/commands/tests/test_git_export.py index 8a2334b34375..330cf65424c4 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_git_export.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_git_export.py @@ -128,6 +128,7 @@ def test_bad_git_repos(self): course_key, 'https://user:blah@example.com/r.git') + @unittest.skip("OldMongo Deprecation") @unittest.skipIf(os.environ.get('GIT_CONFIG') or os.environ.get('GIT_AUTHOR_EMAIL') or os.environ.get('GIT_AUTHOR_NAME') or diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_import.py b/cms/djangoapps/contentstore/management/commands/tests/test_import.py index 3e00def45852..5b90973b0463 100644 --- a/cms/djangoapps/contentstore/management/commands/tests/test_import.py +++ b/cms/djangoapps/contentstore/management/commands/tests/test_import.py @@ -11,7 +11,6 @@ from path import Path as path from openedx.core.djangoapps.django_comment_common.utils import are_permissions_roles_seeded -from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order @@ -73,23 +72,3 @@ def test_truncated_course_with_url(self): # Now load up the course with a similar course_id and verify it loads call_command('import', self.content_dir, self.course_dir) self.assertIsNotNone(store.get_course(self.truncated_key)) - - def test_existing_course_with_different_modulestore(self): - """ - Checks that a course that originally existed in old mongo can be re-imported when - split is the default modulestore. - """ - with modulestore().default_store(ModuleStoreEnum.Type.mongo): - call_command('import', self.content_dir, self.good_dir) - - # Clear out the modulestore mappings, else when the next import command goes to create a destination - # course_key, it will find the existing course and return the mongo course_key. To reproduce TNL-1362, - # the destination course_key needs to be the one for split modulestore. - modulestore().mappings = {} - - with modulestore().default_store(ModuleStoreEnum.Type.split): - call_command('import', self.content_dir, self.good_dir) - course = modulestore().get_course(self.base_course_key) - # With the bug, this fails because the chapter's course_key is the split mongo form, - # while the course's course_key is the old mongo form. - self.assertEqual(str(course.location.course_key), str(course.children[0].course_key)) diff --git a/cms/djangoapps/contentstore/management/commands/tests/test_migrate_to_split.py b/cms/djangoapps/contentstore/management/commands/tests/test_migrate_to_split.py deleted file mode 100644 index ba67bf28a3ea..000000000000 --- a/cms/djangoapps/contentstore/management/commands/tests/test_migrate_to_split.py +++ /dev/null @@ -1,119 +0,0 @@ -""" -Unittests for migrating a course to split mongo -""" - - -from django.core.management import CommandError, call_command -from django.test import TestCase - -from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.django import modulestore -from xmodule.modulestore.exceptions import ItemNotFoundError -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory - - -class TestArgParsing(TestCase): - """ - Tests for parsing arguments for the `migrate_to_split` management command - """ - def setUp(self): # lint-amnesty, pylint: disable=useless-super-delegation - super().setUp() - - def test_no_args(self): - """ - Test the arg length error - """ - errstring = "Error: the following arguments are required: course_key, email" - with self.assertRaisesRegex(CommandError, errstring): - call_command("migrate_to_split") - - def test_invalid_location(self): - """ - Test passing an unparsable course id - """ - errstring = "Invalid location string" - with self.assertRaisesRegex(CommandError, errstring): - call_command("migrate_to_split", "foo", "bar") - - def test_nonexistent_user_id(self): - """ - Test error for using an unknown user primary key - """ - errstring = "No user found identified by 99" - with self.assertRaisesRegex(CommandError, errstring): - call_command("migrate_to_split", "org/course/name", "99") - - def test_nonexistent_user_email(self): - """ - Test error for using an unknown user email - """ - errstring = "No user found identified by fake@example.com" - with self.assertRaisesRegex(CommandError, errstring): - call_command("migrate_to_split", "org/course/name", "fake@example.com") - - -# pylint: disable=protected-access -class TestMigrateToSplit(ModuleStoreTestCase): - """ - Unit tests for migrating a course from old mongo to split mongo - """ - - def setUp(self): - super().setUp() - self.course = CourseFactory(default_store=ModuleStoreEnum.Type.mongo) - - def test_user_email(self): - """ - Test migration for real as well as testing using an email addr to id the user - """ - call_command( - "migrate_to_split", - str(self.course.id), # lint-amnesty, pylint: disable=no-member - str(self.user.email), - ) - split_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.split) - new_key = split_store.make_course_key(self.course.id.org, self.course.id.course, self.course.id.run) # lint-amnesty, pylint: disable=no-member - self.assertTrue( - split_store.has_course(new_key), - "Could not find course" - ) - - def test_user_id(self): - """ - Test that the command accepts the user's primary key - """ - # lack of error implies success - call_command( - "migrate_to_split", - str(self.course.id), # lint-amnesty, pylint: disable=no-member - str(self.user.id), - ) - - def test_locator_string(self): - """ - Test importing to a different course id - """ - call_command( - "migrate_to_split", - str(self.course.id), # lint-amnesty, pylint: disable=no-member - str(self.user.id), - org="org.dept", - course="name", - run="run", - ) - split_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.split) - locator = split_store.make_course_key("org.dept", "name", "run") - course_from_split = split_store.get_course(locator) - self.assertIsNotNone(course_from_split) - - # Getting the original course with mongo course_id - mongo_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo) - mongo_locator = mongo_store.make_course_key(self.course.id.org, self.course.id.course, self.course.id.run) # lint-amnesty, pylint: disable=no-member - course_from_mongo = mongo_store.get_course(mongo_locator) - self.assertIsNotNone(course_from_mongo) - - # Throws ItemNotFoundError when try to access original course with split course_id - split_locator = split_store.make_course_key(self.course.id.org, self.course.id.course, self.course.id.run) # lint-amnesty, pylint: disable=no-member - with self.assertRaises(ItemNotFoundError): - mongo_store.get_course(split_locator) diff --git a/cms/djangoapps/contentstore/tests/test_clone_course.py b/cms/djangoapps/contentstore/tests/test_clone_course.py index 1c84055a113c..6d45ae5469e1 100644 --- a/cms/djangoapps/contentstore/tests/test_clone_course.py +++ b/cms/djangoapps/contentstore/tests/test_clone_course.py @@ -27,25 +27,17 @@ class CloneCourseTest(CourseTestCase): Unit tests for cloning a course """ def test_clone_course(self): - """Tests cloning of a course as follows: XML -> Mongo (+ data) -> Mongo -> Split -> Split""" - # 1. import and populate test toy course - mongo_course1_id = self.import_and_populate_course() - mongo_course2_id = mongo_course1_id + """ + Tests cloning of a course: Split -> Split + """ - # 3. clone course (mongo -> split) with self.store.default_store(ModuleStoreEnum.Type.split): - split_course3_id = CourseLocator( - org="edx3", course="split3", run="2013_Fall" - ) - self.store.clone_course(mongo_course2_id, split_course3_id, self.user.id) - self.assertCoursesEqual(mongo_course2_id, split_course3_id) - - # 4. clone course (split -> split) - split_course4_id = CourseLocator( + split_course1_id = CourseFactory().id + split_course2_id = CourseLocator( org="edx4", course="split4", run="2013_Fall" ) - self.store.clone_course(split_course3_id, split_course4_id, self.user.id) - self.assertCoursesEqual(split_course3_id, split_course4_id) + self.store.clone_course(split_course1_id, split_course2_id, self.user.id) + self.assertCoursesEqual(split_course1_id, split_course2_id) def test_space_in_asset_name_for_rerun_course(self): """ @@ -99,16 +91,28 @@ def test_rerun_course(self): """ Unit tests for :meth: `contentstore.tasks.rerun_course` """ - mongo_course1_id = self.import_and_populate_course() + org = 'edX' + course_number = 'CS101' + course_run = '2015_Q1' + display_name = 'rerun' + fields = {'display_name': display_name} + + # Create a course using split modulestore + split_course = CourseFactory.create( + org=org, + number=course_number, + run=course_run, + display_name=display_name, + default_store=ModuleStoreEnum.Type.split + ) - # rerun from mongo into split split_course3_id = CourseLocator( org="edx3", course="split3", run="rerun_test" ) # Mark the action as initiated fields = {'display_name': 'rerun'} - CourseRerunState.objects.initiated(mongo_course1_id, split_course3_id, self.user, fields['display_name']) - result = rerun_course.delay(str(mongo_course1_id), str(split_course3_id), self.user.id, + CourseRerunState.objects.initiated(split_course.id, split_course3_id, self.user, fields['display_name']) + result = rerun_course.delay(str(split_course.id), str(split_course3_id), self.user.id, json.dumps(fields, cls=EdxJSONEncoder)) self.assertEqual(result.get(), "succeeded") self.assertTrue(has_course_author_access(self.user, split_course3_id), "Didn't grant access") @@ -116,7 +120,7 @@ def test_rerun_course(self): self.assertEqual(rerun_state.state, CourseRerunUIStateManager.State.SUCCEEDED) # try creating rerunning again to same name and ensure it generates error - result = rerun_course.delay(str(mongo_course1_id), str(split_course3_id), self.user.id) + result = rerun_course.delay(str(split_course.id), str(split_course3_id), self.user.id) self.assertEqual(result.get(), "duplicate course") # the below will raise an exception if the record doesn't exist CourseRerunState.objects.find_first( diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index 7d36753472e7..6d0452f8051e 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -7,7 +7,7 @@ from functools import wraps from json import loads from textwrap import dedent -from unittest import SkipTest, mock +from unittest import SkipTest, mock, skip from uuid import uuid4 import ddt @@ -29,12 +29,11 @@ from xmodule.contentstore.django import contentstore from xmodule.contentstore.utils import empty_asset_trashcan, restore_asset_from_trashcan from xmodule.course_module import CourseBlock, Textbook -from xmodule.exceptions import InvalidVersionError from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.inheritance import own_metadata -from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls +from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.xml_exporter import export_course_to_xml from xmodule.modulestore.xml_importer import import_course_from_xml, perform_xlint from xmodule.seq_module import SequenceBlock @@ -212,7 +211,7 @@ def test_asset_import(self): all_thumbnails = content_store.get_all_content_thumbnails_for_course(course.id) self.assertGreater(len(all_thumbnails), 0) - location = AssetKey.from_string('/c4x/edX/toy/asset/just_a_test.jpg') + location = AssetKey.from_string('asset-v1:edX+toy+2012_Fall+type@asset+block@just_a_test.jpg') content = content_store.find(location) self.assertIsNotNone(content) @@ -282,7 +281,7 @@ def test_rewrite_nonportable_links_on_import(self): ) # first check a static asset link - course_key = self.store.make_course_key('edX', 'toy', 'run') + course_key = self.store.make_course_key('edX', 'toy', '2012_Fall') html_module_location = course_key.make_usage_key('html', 'nonportable') html_module = self.store.get_item(html_module_location) self.assertIn('/static/foo.jpg', html_module.data) @@ -325,16 +324,6 @@ def test_export_course_roundtrip(self, mock_get): # check for about content self.verify_content_existence(self.store, root_dir, course_id, 'about', 'about', '.html') - # assert that there is an html and video directory in drafts: - draft_dir = OSFS(root_dir / 'test_export/drafts') - self.assertTrue(draft_dir.exists('html')) - self.assertTrue(draft_dir.exists('video')) - # and assert that they contain the created modules - self.assertIn(self.DRAFT_HTML + ".xml", draft_dir.listdir('html')) - self.assertIn(self.DRAFT_VIDEO + ".xml", draft_dir.listdir('video')) - # and assert the child of the orphaned draft wasn't exported - self.assertNotIn(self.ORPHAN_DRAFT_HTML + ".xml", draft_dir.listdir('html')) - # check for grading_policy.json filesystem = OSFS(root_dir / 'test_export/policies/2012_Fall') self.assertTrue(filesystem.exists('grading_policy.json')) @@ -371,12 +360,9 @@ def check_import(self, root_dir, content_store, course_id): """Imports the course in root_dir into the given course_id and verifies its content""" # reimport import_course_from_xml( - self.store, - self.user.id, - root_dir, - ['test_export'], - static_content_store=content_store, - target_id=course_id, + self.store, self.user.id, root_dir, ['test_export'], + static_content_store=content_store, target_id=course_id, + create_if_not_present=True ) # verify content of the course @@ -551,17 +537,15 @@ def test_export_course_without_content_store(self): import_course_from_xml( self.store, self.user.id, root_dir, ['test_export_no_content_store'], - static_content_store=None, + static_content_store=None, create_if_not_present=True, target_id=course_id ) # Verify reimported course - items = self.store.get_items( course_id, qualifiers={ - 'category': 'sequential', - 'name': 'vertical_sequential', + 'name': 'vertical_sequential' } ) self.assertEqual(len(items), 1) @@ -724,29 +708,6 @@ def test_export_on_invalid_displayname(self, invalid_displayname): # Remove tempdir shutil.rmtree(root_dir) - @mock.patch( - 'lms.djangoapps.ccx.modulestore.CCXModulestoreWrapper.get_item', - mock.Mock(return_value=mock.Mock(children=[])) - ) - def test_export_with_orphan_vertical(self): - """ - Tests that, export does not fail when a parent xblock does not have draft child xblock - information but the draft child xblock has parent information. - """ - # Make an existing unit a draft - self.store.convert_to_draft(self.problem.location, self.user.id) - root_dir = path(mkdtemp_clean()) - export_course_to_xml(self.store, None, self.course.id, root_dir, 'test_export') - - # Verify that problem is exported in the drafts. This is expected because we are - # mocking get_item to for drafts. Expect no draft is exported. - # Specifically get_item is used in `xmodule.modulestore.xml_exporter._export_drafts` - export_draft_dir = OSFS(root_dir / 'test_export/drafts') - self.assertEqual(len(export_draft_dir.listdir('/')), 0) - - # Remove tempdir - shutil.rmtree(root_dir) - def test_assets_overwrite(self): """ Tests that assets will similar 'displayname' will be overwritten during export """ content_store = contentstore() @@ -788,7 +749,7 @@ def test_advanced_components_require_two_clicks(self): def test_malformed_edit_unit_request(self): # just pick one vertical - usage_key = self.course.id.make_usage_key('vertical', None) + usage_key = self.course.id.make_usage_key('vertical', 'test_vertical') resp = self.client.get_html(get_url('container_handler', usage_key)) self.assertEqual(resp.status_code, 400) @@ -804,31 +765,6 @@ def _get_draft_counts(self, item): # lint-amnesty, pylint: disable=missing-func return cnt - def test_get_items(self): - """ - This verifies a bug we had where the None setting in get_items() meant 'wildcard' - Unfortunately, None = published for the revision field, so get_items() would return - both draft and non-draft copies. - """ - self.store.convert_to_draft(self.problem.location, self.user.id) - - # Query get_items() and find the html item. This should just return back a single item (not 2). - direct_store_items = self.store.get_items( - self.course.id, revision=ModuleStoreEnum.RevisionOption.published_only - ) - items_from_direct_store = [item for item in direct_store_items if item.location == self.problem.location] - self.assertEqual(len(items_from_direct_store), 1) - self.assertFalse(getattr(items_from_direct_store[0], 'is_draft', False)) - - # Fetch from the draft store. - draft_store_items = self.store.get_items( - self.course.id, revision=ModuleStoreEnum.RevisionOption.draft_only - ) - items_from_draft_store = [item for item in draft_store_items if item.location == self.problem.location] - self.assertEqual(len(items_from_draft_store), 1) - # TODO the below won't work for split mongo - self.assertTrue(getattr(items_from_draft_store[0], 'is_draft', False)) - def test_draft_metadata(self): """ This verifies a bug we had where inherited metadata was getting written to the @@ -893,25 +829,6 @@ def test_draft_metadata(self): self.assertIn('graceperiod', own_metadata(problem)) self.assertEqual(problem.graceperiod, new_graceperiod) - def test_get_depth_with_drafts(self): - # make sure no draft items have been returned - num_drafts = self._get_draft_counts(self.course) - self.assertEqual(num_drafts, 0) - - # put into draft - self.store.convert_to_draft(self.problem.location, self.user.id) - - # make sure we can query that item and verify that it is a draft - draft_problem = self.store.get_item(self.problem.location) - self.assertTrue(getattr(draft_problem, 'is_draft', False)) - - # now requery with depth - course = self.store.get_course(self.course.id, depth=None) - - # make sure just one draft item have been returned - num_drafts = self._get_draft_counts(course) - self.assertEqual(num_drafts, 1) - @mock.patch('xmodule.course_module.requests.get') def test_import_textbook_as_content_element(self, mock_get): mock_get.return_value.text = dedent(""" @@ -1024,36 +941,19 @@ def test_empty_trashcan(self): self.assertEqual(len(all_assets), 0) self.assertEqual(count, 0) - def test_illegal_draft_crud_ops(self): - # this test presumes old mongo and split_draft not full split - with self.assertRaises(InvalidVersionError): - self.store.convert_to_draft(self.chapter_loc, self.user.id) - - chapter = self.store.get_item(self.chapter_loc) - chapter.data = 'chapter data' - self.store.update_item(chapter, self.user.id) - newobject = self.store.get_item(self.chapter_loc) - self.assertFalse(getattr(newobject, 'is_draft', False)) - - with self.assertRaises(InvalidVersionError): - self.store.unpublish(self.chapter_loc, self.user.id) - def test_bad_contentstore_request(self): """ Test that user get proper responses for urls with invalid url or asset/course key """ - resp = self.client.get_html('/c4x/CDX/123123/asset/&invalid.png') + resp = self.client.get_html('/asset-v1:CDX+123123+2012_Fall+type@asset+block@&invalid.png') self.assertEqual(resp.status_code, 400) - resp = self.client.get_html('/c4x/CDX/123123/asset/invalid.png') + resp = self.client.get_html('/asset-v1:CDX+123123+2012_Fall+type@asset+block@invalid.png') self.assertEqual(resp.status_code, 404) - # Now test that 404 response is returned when user tries to access - # asset of some invalid course from split ModuleStore - with self.store.default_store(ModuleStoreEnum.Type.split): - resp = self.client.get_html('/c4x/InvalidOrg/InvalidCourse/asset/invalid.png') - self.assertEqual(resp.status_code, 404) + resp = self.client.get_html('/c4x/InvalidOrg/InvalidCourse/asset/invalid.png') + self.assertEqual(resp.status_code, 400) @override_waffle_switch(waffle.ENABLE_ACCESSIBILITY_POLICY_PAGE, active=False) def test_disabled_accessibility_page(self): @@ -1063,36 +963,6 @@ def test_disabled_accessibility_page(self): resp = self.client.get_html('/accessibility') self.assertEqual(resp.status_code, 404) - def test_delete_course(self): - """ - This test creates a course, makes a draft item, and deletes the course. This will also assert that the - draft content is also deleted - """ - # add an asset - asset_key = self.course.id.make_asset_key('asset', 'sample_static.html') - content = StaticContent( - asset_key, "Fake asset", "application/text", b"test", - ) - contentstore().save(content) - assets, count = contentstore().get_all_content_for_course(self.course.id) - self.assertGreater(len(assets), 0) - self.assertGreater(count, 0) - - self.store.convert_to_draft(self.vert_loc, self.user.id) - - # delete the course - self.store.delete_course(self.course.id, self.user.id) - - # assert that there's absolutely no non-draft modules in the course - # this should also include all draft items - items = self.store.get_items(self.course.id) - self.assertEqual(len(items), 0) - - # assert that all content in the asset library is also deleted - assets, count = contentstore().get_all_content_for_course(self.course.id) - self.assertEqual(len(assets), 0) - self.assertEqual(count, 0) - def test_course_handouts_rewrites(self): """ Test that the xblock_handler rewrites static handout links @@ -1105,36 +975,15 @@ def test_course_handouts_rewrites(self): # get module info (json) resp = self.client.get(get_url('xblock_handler', handouts.location)) - # make sure we got a successful response self.assertEqual(resp.status_code, 200) # check that /static/ has been converted to the full path # note, we know the link it should be because that's what in the 'toy' course in the test data - asset_key = self.course.id.make_asset_key('asset', 'handouts_sample_handout.txt') - self.assertContains(resp, str(asset_key)) - - def test_prefetch_children(self): - # make sure we haven't done too many round trips to DB: - # 1) the course, - # 2 & 3) for the chapters and sequentials - # Because we're querying from the top of the tree, we cache information needed for inheritance, - # so we don't need to make an extra query to compute it. - # set the branch to 'publish' in order to prevent extra lookups of draft versions - with self.store.branch_setting(ModuleStoreEnum.Branch.published_only, self.course.id): - with check_mongo_calls(3): - course = self.store.get_course(self.course.id, depth=2) - - # make sure we pre-fetched a known sequential which should be at depth=2 - self.assertIn(self.seq_loc, course.system.module_data) - - # make sure we don't have a specific vertical which should be at depth=3 - self.assertNotIn(self.vert_loc, course.system.module_data) - - # Now, test with the branch set to draft. No extra round trips b/c it doesn't go deep enough to get - # beyond direct only categories - with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.course.id): - with check_mongo_calls(3): - self.store.get_course(self.course.id, depth=2) + asset_key = str(self.course.id.make_asset_key('asset', 'handouts_sample_handout.txt')) + # replase last `@` to `/` + index = asset_key.rfind('@') + expected_url = f'{asset_key[:index]}/{asset_key[index+1:]}' + self.assertContains(resp, expected_url) def _check_verticals(self, locations): """ Test getting the editing HTML for each vertical. """ @@ -1205,21 +1054,19 @@ def test_create_course_with_dots(self): self.course_data['run'] = 'run.name' self.assert_created_course() - @ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo) - def test_course_with_different_cases(self, default_store): + def test_course_with_different_cases(self): """ Tests that course can not be created with different case using an AJAX request to course handler. """ course_number = '99x' - with self.store.default_store(default_store): - # Verify create a course passes with lower case. - self.course_data['number'] = course_number.lower() - self.assert_created_course() + # Verify create a course passes with lower case. + self.course_data['number'] = course_number.lower() + self.assert_created_course() - # Verify create a course fail when same course number is provided with different case. - self.course_data['number'] = course_number.upper() - self.assert_course_creation_failed(self.duplicate_course_error) + # Verify create a course fail when same course number is provided with different case. + self.course_data['number'] = course_number.upper() + self.assert_course_creation_failed(self.duplicate_course_error) def test_create_course_check_forum_seeding(self): """Test new course creation and verify forum seeding """ @@ -1350,44 +1197,33 @@ def assert_course_creation_failed(self, error_message): # the user will be enrolled. In the other cases, initially_enrolled will be False. self.assertEqual(initially_enrolled, CourseEnrollment.is_enrolled(self.user, course_id)) - def test_create_course_duplicate_number(self): - """Test new course creation - error path""" - self.client.ajax_post('/course/', self.course_data) - self.course_data['display_name'] = 'Robot Super Course Two' - self.course_data['run'] = '2013_Summer' - - self.assert_course_creation_failed(self.duplicate_course_error) - - @ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo) - def test_create_course_case_change(self, default_store): + def test_create_course_case_change(self): """Test new course creation - error path due to case insensitive name equality""" self.course_data['number'] = '99x' - with self.store.default_store(default_store): - - # Verify that the course was created properly. - self.assert_created_course() + # Verify that the course was created properly. + self.assert_created_course() - # Keep the copy of original org - cache_current = self.course_data['org'] + # Keep the copy of original org + cache_current = self.course_data['org'] - # Change `org` to lower case and verify that course did not get created - self.course_data['org'] = self.course_data['org'].lower() - self.assert_course_creation_failed(self.duplicate_course_error) + # Change `org` to lower case and verify that course did not get created + self.course_data['org'] = self.course_data['org'].lower() + self.assert_course_creation_failed(self.duplicate_course_error) - # Replace the org with its actual value, and keep the copy of course number. - self.course_data['org'] = cache_current - cache_current = self.course_data['number'] + # Replace the org with its actual value, and keep the copy of course number. + self.course_data['org'] = cache_current + cache_current = self.course_data['number'] - self.course_data['number'] = self.course_data['number'].upper() - self.assert_course_creation_failed(self.duplicate_course_error) + self.course_data['number'] = self.course_data['number'].upper() + self.assert_course_creation_failed(self.duplicate_course_error) - # Replace the org with its actual value, and keep the copy of course number. - self.course_data['number'] = cache_current - __ = self.course_data['run'] + # Replace the org with its actual value, and keep the copy of course number. + self.course_data['number'] = cache_current + __ = self.course_data['run'] - self.course_data['run'] = self.course_data['run'].upper() - self.assert_course_creation_failed(self.duplicate_course_error) + self.course_data['run'] = self.course_data['run'].upper() + self.assert_course_creation_failed(self.duplicate_course_error) def test_course_substring(self): """ @@ -1515,7 +1351,9 @@ def test_create_item(self): self.assertEqual(resp.status_code, 200) data = parse_json(resp) - retarget = str(course.id.make_usage_key('chapter', 'REPLACE')).replace('REPLACE', r'([0-9]|[a-f]){3,}') + retarget = str( + course.id.make_usage_key('chapter', 'REPLACE') + ).replace('REPLACE', r'([0-9]|[a-f]){3,}').replace('+', r'\+') self.assertRegex(data['locator'], retarget) def test_capa_module(self): @@ -1625,7 +1463,7 @@ def test_import_into_new_course_id(self): self.assertEqual(course_module.pdf_textbooks[0]["chapters"][1]["url"], '/static/Chapter2.pdf') def test_import_into_new_course_id_wiki_slug_renamespacing(self): - # If reimporting into the same course do not change the wiki_slug. + # If reimporting into the same course change the wiki_slug. target_id = self.store.make_course_key('edX', 'toy', '2012_Fall') course_data = { 'org': target_id.org, @@ -1637,13 +1475,14 @@ def test_import_into_new_course_id_wiki_slug_renamespacing(self): course_module = self.store.get_course(target_id) course_module.wiki_slug = 'toy' course_module.save() + self.assertEqual(course_module.wiki_slug, 'toy') # Import a course with wiki_slug == location.course import_course_from_xml(self.store, self.user.id, TEST_DATA_DIR, ['toy'], target_id=target_id) course_module = self.store.get_course(target_id) - self.assertEqual(course_module.wiki_slug, 'toy') + self.assertEqual(course_module.wiki_slug, 'edX.toy.2012_Fall') - # But change the wiki_slug if it is a different course. + # Change the wiki_slug if it is a different course. target_id = self.store.make_course_key('MITx', '111', '2013_Spring') course_data = { 'org': target_id.org, @@ -1667,7 +1506,7 @@ def test_import_metadata_with_attempts_empty_string(self): import_course_from_xml(self.store, self.user.id, TEST_DATA_DIR, ['simple'], create_if_not_present=True) did_load_item = False try: - course_key = self.store.make_course_key('edX', 'simple', 'problem') + course_key = self.store.make_course_key('edX', 'simple', '2012_Fall') usage_key = course_key.make_usage_key('problem', 'ps01-simple') self.store.get_item(usage_key) did_load_item = True @@ -1677,13 +1516,12 @@ def test_import_metadata_with_attempts_empty_string(self): # make sure we found the item (e.g. it didn't error while loading) self.assertTrue(did_load_item) - @ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo) - def test_forum_id_generation(self, default_store): + def test_forum_id_generation(self): """ Test that a discussion item, even if it doesn't set its discussion_id, consistently generates the same one """ - course = CourseFactory.create(default_store=default_store) + course = CourseFactory.create() # create a discussion item discussion_item = self.store.create_item(self.user.id, course.id, 'discussion', 'new_component') @@ -1807,6 +1645,7 @@ def test_course_handler_with_invalid_course_key_string(self): self.assertEqual(response.status_code, 404) +@skip("OldMongo Deprecation") class MetadataSaveTestCase(ContentStoreTestCase): """Test that metadata is correctly cached and decached.""" @@ -1951,7 +1790,7 @@ def test_rerun_course_no_videos_in_val(self): """ Test when rerunning a course with no videos, VAL copies nothing """ - source_course = CourseFactory.create() + source_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) 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']) videos, __ = get_videos_for_course(str(destination_course_key)) @@ -1964,7 +1803,10 @@ def test_rerun_course_video_upload_token(self): Test when rerunning a course with video upload token, video upload token is not copied to new course. """ # Create a course with video upload token. - source_course = CourseFactory.create(video_upload_pipeline={"course_video_upload_token": 'test-token'}) + source_course = CourseFactory.create( + video_upload_pipeline={"course_video_upload_token": 'test-token'}, + default_store=ModuleStoreEnum.Type.split + ) 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']) @@ -1977,7 +1819,7 @@ def test_rerun_course_video_upload_token(self): self.assertEqual(new_course.video_upload_pipeline, {}) def test_rerun_course_success(self): - source_course = CourseFactory.create() + source_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) create_video( dict( edx_video_id="tree-hugger", @@ -2003,14 +1845,17 @@ def test_rerun_course_success(self): self.assertEqual(new_course.video_upload_pipeline, {}) def test_rerun_course_resets_advertised_date(self): - source_course = CourseFactory.create(advertised_start="01-12-2015") + source_course = CourseFactory.create( + advertised_start="01-12-2015", + default_store=ModuleStoreEnum.Type.split + ) destination_course_key = self.post_rerun_request(source_course.id) destination_course = self.store.get_course(destination_course_key) self.assertEqual(None, destination_course.advertised_start) def test_rerun_of_rerun(self): - source_course = CourseFactory.create() + source_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) rerun_course_key = self.post_rerun_request(source_course.id) rerun_of_rerun_data = { 'org': rerun_course_key.org, @@ -2022,7 +1867,7 @@ def test_rerun_of_rerun(self): 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 + existent_course_key = CourseFactory.create(default_store=ModuleStoreEnum.Type.split).id non_existent_course_key = CourseLocator("org", "non_existent_course", "non_existent_run") destination_course_key = self.post_rerun_request(non_existent_course_key) @@ -2061,7 +1906,7 @@ def test_rerun_course_fail_duplicate_course(self): def test_rerun_with_permission_denied(self): with mock.patch.dict('django.conf.settings.FEATURES', {"ENABLE_CREATOR_GROUP": True}): - source_course = CourseFactory.create() + source_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) auth.add_users(self.user, CourseCreatorRole(), self.user) self.user.is_staff = False self.user.save() @@ -2090,7 +1935,7 @@ def test_rerun_error_trunc_message(self): 'xmodule.modulestore.mixed.MixedModuleStore.clone_course', mock.Mock(side_effect=Exception()), ): - source_course = CourseFactory.create() + source_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) message_too_long = "traceback".rjust(CourseRerunState.MAX_MESSAGE_LENGTH * 2, '-') with mock.patch('traceback.format_exc', return_value=message_too_long): destination_course_key = self.post_rerun_request(source_course.id) @@ -2103,37 +1948,38 @@ def test_rerun_course_wiki_slug(self): """ Test that unique wiki_slug is assigned to rerun course. """ - course_data = { - 'org': 'edX', - 'number': '123', - 'display_name': 'Rerun Course', - 'run': '2013' - } + with self.store.default_store(ModuleStoreEnum.Type.split): + course_data = { + 'org': 'edX', + 'number': '123', + 'display_name': 'Rerun Course', + 'run': '2013' + } - source_wiki_slug = '{}.{}.{}'.format(course_data['org'], course_data['number'], course_data['run']) + source_wiki_slug = '{}.{}.{}'.format(course_data['org'], course_data['number'], course_data['run']) - source_course_key = _get_course_id(self.store, course_data) - _create_course(self, source_course_key, course_data) - source_course = self.store.get_course(source_course_key) + source_course_key = _get_course_id(self.store, course_data) + _create_course(self, source_course_key, course_data) + source_course = self.store.get_course(source_course_key) - # Verify created course's wiki_slug. - self.assertEqual(source_course.wiki_slug, source_wiki_slug) + # Verify created course's wiki_slug. + self.assertEqual(source_course.wiki_slug, source_wiki_slug) - destination_course_data = course_data - destination_course_data['run'] = '2013_Rerun' + destination_course_data = course_data + destination_course_data['run'] = '2013_Rerun' - destination_course_key = self.post_rerun_request( - source_course.id, destination_course_data=destination_course_data - ) - self.verify_rerun_course(source_course.id, destination_course_key, destination_course_data['display_name']) - destination_course = self.store.get_course(destination_course_key) + destination_course_key = self.post_rerun_request( + source_course.id, destination_course_data=destination_course_data + ) + self.verify_rerun_course(source_course.id, destination_course_key, destination_course_data['display_name']) + destination_course = self.store.get_course(destination_course_key) - destination_wiki_slug = '{}.{}.{}'.format( - destination_course.id.org, destination_course.id.course, destination_course.id.run - ) + destination_wiki_slug = '{}.{}.{}'.format( + destination_course.id.org, destination_course.id.course, destination_course.id.run + ) - # Verify rerun course's wiki_slug. - self.assertEqual(destination_course.wiki_slug, destination_wiki_slug) + # Verify rerun course's wiki_slug. + self.assertEqual(destination_course.wiki_slug, destination_wiki_slug) class ContentLicenseTest(ContentStoreTestCase): @@ -2141,6 +1987,7 @@ class ContentLicenseTest(ContentStoreTestCase): Tests around content licenses """ + @skip("OldMongo Deprecation") def test_course_license_export(self): content_store = contentstore() root_dir = path(mkdtemp_clean()) diff --git a/cms/djangoapps/contentstore/tests/test_course_create_rerun.py b/cms/djangoapps/contentstore/tests/test_course_create_rerun.py index c76837912daa..c92f53e7fd7f 100644 --- a/cms/djangoapps/contentstore/tests/test_course_create_rerun.py +++ b/cms/djangoapps/contentstore/tests/test_course_create_rerun.py @@ -17,8 +17,6 @@ from organizations.exceptions import InvalidOrganizationException from organizations.models import Organization from xmodule.course_module import CourseFields -from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory @@ -114,26 +112,23 @@ def test_rerun(self): self.assertEqual(len(course_orgs), 1) self.assertEqual(course_orgs[0]['short_name'], self.source_course_key.org) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_newly_created_course_has_web_certs_enabled(self, store): + def test_newly_created_course_has_web_certs_enabled(self): """ Tests newly created course has web certs enabled by default. """ - with modulestore().default_store(store): - response = self.client.ajax_post(self.course_create_rerun_url, { - 'org': 'orgX', - 'number': 'CS101', - 'display_name': 'Course with web certs enabled', - 'run': '2015_T2' - }) - self.assertEqual(response.status_code, 200) - data = parse_json(response) - new_course_key = CourseKey.from_string(data['course_key']) - course = self.store.get_course(new_course_key) - self.assertTrue(course.cert_html_view_enabled) + response = self.client.ajax_post(self.course_create_rerun_url, { + 'org': 'orgX', + 'number': 'CS101', + 'display_name': 'Course with web certs enabled', + 'run': '2015_T2' + }) + self.assertEqual(response.status_code, 200) + data = parse_json(response) + new_course_key = CourseKey.from_string(data['course_key']) + course = self.store.get_course(new_course_key) + self.assertTrue(course.cert_html_view_enabled) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_course_creation_for_unknown_organization_relaxed(self, store): + def test_course_creation_for_unknown_organization_relaxed(self): """ Tests that when ORGANIZATIONS_AUTOCREATE is True, creating a course-run with an unknown org slug will create an organization @@ -141,40 +136,37 @@ def test_course_creation_for_unknown_organization_relaxed(self, store): """ with self.assertRaises(InvalidOrganizationException): get_organization_by_short_name("orgX") - with modulestore().default_store(store): - response = self.client.ajax_post(self.course_create_rerun_url, { - 'org': 'orgX', - 'number': 'CS101', - 'display_name': 'Course with web certs enabled', - 'run': '2015_T2' - }) - self.assertEqual(response.status_code, 200) - self.assertIsNotNone(get_organization_by_short_name("orgX")) - data = parse_json(response) - new_course_key = CourseKey.from_string(data['course_key']) - course_orgs = get_course_organizations(new_course_key) - self.assertEqual(len(course_orgs), 1) - self.assertEqual(course_orgs[0]['short_name'], 'orgX') + response = self.client.ajax_post(self.course_create_rerun_url, { + 'org': 'orgX', + 'number': 'CS101', + 'display_name': 'Course with web certs enabled', + 'run': '2015_T2' + }) + self.assertEqual(response.status_code, 200) + self.assertIsNotNone(get_organization_by_short_name("orgX")) + data = parse_json(response) + new_course_key = CourseKey.from_string(data['course_key']) + course_orgs = get_course_organizations(new_course_key) + self.assertEqual(len(course_orgs), 1) + self.assertEqual(course_orgs[0]['short_name'], 'orgX') - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) @override_settings(ORGANIZATIONS_AUTOCREATE=False) - def test_course_creation_for_unknown_organization_strict(self, store): + def test_course_creation_for_unknown_organization_strict(self): """ Tests that when ORGANIZATIONS_AUTOCREATE is False, creating a course-run with an unknown org slug will raise a validation error. """ - with modulestore().default_store(store): - response = self.client.ajax_post(self.course_create_rerun_url, { - 'org': 'orgX', - 'number': 'CS101', - 'display_name': 'Course with web certs enabled', - 'run': '2015_T2' - }) - self.assertEqual(response.status_code, 400) - with self.assertRaises(InvalidOrganizationException): - get_organization_by_short_name("orgX") - data = parse_json(response) - self.assertIn('Organization you selected does not exist in the system', data['error']) + response = self.client.ajax_post(self.course_create_rerun_url, { + 'org': 'orgX', + 'number': 'CS101', + 'display_name': 'Course with web certs enabled', + 'run': '2015_T2' + }) + self.assertEqual(response.status_code, 400) + with self.assertRaises(InvalidOrganizationException): + get_organization_by_short_name("orgX") + data = parse_json(response) + self.assertIn('Organization you selected does not exist in the system', data['error']) @ddt.data(True, False) def test_course_creation_for_known_organization(self, organizations_autocreate): @@ -201,23 +193,20 @@ def test_course_creation_for_known_organization(self, organizations_autocreate): self.assertEqual(course_orgs[0]['short_name'], 'orgX') @override_settings(FEATURES={'ENABLE_CREATOR_GROUP': True}) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_course_creation_when_user_not_in_org(self, store): + def test_course_creation_when_user_not_in_org(self): """ Tests course creation when user doesn't have the required role. """ - with modulestore().default_store(store): - response = self.client.ajax_post(self.course_create_rerun_url, { - 'org': 'TestorgX', - 'number': 'CS101', - 'display_name': 'Course with web certs enabled', - 'run': '2021_T1' - }) - self.assertEqual(response.status_code, 403) + response = self.client.ajax_post(self.course_create_rerun_url, { + 'org': 'TestorgX', + 'number': 'CS101', + 'display_name': 'Course with web certs enabled', + 'run': '2021_T1' + }) + self.assertEqual(response.status_code, 403) @override_settings(FEATURES={'ENABLE_CREATOR_GROUP': True}) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_course_creation_when_user_in_org_with_creator_role(self, store): + def test_course_creation_when_user_in_org_with_creator_role(self): """ Tests course creation with user having the organization content creation role. """ @@ -227,22 +216,20 @@ def test_course_creation_when_user_in_org_with_creator_role(self, store): 'description': 'Testing Organization Description', }) update_org_role(self.global_admin, OrgContentCreatorRole, self.user, [self.source_course_key.org]) - with modulestore().default_store(store): - response = self.client.ajax_post(self.course_create_rerun_url, { - 'org': self.source_course_key.org, - 'number': 'CS101', - 'display_name': 'Course with web certs enabled', - 'run': '2021_T1' - }) - self.assertEqual(response.status_code, 200) + response = self.client.ajax_post(self.course_create_rerun_url, { + 'org': self.source_course_key.org, + 'number': 'CS101', + 'display_name': 'Course with web certs enabled', + 'run': '2021_T1' + }) + self.assertEqual(response.status_code, 200) @override_settings(FEATURES={'ENABLE_CREATOR_GROUP': True}) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) @mock.patch( 'cms.djangoapps.course_creators.admin.render_to_string', mock.Mock(side_effect=mock_render_to_string, autospec=True) ) - def test_course_creation_with_all_org_checked(self, store): + def test_course_creation_with_all_org_checked(self): """ Tests course creation with user having permission to create course for all organization. """ @@ -254,22 +241,20 @@ def test_course_creation_with_all_org_checked(self, store): self.course_creator_entry.all_organizations = True self.course_creator_entry.state = CourseCreator.GRANTED self.creator_admin.save_model(self.request, self.course_creator_entry, None, True) - with modulestore().default_store(store): - response = self.client.ajax_post(self.course_create_rerun_url, { - 'org': self.source_course_key.org, - 'number': 'CS101', - 'display_name': 'Course with web certs enabled', - 'run': '2021_T1' - }) - self.assertEqual(response.status_code, 200) + response = self.client.ajax_post(self.course_create_rerun_url, { + 'org': self.source_course_key.org, + 'number': 'CS101', + 'display_name': 'Course with web certs enabled', + 'run': '2021_T1' + }) + self.assertEqual(response.status_code, 200) @override_settings(FEATURES={'ENABLE_CREATOR_GROUP': True}) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) @mock.patch( 'cms.djangoapps.course_creators.admin.render_to_string', mock.Mock(side_effect=mock_render_to_string, autospec=True) ) - def test_course_creation_with_permission_for_specific_organization(self, store): + def test_course_creation_with_permission_for_specific_organization(self): """ Tests course creation with user having permission to create course for specific organization. """ @@ -283,22 +268,20 @@ def test_course_creation_with_permission_for_specific_organization(self, store): self.creator_admin.save_model(self.request, self.course_creator_entry, None, True) dc_org_object = Organization.objects.get(name='Test Organization') self.course_creator_entry.organizations.add(dc_org_object) - with modulestore().default_store(store): - response = self.client.ajax_post(self.course_create_rerun_url, { - 'org': self.source_course_key.org, - 'number': 'CS101', - 'display_name': 'Course with web certs enabled', - 'run': '2021_T1' - }) - self.assertEqual(response.status_code, 200) + response = self.client.ajax_post(self.course_create_rerun_url, { + 'org': self.source_course_key.org, + 'number': 'CS101', + 'display_name': 'Course with web certs enabled', + 'run': '2021_T1' + }) + self.assertEqual(response.status_code, 200) @override_settings(FEATURES={'ENABLE_CREATOR_GROUP': True}) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) @mock.patch( 'cms.djangoapps.course_creators.admin.render_to_string', mock.Mock(side_effect=mock_render_to_string, autospec=True) ) - def test_course_creation_without_permission_for_specific_organization(self, store): + def test_course_creation_without_permission_for_specific_organization(self): """ Tests course creation with user not having permission to create course for specific organization. """ @@ -319,11 +302,10 @@ def test_course_creation_without_permission_for_specific_organization(self, stor # When the user tries to create course under `Test Organization` it throws a 403. dc_org_object = Organization.objects.get(name='DC') self.course_creator_entry.organizations.add(dc_org_object) - with modulestore().default_store(store): - response = self.client.ajax_post(self.course_create_rerun_url, { - 'org': self.source_course_key.org, - 'number': 'CS101', - 'display_name': 'Course with web certs enabled', - 'run': '2021_T1' - }) - self.assertEqual(response.status_code, 403) + response = self.client.ajax_post(self.course_create_rerun_url, { + 'org': self.source_course_key.org, + 'number': 'CS101', + 'display_name': 'Course with web certs enabled', + 'run': '2021_T1' + }) + self.assertEqual(response.status_code, 403) diff --git a/cms/djangoapps/contentstore/tests/test_course_listing.py b/cms/djangoapps/contentstore/tests/test_course_listing.py index 44fe762f7333..c141786499ac 100644 --- a/cms/djangoapps/contentstore/tests/test_course_listing.py +++ b/cms/djangoapps/contentstore/tests/test_course_listing.py @@ -162,12 +162,8 @@ def test_courses_list_with_ccx_courses(self): courses_iter, __ = _accessible_courses_iter_for_tests(self.request) self.assertEqual(len(list(courses_iter)), 0) - @ddt.data( - (ModuleStoreEnum.Type.split, 2), - (ModuleStoreEnum.Type.mongo, 1) - ) @ddt.unpack - def test_staff_course_listing(self, default_store, mongo_calls): + def test_staff_course_listing(self): """ Create courses and verify they take certain amount of mongo calls to call get_courses_accessible_to_user. Also verify that fetch accessible courses list for staff user returns CourseSummary instances. @@ -177,11 +173,10 @@ def test_staff_course_listing(self, default_store, mongo_calls): GlobalStaff().add_users(self.user) self.assertTrue(GlobalStaff().has_user(self.user)) - with self.store.default_store(default_store): - # Create few courses - for num in range(TOTAL_COURSES_COUNT): - course_location = self.store.make_course_key('Org', 'CreatedCourse' + str(num), 'Run') - self._create_course_with_access_groups(course_location, self.user) + # Create few courses + for num in range(TOTAL_COURSES_COUNT): + course_location = self.store.make_course_key('Org', 'CreatedCourse' + str(num), 'Run') + self._create_course_with_access_groups(course_location, self.user) # Fetch accessible courses list & verify their count courses_list_by_staff, __ = get_courses_accessible_to_user(self.request) @@ -192,7 +187,7 @@ def test_staff_course_listing(self, default_store, mongo_calls): self.assertTrue(all(isinstance(course, CourseSummary) for course in courses_list_by_staff)) # Now count the db queries for staff - with check_mongo_calls(mongo_calls): + with check_mongo_calls(2): list(_accessible_courses_summary_iter(self.request)) @ddt.data(ModuleStoreEnum.Type.split) @@ -248,7 +243,6 @@ def test_get_course_list_with_invalid_course_location(self, store): @ddt.data( (ModuleStoreEnum.Type.split, 1, 2), - (ModuleStoreEnum.Type.mongo, 1, 2), ) @ddt.unpack def test_course_listing_performance(self, store, courses_list_from_group_calls, courses_list_calls): diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py index 3b36efb4a977..ab852d20bf7f 100644 --- a/cms/djangoapps/contentstore/tests/test_course_settings.py +++ b/cms/djangoapps/contentstore/tests/test_course_settings.py @@ -7,7 +7,7 @@ import datetime import json import unittest -from unittest import mock +from unittest import mock, skip from unittest.mock import Mock, patch import ddt @@ -40,7 +40,6 @@ ) from openedx.core.djangoapps.models.course_details import CourseDetails from xmodule.fields import Date # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order @@ -542,10 +541,9 @@ def test_fetch_grader(self): @mock.patch('common.djangoapps.track.event_transaction_utils.uuid4') @mock.patch('cms.djangoapps.models.settings.course_grading.tracker') @mock.patch('cms.djangoapps.contentstore.signals.signals.GRADING_POLICY_CHANGED.send') - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_update_from_json(self, store, send_signal, tracker, uuid): + def test_update_from_json(self, send_signal, tracker, uuid): uuid.return_value = "mockUUID" - self.course = CourseFactory.create(default_store=store) + self.course = CourseFactory.create() test_grader = CourseGradingModel.fetch(self.course.id) # there should be no event raised after this call, since nothing got modified altered_grader = CourseGradingModel.update_from_json(self.course.id, test_grader.__dict__, self.user) @@ -600,14 +598,13 @@ def test_update_from_json(self, store, send_signal, tracker, uuid): ) ]) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_must_fire_grading_event_and_signal_multiple_type(self, store): + def test_must_fire_grading_event_and_signal_multiple_type(self): """ Verifies that 'must_fire_grading_event_and_signal' ignores (returns False) if we modify short_label and or name use test_must_fire_grading_event_and_signal_multiple_type_2_split to run this test only """ - self.course = CourseFactory.create(default_store=store) + self.course = CourseFactory.create() # .raw_grader approximates what our UI sends down. It uses decimal representation of percent # without it, the weights would be percentages raw_grader_list = modulestore().get_course(self.course.id).raw_grader @@ -626,14 +623,13 @@ def test_must_fire_grading_event_and_signal_multiple_type(self, store): self.assertTrue(result) @override_waffle_flag(MATERIAL_RECOMPUTE_ONLY_FLAG, True) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_must_fire_grading_event_and_signal_multiple_type_waffle_on(self, store): + def test_must_fire_grading_event_and_signal_multiple_type_waffle_on(self): """ Verifies that 'must_fire_grading_event_and_signal' ignores (returns False) if we modify short_label and or name use test_must_fire_grading_event_and_signal_multiple_type_2_split to run this test only """ - self.course = CourseFactory.create(default_store=store) + self.course = CourseFactory.create() # .raw_grader approximates what our UI sends down. It uses decimal representation of percent # without it, the weights would be percentages raw_grader_list = modulestore().get_course(self.course.id).raw_grader @@ -651,14 +647,13 @@ def test_must_fire_grading_event_and_signal_multiple_type_waffle_on(self, store) ) self.assertFalse(result) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_must_fire_grading_event_and_signal_return_true(self, store): + def test_must_fire_grading_event_and_signal_return_true(self): """ Verifies that 'must_fire_grading_event_and_signal' ignores (returns False) if we modify short_label and or name use _2_split suffix to run this test only """ - self.course = CourseFactory.create(default_store=store) + self.course = CourseFactory.create() # .raw_grader approximates what our UI sends down. It uses decimal representation of percent # without it, the weights would be percentages raw_grader_list = modulestore().get_course(self.course.id).raw_grader @@ -915,6 +910,7 @@ def setup_test_set_get_section_grader_ajax(self): section = sections[0] # just take the first one return reverse_usage_url('xblock_handler', section.location) + @skip("OldMongo Deprecation") def test_set_get_section_grader_ajax(self): """ Test setting and getting section grades via the grade as url diff --git a/cms/djangoapps/contentstore/tests/test_courseware_index.py b/cms/djangoapps/contentstore/tests/test_courseware_index.py index 9dbbfffdd059..c5454d3bde36 100644 --- a/cms/djangoapps/contentstore/tests/test_courseware_index.py +++ b/cms/djangoapps/contentstore/tests/test_courseware_index.py @@ -32,7 +32,6 @@ from xmodule.modulestore.django import SignalHandler, modulestore # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.django_utils import ( # lint-amnesty, pylint: disable=wrong-import-order ModuleStoreTestCase, - TEST_DATA_MONGO_MODULESTORE, SharedModuleStoreTestCase, ) from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, LibraryFactory # lint-amnesty, pylint: disable=wrong-import-order @@ -125,22 +124,21 @@ def update_item(self, store, item): @pytest.mark.django_db -@ddt.ddt class TestCoursewareSearchIndexer(MixedWithOptionsTestCase): """ Tests the operation of the CoursewareSearchIndexer """ - WORKS_WITH_STORES = (ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) ENABLED_SIGNALS = ['course_deleted'] def setUp(self): super().setUp() - self.course = None self.chapter = None self.sequential = None self.vertical = None self.html_unit = None + self.setup_course_base(self.store) + def setup_course_base(self, store): """ Set up the for the course outline tests. @@ -463,58 +461,45 @@ def _test_exception(self, store): with self.assertRaises(SearchIndexingError): self.reindex_course(store) - @ddt.data(*WORKS_WITH_STORES) - def test_indexing_course(self, store_type): - self._perform_test_using_store(store_type, self._test_indexing_course) + def test_indexing_course(self): + self._test_indexing_course(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_not_indexing_unpublished_content(self, store_type): - self._perform_test_using_store(store_type, self._test_not_indexing_unpublished_content) + def test_not_indexing_unpublished_content(self): + self._test_not_indexing_unpublished_content(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_deleting_item(self, store_type): - self._perform_test_using_store(store_type, self._test_deleting_item) + def test_deleting_item(self): + self._test_deleting_item(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_start_date_propagation(self, store_type): - self._perform_test_using_store(store_type, self._test_start_date_propagation) + def test_start_date_propagation(self): + self._test_start_date_propagation(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_search_disabled(self, store_type): - self._perform_test_using_store(store_type, self._test_search_disabled) + def test_search_disabled(self): + self._test_search_disabled(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_time_based_index(self, store_type): - self._perform_test_using_store(store_type, self._test_time_based_index) + def test_time_based_index(self): + self._test_time_based_index(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_exception(self, store_type): - self._perform_test_using_store(store_type, self._test_exception) + def test_exception(self): + self._test_exception(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_course_about_property_index(self, store_type): - self._perform_test_using_store(store_type, self._test_course_about_property_index) + def test_course_about_property_index(self): + self._test_course_about_property_index(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_course_about_store_index(self, store_type): - self._perform_test_using_store(store_type, self._test_course_about_store_index) + def test_course_about_store_index(self): + self._test_course_about_store_index(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_course_about_mode_index(self, store_type): - self._perform_test_using_store(store_type, self._test_course_about_mode_index) + def test_course_about_mode_index(self): + self._test_course_about_mode_index(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_course_location_info(self, store_type): - self._perform_test_using_store(store_type, self._test_course_location_info) + def test_course_location_info(self): + self._test_course_location_info(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_course_location_null(self, store_type): - self._perform_test_using_store(store_type, self._test_course_location_null) + def test_course_location_null(self): + self._test_course_location_null(self.store) - @ddt.data(*WORKS_WITH_STORES) - def test_delete_course_from_search_index_after_course_deletion(self, store_type): + def test_delete_course_from_search_index_after_course_deletion(self): """ Test for removing course from CourseAboutSearchIndexer """ - self._perform_test_using_store(store_type, self._test_delete_course_from_search_index_after_course_deletion) + self._test_delete_course_from_search_index_after_course_deletion(self.store) @patch('django.conf.settings.SEARCH_ENGINE', 'search.tests.utils.ForceRefreshElasticSearchEngine') @@ -522,8 +507,6 @@ def test_delete_course_from_search_index_after_course_deletion(self, store_type) class TestLargeCourseDeletions(MixedWithOptionsTestCase): """ Tests to excerise deleting items from a course """ - WORKS_WITH_STORES = (ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def _clean_course_id(self): """ Clean all documents from the index that have a specific course provided. @@ -540,6 +523,7 @@ def _clean_course_id(self): def setUp(self): super().setUp() self.course_id = None + self.setup_course_base(self.store) def tearDown(self): super().tearDown() @@ -594,9 +578,8 @@ def _test_large_course_deletion(self, store): @skip("This test is to see how we handle very large courses, to ensure that the delete" "procedure works smoothly - too long to run during the normal course of things") - @ddt.data(*WORKS_WITH_STORES) - def test_large_course_deletion(self, store_type): - self._perform_test_using_store(store_type, self._test_large_course_deletion) + def test_large_course_deletion(self): + self._test_large_course_deletion(self.store) class TestTaskExecution(SharedModuleStoreTestCase): @@ -1358,10 +1341,3 @@ def test_different_groups_indexed_on_same_vertical_html_blocks(self): self.assertIn(self._html_group_result(self.html_unit2, [1]), indexed_content) self.assertIn(self._html_group_result(self.html_unit3, [0]), indexed_content) mock_index.reset_mock() - - -class GroupConfigurationSearchMongo(GroupConfigurationSearchSplit): # pylint: disable=test-inherits-tests - """ - Tests indexing of content groups on course modules using mongo modulestore. - """ - MODULESTORE = TEST_DATA_MONGO_MODULESTORE diff --git a/cms/djangoapps/contentstore/tests/test_export_git.py b/cms/djangoapps/contentstore/tests/test_export_git.py index d853a7a4a3c1..f2e19b209cc5 100644 --- a/cms/djangoapps/contentstore/tests/test_export_git.py +++ b/cms/djangoapps/contentstore/tests/test_export_git.py @@ -7,6 +7,7 @@ import os import shutil import subprocess +from unittest import skip from uuid import uuid4 from django.conf import settings @@ -97,6 +98,7 @@ def test_exception_translation(self): response = self.client.get(f'{self.test_url}?action=push') self.assertNotContains(response, 'django.utils.functional.__proxy__') + @skip("OldMongo Deprecation") def test_course_export_success(self): """ Test successful course export response. @@ -106,6 +108,7 @@ def test_course_export_success(self): response = self.client.get(f'{self.test_url}?action=push') self.assertContains(response, 'Export Succeeded') + @skip("OldMongo Deprecation") def test_repo_with_dots(self): """ Regression test for a bad directory pathing of repo's that have dots. @@ -114,6 +117,7 @@ def test_repo_with_dots(self): response = self.client.get(f'{self.test_url}?action=push') self.assertContains(response, 'Export Succeeded') + @skip("OldMongo Deprecation") def test_dirty_repo(self): """ Add additional items not in the repo and make sure they aren't diff --git a/cms/djangoapps/contentstore/tests/test_i18n.py b/cms/djangoapps/contentstore/tests/test_i18n.py index 30e031a43d53..b80a77adf4f7 100644 --- a/cms/djangoapps/contentstore/tests/test_i18n.py +++ b/cms/djangoapps/contentstore/tests/test_i18n.py @@ -9,7 +9,7 @@ from django.utils import translation from django.utils.translation import get_language from xmodule.modulestore.django import ModuleI18nService -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient @@ -55,9 +55,10 @@ def _translation(domain, localedir=None, languages=None): # pylint: disable=unu return _translation +@skip("OldMongo Deprecation") class TestModuleI18nService(ModuleStoreTestCase): """ Test ModuleI18nService """ - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE def setUp(self): """ Setting up tests """ diff --git a/cms/djangoapps/contentstore/tests/test_import.py b/cms/djangoapps/contentstore/tests/test_import.py index 4c63ecd735d8..b8ea250a7080 100644 --- a/cms/djangoapps/contentstore/tests/test_import.py +++ b/cms/djangoapps/contentstore/tests/test_import.py @@ -5,6 +5,7 @@ import copy +from unittest import skip from unittest.mock import patch from uuid import uuid4 @@ -18,7 +19,6 @@ from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -from xmodule.modulestore.tests.factories import check_exact_number_of_calls, check_number_of_calls from xmodule.modulestore.xml_importer import import_course_from_xml TEST_DATA_CONTENTSTORE = copy.deepcopy(settings.CONTENTSTORE) @@ -175,31 +175,15 @@ def test_tab_name_imports_correctly(self): print(f"course tabs = {course.tabs}") self.assertEqual(course.tabs[1]['name'], 'Syllabus') - def test_import_performance_mongo(self): - store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo) - - # we try to refresh the inheritance tree for each update_item in the import - with check_exact_number_of_calls(store, 'refresh_cached_metadata_inheritance_tree', 28): - - # _get_cached_metadata_inheritance_tree should be called once - with check_exact_number_of_calls(store, '_get_cached_metadata_inheritance_tree', 1): - - # with bulk-edit in progress, the inheritance tree should be recomputed only at the end of the import - # NOTE: On Jenkins, with memcache enabled, the number of calls here is 1. - # Locally, without memcache, the number of calls is 1 (publish no longer counted) - with check_number_of_calls(store, '_compute_metadata_inheritance_tree', 1): - self.load_test_import_course(create_if_not_present=False, module_store=store) - - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_reimport(self, default_ms_type): - with modulestore().default_store(default_ms_type): - __, __, course = self.load_test_import_course(create_if_not_present=True) - self.load_test_import_course(target_id=course.id) + def test_reimport(self): + __, __, course = self.load_test_import_course(create_if_not_present=True) + self.load_test_import_course(target_id=course.id) + @skip("OldMongo Deprecation") def test_rewrite_reference_list(self): # This test fails with split modulestore (the HTML component is not in "different_course_id" namespace). # More investigation needs to be done. - module_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo) + module_store = modulestore() target_id = module_store.make_course_key('testX', 'conditional_copy', 'copy_run') import_course_from_xml( module_store, @@ -272,22 +256,20 @@ def _verify_split_test_import(self, target_course_name, source_course_name, spli self.assertEqual(remapped_verticals, split_test_module.group_id_to_child) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_video_components_present_while_import(self, store): + def test_video_components_present_while_import(self): """ Test that video components with same edx_video_id are present while re-importing """ - with modulestore().default_store(store): - module_store = modulestore() - course_id = module_store.make_course_key('edX', 'test_import_course', '2012_Fall') + module_store = modulestore() + course_id = module_store.make_course_key('edX', 'test_import_course', '2012_Fall') - # Import first time - __, __, course = self.load_test_import_course(target_id=course_id, module_store=module_store) + # Import first time + __, __, course = self.load_test_import_course(target_id=course_id, module_store=module_store) - # Re-import - __, __, re_course = self.load_test_import_course(target_id=course.id, module_store=module_store) + # Re-import + __, __, re_course = self.load_test_import_course(target_id=course.id, module_store=module_store) - vertical = module_store.get_item(re_course.id.make_usage_key('vertical', 'vertical_test')) + vertical = module_store.get_item(re_course.id.make_usage_key('vertical', 'vertical_test')) - video = module_store.get_item(vertical.children[1]) - self.assertEqual(video.display_name, 'default') + video = module_store.get_item(vertical.children[1]) + self.assertEqual(video.display_name, 'default') diff --git a/cms/djangoapps/contentstore/tests/test_import_pure_xblock.py b/cms/djangoapps/contentstore/tests/test_import_pure_xblock.py index a4a4368bdf59..63e5e26b82e7 100644 --- a/cms/djangoapps/contentstore/tests/test_import_pure_xblock.py +++ b/cms/djangoapps/contentstore/tests/test_import_pure_xblock.py @@ -7,7 +7,6 @@ from xblock.core import XBlock from xblock.fields import String -from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore from xmodule.modulestore.mongo.draft import as_draft from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase @@ -41,14 +40,6 @@ def test_import_public(self): 'set by xml' ) - @XBlock.register_temp_plugin(StubXBlock) - def test_import_draft(self): - self._assert_import( - 'pure_xblock_draft', - 'set by xml', - has_draft=True - ) - def _assert_import(self, course_dir, expected_field_val, has_draft=False): """ Import a course from XML, then verify that the XBlock was loaded @@ -66,7 +57,7 @@ def _assert_import(self, course_dir, expected_field_val, has_draft=False): """ # It is necessary to use the "old mongo" modulestore because split doesn't work # with the "has_draft" logic below. - store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo) # pylint: disable=protected-access + store = modulestore() courses = import_course_from_xml( store, self.user.id, TEST_DATA_DIR, [course_dir], create_if_not_present=True ) diff --git a/cms/djangoapps/contentstore/tests/test_libraries.py b/cms/djangoapps/contentstore/tests/test_libraries.py index 91dc14983b86..feb13882f2da 100644 --- a/cms/djangoapps/contentstore/tests/test_libraries.py +++ b/cms/djangoapps/contentstore/tests/test_libraries.py @@ -1014,28 +1014,3 @@ def test_duplicated_version(self): self.assertEqual(self.lc_block.source_library_version, duplicate.source_library_version) problem2_in_course = store.get_item(duplicate.children[0]) self.assertEqual(problem2_in_course.display_name, self.original_display_name) - - -class TestIncompatibleModuleStore(LibraryTestCase): - """ - Tests for proper validation errors with an incompatible course modulestore. - """ - - def setUp(self): - super().setUp() - # Create a course in an incompatible modulestore. - with modulestore().default_store(ModuleStoreEnum.Type.mongo): - self.course = CourseFactory.create() - - # Add a LibraryContent block to the course: - self.lc_block = self._add_library_content_block(self.course, self.lib_key) - - def test_incompatible_modulestore(self): - """ - Verifies that, if a user is using a modulestore that doesn't support libraries, - a validation error will be produced. - """ - validation = self.lc_block.validate() - self.assertEqual(validation.summary.type, validation.summary.ERROR) - self.assertIn( - "This course does not support content libraries.", validation.summary.text) diff --git a/cms/djangoapps/contentstore/tests/test_orphan.py b/cms/djangoapps/contentstore/tests/test_orphan.py index e0489f73e6e7..6431f698783c 100644 --- a/cms/djangoapps/contentstore/tests/test_orphan.py +++ b/cms/djangoapps/contentstore/tests/test_orphan.py @@ -80,12 +80,11 @@ class TestOrphan(TestOrphanBase): Test finding orphans via view and django config """ - @ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo) - def test_get_orphans(self, default_store): + def test_get_orphans(self): """ Test that the orphan handler finds the orphans """ - course = self.create_course_with_orphans(default_store) + course = self.create_course_with_orphans(ModuleStoreEnum.Type.split) orphan_url = reverse_course_url('orphan_handler', course.id) orphans = json.loads( @@ -104,7 +103,6 @@ def test_get_orphans(self, default_store): @ddt.data( (ModuleStoreEnum.Type.split, 5, 3), - (ModuleStoreEnum.Type.mongo, 34, 12), ) @ddt.unpack def test_delete_orphans(self, default_store, max_mongo_calls, min_mongo_calls): @@ -126,12 +124,11 @@ def test_delete_orphans(self, default_store, max_mongo_calls, min_mongo_calls): # parent are not deleted self.assertTrue(self.store.has_item(course.id.make_usage_key('html', "multi_parent_html"))) - @ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo) - def test_not_permitted(self, default_store): + def test_not_permitted(self): """ Test that auth restricts get and delete appropriately """ - course = self.create_course_with_orphans(default_store) + course = self.create_course_with_orphans(ModuleStoreEnum.Type.split) orphan_url = reverse_course_url('orphan_handler', course.id) test_user_client, test_user = self.create_non_staff_authed_user_client() diff --git a/cms/djangoapps/contentstore/tests/test_proctoring.py b/cms/djangoapps/contentstore/tests/test_proctoring.py index d398bc896a59..95eba736f665 100644 --- a/cms/djangoapps/contentstore/tests/test_proctoring.py +++ b/cms/djangoapps/contentstore/tests/test_proctoring.py @@ -4,6 +4,7 @@ from datetime import datetime, timedelta +from unittest import skip from unittest.mock import patch import ddt @@ -11,20 +12,21 @@ from edx_proctoring.api import get_all_exams_for_course, get_review_policy_by_exam_id from pytz import UTC from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from cms.djangoapps.contentstore.signals.handlers import listen_for_course_publish from common.djangoapps.student.tests.factories import UserFactory +@skip("OldMongo Deprecation") @ddt.ddt @patch.dict('django.conf.settings.FEATURES', {'ENABLE_SPECIAL_EXAMS': True}) class TestProctoredExams(ModuleStoreTestCase): """ Tests for the publishing of proctored exams """ - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE def setUp(self): """ diff --git a/cms/djangoapps/contentstore/tests/test_tasks.py b/cms/djangoapps/contentstore/tests/test_tasks.py index ad904e3e4b9d..d037f1d99c2d 100644 --- a/cms/djangoapps/contentstore/tests/test_tasks.py +++ b/cms/djangoapps/contentstore/tests/test_tasks.py @@ -23,6 +23,7 @@ from common.djangoapps.student.tests.factories import UserFactory from openedx.core.djangoapps.embargo.models import Country, CountryAccessRule, RestrictedCourse from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE TEST_DATA_CONTENTSTORE = copy.deepcopy(settings.CONTENTSTORE) TEST_DATA_CONTENTSTORE['DOC_STORE_CONFIG']['db'] = 'test_xcontent_%s' % uuid4().hex @@ -117,6 +118,9 @@ def test_success(self): @override_settings(CONTENTSTORE=TEST_DATA_CONTENTSTORE) class RerunCourseTaskTestCase(CourseTestCase): # lint-amnesty, pylint: disable=missing-class-docstring + + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE + def _rerun_course(self, old_course_key, new_course_key): CourseRerunState.objects.initiated(old_course_key, new_course_key, self.user, 'Test Re-run') rerun_course(str(old_course_key), str(new_course_key), self.user.id) diff --git a/cms/djangoapps/contentstore/tests/test_users_default_role.py b/cms/djangoapps/contentstore/tests/test_users_default_role.py index 82bd4e960b9e..5698073bfad4 100644 --- a/cms/djangoapps/contentstore/tests/test_users_default_role.py +++ b/cms/djangoapps/contentstore/tests/test_users_default_role.py @@ -3,7 +3,8 @@ after deleting it creates same course again """ -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase +from unittest import skip +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient from cms.djangoapps.contentstore.utils import delete_course, reverse_url @@ -15,7 +16,7 @@ class TestUsersDefaultRole(ModuleStoreTestCase): """ Unit tests for checking enrollment and default forum role "Student" of a logged in user """ - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE def setUp(self): """ @@ -92,6 +93,7 @@ def test_user_role_on_course_recreate(self): # check that user has his default "Student" forum role for this course self.assertTrue(self.user.roles.filter(name="Student", course_id=self.course_key)) + @skip("OldMongo Deprecation") def test_user_role_on_course_recreate_with_change_name_case(self): """ Test that creating same course again with different name case after deleting it gives user diff --git a/cms/djangoapps/contentstore/tests/test_utils.py b/cms/djangoapps/contentstore/tests/test_utils.py index b166de0ef9c7..80c4cdce59fb 100644 --- a/cms/djangoapps/contentstore/tests/test_utils.py +++ b/cms/djangoapps/contentstore/tests/test_utils.py @@ -1,7 +1,7 @@ """ Tests for utils. """ import collections from datetime import datetime, timedelta -from unittest import mock +from unittest import mock, skip from unittest.mock import Mock, patch from uuid import uuid4 @@ -411,6 +411,7 @@ def verify_all_components_visible_to_all(): verify_all_components_visible_to_all() + @skip("OldMongo Deprecation") def test_sequential_and_problem_have_group_access(self): """ Tests when group_access is set on a few different components. """ self.set_group_access(self.sequential, {1: [0]}) diff --git a/cms/djangoapps/contentstore/tests/utils.py b/cms/djangoapps/contentstore/tests/utils.py index fabfb2c75fd7..54455bdf3841 100644 --- a/cms/djangoapps/contentstore/tests/utils.py +++ b/cms/djangoapps/contentstore/tests/utils.py @@ -10,12 +10,12 @@ from django.conf import settings from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user from django.test.client import Client -from opaque_keys.edx.keys import AssetKey, CourseKey +from opaque_keys.edx.keys import AssetKey from xmodule.contentstore.django import contentstore from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.inheritance import own_metadata from xmodule.modulestore.split_mongo.split import SplitMongoModuleStore -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_MODULESTORE, ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.utils import ProceduralCourseTestMixin from xmodule.modulestore.xml_importer import import_course_from_xml @@ -74,7 +74,7 @@ class CourseTestCase(ProceduralCourseTestMixin, ModuleStoreTestCase): Base class for Studio tests that require a logged in user and a course. Also provides helper methods for manipulating and verifying the course. """ - MODULESTORE = TEST_DATA_MONGO_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE def setUp(self): """ @@ -124,15 +124,18 @@ def save_course(self): SEQUENTIAL = 'vertical_sequential' DRAFT_HTML = 'draft_html' DRAFT_VIDEO = 'draft_video' - LOCKED_ASSET_KEY = AssetKey.from_string('/c4x/edX/toy/asset/sample_static.html') + LOCKED_ASSET_KEY = AssetKey.from_string('asset-v1:edX+toy+2012_Fall+type@asset+block@sample_static.html') def import_and_populate_course(self): """ Imports the test toy course and populates it with additional test data """ content_store = contentstore() - import_course_from_xml(self.store, self.user.id, TEST_DATA_DIR, ['toy'], static_content_store=content_store) - course_id = CourseKey.from_string('/'.join(['edX', 'toy', '2012_Fall'])) + import_course_from_xml( + self.store, self.user.id, TEST_DATA_DIR, ['toy'], static_content_store=content_store, verbose=True, + create_if_not_present=True + ) + course_id = self.store.make_course_key('edX', 'toy', '2012_Fall') # create an Orphan # We had a bug where orphaned draft nodes caused export to fail. This is here to cover that case. @@ -155,11 +158,6 @@ def import_and_populate_course(self): orphan_draft_vertical.children.append(orphan_draft_html.location) self.store.update_item(orphan_draft_vertical, self.user.id) - # create a Draft vertical - vertical = self.store.get_item(course_id.make_usage_key('vertical', self.TEST_VERTICAL), depth=1) - draft_vertical = self.store.convert_to_draft(vertical.location, self.user.id) - self.assertTrue(self.store.has_published_version(draft_vertical)) - # create a Private (draft only) vertical private_vertical = self.store.create_item(self.user.id, course_id, 'vertical', self.PRIVATE_VERTICAL) self.assertFalse(self.store.has_published_version(private_vertical)) @@ -185,24 +183,10 @@ def import_and_populate_course(self): self.store.update_item(public_vertical, self.user.id) # publish changes to vertical self.store.publish(public_vertical.location, self.user.id) - # convert html/video to draft - self.store.convert_to_draft(draft_html.location, self.user.id) - self.store.convert_to_draft(draft_video.location, self.user.id) # lock an asset content_store.set_attr(self.LOCKED_ASSET_KEY, 'locked', True) - # create a non-portable link - should be rewritten in new courses - html_module = self.store.get_item(course_id.make_usage_key('html', 'nonportable')) - new_data = html_module.data = html_module.data.replace( - '/static/', - f'/c4x/{course_id.org}/{course_id.course}/asset/' - ) - self.store.update_item(html_module, self.user.id) - - html_module = self.store.get_item(html_module.location) - self.assertEqual(new_data, html_module.data) - return course_id def check_populated_course(self, course_id): @@ -234,12 +218,7 @@ def get_and_verify_publish_state(item_type, item_name, publish_state): for child in vertical.get_children(): verify_item_publish_state(child, True) - # verify that it has a draft too - self.assertTrue(getattr(vertical, "is_draft", False)) - - # make sure that we don't have a sequential that is in draft mode sequential = get_and_verify_publish_state('sequential', self.SEQUENTIAL, True) - self.assertFalse(getattr(sequential, "is_draft", False)) # verify that we have the private vertical private_vertical = get_and_verify_publish_state('vertical', self.PRIVATE_VERTICAL, False) @@ -248,22 +227,20 @@ def get_and_verify_publish_state(item_type, item_name, publish_state): public_vertical = get_and_verify_publish_state('vertical', self.PUBLISHED_VERTICAL, True) # verify that we have the draft html - draft_html = self.store.get_item(course_id.make_usage_key('html', self.DRAFT_HTML)) - self.assertTrue(getattr(draft_html, 'is_draft', False)) + html = self.store.get_item(course_id.make_usage_key('html', self.DRAFT_HTML)) # verify that we have the draft video - draft_video = self.store.get_item(course_id.make_usage_key('video', self.DRAFT_VIDEO)) - self.assertTrue(getattr(draft_video, 'is_draft', False)) + video = self.store.get_item(course_id.make_usage_key('video', self.DRAFT_VIDEO)) # verify verticals are children of sequential for vert in [vertical, private_vertical, public_vertical]: self.assertIn(vert.location, sequential.children) # verify draft html is the child of the public vertical - self.assertIn(draft_html.location, public_vertical.children) + self.assertIn(html.location, public_vertical.children) # verify draft video is the child of the public vertical - self.assertIn(draft_video.location, public_vertical.children) + self.assertIn(video.location, public_vertical.children) # verify textbook exists course = self.store.get_course(course_id) diff --git a/cms/djangoapps/contentstore/views/tests/test_assets.py b/cms/djangoapps/contentstore/views/tests/test_assets.py index 6ee861888809..ea6c0d35de38 100644 --- a/cms/djangoapps/contentstore/views/tests/test_assets.py +++ b/cms/djangoapps/contentstore/views/tests/test_assets.py @@ -6,7 +6,7 @@ import json from datetime import datetime from io import BytesIO -from unittest import mock +from unittest import mock, skip from unittest.mock import patch from ddt import data, ddt @@ -73,6 +73,7 @@ def get_sample_asset(self, name, asset_type='text'): return sample_asset +@skip("OldMongo Deprecation") class BasicAssetsTestCase(AssetsTestCase): """ Test getting assets via html w/o additional args @@ -439,6 +440,7 @@ def test_basic(self): self.assertIsNone(output["thumbnail"]) +@skip("OldMongo Deprecation") class LockAssetTestCase(AssetsTestCase): """ Unit test for locking and unlocking an asset. @@ -499,6 +501,7 @@ def post_asset_update(lock, course): verify_asset_locked_state(False) +@skip("OldMongo Deprecation") class DeleteAssetTestCase(AssetsTestCase): """ Unit test for removing an asset. diff --git a/cms/djangoapps/contentstore/views/tests/test_container_page.py b/cms/djangoapps/contentstore/views/tests/test_container_page.py index 599cd4f51957..a6546deb11fb 100644 --- a/cms/djangoapps/contentstore/views/tests/test_container_page.py +++ b/cms/djangoapps/contentstore/views/tests/test_container_page.py @@ -5,6 +5,7 @@ import datetime import re +from unittest import skip from unittest.mock import Mock, patch from django.http import Http404 @@ -190,11 +191,12 @@ def _create_item(self, parent_location, category, display_name, **kwargs): **kwargs ) + @skip("OldMongo Deprecation") def test_public_child_container_preview_html(self): """ Verify that a public container rendered as a child of the container page returns the expected HTML. """ - empty_child_container = self._create_item(self.vertical.location, 'split_test', 'Split Test') + empty_child_container = self._create_item(self.vertical.location, 'split_test', 'Split Test 1') published_empty_child_container = self.store.publish(empty_child_container.location, self.user.id) self.validate_preview_html(published_empty_child_container, self.reorderable_child_view, can_add=False) @@ -202,7 +204,7 @@ def test_draft_child_container_preview_html(self): """ Verify that a draft container rendered as a child of the container page returns the expected HTML. """ - empty_child_container = self._create_item(self.vertical.location, 'split_test', 'Split Test') + empty_child_container = self._create_item(self.vertical.location, 'split_test', 'Split Test 1') self.validate_preview_html(empty_child_container, self.reorderable_child_view, can_add=False) @patch( diff --git a/cms/djangoapps/contentstore/views/tests/test_course_index.py b/cms/djangoapps/contentstore/views/tests/test_course_index.py index 04b66498b01d..2c524de6a9a1 100644 --- a/cms/djangoapps/contentstore/views/tests/test_course_index.py +++ b/cms/djangoapps/contentstore/views/tests/test_course_index.py @@ -96,6 +96,7 @@ def _assert_library_tab_present(response): index_response = self.client.get(index_url, {}, HTTP_ACCEPT='text/html') _assert_library_tab_present(index_response) + @skip("OldMongo Deprecation") def test_is_staff_access(self): """ Test that people with is_staff see the courses and can navigate into them @@ -115,6 +116,7 @@ def test_negative_conditions(self): else: self.assertEqual(response.status_code, 403) + @skip("OldMongo Deprecation") def test_course_staff_access(self): """ Make and register course_staff and ensure they can access the courses @@ -584,6 +586,7 @@ def _verify_deprecated_info(self, course_id, advanced_modules, info, deprecated_ reverse_course_url('advanced_settings_handler', course_id) ) + @skip("OldMongo Deprecation") @ddt.data( [{'publish': True}, ['notes']], [{'publish': False}, ['notes']], @@ -604,6 +607,7 @@ def test_verify_deprecated_warning_message(self, publish, block_types): block_types ) + @skip("OldMongo Deprecation") @ddt.data( (["a", "b", "c"], ["a", "b", "c"]), (["a", "b", "c"], ["a", "b", "d"]), @@ -835,6 +839,7 @@ def test_reindex_seq_error_json_responses(self, mock_index_dictionary): with self.assertRaises(SearchIndexingError): reindex_course_and_check_access(self.course.id, self.user) + @skip("OldMongo Deprecation") @mock.patch('xmodule.modulestore.mongo.base.MongoModuleStore.get_course') def test_reindex_no_item(self, mock_get_course): """ @@ -923,6 +928,7 @@ def test_indexing_html_error_responses(self, mock_index_dictionary): with self.assertRaises(SearchIndexingError): CoursewareSearchIndexer.do_course_reindex(modulestore(), self.course.id) + @skip("OldMongo Deprecation") @mock.patch('xmodule.seq_module.SequenceBlock.index_dictionary') def test_indexing_seq_error_responses(self, mock_index_dictionary): """ @@ -945,7 +951,8 @@ def test_indexing_seq_error_responses(self, mock_index_dictionary): with self.assertRaises(SearchIndexingError): CoursewareSearchIndexer.do_course_reindex(modulestore(), self.course.id) - @mock.patch('xmodule.modulestore.mongo.base.MongoModuleStore.get_course') + @skip("OldMongo Deprecation") + @mock.patch('xmodule.modulestore.split_mongo.split.SplitMongoModuleStore.get_course') def test_indexing_no_item(self, mock_get_course): """ Test system logs an error if no item found. diff --git a/cms/djangoapps/contentstore/views/tests/test_group_configurations.py b/cms/djangoapps/contentstore/views/tests/test_group_configurations.py index 728d2d980890..0d95abfc96d2 100644 --- a/cms/djangoapps/contentstore/views/tests/test_group_configurations.py +++ b/cms/djangoapps/contentstore/views/tests/test_group_configurations.py @@ -5,6 +5,7 @@ import json from operator import itemgetter +from unittest import skip from unittest.mock import patch import ddt @@ -64,9 +65,9 @@ def _create_content_experiment(self, cid=-1, group_id=None, cid_for_problem=None parent_location=sequential.location, display_name=f'Test Unit {name_suffix}' ) - c0_url = self.course.id.make_usage_key("vertical", "split_test_cond0") - c1_url = self.course.id.make_usage_key("vertical", "split_test_cond1") - c2_url = self.course.id.make_usage_key("vertical", "split_test_cond2") + c0_url = self.course.id.make_usage_key("vertical", f"split_test_cond0_{name_suffix}") + c1_url = self.course.id.make_usage_key("vertical", f"split_test_cond1_{name_suffix}") + c2_url = self.course.id.make_usage_key("vertical", f"split_test_cond2_{name_suffix}") split_test = ItemFactory.create( category='split_test', parent_location=vertical.location, @@ -770,13 +771,12 @@ def test_can_get_correct_usage_info_for_content_groups(self): self.assertEqual(actual, expected) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_can_get_correct_usage_info_with_orphan(self, module_store_type): + def test_can_get_correct_usage_info_with_orphan(self): """ Test if content group json updated successfully with usage information even if there is an orphan in content group. """ - self.course = CourseFactory.create(default_store=module_store_type) + self.course = CourseFactory.create() self._add_user_partitions(count=1, scheme_id='cohort') vertical, __ = self._create_problem_with_content_group(cid=0, group_id=1, name_suffix='0', orphan=True) @@ -784,16 +784,8 @@ def test_can_get_correct_usage_info_with_orphan(self, module_store_type): self.assertEqual(len(self.store.get_orphans(self.course.id)), 1) self.assertIn(vertical.location, self.store.get_orphans(self.course.id)) - # Get the expected content group information based on module store. - if module_store_type == ModuleStoreEnum.Type.mongo: - expected = self._get_expected_content_group(usage_for_group=[ - { - 'url': f'/container/{vertical.location}', - 'label': 'Test Unit 0 / Test Problem 0' - } - ]) - else: - expected = self._get_expected_content_group(usage_for_group=[]) + # Get the expected content group information. + expected = self._get_expected_content_group(usage_for_group=[]) # Get the actual content group information actual = self._get_user_partition('cohort') @@ -801,6 +793,7 @@ def test_can_get_correct_usage_info_with_orphan(self, module_store_type): # Assert that actual content group information is same as expected one. self.assertEqual(actual, expected) + @skip("OldMongo Deprecation") def test_can_use_one_content_group_in_multiple_problems(self): """ Test if multiple problems are present in usage info when they use same @@ -848,6 +841,7 @@ def test_group_configuration_not_used(self): }] self.assertEqual(actual, expected) + @skip("OldMongo Deprecation") def test_can_get_correct_usage_info_for_split_test(self): """ When a split test is created and content group access is set for a problem within a group, @@ -1060,6 +1054,7 @@ def test_can_use_one_configuration_in_multiple_experiments(self): }] self.assertEqual(actual, expected) + @skip("OldMongo Deprecation") def test_can_handle_without_parent(self): """ Test if it possible to handle case when split_test has no parent. diff --git a/cms/djangoapps/contentstore/views/tests/test_import_export.py b/cms/djangoapps/contentstore/views/tests/test_import_export.py index 280ea4d469b6..68e7bd9ccb9f 100644 --- a/cms/djangoapps/contentstore/views/tests/test_import_export.py +++ b/cms/djangoapps/contentstore/views/tests/test_import_export.py @@ -6,7 +6,6 @@ import json import logging import os -import re import shutil import tarfile import tempfile @@ -28,6 +27,7 @@ from storages.backends.s3boto import S3BotoStorage from storages.backends.s3boto3 import S3Boto3Storage from user_tasks.models import UserTaskStatus +from xblock.plugin import PluginMissingError from cms.djangoapps.contentstore import errors as import_error from cms.djangoapps.contentstore.storage import course_import_export_storage @@ -749,36 +749,11 @@ def test_unknown_xblock_top_level(self): """ Export unknown XBlock type (i.e. we uninstalled the XBlock), top level. """ - fake_xblock = ItemFactory.create( - parent_location=self.course.location, - category='not_a_real_block_type' - ) - self.store.publish(fake_xblock.location, self.user.id) - - # Now check the resulting export - tar_ball = self.test_export_async() - course_file_path = next( - path for path in tar_ball.getnames() - if re.match(r'\w+/course/\w+.xml', path) - ) - course_file = tar_ball.extractfile(course_file_path) - course_xml = lxml.etree.parse(course_file) - course_elem = course_xml.getroot() - - # The course run file still has a child pointer to the unknown type and - # creates the pointer tag... - self.assertEqual(course_elem.tag, 'course') - unknown_elem = course_elem[0] - self.assertEqual(unknown_elem.tag, 'not_a_real_block_type') - # Non empty url_name attribute (the generated ID) - self.assertTrue(unknown_elem.attrib['url_name']) - - # But there should be no file exported for our fake block type. Without - # the XBlock installed, we don't know how to serialize it properly. - assert not any( - '/not_a_real_block_type/' in path - for path in tar_ball.getnames() - ) + with self.assertRaisesMessage(PluginMissingError, 'not_a_real_block_type'): + ItemFactory.create( + parent_location=self.course.location, + category='not_a_real_block_type' + ) def test_unknown_xblock_subsection_level(self): """ @@ -789,46 +764,11 @@ def test_unknown_xblock_subsection_level(self): category='vertical', display_name='sample_vertical', ) - fake_xblock = ItemFactory.create( - parent_location=vertical.location, - category='not_a_real_block_type', - ) - self.store.publish(fake_xblock.location, self.user.id) - - # Now check the resulting export - tar_ball = self.test_export_async() - course_file_path = next( - path for path in tar_ball.getnames() - if re.match(r'\w+/course/\w+.xml', path) - ) - course_file = tar_ball.extractfile(course_file_path) - course_xml = lxml.etree.parse(course_file) - course_elem = course_xml.getroot() - - # The course run file should have a vertical that points to the - # non-existant block. - self.assertEqual(course_elem.tag, 'course') - self.assertEqual(course_elem[0].tag, 'vertical') # This is just a reference - - vert_file_path = next( - path for path in tar_ball.getnames() - if re.match(r'\w+/vertical/\w+.xml', path) - ) - vert_file = tar_ball.extractfile(vert_file_path) - vert_xml = lxml.etree.parse(vert_file) - vert_elem = vert_xml.getroot() - self.assertEqual(vert_elem.tag, 'vertical') - self.assertEqual(len(vert_elem), 1) - unknown_elem = vert_elem[0] - self.assertEqual(unknown_elem.tag, 'not_a_real_block_type') - # Non empty url_name attribute (the generated ID) - self.assertTrue(unknown_elem.attrib['url_name']) - - # There should be no file exported for our fake block type - assert not any( - '/not_a_real_block_type/' in path - for path in tar_ball.getnames() - ) + with self.assertRaisesMessage(PluginMissingError, 'not_a_real_block_type'): + ItemFactory.create( + parent_location=vertical.location, + category='not_a_real_block_type', + ) def _verify_export_failure(self, expected_text): """ Export failure helper method. """ diff --git a/cms/djangoapps/contentstore/views/tests/test_item.py b/cms/djangoapps/contentstore/views/tests/test_item.py index 055cea6401c2..be3ef7ad1e86 100644 --- a/cms/djangoapps/contentstore/views/tests/test_item.py +++ b/cms/djangoapps/contentstore/views/tests/test_item.py @@ -4,6 +4,7 @@ import json import re from datetime import datetime, timedelta +from unittest import skip from unittest.mock import Mock, PropertyMock, patch import ddt @@ -92,13 +93,11 @@ def setUp(self): self.course_key = self.course.id self.usage_key = self.course.location - def get_item_from_modulestore(self, usage_key, verify_is_draft=False): + def get_item_from_modulestore(self, usage_key): """ Get the item referenced by the UsageKey from the modulestore """ item = self.store.get_item(usage_key) - if verify_is_draft: - self.assertTrue(getattr(item, 'is_draft', False)) return item def response_usage_key(self, response): @@ -167,6 +166,7 @@ def _get_container_preview_with_error(self, usage_key, expected_code, data=None, self.assertContains(resp, content_contains, status_code=expected_code) return resp + @skip("OldMongo Deprecation") @ddt.data( (1, 17, 15, 16, 12), (2, 17, 15, 16, 12), @@ -185,13 +185,14 @@ def test_get_query_count(self, branching_factor, chapter_queries, section_querie with check_mongo_calls(problem_queries): self.client.get(reverse_usage_url('xblock_handler', self.populated_usage_keys['problem'][-1])) + @skip("OldMongo Deprecation") @ddt.data( (1, 30), (2, 32), (3, 34), ) @ddt.unpack - def test_container_get_query_count(self, branching_factor, unit_queries,): + def test_container_get_query_count(self, branching_factor, unit_queries): self.populate_course(branching_factor) with check_mongo_calls(unit_queries): self.client.get(reverse_usage_url('xblock_container_handler', self.populated_usage_keys['vertical'][-1])) @@ -483,9 +484,8 @@ def assert_xblock_info(xblock, xblock_info): class DeleteItem(ItemTest): """Tests for '/xblock' DELETE url.""" - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_delete_static_page(self, store): - course = CourseFactory.create(default_store=store) + def test_delete_static_page(self): + course = CourseFactory.create() # Add static tab resp = self.create_xblock(category='static_tab', parent_usage_key=course.location) usage_key = self.response_usage_key(resp) @@ -532,7 +532,7 @@ def test_create_nicely(self): boilerplate=template_id ) prob_usage_key = self.response_usage_key(resp) - problem = self.get_item_from_modulestore(prob_usage_key, verify_is_draft=True) + problem = self.get_item_from_modulestore(prob_usage_key) # check against the template template = ProblemBlock.get_template(template_id) self.assertEqual(problem.data, template['data']) @@ -700,7 +700,7 @@ def setUp(self): self.html_usage_key = self.response_usage_key(resp) # Create a second sequential just (testing children of children) - self.create_xblock(parent_usage_key=self.chapter_usage_key, category='sequential2') + self.create_xblock(parent_usage_key=self.chapter_usage_key, category='sequential') def test_duplicate_equality(self): """ @@ -844,7 +844,7 @@ def setup_and_verify_content_experiment(self, partition_id): Arguments: partition_id (int): User partition id. """ - split_test = self.get_item_from_modulestore(self.split_test_usage_key, verify_is_draft=True) + split_test = self.get_item_from_modulestore(self.split_test_usage_key) # Initially, no user_partition_id is set, and the split_test has no children. self.assertEqual(split_test.user_partition_id, -1) @@ -855,7 +855,7 @@ def setup_and_verify_content_experiment(self, partition_id): reverse_usage_url("xblock_handler", self.split_test_usage_key), data={'metadata': {'user_partition_id': str(partition_id)}} ) - split_test = self.get_item_from_modulestore(self.split_test_usage_key, verify_is_draft=True) + split_test = self.get_item_from_modulestore(self.split_test_usage_key) self.assertEqual(split_test.user_partition_id, partition_id) self.assertEqual(len(split_test.children), len(self.course.user_partitions[partition_id].groups)) return split_test @@ -918,15 +918,14 @@ def assert_move_item(self, source_usage_key, target_usage_key, target_index=None self.assertIn(source_usage_key, target_parent.children) self.assertNotIn(source_usage_key, source_parent.children) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_move_component(self, store_type): + def test_move_component(self): """ Test move component with different xblock types. Arguments: store_type (ModuleStoreEnum.Type): Type of modulestore to create test course in. """ - self.setup_course(default_store=store_type) + self.setup_course() for source_usage_key, target_usage_key in [ (self.html_usage_key, self.vert2_usage_key), (self.vert_usage_key, self.seq2_usage_key), @@ -1131,7 +1130,7 @@ def test_can_not_move_content_experiment_into_its_children(self): reverse_usage_url("xblock_handler", child_split_test_usage_key), data={'metadata': {'user_partition_id': str(0)}} ) - child_split_test = self.get_item_from_modulestore(self.split_test_usage_key, verify_is_draft=True) + child_split_test = self.get_item_from_modulestore(self.split_test_usage_key) # Try to move content experiment further down the level to a child group A nested inside main group A. response = self._move_component(self.split_test_usage_key, child_split_test.children[0]) @@ -1186,6 +1185,7 @@ def _verify_validation_message(self, message, expected_message, expected_message self.assertEqual(message.text, expected_message) self.assertEqual(message.type, expected_message_type) + @skip("OldMongo Deprecation") def test_move_component_nonsensical_access_restriction_validation(self): """ Test that moving a component with non-contradicting access @@ -1255,8 +1255,7 @@ def test_move_logging(self, mock_logger): insert_at ) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_move_and_discard_changes(self, store_type): + def test_move_and_discard_changes(self): """ Verifies that discard changes operation brings moved component back to source location and removes the component from target location. @@ -1264,7 +1263,7 @@ def test_move_and_discard_changes(self, store_type): Arguments: store_type (ModuleStoreEnum.Type): Type of modulestore to create test course in. """ - self.setup_course(default_store=store_type) + self.setup_course() old_parent_loc = self.store.get_parent_location(self.html_usage_key) @@ -1308,15 +1307,14 @@ def test_move_and_discard_changes(self, store_type): self.assertIn(self.html_usage_key, source_parent.children) self.assertNotIn(self.html_usage_key, target_parent.children) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_move_item_not_found(self, store_type=ModuleStoreEnum.Type.mongo): + def test_move_item_not_found(self): """ Test that an item not found exception raised when an item is not found when getting the item. Arguments: store_type (ModuleStoreEnum.Type): Type of modulestore to create test course in. """ - self.setup_course(default_store=store_type) + self.setup_course() data = { 'move_source_locator': str(self.usage_key.course_key.make_usage_key('html', 'html_test')), @@ -1437,26 +1435,26 @@ def test_delete_field(self): self.problem_update_url, data={'metadata': {'rerandomize': 'onreset'}} ) - problem = self.get_item_from_modulestore(self.problem_usage_key, verify_is_draft=True) + problem = self.get_item_from_modulestore(self.problem_usage_key) self.assertEqual(problem.rerandomize, 'onreset') self.client.ajax_post( self.problem_update_url, data={'metadata': {'rerandomize': None}} ) - problem = self.get_item_from_modulestore(self.problem_usage_key, verify_is_draft=True) + problem = self.get_item_from_modulestore(self.problem_usage_key) self.assertEqual(problem.rerandomize, 'never') def test_null_field(self): """ Sending null in for a field 'deletes' it """ - problem = self.get_item_from_modulestore(self.problem_usage_key, verify_is_draft=True) + problem = self.get_item_from_modulestore(self.problem_usage_key) self.assertIsNotNone(problem.markdown) self.client.ajax_post( self.problem_update_url, data={'nullout': ['markdown']} ) - problem = self.get_item_from_modulestore(self.problem_usage_key, verify_is_draft=True) + problem = self.get_item_from_modulestore(self.problem_usage_key) self.assertIsNone(problem.markdown) def test_date_fields(self): @@ -1517,7 +1515,7 @@ def test_update_generic_fields(self): } } ) - problem = self.get_item_from_modulestore(self.problem_usage_key, verify_is_draft=True) + problem = self.get_item_from_modulestore(self.problem_usage_key) self.assertEqual(problem.display_name, new_display_name) self.assertEqual(problem.max_attempts, new_max_attempts) @@ -1714,7 +1712,7 @@ def test_republish(self): } ) self.assertFalse(self._is_location_published(self.problem_usage_key)) - draft = self.get_item_from_modulestore(self.problem_usage_key, verify_is_draft=True) + draft = self.get_item_from_modulestore(self.problem_usage_key) self.assertEqual(draft.display_name, new_display_name) # Publish the item @@ -1772,7 +1770,7 @@ def _make_draft_content_different_from_published(self): self.problem_update_url, data={'metadata': {'due': '2077-10-10T04:00Z'}} ) - updated_draft = self.get_item_from_modulestore(self.problem_usage_key, verify_is_draft=True) + updated_draft = self.get_item_from_modulestore(self.problem_usage_key) self.assertEqual(updated_draft.due, datetime(2077, 10, 10, 4, 0, tzinfo=UTC)) self.assertIsNone(published.due) # Fetch the published version again to make sure the due date is still unset. @@ -1814,7 +1812,7 @@ def test_published_and_draft_contents_with_update(self): ) # Both published and draft content should be different - draft = self.get_item_from_modulestore(self.problem_usage_key, verify_is_draft=True) + draft = self.get_item_from_modulestore(self.problem_usage_key) self.assertNotEqual(draft.data, published.data) # Get problem by 'xblock_handler' @@ -1828,12 +1826,13 @@ def test_published_and_draft_contents_with_update(self): self.assertEqual(resp.status_code, 200) # Both published and draft content should still be different - draft = self.get_item_from_modulestore(self.problem_usage_key, verify_is_draft=True) + draft = self.get_item_from_modulestore(self.problem_usage_key) self.assertNotEqual(draft.data, published.data) # Fetch the published version again to make sure the data is correct. published = modulestore().get_item(published.location, revision=ModuleStoreEnum.RevisionOption.published_only) self.assertNotEqual(draft.data, published.data) + @skip("OldMongo Deprecation") def test_publish_states_of_nested_xblocks(self): """ Test publishing of a unit page containing a nested xblock """ @@ -1970,7 +1969,7 @@ def _update_partition_id(self, partition_id): ) # Verify the partition_id was saved. - split_test = self.get_item_from_modulestore(self.split_test_usage_key, verify_is_draft=True) + split_test = self.get_item_from_modulestore(self.split_test_usage_key) self.assertEqual(partition_id, split_test.user_partition_id) return split_test @@ -1978,7 +1977,7 @@ def _assert_children(self, expected_number): """ Verifies the number of children of the split_test instance. """ - split_test = self.get_item_from_modulestore(self.split_test_usage_key, True) + split_test = self.get_item_from_modulestore(self.split_test_usage_key) self.assertEqual(expected_number, len(split_test.children)) return split_test @@ -1987,7 +1986,7 @@ def test_create_groups(self): Test that verticals are created for the configuration groups when a spit test module is edited. """ - split_test = self.get_item_from_modulestore(self.split_test_usage_key, verify_is_draft=True) + split_test = self.get_item_from_modulestore(self.split_test_usage_key) # Initially, no user_partition_id is set, and the split_test has no children. self.assertEqual(-1, split_test.user_partition_id) self.assertEqual(0, len(split_test.children)) @@ -1997,8 +1996,8 @@ def test_create_groups(self): # Verify that child verticals have been set to match the groups self.assertEqual(2, len(split_test.children)) - vertical_0 = self.get_item_from_modulestore(split_test.children[0], verify_is_draft=True) - vertical_1 = self.get_item_from_modulestore(split_test.children[1], verify_is_draft=True) + vertical_0 = self.get_item_from_modulestore(split_test.children[0]) + vertical_1 = self.get_item_from_modulestore(split_test.children[1]) self.assertEqual("vertical", vertical_0.category) self.assertEqual("vertical", vertical_1.category) self.assertEqual("Group ID " + str(MINIMUM_STATIC_PARTITION_ID + 1), vertical_0.display_name) @@ -2013,7 +2012,7 @@ def test_split_xblock_info_group_name(self): """ Test that concise outline for split test component gives display name as group name. """ - split_test = self.get_item_from_modulestore(self.split_test_usage_key, verify_is_draft=True) + split_test = self.get_item_from_modulestore(self.split_test_usage_key) # Initially, no user_partition_id is set, and the split_test has no children. self.assertEqual(split_test.user_partition_id, -1) self.assertEqual(len(split_test.children), 0) @@ -2051,9 +2050,9 @@ def test_change_user_partition_id(self): self.assertEqual(5, len(split_test.children)) self.assertEqual(initial_vertical_0_location, split_test.children[0]) self.assertEqual(initial_vertical_1_location, split_test.children[1]) - vertical_0 = self.get_item_from_modulestore(split_test.children[2], verify_is_draft=True) - vertical_1 = self.get_item_from_modulestore(split_test.children[3], verify_is_draft=True) - vertical_2 = self.get_item_from_modulestore(split_test.children[4], verify_is_draft=True) + vertical_0 = self.get_item_from_modulestore(split_test.children[2]) + vertical_1 = self.get_item_from_modulestore(split_test.children[3]) + vertical_2 = self.get_item_from_modulestore(split_test.children[4]) # Verify that the group_id_to child mapping is correct. self.assertEqual(3, len(split_test.group_id_to_child)) @@ -2563,31 +2562,26 @@ def test_json_responses(self): json_response = json.loads(resp.content.decode('utf-8')) self.validate_course_xblock_info(json_response, course_outline=True) - @ddt.data( - (ModuleStoreEnum.Type.split, 3, 3), - (ModuleStoreEnum.Type.mongo, 5, 7), - ) @ddt.unpack - def test_xblock_outline_handler_mongo_calls(self, store_type, chapter_queries, chapter_queries_1): - with self.store.default_store(store_type): - course = CourseFactory.create() - chapter = ItemFactory.create( - parent_location=course.location, category='chapter', display_name='Week 1' - ) - outline_url = reverse_usage_url('xblock_outline_handler', chapter.location) - with check_mongo_calls(chapter_queries): - self.client.get(outline_url, HTTP_ACCEPT='application/json') + def test_xblock_outline_handler_mongo_calls(self): + course = CourseFactory.create() + chapter = ItemFactory.create( + parent_location=course.location, category='chapter', display_name='Week 1' + ) + outline_url = reverse_usage_url('xblock_outline_handler', chapter.location) + with check_mongo_calls(3): + self.client.get(outline_url, HTTP_ACCEPT='application/json') - sequential = ItemFactory.create( - parent_location=chapter.location, category='sequential', display_name='Sequential 1' - ) + sequential = ItemFactory.create( + parent_location=chapter.location, category='sequential', display_name='Sequential 1' + ) - ItemFactory.create( - parent_location=sequential.location, category='vertical', display_name='Vertical 1' - ) - # calls should be same after adding two new children for split only. - with check_mongo_calls(chapter_queries_1): - self.client.get(outline_url, HTTP_ACCEPT='application/json') + ItemFactory.create( + parent_location=sequential.location, category='vertical', display_name='Vertical 1' + ) + # calls should be same after adding two new children for split only. + with check_mongo_calls(3): + self.client.get(outline_url, HTTP_ACCEPT='application/json') def test_entrance_exam_chapter_xblock_info(self): chapter = ItemFactory.create( @@ -2703,28 +2697,26 @@ def test_component_xblock_info(self): ) self.validate_component_xblock_info(xblock_info) - @ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo) - def test_validate_start_date(self, store_type): + def test_validate_start_date(self): """ Validate if start-date year is less than 1900 reset the date to DEFAULT_START_DATE. """ - with self.store.default_store(store_type): - course = CourseFactory.create() - chapter = ItemFactory.create( - parent_location=course.location, category='chapter', display_name='Week 1' - ) + course = CourseFactory.create() + chapter = ItemFactory.create( + parent_location=course.location, category='chapter', display_name='Week 1' + ) - chapter.start = datetime(year=1899, month=1, day=1, tzinfo=UTC) + chapter.start = datetime(year=1899, month=1, day=1, tzinfo=UTC) - xblock_info = create_xblock_info( - chapter, - include_child_info=True, - include_children_predicate=ALWAYS, - include_ancestor_info=True, - user=self.user - ) + xblock_info = create_xblock_info( + chapter, + include_child_info=True, + include_children_predicate=ALWAYS, + include_ancestor_info=True, + user=self.user + ) - self.assertEqual(xblock_info['start'], DEFAULT_START_DATE.strftime('%Y-%m-%dT%H:%M:%SZ')) + self.assertEqual(xblock_info['start'], DEFAULT_START_DATE.strftime('%Y-%m-%dT%H:%M:%SZ')) def test_highlights_enabled(self): self.course.highlights_enabled_for_messaging = True @@ -2846,6 +2838,7 @@ def validate_xblock_info_consistency(self, xblock_info, has_ancestor_info=False, self.assertIsNone(xblock_info.get('child_info', None)) +@skip("OldMongo Deprecation") @patch.dict('django.conf.settings.FEATURES', {'ENABLE_SPECIAL_EXAMS': True}) @ddt.ddt class TestSpecialExamXBlockInfo(ItemTest): @@ -3185,9 +3178,8 @@ def test_empty_chapter(self): xblock_info = self._get_xblock_info(empty_chapter.location) self._verify_visibility_state(xblock_info, VisibilityState.unscheduled) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_chapter_self_paced_default_start_date(self, store_type): - course = CourseFactory.create(default_store=store_type) + def test_chapter_self_paced_default_start_date(self): + course = CourseFactory.create() course.self_paced = True self.store.update_item(course, self.user.id) chapter = self._create_child(course, 'chapter', "Test Chapter") @@ -3250,6 +3242,7 @@ def test_unpublished_changes(self): self._verify_visibility_state(xblock_info, VisibilityState.needs_attention, path=self.FIRST_UNIT_PATH) self._verify_visibility_state(xblock_info, VisibilityState.staff_only, path=self.SECOND_UNIT_PATH) + @skip("OldMongo Deprecation") def test_partially_released_section(self): chapter = self._create_child(self.course, 'chapter', "Test Chapter") released_sequential = self._create_child(chapter, 'sequential', "Released Sequential") @@ -3408,8 +3401,7 @@ def test_locked_unit_staff_only_message(self): self._verify_has_staff_only_message(xblock_info, True, path=self.FIRST_SUBSECTION_PATH) self._verify_has_staff_only_message(xblock_info, True, path=self.FIRST_UNIT_PATH) - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_self_paced_item_visibility_state(self, store_type): + def test_self_paced_item_visibility_state(self): """ Test that in self-paced course, item has `live` visibility state. Test that when item was initially in `scheduled` state in instructor mode, change course pacing to self-paced, @@ -3417,7 +3409,7 @@ def test_self_paced_item_visibility_state(self, store_type): """ # Create course, chapter and setup future release date to make chapter in scheduled state - course = CourseFactory.create(default_store=store_type) + course = CourseFactory.create() chapter = self._create_child(course, 'chapter', "Test Chapter") self._set_release_date(chapter.location, datetime.now(UTC) + timedelta(days=1)) diff --git a/cms/djangoapps/contentstore/views/tests/test_preview.py b/cms/djangoapps/contentstore/views/tests/test_preview.py index 66e934911f06..6f239db54d68 100644 --- a/cms/djangoapps/contentstore/views/tests/test_preview.py +++ b/cms/djangoapps/contentstore/views/tests/test_preview.py @@ -4,7 +4,7 @@ import re -from unittest import mock +from unittest import mock, skip import ddt from django.test.client import Client, RequestFactory @@ -15,10 +15,9 @@ from xmodule.contentstore.django import contentstore from xmodule.lti_module import LTIBlock -from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import ( - TEST_DATA_MONGO_MODULESTORE, ModuleStoreTestCase, upload_file_to_course, + TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase, upload_file_to_course, ) from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.test_asides import AsideTestType @@ -45,7 +44,7 @@ def test_preview_fragment(self): Test for calling get_preview_html. Ensures data-usage-id is correctly set and asides are correctly included. """ - course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) + course = CourseFactory.create() html = ItemFactory.create( parent_location=course.location, category="html", @@ -93,7 +92,7 @@ def test_preview_no_asides(self): Test for calling get_preview_html. Ensures data-usage-id is correctly set and asides are correctly excluded because they are not enabled. """ - course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) + course = CourseFactory.create() html = ItemFactory.create( parent_location=course.location, category="html", @@ -127,52 +126,49 @@ def test_preview_conditional_module_children_context(self, mock_is_condition_sat client = Client() client.login(username=self.user.username, password=self.user_password) - with self.store.default_store(ModuleStoreEnum.Type.split): - course = CourseFactory.create() - - conditional_block = ItemFactory.create( - parent_location=course.location, - category="conditional" - ) - - # child conditional_block - ItemFactory.create( - parent_location=conditional_block.location, - category="conditional" - ) - - url = reverse_usage_url( - 'preview_handler', - conditional_block.location, - kwargs={'handler': 'xmodule_handler/conditional_get'} - ) - response = client.post(url) - self.assertEqual(response.status_code, 200) - - @ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo) - def test_block_branch_not_changed_by_preview_handler(self, default_store): + course = CourseFactory.create() + + conditional_block = ItemFactory.create( + parent_location=course.location, + category="conditional" + ) + + # child conditional_block + ItemFactory.create( + parent_location=conditional_block.location, + category="conditional" + ) + + url = reverse_usage_url( + 'preview_handler', + conditional_block.location, + kwargs={'handler': 'xmodule_handler/conditional_get'} + ) + response = client.post(url) + self.assertEqual(response.status_code, 200) + + def test_block_branch_not_changed_by_preview_handler(self): """ Tests preview_handler should not update blocks being previewed """ client = Client() client.login(username=self.user.username, password=self.user_password) - with self.store.default_store(default_store): - course = CourseFactory.create() + course = CourseFactory.create() - block = ItemFactory.create( - parent_location=course.location, - category="problem" - ) + block = ItemFactory.create( + parent_location=course.location, + category="problem" + ) - url = reverse_usage_url( - 'preview_handler', - block.location, - kwargs={'handler': 'xmodule_handler/problem_check'} - ) - response = client.post(url) - self.assertEqual(response.status_code, 200) - self.assertFalse(modulestore().has_changes(modulestore().get_item(block.location))) + url = reverse_usage_url( + 'preview_handler', + block.location, + kwargs={'handler': 'xmodule_handler/problem_check'} + ) + response = client.post(url) + self.assertEqual(response.status_code, 200) + self.assertFalse(modulestore().has_changes(modulestore().get_item(block.location))) @XBlock.needs("field-data") @@ -229,8 +225,8 @@ class CmsModuleSystemShimTest(ModuleStoreTestCase): """ Tests that the deprecated attributes in the Module System (XBlock Runtime) return the expected values. """ - MODULESTORE = TEST_DATA_MONGO_MODULESTORE - COURSE_ID = 'edX/CmsModuleShimTest/2021_Fall' + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE + COURSE_ID = 'course-v1:edX+LmsModuleShimTest+2021_Fall' PYTHON_LIB_FILENAME = 'test_python_lib.zip' PYTHON_LIB_SOURCE_FILE = './common/test/data/uploads/python_lib.zip' @@ -239,8 +235,7 @@ def setUp(self): Set up the user, course and other fields that will be used to instantiate the runtime. """ super().setUp() - org, number, run = self.COURSE_ID.split('/') - self.course = CourseFactory.create(org=org, number=number, run=run) + self.course = CourseFactory.create(org='edX', number='LmsModuleShimTest', run='2021_Fall') self.user = UserFactory() self.request = RequestFactory().get('/dummy-url') self.request.user = self.user @@ -263,7 +258,7 @@ def test_render_template(self): html = get_preview_fragment(self.request, descriptor, {'element_id': 142}).content assert '
Testing the MakoService
' in html - @override_settings(COURSES_WITH_UNSAFE_CODE=[COURSE_ID]) + @override_settings(COURSES_WITH_UNSAFE_CODE=[r'course-v1:edX\+LmsModuleShimTest\+2021_Fall']) def test_can_execute_unsafe_code(self): assert self.runtime.can_execute_unsafe_code() @@ -312,6 +307,7 @@ def test_anonymous_user_id_individual_per_student(self): ) assert runtime.anonymous_student_id == '26262401c528d7c4a6bbeabe0455ec46' + @skip("OldMongo Deprecation") @override_waffle_flag(INDIVIDUALIZE_ANONYMOUS_USER_ID, active=True) def test_anonymous_user_id_individual_per_course(self): """Test anonymous_user_id on a block which uses per-course anonymous IDs""" diff --git a/cms/djangoapps/maintenance/tests.py b/cms/djangoapps/maintenance/tests.py index 453d2a9a3e0e..07a4f5322958 100644 --- a/cms/djangoapps/maintenance/tests.py +++ b/cms/djangoapps/maintenance/tests.py @@ -12,7 +12,6 @@ from cms.djangoapps.contentstore.management.commands.utils import get_course_versions from common.djangoapps.student.tests.factories import AdminFactory, UserFactory from openedx.features.announcements.models import Announcement -from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory # lint-amnesty, pylint: disable=wrong-import-order @@ -140,7 +139,7 @@ def setup_test_course(self): Returns: course: a course object """ - course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split) + course = CourseFactory.create() # Add some changes to course chapter = ItemFactory.create(category='chapter', parent_location=course.location) self.store.create_child( @@ -169,34 +168,6 @@ def test_invalid_course_key_messages(self, course_key, error_message): error_message=error_message ) - def test_mongo_course(self): - """ - Test that we get a error message on old mongo courses. - """ - # validate non split error message - course = CourseFactory.create(default_store=ModuleStoreEnum.Type.mongo) - self.verify_error_message( - data={'course-id': str(course.id)}, - error_message='Force publishing course is not supported with old mongo courses.' - ) - - def test_mongo_course_with_split_course_key(self): - """ - Test that we get an error message `course_key_not_found` for a provided split course key - if we already have an old mongo course. - """ - # validate non split error message - course = CourseFactory.create(org='e', number='d', run='X', default_store=ModuleStoreEnum.Type.mongo) - self.verify_error_message( - data={'course-id': str(course.id)}, - error_message='Force publishing course is not supported with old mongo courses.' - ) - # Now search for the course key in split version. - self.verify_error_message( - data={'course-id': 'course-v1:e+d+X'}, - error_message=COURSE_KEY_ERROR_MESSAGES['course_key_not_found'] - ) - def test_already_published(self): """ Test that when a course is forcefully publish, we get a 'course is already published' message. diff --git a/cms/lib/xblock/test/test_authoring_mixin.py b/cms/lib/xblock/test/test_authoring_mixin.py index 6028f39614a2..c604b56ebc95 100644 --- a/cms/lib/xblock/test/test_authoring_mixin.py +++ b/cms/lib/xblock/test/test_authoring_mixin.py @@ -3,10 +3,11 @@ """ +from unittest import skip from django.conf import settings from django.test.utils import override_settings from xblock.core import XBlock -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.partitions.partitions import ( ENROLLMENT_TRACK_PARTITION_ID, @@ -23,7 +24,7 @@ class AuthoringMixinTestCase(ModuleStoreTestCase): """ Tests the studio authoring XBlock mixin. """ - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE GROUP_NO_LONGER_EXISTS = "This group no longer exists" NO_CONTENT_OR_ENROLLMENT_GROUPS = "Access to this component is not restricted" NO_CONTENT_ENROLLMENT_TRACK_ENABLED = "You can restrict access to this component to learners in specific enrollment tracks or content groups" # lint-amnesty, pylint: disable=line-too-long @@ -158,6 +159,7 @@ def test_html_empty_partition_staff_locked(self): [self.STAFF_LOCKED, self.CONTENT_GROUPS_TITLE, self.ENROLLMENT_GROUPS_TITLE] ) + @skip("OldMongo Deprecation") def test_html_populated_partition_staff_locked(self): self.create_content_groups(self.pet_groups) self.set_staff_only(self.vertical_location) @@ -178,6 +180,7 @@ def test_html_false_content_group(self): [self.STAFF_LOCKED] ) + @skip("OldMongo Deprecation") def test_html_false_content_group_staff_locked(self): self.create_content_groups(self.pet_groups) self.set_staff_only(self.vertical_location) diff --git a/common/djangoapps/static_replace/test/test_static_replace.py b/common/djangoapps/static_replace/test/test_static_replace.py index 093ff9de0698..c386748ecc55 100644 --- a/common/djangoapps/static_replace/test/test_static_replace.py +++ b/common/djangoapps/static_replace/test/test_static_replace.py @@ -268,7 +268,7 @@ def setUpClass(cls): super().setUpClass() - names_and_prefixes = [(ModuleStoreEnum.Type.split, 'split'), (ModuleStoreEnum.Type.mongo, 'old')] + names_and_prefixes = [(ModuleStoreEnum.Type.split, 'split')] for store, prefix in names_and_prefixes: with cls.store.default_store(store): cls.courses[prefix] = CourseFactory.create(org='a', course='b', run=prefix) @@ -592,202 +592,6 @@ def test_canonical_asset_path_with_new_style_assets(self, base_url, start, expec asset_path = StaticContent.get_canonicalized_asset_path(self.courses[prefix].id, start, base_url, exts) assert re.match(expected, asset_path) is not None - @ddt.data( - # No leading slash. - ('', '{prfx}_ünlöck.png', '/{c4x}/{prfx}_ünlöck.png', 1), - ('', '{prfx}_lock.png', '/{c4x}/{prfx}_lock.png', 1), - ('', 'weird {prfx}_ünlöck.png', '/{c4x}/weird_{prfx}_ünlöck.png', 1), - ('', '{prfx}_excluded.html', '/{base_c4x}/{prfx}_excluded.html', 1), - ('', '{prfx}_not_excluded.htm', '/{c4x}/{prfx}_not_excluded.htm', 1), - ('dev', '{prfx}_ünlöck.png', '//dev/{c4x}/{prfx}_ünlöck.png', 1), - ('dev', '{prfx}_lock.png', '/{c4x}/{prfx}_lock.png', 1), - ('dev', 'weird {prfx}_ünlöck.png', '//dev/{c4x}/weird_{prfx}_ünlöck.png', 1), - ('dev', '{prfx}_excluded.html', '/{base_c4x}/{prfx}_excluded.html', 1), - ('dev', '{prfx}_not_excluded.htm', '//dev/{c4x}/{prfx}_not_excluded.htm', 1), - # No leading slash with subdirectory. This ensures we probably substitute slashes. - ('', 'special/{prfx}_ünlöck.png', '/{c4x}/special_{prfx}_ünlöck.png', 1), - ('', 'special/{prfx}_lock.png', '/{c4x}/special_{prfx}_lock.png', 1), - ('', 'special/weird {prfx}_ünlöck.png', '/{c4x}/special_weird_{prfx}_ünlöck.png', 1), - ('', 'special/{prfx}_excluded.html', '/{base_c4x}/special_{prfx}_excluded.html', 1), - ('', 'special/{prfx}_not_excluded.htm', '/{c4x}/special_{prfx}_not_excluded.htm', 1), - ('dev', 'special/{prfx}_ünlöck.png', '//dev/{c4x}/special_{prfx}_ünlöck.png', 1), - ('dev', 'special/{prfx}_lock.png', '/{c4x}/special_{prfx}_lock.png', 1), - ('dev', 'special/weird {prfx}_ünlöck.png', '//dev/{c4x}/special_weird_{prfx}_ünlöck.png', 1), - ('dev', 'special/{prfx}_excluded.html', '/{base_c4x}/special_{prfx}_excluded.html', 1), - ('dev', 'special/{prfx}_not_excluded.htm', '//dev/{c4x}/special_{prfx}_not_excluded.htm', 1), - # Leading slash. - ('', '/{prfx}_ünlöck.png', '/{c4x}/{prfx}_ünlöck.png', 1), - ('', '/{prfx}_lock.png', '/{c4x}/{prfx}_lock.png', 1), - ('', '/weird {prfx}_ünlöck.png', '/{c4x}/weird_{prfx}_ünlöck.png', 1), - ('', '/{prfx}_excluded.html', '/{base_c4x}/{prfx}_excluded.html', 1), - ('', '/{prfx}_not_excluded.htm', '/{c4x}/{prfx}_not_excluded.htm', 1), - ('dev', '/{prfx}_ünlöck.png', '//dev/{c4x}/{prfx}_ünlöck.png', 1), - ('dev', '/{prfx}_lock.png', '/{c4x}/{prfx}_lock.png', 1), - ('dev', '/weird {prfx}_ünlöck.png', '//dev/{c4x}/weird_{prfx}_ünlöck.png', 1), - ('dev', '/{prfx}_excluded.html', '/{base_c4x}/{prfx}_excluded.html', 1), - ('dev', '/{prfx}_not_excluded.htm', '//dev/{c4x}/{prfx}_not_excluded.htm', 1), - # Leading slash with subdirectory. This ensures we properly substitute slashes. - ('', '/special/{prfx}_ünlöck.png', '/{c4x}/special_{prfx}_ünlöck.png', 1), - ('', '/special/{prfx}_lock.png', '/{c4x}/special_{prfx}_lock.png', 1), - ('', '/special/weird {prfx}_ünlöck.png', '/{c4x}/special_weird_{prfx}_ünlöck.png', 1), - ('', '/special/{prfx}_excluded.html', '/{base_c4x}/special_{prfx}_excluded.html', 1), - ('', '/special/{prfx}_not_excluded.htm', '/{c4x}/special_{prfx}_not_excluded.htm', 1), - ('dev', '/special/{prfx}_ünlöck.png', '//dev/{c4x}/special_{prfx}_ünlöck.png', 1), - ('dev', '/special/{prfx}_lock.png', '/{c4x}/special_{prfx}_lock.png', 1), - ('dev', '/special/weird {prfx}_ünlöck.png', '//dev/{c4x}/special_weird_{prfx}_ünlöck.png', 1), - ('dev', '/special/{prfx}_excluded.html', '/{base_c4x}/special_{prfx}_excluded.html', 1), - ('dev', '/special/{prfx}_not_excluded.htm', '//dev/{c4x}/special_{prfx}_not_excluded.htm', 1), - # Static path. - ('', '/static/{prfx}_ünlöck.png', '/{c4x}/{prfx}_ünlöck.png', 1), - ('', '/static/{prfx}_lock.png', '/{c4x}/{prfx}_lock.png', 1), - ('', '/static/weird {prfx}_ünlöck.png', '/{c4x}/weird_{prfx}_ünlöck.png', 1), - ('', '/static/{prfx}_excluded.html', '/{base_c4x}/{prfx}_excluded.html', 1), - ('', '/static/{prfx}_not_excluded.htm', '/{c4x}/{prfx}_not_excluded.htm', 1), - ('dev', '/static/{prfx}_ünlöck.png', '//dev/{c4x}/{prfx}_ünlöck.png', 1), - ('dev', '/static/{prfx}_lock.png', '/{c4x}/{prfx}_lock.png', 1), - ('dev', '/static/weird {prfx}_ünlöck.png', '//dev/{c4x}/weird_{prfx}_ünlöck.png', 1), - ('dev', '/static/{prfx}_excluded.html', '/{base_c4x}/{prfx}_excluded.html', 1), - ('dev', '/static/{prfx}_not_excluded.htm', '//dev/{c4x}/{prfx}_not_excluded.htm', 1), - # Static path with subdirectory. This ensures we properly substitute slashes. - ('', '/static/special/{prfx}_ünlöck.png', '/{c4x}/special_{prfx}_ünlöck.png', 1), - ('', '/static/special/{prfx}_lock.png', '/{c4x}/special_{prfx}_lock.png', 1), - ('', '/static/special/weird {prfx}_ünlöck.png', '/{c4x}/special_weird_{prfx}_ünlöck.png', 1), - ('', '/static/special/{prfx}_excluded.html', '/{base_c4x}/special_{prfx}_excluded.html', 1), - ('', '/static/special/{prfx}_not_excluded.htm', '/{c4x}/special_{prfx}_not_excluded.htm', 1), - ('dev', '/static/special/{prfx}_ünlöck.png', '//dev/{c4x}/special_{prfx}_ünlöck.png', 1), - ('dev', '/static/special/{prfx}_lock.png', '/{c4x}/special_{prfx}_lock.png', 1), - ('dev', '/static/special/weird {prfx}_ünlöck.png', '//dev/{c4x}/special_weird_{prfx}_ünlöck.png', 1), - ('dev', '/static/special/{prfx}_excluded.html', '/{base_c4x}/special_{prfx}_excluded.html', 1), - ('dev', '/static/special/{prfx}_not_excluded.htm', '//dev/{c4x}/special_{prfx}_not_excluded.htm', 1), - # Static path with query parameter. - ( - '', - '/static/{prfx}_ünlöck.png?foo=/static/{prfx}_lock.png', - '/{c4x}/{prfx}_ünlöck.png?foo={encoded_c4x}{prfx}_lock.png', - 2 - ), - ( - '', - '/static/{prfx}_lock.png?foo=/static/{prfx}_ünlöck.png', - '/{c4x}/{prfx}_lock.png?foo={encoded_c4x}{prfx}_ünlöck.png', - 2 - ), - ( - '', - '/static/{prfx}_excluded.html?foo=/static/{prfx}_excluded.html', - '/{base_c4x}/{prfx}_excluded.html?foo={encoded_base_c4x}{prfx}_excluded.html', - 2 - ), - ( - '', - '/static/{prfx}_excluded.html?foo=/static/{prfx}_not_excluded.htm', - '/{base_c4x}/{prfx}_excluded.html?foo={encoded_c4x}{prfx}_not_excluded.htm', - 2 - ), - ( - '', - '/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_excluded.html', - '/{c4x}/{prfx}_not_excluded.htm?foo={encoded_base_c4x}{prfx}_excluded.html', - 2 - ), - ( - '', - '/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_not_excluded.htm', - '/{c4x}/{prfx}_not_excluded.htm?foo={encoded_c4x}{prfx}_not_excluded.htm', - 2 - ), - ( - 'dev', - '/static/{prfx}_ünlöck.png?foo=/static/{prfx}_lock.png', - '//dev/{c4x}/{prfx}_ünlöck.png?foo={encoded_c4x}{prfx}_lock.png', - 2 - ), - ( - 'dev', - '/static/{prfx}_lock.png?foo=/static/{prfx}_ünlöck.png', - '/{c4x}/{prfx}_lock.png?foo={encoded_base_url}{encoded_c4x}{prfx}_ünlöck.png', - 2 - ), - ( - 'dev', - '/static/{prfx}_excluded.html?foo=/static/{prfx}_excluded.html', - '/{base_c4x}/{prfx}_excluded.html?foo={encoded_base_c4x}{prfx}_excluded.html', - 2 - ), - ( - 'dev', - '/static/{prfx}_excluded.html?foo=/static/{prfx}_not_excluded.htm', - '/{base_c4x}/{prfx}_excluded.html?foo={encoded_base_url}{encoded_c4x}{prfx}_not_excluded.htm', - 2 - ), - ( - 'dev', - '/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_excluded.html', - '//dev/{c4x}/{prfx}_not_excluded.htm?foo={encoded_base_c4x}{prfx}_excluded.html', - 2 - ), - ( - 'dev', - '/static/{prfx}_not_excluded.htm?foo=/static/{prfx}_not_excluded.htm', - '//dev/{c4x}/{prfx}_not_excluded.htm?foo={encoded_base_url}{encoded_c4x}{prfx}_not_excluded.htm', - 2 - ), - # Old, c4x-style path. - ('', '/{c4x}/{prfx}_ünlöck.png', '/{c4x}/{prfx}_ünlöck.png', 1), - ('', '/{c4x}/{prfx}_lock.png', '/{c4x}/{prfx}_lock.png', 1), - ('', '/{c4x}/weird_{prfx}_lock.png', '/{c4x}/weird_{prfx}_lock.png', 1), - ('', '/{c4x}/{prfx}_excluded.html', '/{base_c4x}/{prfx}_excluded.html', 1), - ('', '/{c4x}/{prfx}_not_excluded.htm', '/{c4x}/{prfx}_not_excluded.htm', 1), - ('dev', '/{c4x}/{prfx}_ünlöck.png', '//dev/{c4x}/{prfx}_ünlöck.png', 1), - ('dev', '/{c4x}/{prfx}_lock.png', '/{c4x}/{prfx}_lock.png', 1), - ('dev', '/{c4x}/weird_{prfx}_ünlöck.png', '//dev/{c4x}/weird_{prfx}_ünlöck.png', 1), - ('dev', '/{c4x}/{prfx}_excluded.html', '/{base_c4x}/{prfx}_excluded.html', 1), - ('dev', '/{c4x}/{prfx}_not_excluded.htm', '//dev/{c4x}/{prfx}_not_excluded.htm', 1), - ) - @ddt.unpack - def test_canonical_asset_path_with_c4x_style_assets(self, base_url, start, expected, mongo_calls): - exts = ['.html', '.tm'] - prefix = 'old' - base_c4x_block = 'c4x/a/b/asset' - adjusted_c4x_block = base_c4x_block - encoded_c4x_block = quote('/' + base_c4x_block + '/') - encoded_base_url = quote('//' + base_url) - encoded_base_c4x_block = encoded_c4x_block - - start = start.format( - prfx=prefix, - encoded_base_url=encoded_base_url, - c4x=base_c4x_block, - encoded_c4x=encoded_c4x_block - ) - - # Adjust for content digest. This gets dicey quickly and we have to order our steps: - # - replace format markets because they have curly braces - # - encode Unicode characters to percent-encoded - # - finally shove back in our regex patterns - digest = CanonicalContentTest.get_content_digest_for_asset_path(prefix, start) - if digest: - adjusted_c4x_block = 'assets/courseware/VMARK/HMARK/c4x/a/b/asset' - encoded_c4x_block = quote('/' + adjusted_c4x_block + '/') - - expected = expected.format( - prfx=prefix, - encoded_base_url=encoded_base_url, - base_c4x=base_c4x_block, - c4x=adjusted_c4x_block, - encoded_c4x=encoded_c4x_block, - encoded_base_c4x=encoded_base_c4x_block, - ) - - expected = encode_unicode_characters_in_url(expected) - expected = expected.replace('VMARK', r'v[\d]') - expected = expected.replace('HMARK', '[a-f0-9]{32}') - expected = expected.replace('+', r'\+').replace('?', r'\?') - - with check_mongo_calls(mongo_calls): - asset_path = StaticContent.get_canonicalized_asset_path(self.courses[prefix].id, start, base_url, exts) - assert re.match(expected, asset_path) is not None - class ReplaceURLServiceTest(TestCase): """ @@ -846,7 +650,6 @@ def test_replace_jump_to_id_urls_not_called(self): assert not self.mock_replace_jump_to_id_urls.called -@ddt.ddt class TestReplaceURLWrapper(SharedModuleStoreTestCase): """ Tests for replace_url_wrapper utility function. @@ -855,28 +658,19 @@ class TestReplaceURLWrapper(SharedModuleStoreTestCase): @classmethod def setUpClass(cls): super().setUpClass() - cls.course_mongo = CourseFactory.create( - default_store=ModuleStoreEnum.Type.mongo, - org='TestX', - number='TS01', - run='2015' - ) - cls.course_split = CourseFactory.create( - default_store=ModuleStoreEnum.Type.split, + cls.course = CourseFactory.create( org='TestX', number='TS02', run='2015' ) - @ddt.data('course_mongo', 'course_split') - def test_replace_jump_to_id_urls(self, course_id): + def test_replace_jump_to_id_urls(self): """ Verify that the jump-to URL has been replaced. """ - course = getattr(self, course_id) - replace_url_service = ReplaceURLService(course_id=course.id, jump_to_id_base_url='/base_url/') + replace_url_service = ReplaceURLService(course_id=self.course.id, jump_to_id_base_url='/base_url/') test_replace = replace_urls_wrapper( - block=course, + block=self.course, view='baseview', frag=Fragment(''), context=None, @@ -885,40 +679,28 @@ def test_replace_jump_to_id_urls(self, course_id): assert isinstance(test_replace, Fragment) assert test_replace.content == '' - @ddt.data( - ('course_mongo', ''), - ('course_split', '') - ) - @ddt.unpack - def test_replace_course_urls(self, course_id, anchor_tag): + def test_replace_course_urls(self): """ Verify that the course URL has been replaced. """ - course = getattr(self, course_id) - replace_url_service = ReplaceURLService(course_id=course.id) + replace_url_service = ReplaceURLService(course_id=self.course.id) test_replace = replace_urls_wrapper( - block=course, + block=self.course, view='baseview', frag=Fragment(''), context=None, replace_url_service=replace_url_service ) assert isinstance(test_replace, Fragment) - assert test_replace.content == anchor_tag + assert test_replace.content == '' - @ddt.data( - ('course_mongo', ''), - ('course_split', '') - ) - @ddt.unpack - def test_replace_static_urls(self, course_id, anchor_tag): + def test_replace_static_urls(self): """ Verify that the static URL has been replaced. """ - course = getattr(self, course_id) - replace_url_service = ReplaceURLService(course_id=course.id) + replace_url_service = ReplaceURLService(course_id=self.course.id) test_replace = replace_urls_wrapper( - block=course, + block=self.course, view='baseview', frag=Fragment(''), context=None, @@ -926,4 +708,4 @@ def test_replace_static_urls(self, course_id, anchor_tag): static_replace_only=True ) assert isinstance(test_replace, Fragment) - assert test_replace.content == anchor_tag + assert test_replace.content == '' diff --git a/common/djangoapps/student/tests/test_certificates.py b/common/djangoapps/student/tests/test_certificates.py index f935653e3460..6bfb57721b1a 100644 --- a/common/djangoapps/student/tests/test_certificates.py +++ b/common/djangoapps/student/tests/test_certificates.py @@ -11,7 +11,7 @@ from django.urls import reverse from pytz import UTC from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, SharedModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory from xmodule.data import CertificatesDisplayBehaviors @@ -32,7 +32,7 @@ class CertificateDisplayTestBase(SharedModuleStoreTestCase): """Tests display of certificates on the student dashboard. """ - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE USERNAME = "test_user" PASSWORD = "password" @@ -76,6 +76,7 @@ def _create_certificate(self, enrollment_mode): ) +@unittest.skip("OldMongo Deprecation") @ddt.ddt @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') class CertificateDashboardMessageDisplayTest(CertificateDisplayTestBase): diff --git a/common/djangoapps/student/tests/test_course_listing.py b/common/djangoapps/student/tests/test_course_listing.py index e93ec5f81747..5478a1c39aff 100644 --- a/common/djangoapps/student/tests/test_course_listing.py +++ b/common/djangoapps/student/tests/test_course_listing.py @@ -105,12 +105,13 @@ def test_errored_course_regular_access(self): """ Test the course list for regular staff when get_course returns an ErrorBlock """ - # pylint: disable=protected-access - mongo_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo) - course_key = mongo_store.make_course_key('Org1', 'Course1', 'Run1') - self._create_course_with_access_groups(course_key, default_store=ModuleStoreEnum.Type.mongo) + store = modulestore() + course_key = store.make_course_key('Org1', 'Course1', 'Run1') + self._create_course_with_access_groups(course_key) - with mock.patch('xmodule.modulestore.mongo.base.MongoKeyValueStore', mock.Mock(side_effect=Exception)): + with mock.patch( + 'xmodule.modulestore.split_mongo.caching_descriptor_system.SplitMongoKVS', mock.Mock(side_effect=Exception) + ): assert isinstance(modulestore().get_course(course_key), ErrorBlock) # Invalidate (e.g., delete) the corresponding CourseOverview, forcing get_course to be called. @@ -124,14 +125,14 @@ def test_course_listing_errored_deleted_courses(self): Create good courses, courses that won't load, and deleted courses which still have roles. Test course listing. """ - mongo_store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo) # lint-amnesty, pylint: disable=protected-access + store = modulestore() - good_location = mongo_store.make_course_key('testOrg', 'testCourse', 'RunBabyRun') - self._create_course_with_access_groups(good_location, default_store=ModuleStoreEnum.Type.mongo) + good_location = store.make_course_key('testOrg', 'testCourse', 'RunBabyRun') + self._create_course_with_access_groups(good_location) - course_location = mongo_store.make_course_key('testOrg', 'doomedCourse', 'RunBabyRun') - self._create_course_with_access_groups(course_location, default_store=ModuleStoreEnum.Type.mongo) - mongo_store.delete_course(course_location, ModuleStoreEnum.UserID.test) + course_location = store.make_course_key('testOrg', 'doomedCourse', 'RunBabyRun') + self._create_course_with_access_groups(course_location) + store.delete_course(course_location, ModuleStoreEnum.UserID.test) courses_list = list(get_course_enrollments(self.student, None, [])) assert len(courses_list) == 1, courses_list diff --git a/common/djangoapps/student/tests/test_views.py b/common/djangoapps/student/tests/test_views.py index 9d88752bf1a1..6786411e2c54 100644 --- a/common/djangoapps/student/tests/test_views.py +++ b/common/djangoapps/student/tests/test_views.py @@ -34,7 +34,6 @@ remove_prerequisite_course, set_prerequisite_courses ) -from common.djangoapps.util.testing import UrlResetMixin # lint-amnesty, pylint: disable=unused-import from lms.djangoapps.certificates.tests.factories import GeneratedCertificateFactory from lms.djangoapps.certificates.data import CertificateStatuses from lms.djangoapps.commerce.utils import EcommerceService @@ -45,7 +44,6 @@ from openedx.features.course_duration_limits.models import CourseDurationLimitConfig from openedx.features.course_experience.tests.views.helpers import add_course_mode from xmodule.data import CertificatesDisplayBehaviors # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory # lint-amnesty, pylint: disable=wrong-import-order @@ -288,16 +286,15 @@ def test_cert_available_message_after_course_end(self): *itertools.product( [True, False], [True, False], - [ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split], ) ) @ddt.unpack - def test_sharing_icons_for_future_course(self, set_marketing, set_social_sharing, modulestore_type): + def test_sharing_icons_for_future_course(self, set_marketing, set_social_sharing): """ Verify that the course sharing icons show up if course is starting in future and any of marketing or social sharing urls are set. """ - self.course = CourseFactory.create(start=TOMORROW, emit_signals=True, default_store=modulestore_type) # lint-amnesty, pylint: disable=attribute-defined-outside-init + self.course = CourseFactory.create(start=TOMORROW, emit_signals=True) # lint-amnesty, pylint: disable=attribute-defined-outside-init self.course_enrollment = CourseEnrollmentFactory(course_id=self.course.id, user=self.user) # lint-amnesty, pylint: disable=attribute-defined-outside-init self.set_course_sharing_urls(set_marketing, set_social_sharing) diff --git a/common/djangoapps/student/tests/tests.py b/common/djangoapps/student/tests/tests.py index f607821cf766..23f9101e5b52 100644 --- a/common/djangoapps/student/tests/tests.py +++ b/common/djangoapps/student/tests/tests.py @@ -50,7 +50,7 @@ from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from xmodule.modulestore.tests.django_utils import ModuleStoreEnum, ModuleStoreTestCase, SharedModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.factories import CourseFactory, check_mongo_calls # lint-amnesty, pylint: disable=wrong-import-order from xmodule.data import CertificatesDisplayBehaviors # lint-amnesty, pylint: disable=wrong-import-order @@ -472,8 +472,7 @@ def test_linked_in_add_to_profile_btn_with_certificate(self): ))) @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_dashboard_metadata_caching(self, modulestore_type): + def test_dashboard_metadata_caching(self): """ Check that the student dashboard makes use of course metadata caching. @@ -481,10 +480,6 @@ def test_dashboard_metadata_caching(self, modulestore_type): CourseOverview. The student dashboard should never have to make calls to the modulestore. - Arguments: - modulestore_type (ModuleStoreEnum.Type): Type of modulestore to create - test course in. - Note to future developers: If you break this test so that the "check_mongo_calls(0)" fails, please do NOT change it to "check_mongo_calls(n>=1)". Instead, change @@ -494,7 +489,7 @@ def test_dashboard_metadata_caching(self, modulestore_type): """ # Create a course and log in the user. # Creating a new course will trigger a publish event and the course will be cached - test_course = CourseFactory.create(default_store=modulestore_type, emit_signals=True) + test_course = CourseFactory.create(emit_signals=True) self.client.login(username="jack", password="test") with check_mongo_calls(0): diff --git a/lms/djangoapps/course_api/blocks/tests/test_api.py b/lms/djangoapps/course_api/blocks/tests/test_api.py index 8bf7b9d518ed..7f70267b0b0a 100644 --- a/lms/djangoapps/course_api/blocks/tests/test_api.py +++ b/lms/djangoapps/course_api/blocks/tests/test_api.py @@ -211,7 +211,7 @@ class TestGetBlocksQueryCounts(TestGetBlocksQueryCountsBase): @ddt.data( *product( - (ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split), + (ModuleStoreEnum.Type.split,), (True, False), ) ) @@ -226,8 +226,6 @@ def test_query_counts_cached(self, store_type, with_storage_backing): ) @ddt.data( - (ModuleStoreEnum.Type.mongo, 5, True, 24), - (ModuleStoreEnum.Type.mongo, 5, False, 14), (ModuleStoreEnum.Type.split, 2, True, 24), (ModuleStoreEnum.Type.split, 2, False, 14), ) diff --git a/lms/djangoapps/course_api/tests/test_serializers.py b/lms/djangoapps/course_api/tests/test_serializers.py index 7bba11d54055..7c3b59fdfecf 100644 --- a/lms/djangoapps/course_api/tests/test_serializers.py +++ b/lms/djangoapps/course_api/tests/test_serializers.py @@ -3,6 +3,7 @@ """ +from collections import OrderedDict from datetime import datetime from unittest import TestCase @@ -12,7 +13,7 @@ from rest_framework.test import APIRequestFactory from xblock.core import XBlock from xmodule.course_module import DEFAULT_START_DATE -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.factories import check_mongo_calls from openedx.core.djangoapps.content.course_overviews.models import CourseOverview @@ -31,7 +32,7 @@ class TestCourseSerializer(CourseApiFactoryMixin, ModuleStoreTestCase): maxDiff = 5000 # long enough to show mismatched dicts, in case of error serializer_class = CourseSerializer - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE ENABLED_SIGNALS = ['course_published'] def setUp(self): @@ -40,45 +41,47 @@ def setUp(self): self.honor_user = self.create_user('honor', is_staff=False) self.request_factory = APIRequestFactory() - course_id = 'edX/toy/2012_Fall' - banner_image_uri = '/c4x/edX/toy/asset/images_course_image.jpg' + course_id = 'course-v1:edX+toy+2012_Fall' + banner_image_uri = '/asset-v1:edX+toy+2012_Fall+type@asset+block@images_course_image.jpg' banner_image_absolute_uri = 'http://testserver' + banner_image_uri - image_path = '/c4x/edX/toy/asset/just_a_test.jpg' + image_path = '/asset-v1:edX+toy+2012_Fall+type@asset+block@just_a_test.jpg' image_url = 'http://testserver' + image_path self.expected_data = { 'id': course_id, 'name': 'Toy Course', 'number': 'toy', 'org': 'edX', - 'short_description': 'A course about toys.', - 'media': { - 'banner_image': { - 'uri': banner_image_uri, - 'uri_absolute': banner_image_absolute_uri, - }, - 'course_image': { - 'uri': image_path, - }, - 'course_video': { - 'uri': 'http://www.youtube.com/watch?v=test_youtube_id', - }, - 'image': { - 'raw': image_url, - 'small': image_url, - 'large': image_url, - }, - }, + 'short_description': None, + 'media': OrderedDict([ + ( + 'banner_image', + OrderedDict([ + ('uri', banner_image_uri), + ('uri_absolute', banner_image_absolute_uri) + ]) + ), + ('course_image', OrderedDict([('uri', image_path)])), + ('course_video', OrderedDict([('uri', None)])), + ( + 'image', + OrderedDict([ + ('raw', image_url), + ('small', image_url), + ('large', image_url) + ]) + )] + ), 'start': '2015-07-17T12:00:00Z', 'start_type': 'timestamp', 'start_display': 'July 17, 2015', 'end': '2015-09-19T18:00:00Z', 'enrollment_start': '2015-06-15T00:00:00Z', 'enrollment_end': '2015-07-15T00:00:00Z', - 'blocks_url': 'http://testserver/api/courses/v2/blocks/?course_id=edX%2Ftoy%2F2012_Fall', - 'effort': '6 hours', + 'blocks_url': 'http://testserver/api/courses/v2/blocks/?course_id=course-v1%3AedX%2Btoy%2B2012_Fall', + 'effort': None, 'pacing': 'instructor', 'mobile_available': True, - 'hidden': True, # because it's an old mongo course + 'hidden': False, 'invitation_only': False, # 'course_id' is a deprecated field, please use 'id' instead. @@ -125,14 +128,14 @@ def test_advertised_start(self): advertised_start='The Ides of March' ) result = self._get_result(course) - assert result['course_id'] == 'edX/custom/2012_Fall' + assert result['course_id'] == 'course-v1:edX+custom+2012_Fall' assert result['start_type'] == 'string' assert result['start_display'] == 'The Ides of March' def test_empty_start(self): course = self.create_course(start=DEFAULT_START_DATE, course='custom') result = self._get_result(course) - assert result['course_id'] == 'edX/custom/2012_Fall' + assert result['course_id'] == 'course-v1:edX+custom+2012_Fall' assert result['start_type'] == 'empty' assert result['start_display'] is None @@ -154,8 +157,8 @@ class TestCourseDetailSerializer(TestCourseSerializer): # lint-amnesty, pylint: CourseDetailSerializer serializer class. """ - # 1 mongo call is made to get the course About overview text. - expected_mongo_calls = 1 + # 2 mongo call is made to get the course About overview text. + expected_mongo_calls = 2 serializer_class = CourseDetailSerializer def setUp(self): diff --git a/lms/djangoapps/course_blocks/transformers/tests/test_load_override_data.py b/lms/djangoapps/course_blocks/transformers/tests/test_load_override_data.py index e522bc5b65d3..0dc844af2bd1 100644 --- a/lms/djangoapps/course_blocks/transformers/tests/test_load_override_data.py +++ b/lms/djangoapps/course_blocks/transformers/tests/test_load_override_data.py @@ -8,7 +8,7 @@ import ddt import pytz from xmodule.modulestore.django import modulestore -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.factories import ToyCourseFactory from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory @@ -32,7 +32,7 @@ class TestOverrideDataTransformer(ModuleStoreTestCase): """ Test proper behavior for OverrideDataTransformer """ - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE @classmethod def setUpClass(cls): @@ -52,9 +52,6 @@ def setUp(self): self.learner.id, subsection.location, 'html', 'new_component' ) CourseEnrollmentFactory.create(user=self.learner, course_id=self.course_key, is_active=True) - self.block = self.store.create_child( - self.learner2.id, subsection.location, 'html', 'new_component' - ) CourseEnrollmentFactory.create(user=self.learner2, course_id=self.course_key, is_active=True) @ddt.data(*REQUESTED_FIELDS) diff --git a/lms/djangoapps/course_wiki/tests/test_access.py b/lms/djangoapps/course_wiki/tests/test_access.py index 86c6e54b8a9b..daf51c7c0054 100644 --- a/lms/djangoapps/course_wiki/tests/test_access.py +++ b/lms/djangoapps/course_wiki/tests/test_access.py @@ -5,7 +5,7 @@ from django.contrib.auth.models import Group from wiki.models import URLPath -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory from common.djangoapps.student.tests.factories import InstructorFactory @@ -18,14 +18,14 @@ class TestWikiAccessBase(ModuleStoreTestCase): """Base class for testing wiki access.""" - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE def setUp(self): super().setUp() self.wiki = get_or_create_root() - self.course_math101 = CourseFactory.create(org='org', number='math101', display_name='Course', metadata={'use_unique_wiki_id': 'false'}) # lint-amnesty, pylint: disable=line-too-long + self.course_math101 = CourseFactory.create(org='org', number='math101', display_name='Course') # lint-amnesty, pylint: disable=line-too-long self.course_math101_staff = self.create_staff_for_course(self.course_math101) wiki_math101 = self.create_urlpath(self.wiki, course_wiki_slug(self.course_math101)) @@ -33,7 +33,7 @@ def setUp(self): wiki_math101_page_page = self.create_urlpath(wiki_math101_page, 'Grandchild') self.wiki_math101_pages = [wiki_math101, wiki_math101_page, wiki_math101_page_page] - self.course_math101b = CourseFactory.create(org='org', number='math101b', display_name='Course', metadata={'use_unique_wiki_id': 'true'}) # lint-amnesty, pylint: disable=line-too-long + self.course_math101b = CourseFactory.create(org='org', number='math101b', display_name='Course') # lint-amnesty, pylint: disable=line-too-long self.course_math101b_staff = self.create_staff_for_course(self.course_math101b) wiki_math101b = self.create_urlpath(self.wiki, course_wiki_slug(self.course_math101b)) diff --git a/lms/djangoapps/course_wiki/tests/test_middleware.py b/lms/djangoapps/course_wiki/tests/test_middleware.py index 16937cc77289..7836f4d4fbf2 100644 --- a/lms/djangoapps/course_wiki/tests/test_middleware.py +++ b/lms/djangoapps/course_wiki/tests/test_middleware.py @@ -5,7 +5,7 @@ from django.test.client import Client from wiki.models import URLPath -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory from common.djangoapps.student.tests.factories import InstructorFactory @@ -14,7 +14,7 @@ class TestWikiAccessMiddleware(ModuleStoreTestCase): """Tests for WikiAccessMiddleware.""" - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE def setUp(self): """Test setup.""" @@ -22,7 +22,7 @@ def setUp(self): self.wiki = get_or_create_root() - self.course_math101 = CourseFactory.create(org='edx', number='math101', display_name='2014', metadata={'use_unique_wiki_id': 'false'}) # lint-amnesty, pylint: disable=line-too-long + self.course_math101 = CourseFactory.create(org='edx', number='math101', display_name='2014') # lint-amnesty, pylint: disable=line-too-long self.course_math101_instructor = InstructorFactory(course_key=self.course_math101.id, username='instructor', password='secret') # lint-amnesty, pylint: disable=line-too-long self.wiki_math101 = URLPath.create_article(self.wiki, 'math101', title='math101') @@ -31,6 +31,6 @@ def setUp(self): def test_url_tranform(self): """Test that the correct prefix ('/courses/') is added to the urls in the wiki.""" - response = self.client.get('/courses/edx/math101/2014/wiki/math101/') - self.assertContains(response, '/courses/edx/math101/2014/wiki/math101/_edit/') - self.assertContains(response, '/courses/edx/math101/2014/wiki/math101/_settings/') + response = self.client.get('/courses/course-v1:edx+math101+2014/wiki/math101/') + self.assertContains(response, '/courses/course-v1:edx+math101+2014/wiki/math101/_edit/') + self.assertContains(response, '/courses/course-v1:edx+math101+2014/wiki/math101/_settings/') diff --git a/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py b/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py index 230dbbc7b523..075703bab967 100644 --- a/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py +++ b/lms/djangoapps/courseware/management/commands/tests/test_dump_course.py @@ -14,7 +14,6 @@ from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import ( - TEST_DATA_MONGO_MODULESTORE, TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase ) @@ -223,15 +222,6 @@ def check_export_file(self, tar_file): # pylint: disable=missing-function-docst assert_in('edX-simple-2012_Fall/sequential/Lecture_2.xml', names) -class CommandsMongoTestCase(CommandsTestBase): - """ - Test case for management commands using the mixed mongo modulestore with old mongo as the default. - - """ - MODULESTORE = TEST_DATA_MONGO_MODULESTORE - __test__ = True - - class CommandSplitMongoTestCase(CommandsTestBase): """ Test case for management commands using the mixed mongo modulestore with split as the default. diff --git a/lms/djangoapps/courseware/tests/helpers.py b/lms/djangoapps/courseware/tests/helpers.py index b362ece11f1b..c463163329ef 100644 --- a/lms/djangoapps/courseware/tests/helpers.py +++ b/lms/djangoapps/courseware/tests/helpers.py @@ -31,7 +31,7 @@ from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory from common.djangoapps.util.date_utils import strftime_localized_html from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_MODULESTORE, ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory # lint-amnesty, pylint: disable=wrong-import-order from xmodule.tests import get_test_descriptor_system, get_test_system # lint-amnesty, pylint: disable=wrong-import-order @@ -52,10 +52,9 @@ class BaseTestXmodule(ModuleStoreTestCase): This class should not contain any tests, because CATEGORY should be defined in child class. """ - MODULESTORE = TEST_DATA_MONGO_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE USER_COUNT = 2 - COURSE_DATA = {} # Data from YAML xmodule/templates/NAME/default.yaml CATEGORY = "vertical" @@ -99,7 +98,7 @@ def initialize_module(self, runtime_kwargs=None, **kwargs): # lint-amnesty, pyl self.item_url = str(self.item_descriptor.location) def setup_course(self): # lint-amnesty, pylint: disable=missing-function-docstring - self.course = CourseFactory.create(data=self.COURSE_DATA) + self.course = CourseFactory.create() # Turn off cache. modulestore().request_cache = None diff --git a/lms/djangoapps/courseware/tests/test_courses.py b/lms/djangoapps/courseware/tests/test_courses.py index 7dd231b1eb1c..561d355628bd 100644 --- a/lms/djangoapps/courseware/tests/test_courses.py +++ b/lms/djangoapps/courseware/tests/test_courses.py @@ -20,9 +20,8 @@ from opaque_keys.edx.keys import CourseKey from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import _get_modulestore_branch_setting, modulestore -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase -from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls -from xmodule.modulestore.xml_importer import import_course_from_xml +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase +from xmodule.modulestore.tests.factories import CourseFactory, ToyCourseFactory, ItemFactory, check_mongo_calls from xmodule.tests.xml import XModuleXmlImportTest from xmodule.tests.xml import factories as xml @@ -39,13 +38,11 @@ get_courses, get_current_child ) -from lms.djangoapps.courseware.exceptions import CourseAccessRedirect from lms.djangoapps.courseware.model_data import FieldDataCache from lms.djangoapps.courseware.module_render import get_module_for_descriptor from lms.djangoapps.courseware.courseware_access_exception import CoursewareAccessException from openedx.core.djangolib.testing.utils import get_mock_request from openedx.core.lib.courses import course_image_url -from openedx.core.lib.courses import get_course_by_id from common.djangoapps.student.tests.factories import UserFactory CMS_BASE_TEST = 'testcms' @@ -89,18 +86,6 @@ def test_get_course_func_with_access_error(self, course_access_func_name): assert error.value.access_response.error_code == 'not_visible_to_user' assert not error.value.access_response.has_access - @ddt.data(GET_COURSE_WITH_ACCESS, GET_COURSE_OVERVIEW_WITH_ACCESS) - def test_old_mongo_access_error(self, course_access_func_name): - course_access_func = self.COURSE_ACCESS_FUNCS[course_access_func_name] - user = UserFactory.create() - with self.store.default_store(ModuleStoreEnum.Type.mongo): - course = CourseFactory.create() - - with pytest.raises(CourseAccessRedirect) as error: - course_access_func(user, 'load', course.id) - assert error.value.access_error.error_code == 'old_mongo' - assert not error.value.access_error.has_access - @ddt.data( (GET_COURSE_WITH_ACCESS, 2), (GET_COURSE_OVERVIEW_WITH_ACCESS, 0), @@ -281,7 +266,7 @@ def test_spaces_in_image_name(self): class CoursesRenderTest(ModuleStoreTestCase): """Test methods related to rendering courses content.""" - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE # TODO: this test relies on the specific setup of the toy course. # It should be rewritten to build the course it needs and then test that. @@ -291,17 +276,15 @@ def setUp(self): """ super().setUp() - store = modulestore() - course_items = import_course_from_xml(store, self.user.id, TEST_DATA_DIR, ['toy']) - course_key = course_items[0].id - self.course = get_course_by_id(course_key) + self.course = ToyCourseFactory() self.addCleanup(set_current_request, None) self.request = get_mock_request(UserFactory.create()) def test_get_course_info_section_render(self): # Test render works okay course_info = get_course_info_section(self.request, self.request.user, self.course, 'handouts') - assert course_info == "Sample" + assert course_info == \ + "Sample" # Test when render raises an exception with mock.patch('lms.djangoapps.courseware.courses.get_module') as mock_module_render: diff --git a/lms/djangoapps/courseware/tests/test_discussion_xblock.py b/lms/djangoapps/courseware/tests/test_discussion_xblock.py index e5ee524ec8a7..09d3b1cf1599 100644 --- a/lms/djangoapps/courseware/tests/test_discussion_xblock.py +++ b/lms/djangoapps/courseware/tests/test_discussion_xblock.py @@ -17,8 +17,7 @@ from web_fragments.fragment import Fragment from xblock.field_data import DictFieldData from xmodule.discussion_block import DiscussionXBlock, loader -from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, SharedModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import ItemFactory, ToyCourseFactory from lms.djangoapps.course_api.blocks.tests.helpers import deserialize_usage_key @@ -261,7 +260,7 @@ class TestXBlockInCourse(SharedModuleStoreTestCase): """ Test the discussion xblock as rendered in the course and course API. """ - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE @classmethod def setUpClass(cls): @@ -309,52 +308,50 @@ def test_html_with_user(self): assert 'data-user-create-comment="false"' in html assert 'data-user-create-subcomment="false"' in html - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) - def test_discussion_render_successfully_with_orphan_parent(self, default_store): + def test_discussion_render_successfully_with_orphan_parent(self): """ Test that discussion xblock render successfully if discussion xblock is child of an orphan. """ - with self.store.default_store(default_store): - orphan_sequential = self.store.create_item(self.user.id, self.course.id, 'sequential') + orphan_sequential = self.store.create_item(self.user.id, self.course.id, 'sequential') - vertical = self.store.create_child( - self.user.id, - orphan_sequential.location, - 'vertical', - block_id=self.course.location.block_id - ) + vertical = self.store.create_child( + self.user.id, + orphan_sequential.location, + 'vertical', + block_id=self.course.location.block_id + ) - discussion = self.store.create_child( - self.user.id, - vertical.location, - 'discussion', - block_id=self.course.location.block_id - ) + discussion = self.store.create_child( + self.user.id, + vertical.location, + 'discussion', + block_id=self.course.location.block_id + ) - discussion = self.store.get_item(discussion.location) + discussion = self.store.get_item(discussion.location) - root = self.get_root(discussion) - # Assert that orphan sequential is root of the discussion xblock. - assert orphan_sequential.location.block_type == root.location.block_type - assert orphan_sequential.location.block_id == root.location.block_id + root = self.get_root(discussion) + # Assert that orphan sequential is root of the discussion xblock. + assert orphan_sequential.location.block_type == root.location.block_type + assert orphan_sequential.location.block_id == root.location.block_id - # Get xblock bound to a user and a descriptor. - discussion_xblock = get_module_for_descriptor_internal( - user=self.user, - descriptor=discussion, - student_data=mock.Mock(name='student_data'), - course_id=self.course.id, - track_function=mock.Mock(name='track_function'), - request_token='request_token', - ) + # Get xblock bound to a user and a descriptor. + discussion_xblock = get_module_for_descriptor_internal( + user=self.user, + descriptor=discussion, + student_data=mock.Mock(name='student_data'), + course_id=self.course.id, + track_function=mock.Mock(name='track_function'), + request_token='request_token', + ) - fragment = discussion_xblock.render('student_view') - html = fragment.content + fragment = discussion_xblock.render('student_view') + html = fragment.content - assert isinstance(discussion_xblock, DiscussionXBlock) - assert 'data-user-create-comment="false"' in html - assert 'data-user-create-subcomment="false"' in html + assert isinstance(discussion_xblock, DiscussionXBlock) + assert 'data-user-create-comment="false"' in html + assert 'data-user-create-subcomment="false"' in html def test_discussion_student_view_data(self): """ diff --git a/lms/djangoapps/courseware/tests/test_group_access.py b/lms/djangoapps/courseware/tests/test_group_access.py index 6d42caf09077..278f28bc7e0e 100644 --- a/lms/djangoapps/courseware/tests/test_group_access.py +++ b/lms/djangoapps/courseware/tests/test_group_access.py @@ -7,7 +7,7 @@ import ddt from stevedore.extension import Extension, ExtensionManager from xmodule.modulestore.django import modulestore -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.partitions.partitions import USER_PARTITION_SCHEME_NAMESPACE, Group, UserPartition @@ -57,7 +57,7 @@ class GroupAccessTestCase(ModuleStoreTestCase): Tests to ensure that has_access() correctly enforces the visibility restrictions specified in the `group_access` field of XBlocks. """ - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE def set_user_group(self, user, partition, group): """ diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 15b33844790d..cf1bb5131d7f 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -48,7 +48,7 @@ from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import ( - TEST_DATA_MONGO_AMNESTY_MODULESTORE, + TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase, SharedModuleStoreTestCase, upload_file_to_course, @@ -1562,7 +1562,7 @@ def test_course_image(self): self.course.static_asset_path = "" @override_settings(DEFAULT_COURSE_ABOUT_IMAGE_URL='test.png') - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) + @ddt.data(ModuleStoreEnum.Type.split) def test_course_image_for_split_course(self, store): """ for split courses if course_image is empty then course_image_url will be @@ -1658,7 +1658,7 @@ def student_view(self, context=None): # pylint: disable=unused-argument @patch('lms.djangoapps.courseware.module_render.has_access', Mock(return_value=True, autospec=True)) class TestStaffDebugInfo(SharedModuleStoreTestCase): """Tests to verify that Staff Debug Info panel and histograms are displayed to staff.""" - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE @classmethod def setUpClass(cls): @@ -2436,13 +2436,13 @@ def setUp(self): super().setUp() XBlockConfiguration(name='video', enabled=False).save() - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) + @ddt.data(ModuleStoreEnum.Type.split) def test_get_item(self, default_ms): with self.store.default_store(default_ms): course = CourseFactory() self._verify_descriptor('video', course, 'HiddenDescriptorWithMixins') - @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split) + @ddt.data(ModuleStoreEnum.Type.split) def test_dynamic_updates(self, default_ms): """Tests that the list of disabled xblocks can dynamically update.""" with self.store.default_store(default_ms): @@ -2478,8 +2478,8 @@ class LmsModuleSystemShimTest(SharedModuleStoreTestCase): """ Tests that the deprecated attributes in the LMS Module System (XBlock Runtime) return the expected values. """ - MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE - COURSE_ID = 'edX/LmsModuleShimTest/2021_Fall' + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE + COURSE_ID = 'course-v1:edX+LmsModuleShimTest+2021_Fall' PYTHON_LIB_FILENAME = 'test_python_lib.zip' PYTHON_LIB_SOURCE_FILE = './common/test/data/uploads/python_lib.zip' @@ -2489,7 +2489,9 @@ def setUpClass(cls): Set up the course and descriptor used to instantiate the runtime. """ super().setUpClass() - org, number, run = cls.COURSE_ID.split('/') + org = 'edX' + number = 'LmsModuleShimTest' + run = '2021_Fall' cls.course = CourseFactory.create(org=org, number=number, run=run) cls.descriptor = ItemFactory(category="vertical", parent=cls.course) cls.problem_descriptor = ItemFactory(category="problem", parent=cls.course) @@ -2633,8 +2635,7 @@ def test_xqueue(self): assert xqueue['interface'].url == 'http://sandbox-xqueue.edx.org' assert xqueue['default_queuename'] == 'edX-LmsModuleShimTest' assert xqueue['waittime'] == 5 - callback_url = ('http://localhost:8000/courses/edX/LmsModuleShimTest/2021_Fall/xqueue/232/' - + str(self.descriptor.location)) + callback_url = f'http://localhost:8000/courses/{self.course.id}/xqueue/232/{self.descriptor.location}' assert xqueue['construct_callback']() == f'{callback_url}/score_update' assert xqueue['construct_callback']('mock_dispatch') == f'{callback_url}/mock_dispatch' @@ -2665,15 +2666,15 @@ def test_xqueue_settings(self): assert xqueue['interface'].url == 'http://xqueue.url' assert xqueue['default_queuename'] == 'edX-LmsModuleShimTest' assert xqueue['waittime'] == 15 - callback_url = f'http://alt.url/courses/edX/LmsModuleShimTest/2021_Fall/xqueue/232/{self.descriptor.location}' + callback_url = f'http://alt.url/courses/{self.course.id}/xqueue/232/{self.descriptor.location}' assert xqueue['construct_callback']() == f'{callback_url}/score_update' assert xqueue['construct_callback']('mock_dispatch') == f'{callback_url}/mock_dispatch' - @override_settings(COURSES_WITH_UNSAFE_CODE=[COURSE_ID]) + @override_settings(COURSES_WITH_UNSAFE_CODE=[r'course-v1:edX\+LmsModuleShimTest\+2021_Fall']) def test_can_execute_unsafe_code_when_allowed(self): assert self.runtime.can_execute_unsafe_code() - @override_settings(COURSES_WITH_UNSAFE_CODE=['edX/full/2012_Fall']) + @override_settings(COURSES_WITH_UNSAFE_CODE=[r'course-v1:edX\+full\+2021_Fall']) def test_cannot_execute_unsafe_code_when_disallowed(self): assert not self.runtime.can_execute_unsafe_code() diff --git a/lms/djangoapps/courseware/tests/test_tabs.py b/lms/djangoapps/courseware/tests/test_tabs.py index 42687d441275..35d3296bda61 100644 --- a/lms/djangoapps/courseware/tests/test_tabs.py +++ b/lms/djangoapps/courseware/tests/test_tabs.py @@ -38,7 +38,7 @@ ) from xmodule import tabs as xmodule_tabs # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.django_utils import ( # lint-amnesty, pylint: disable=wrong-import-order - TEST_DATA_MIXED_MODULESTORE, + TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase, SharedModuleStoreTestCase ) @@ -435,7 +435,7 @@ class TextBookCourseViewsTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest """ Validate tab behavior when dealing with textbooks. """ - MODULESTORE = TEST_DATA_MIXED_MODULESTORE + MODULESTORE = TEST_DATA_SPLIT_MODULESTORE @classmethod def setUpClass(cls): diff --git a/lms/djangoapps/courseware/tests/test_video_handlers.py b/lms/djangoapps/courseware/tests/test_video_handlers.py index 91ad34d0b504..3aaeba0c4a8c 100644 --- a/lms/djangoapps/courseware/tests/test_video_handlers.py +++ b/lms/djangoapps/courseware/tests/test_video_handlers.py @@ -143,6 +143,7 @@ def initialize_block(self, data=None, **kwargs): # a lot of tests code, parse and set the values as fields. fields_data = VideoBlock.parse_video_xml(data) kwargs.update(fields_data) + kwargs.pop('source', None) super().initialize_module(**kwargs) def setUp(self): diff --git a/lms/djangoapps/courseware/tests/test_video_mongo.py b/lms/djangoapps/courseware/tests/test_video_mongo.py index c84bf675b794..34255fd722d5 100644 --- a/lms/djangoapps/courseware/tests/test_video_mongo.py +++ b/lms/djangoapps/courseware/tests/test_video_mongo.py @@ -36,9 +36,8 @@ from path import Path as path from xmodule.contentstore.content import StaticContent from xmodule.exceptions import NotFoundError -from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.inheritance import own_metadata -from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_MODULESTORE, TEST_DATA_SPLIT_MODULESTORE +from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE from xmodule.tests.test_import import DummySystem from xmodule.tests.test_video import VideoBlockTestBase from xmodule.video_module import VideoBlock, bumper_utils, video_utils @@ -55,10 +54,6 @@ from .test_video_handlers import BaseTestVideoXBlock, TestVideo from .test_video_xml import SOURCE_XML -MODULESTORES = { - ModuleStoreEnum.Type.mongo: TEST_DATA_MONGO_MODULESTORE, - ModuleStoreEnum.Type.split: TEST_DATA_SPLIT_MODULESTORE, -} TRANSCRIPT_FILE_SRT_DATA = """ 1 @@ -281,7 +276,7 @@ def test_get_html_track(self): # lint-amnesty, pylint: disable=redefined-outer-name SOURCE_XML = """