test: prepare tests for removing support for children in Old Mongo
This commit is contained in:
committed by
David Ormsbee
parent
f6870f7ae7
commit
8f88422c4a
@@ -6,7 +6,6 @@ from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
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,40 @@ class BackfillCourseOutlinesTest(SharedModuleStoreTestCase):
|
||||
"""
|
||||
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 +83,8 @@ class BackfillCourseOutlinesTest(SharedModuleStoreTestCase):
|
||||
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 +94,16 @@ class BackfillCourseOutlinesTest(SharedModuleStoreTestCase):
|
||||
|
||||
# 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"),
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"""Tests running the delete_orphan command"""
|
||||
|
||||
|
||||
import ddt
|
||||
from django.core.management import CommandError, call_command
|
||||
|
||||
from cms.djangoapps.contentstore.tests.test_orphan import TestOrphanBase
|
||||
@@ -9,7 +8,6 @@ from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable
|
||||
from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestDeleteOrphan(TestOrphanBase):
|
||||
"""
|
||||
Tests for running the delete_orphan management command.
|
||||
@@ -23,26 +21,24 @@ class TestDeleteOrphan(TestOrphanBase):
|
||||
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')
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import shutil
|
||||
import unittest
|
||||
from tempfile import mkdtemp
|
||||
|
||||
import ddt
|
||||
from django.core.management import CommandError, call_command
|
||||
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
@@ -29,7 +28,6 @@ class TestArgParsingCourseExport(unittest.TestCase):
|
||||
call_command('export')
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestCourseExport(ModuleStoreTestCase):
|
||||
"""
|
||||
Test exporting a course
|
||||
@@ -45,16 +43,15 @@ class TestCourseExport(ModuleStoreTestCase):
|
||||
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(default_store=ModuleStoreEnum.Type.split)
|
||||
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'."
|
||||
|
||||
@@ -9,7 +9,6 @@ import unittest
|
||||
from io import StringIO
|
||||
from tempfile import mkdtemp
|
||||
|
||||
import ddt
|
||||
from django.core.management import CommandError, call_command
|
||||
from path import Path as path
|
||||
|
||||
@@ -32,7 +31,6 @@ class TestArgParsingCourseExportOlx(unittest.TestCase):
|
||||
call_command('export_olx')
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestCourseExportOlx(ModuleStoreTestCase):
|
||||
"""
|
||||
Test exporting OLX content from a course or library.
|
||||
@@ -74,9 +72,8 @@ class TestCourseExportOlx(ModuleStoreTestCase):
|
||||
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 +88,8 @@ class TestCourseExportOlx(ModuleStoreTestCase):
|
||||
# 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)
|
||||
def test_export_course_stdout(self):
|
||||
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)
|
||||
|
||||
@@ -17,8 +17,6 @@ from organizations.api import add_organization, get_course_organizations, get_or
|
||||
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 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
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 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
"""
|
||||
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 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
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 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
'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 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
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 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
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 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
# 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)
|
||||
|
||||
@@ -162,12 +162,7 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
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 +172,10 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
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,15 +186,14 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
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)
|
||||
def test_get_course_list_with_invalid_course_location(self, store):
|
||||
def test_get_course_list_with_invalid_course_location(self):
|
||||
"""
|
||||
Test getting courses with invalid course location (course deleted from modulestore).
|
||||
"""
|
||||
with self.store.default_store(store):
|
||||
with self.store.default_store(ModuleStoreEnum.Type.split):
|
||||
course_key = self.store.make_course_key('Org', 'Course', 'Run')
|
||||
course = self._create_course_with_access_groups(course_key, self.user)
|
||||
|
||||
@@ -246,12 +239,7 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
[0, 0, 0]
|
||||
)
|
||||
|
||||
@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):
|
||||
def test_course_listing_performance(self):
|
||||
"""
|
||||
Create large number of courses and give access of some of these courses to the user and
|
||||
compare the time to fetch accessible courses for the user through traversing all courses and
|
||||
@@ -261,16 +249,15 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
user_course_ids = random.sample(list(range(TOTAL_COURSES_COUNT)), USER_COURSES_COUNT)
|
||||
|
||||
# create courses and assign those to the user which have their number in user_course_ids
|
||||
with self.store.default_store(store):
|
||||
for number in range(TOTAL_COURSES_COUNT):
|
||||
org = f'Org{number}'
|
||||
course = f'Course{number}'
|
||||
run = f'Run{number}'
|
||||
course_location = self.store.make_course_key(org, course, run)
|
||||
if number in user_course_ids:
|
||||
self._create_course_with_access_groups(course_location, self.user)
|
||||
else:
|
||||
self._create_course_with_access_groups(course_location)
|
||||
for number in range(TOTAL_COURSES_COUNT):
|
||||
org = f'Org{number}'
|
||||
course = f'Course{number}'
|
||||
run = f'Run{number}'
|
||||
course_location = self.store.make_course_key(org, course, run)
|
||||
if number in user_course_ids:
|
||||
self._create_course_with_access_groups(course_location, self.user)
|
||||
else:
|
||||
self._create_course_with_access_groups(course_location)
|
||||
|
||||
# get courses by iterating through all courses
|
||||
courses_iter, __ = _accessible_courses_iter_for_tests(self.request)
|
||||
@@ -288,10 +275,10 @@ class TestCourseListing(ModuleStoreTestCase):
|
||||
courses_list, __ = _accessible_courses_list_from_groups(self.request)
|
||||
self.assertEqual(len(courses_list), USER_COURSES_COUNT)
|
||||
|
||||
with self.assertNumQueries(courses_list_from_group_calls, table_ignorelist=WAFFLE_TABLES):
|
||||
with self.assertNumQueries(1, table_ignorelist=WAFFLE_TABLES):
|
||||
_accessible_courses_list_from_groups(self.request)
|
||||
|
||||
with self.assertNumQueries(courses_list_calls, table_ignorelist=WAFFLE_TABLES):
|
||||
with self.assertNumQueries(2, table_ignorelist=WAFFLE_TABLES):
|
||||
_accessible_courses_iter_for_tests(self.request)
|
||||
|
||||
def test_course_listing_errored_deleted_courses(self):
|
||||
|
||||
@@ -32,7 +32,6 @@ from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable
|
||||
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,
|
||||
TEST_DATA_SPLIT_MODULESTORE,
|
||||
SharedModuleStoreTestCase,
|
||||
)
|
||||
@@ -130,7 +129,6 @@ class MixedWithOptionsTestCase(ModuleStoreTestCase):
|
||||
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):
|
||||
@@ -142,6 +140,8 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase):
|
||||
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.
|
||||
@@ -464,58 +464,45 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase):
|
||||
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')
|
||||
@@ -523,8 +510,6 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase):
|
||||
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.
|
||||
@@ -541,6 +526,7 @@ class TestLargeCourseDeletions(MixedWithOptionsTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.course_id = None
|
||||
self.setup_course_base(self.store)
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
@@ -595,9 +581,8 @@ class TestLargeCourseDeletions(MixedWithOptionsTestCase):
|
||||
|
||||
@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):
|
||||
@@ -1360,10 +1345,3 @@ class GroupConfigurationSearchSplit(CourseTestCase, MixedWithOptionsTestCase):
|
||||
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
|
||||
|
||||
@@ -8,9 +8,11 @@ from unittest import mock, skip
|
||||
|
||||
from django.utils import translation
|
||||
from django.utils.translation import get_language
|
||||
from xblock.core import XBlock
|
||||
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 xmodule.tests.test_export import PureXBlock
|
||||
|
||||
from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient
|
||||
from cms.djangoapps.contentstore.views.preview import _preview_module_system
|
||||
@@ -57,8 +59,9 @@ class FakeTranslations(ModuleI18nService):
|
||||
|
||||
class TestModuleI18nService(ModuleStoreTestCase):
|
||||
""" Test ModuleI18nService """
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
@XBlock.register_temp_plugin(PureXBlock, 'pure')
|
||||
def setUp(self):
|
||||
""" Setting up tests """
|
||||
super().setUp()
|
||||
|
||||
@@ -5,7 +5,6 @@ Test finding orphans via the view and django config
|
||||
|
||||
import json
|
||||
|
||||
import ddt
|
||||
from opaque_keys.edx.locator import BlockUsageLocator
|
||||
|
||||
from cms.djangoapps.contentstore.tests.utils import CourseTestCase
|
||||
@@ -74,18 +73,16 @@ class TestOrphanBase(CourseTestCase):
|
||||
self.assertEqual(len(self.store.get_orphans(course_key)), number)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
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(
|
||||
@@ -102,19 +99,14 @@ class TestOrphan(TestOrphanBase):
|
||||
location = course.location.replace(category='html', name='OrphanHtml')
|
||||
self.assertIn(str(location), orphans)
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.split, 5, 3),
|
||||
(ModuleStoreEnum.Type.mongo, 34, 11),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_delete_orphans(self, default_store, max_mongo_calls, min_mongo_calls):
|
||||
def test_delete_orphans(self):
|
||||
"""
|
||||
Test that the orphan handler deletes 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)
|
||||
|
||||
with check_mongo_calls_range(max_mongo_calls, min_mongo_calls):
|
||||
with check_mongo_calls_range(5, 3):
|
||||
self.client.delete(orphan_url)
|
||||
|
||||
orphans = json.loads(
|
||||
@@ -126,12 +118,11 @@ class TestOrphan(TestOrphanBase):
|
||||
# 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()
|
||||
@@ -141,8 +132,7 @@ class TestOrphan(TestOrphanBase):
|
||||
response = test_user_client.delete(orphan_url)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.split)
|
||||
def test_path_to_location_for_orphan_vertical(self, module_store):
|
||||
def test_path_to_location_for_orphan_vertical(self):
|
||||
r"""
|
||||
Make sure that path_to_location works with a component having multiple vertical parents,
|
||||
from which one of them is orphan.
|
||||
@@ -156,7 +146,7 @@ class TestOrphan(TestOrphanBase):
|
||||
html
|
||||
"""
|
||||
# Get a course with orphan modules
|
||||
course = self.create_course_with_orphans(module_store)
|
||||
course = self.create_course_with_orphans(ModuleStoreEnum.Type.split)
|
||||
|
||||
# Fetch the required course components.
|
||||
vertical1 = self.store.get_item(BlockUsageLocator(course.id, 'vertical', 'Vertical1'))
|
||||
@@ -190,8 +180,7 @@ class TestOrphan(TestOrphanBase):
|
||||
self.assertEqual(len(path), 6)
|
||||
self.assertEqual(path, expected_path)
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.split)
|
||||
def test_path_to_location_for_orphan_chapter(self, module_store):
|
||||
def test_path_to_location_for_orphan_chapter(self):
|
||||
r"""
|
||||
Make sure that path_to_location works with a component having multiple chapter parents,
|
||||
from which one of them is orphan
|
||||
@@ -206,7 +195,7 @@ class TestOrphan(TestOrphanBase):
|
||||
|
||||
"""
|
||||
# Get a course with orphan modules
|
||||
course = self.create_course_with_orphans(module_store)
|
||||
course = self.create_course_with_orphans(ModuleStoreEnum.Type.split)
|
||||
orphan_chapter = self.store.get_item(BlockUsageLocator(course.id, 'chapter', 'OrphanChapter'))
|
||||
chapter1 = self.store.get_item(BlockUsageLocator(course.id, 'chapter', 'Chapter1'))
|
||||
vertical1 = self.store.get_item(BlockUsageLocator(course.id, 'vertical', 'Vertical1'))
|
||||
|
||||
@@ -12,7 +12,6 @@ from django.urls import reverse
|
||||
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 @@ class TestForcePublish(MaintenanceViewTestCase):
|
||||
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 @@ class TestForcePublish(MaintenanceViewTestCase):
|
||||
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.
|
||||
|
||||
@@ -268,7 +268,7 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
|
||||
|
||||
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 @@ class CanonicalContentTest(SharedModuleStoreTestCase):
|
||||
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):
|
||||
"""
|
||||
@@ -855,28 +659,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('<a href="/jump_to_id/id">'),
|
||||
context=None,
|
||||
@@ -885,40 +680,28 @@ class TestReplaceURLWrapper(SharedModuleStoreTestCase):
|
||||
assert isinstance(test_replace, Fragment)
|
||||
assert test_replace.content == '<a href="/base_url/id">'
|
||||
|
||||
@ddt.data(
|
||||
('course_mongo', '<a href="/courses/TestX/TS01/2015/id">'),
|
||||
('course_split', '<a href="/courses/course-v1:TestX+TS02+2015/id">')
|
||||
)
|
||||
@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('<a href="/course/id">'),
|
||||
context=None,
|
||||
replace_url_service=replace_url_service
|
||||
)
|
||||
assert isinstance(test_replace, Fragment)
|
||||
assert test_replace.content == anchor_tag
|
||||
assert test_replace.content == '<a href="/courses/course-v1:TestX+TS02+2015/id">'
|
||||
|
||||
@ddt.data(
|
||||
('course_mongo', '<a href="/c4x/TestX/TS01/asset/id">'),
|
||||
('course_split', '<a href="/asset-v1:TestX+TS02+2015+type@asset+block/id">')
|
||||
)
|
||||
@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('<a href="/static/id">'),
|
||||
context=None,
|
||||
@@ -926,4 +709,4 @@ class TestReplaceURLWrapper(SharedModuleStoreTestCase):
|
||||
static_replace_only=True
|
||||
)
|
||||
assert isinstance(test_replace, Fragment)
|
||||
assert test_replace.content == anchor_tag
|
||||
assert test_replace.content == '<a href="/asset-v1:TestX+TS02+2015+type@asset+block/id">'
|
||||
|
||||
@@ -45,7 +45,6 @@ from openedx.core.djangoapps.site_configuration.tests.test_util import with_site
|
||||
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
|
||||
|
||||
@@ -296,16 +295,15 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin,
|
||||
*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)
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin
|
||||
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 @@ class DashboardTest(ModuleStoreTestCase, TestVerificationBase):
|
||||
)))
|
||||
|
||||
@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 @@ class DashboardTest(ModuleStoreTestCase, TestVerificationBase):
|
||||
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 @@ class DashboardTest(ModuleStoreTestCase, TestVerificationBase):
|
||||
"""
|
||||
# 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):
|
||||
|
||||
@@ -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 @@ class TestGetBlocksQueryCounts(TestGetBlocksQueryCountsBase):
|
||||
)
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.mongo, 19, True, 24),
|
||||
(ModuleStoreEnum.Type.mongo, 19, False, 14),
|
||||
(ModuleStoreEnum.Type.split, 2, True, 24),
|
||||
(ModuleStoreEnum.Type.split, 2, False, 14),
|
||||
)
|
||||
|
||||
@@ -14,7 +14,6 @@ from django.core.management import call_command
|
||||
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 @@ class CommandsTestBase(SharedModuleStoreTestCase):
|
||||
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.
|
||||
|
||||
@@ -20,9 +20,8 @@ from django.urls import reverse
|
||||
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 @@ from lms.djangoapps.courseware.courses import (
|
||||
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 @@ class CoursesTest(ModuleStoreTestCase):
|
||||
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 @@ class XmlCourseImageTestCase(XModuleXmlImportTest):
|
||||
|
||||
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 @@ class CoursesRenderTest(ModuleStoreTestCase):
|
||||
"""
|
||||
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 == "<a href='/c4x/edX/toy/asset/handouts_sample_handout.txt'>Sample</a>"
|
||||
assert course_info == \
|
||||
"<a href='/asset-v1:edX+toy+2012_Fall+type@asset+block/handouts_sample_handout.txt'>Sample</a>"
|
||||
|
||||
# Test when render raises an exception
|
||||
with mock.patch('lms.djangoapps.courseware.courses.get_module') as mock_module_render:
|
||||
|
||||
@@ -17,8 +17,7 @@ from opaque_keys.edx.keys import CourseKey
|
||||
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 @@ class TestXBlockInCourse(SharedModuleStoreTestCase):
|
||||
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):
|
||||
"""
|
||||
|
||||
@@ -7,7 +7,7 @@ access control rules.
|
||||
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):
|
||||
"""
|
||||
|
||||
@@ -49,7 +49,7 @@ from xmodule.lti_module import LTIBlock
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import ModuleI18nService, modulestore
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
TEST_DATA_MONGO_AMNESTY_MODULESTORE,
|
||||
TEST_DATA_SPLIT_MODULESTORE,
|
||||
ModuleStoreTestCase,
|
||||
SharedModuleStoreTestCase,
|
||||
upload_file_to_course,
|
||||
@@ -1588,13 +1588,12 @@ class TestHtmlModifiers(ModuleStoreTestCase):
|
||||
self.course.static_asset_path = ""
|
||||
|
||||
@override_settings(DEFAULT_COURSE_ABOUT_IMAGE_URL='test.png')
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_course_image_for_split_course(self, store):
|
||||
def test_course_image_for_split_course(self):
|
||||
"""
|
||||
for split courses if course_image is empty then course_image_url will be
|
||||
the default image url defined in settings
|
||||
"""
|
||||
self.course = CourseFactory.create(default_store=store)
|
||||
self.course = CourseFactory.create()
|
||||
self.course.course_image = ''
|
||||
|
||||
url = course_image_url(self.course)
|
||||
@@ -1684,7 +1683,7 @@ class DetachedXBlock(XBlock):
|
||||
@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):
|
||||
@@ -2600,26 +2599,22 @@ class TestDisabledXBlockTypes(ModuleStoreTestCase):
|
||||
super().setUp()
|
||||
XBlockConfiguration(name='video', enabled=False).save()
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, 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')
|
||||
def test_get_item(self):
|
||||
course = CourseFactory()
|
||||
self._verify_descriptor('video', course, 'HiddenDescriptorWithMixins')
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_dynamic_updates(self, default_ms):
|
||||
def test_dynamic_updates(self):
|
||||
"""Tests that the list of disabled xblocks can dynamically update."""
|
||||
with self.store.default_store(default_ms):
|
||||
course = CourseFactory()
|
||||
item_usage_id = self._verify_descriptor('problem', course, 'ProblemBlockWithMixins')
|
||||
XBlockConfiguration(name='problem', enabled=False).save()
|
||||
course = CourseFactory()
|
||||
item_usage_id = self._verify_descriptor('problem', course, 'ProblemBlockWithMixins')
|
||||
XBlockConfiguration(name='problem', enabled=False).save()
|
||||
|
||||
# First verify that the cached value is used until there is a new request cache.
|
||||
self._verify_descriptor('problem', course, 'ProblemBlockWithMixins', item_usage_id)
|
||||
# First verify that the cached value is used until there is a new request cache.
|
||||
self._verify_descriptor('problem', course, 'ProblemBlockWithMixins', item_usage_id)
|
||||
|
||||
# Now simulate a new request cache.
|
||||
self.store.request_cache.data.clear()
|
||||
self._verify_descriptor('problem', course, 'HiddenDescriptorWithMixins', item_usage_id)
|
||||
# Now simulate a new request cache.
|
||||
self.store.request_cache.data.clear()
|
||||
self._verify_descriptor('problem', course, 'HiddenDescriptorWithMixins', item_usage_id)
|
||||
|
||||
def _verify_descriptor(self, category, course, descriptor, item_id=None):
|
||||
"""
|
||||
@@ -2642,8 +2637,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'
|
||||
|
||||
@@ -2653,7 +2648,9 @@ class LmsModuleSystemShimTest(SharedModuleStoreTestCase):
|
||||
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)
|
||||
@@ -2797,8 +2794,7 @@ class LmsModuleSystemShimTest(SharedModuleStoreTestCase):
|
||||
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'
|
||||
|
||||
@@ -2829,15 +2825,15 @@ class LmsModuleSystemShimTest(SharedModuleStoreTestCase):
|
||||
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()
|
||||
|
||||
@@ -2883,6 +2879,7 @@ class LmsModuleSystemShimTest(SharedModuleStoreTestCase):
|
||||
assert self.runtime.replace_jump_to_id_urls(html) == \
|
||||
static_replace.replace_jump_to_id_urls(html, self.course.id, jump_to_id_base_url)
|
||||
|
||||
@XBlock.register_temp_plugin(PureXBlock, 'pure')
|
||||
@XBlock.register_temp_plugin(PureXBlockWithChildren, identifier='xblock')
|
||||
def test_course_id(self):
|
||||
descriptor = ItemFactory(category="pure", parent=self.course)
|
||||
|
||||
@@ -38,7 +38,7 @@ from common.djangoapps.util.milestones_helpers import (
|
||||
)
|
||||
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):
|
||||
|
||||
@@ -143,7 +143,6 @@ class TestJumpTo(ModuleStoreTestCase):
|
||||
assert response.url.split('?')[0] == expected_url
|
||||
|
||||
@ddt.data(
|
||||
(False, ModuleStoreEnum.Type.mongo),
|
||||
(False, ModuleStoreEnum.Type.split),
|
||||
(True, ModuleStoreEnum.Type.split),
|
||||
)
|
||||
@@ -167,9 +166,8 @@ class TestJumpTo(ModuleStoreTestCase):
|
||||
assert response.url == expected_redirect_url
|
||||
|
||||
@set_preview_mode(True)
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_jump_to_legacy_from_sequence(self, store_type):
|
||||
with self.store.default_store(store_type):
|
||||
def test_jump_to_legacy_from_sequence(self):
|
||||
with self.store.default_store(ModuleStoreEnum.Type.split):
|
||||
course = CourseFactory.create()
|
||||
chapter = ItemFactory.create(category='chapter', parent_location=course.location)
|
||||
sequence = ItemFactory.create(category='sequential', parent_location=chapter.location)
|
||||
@@ -195,9 +193,8 @@ class TestJumpTo(ModuleStoreTestCase):
|
||||
assert response.url == expected_redirect_url
|
||||
|
||||
@set_preview_mode(True)
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_jump_to_legacy_from_module(self, store_type):
|
||||
with self.store.default_store(store_type):
|
||||
def test_jump_to_legacy_from_module(self):
|
||||
with self.store.default_store(ModuleStoreEnum.Type.split):
|
||||
course = CourseFactory.create()
|
||||
chapter = ItemFactory.create(category='chapter', parent_location=course.location)
|
||||
sequence = ItemFactory.create(category='sequential', parent_location=chapter.location)
|
||||
@@ -251,9 +248,8 @@ class TestJumpTo(ModuleStoreTestCase):
|
||||
# The new courseware experience does not support this sort of course structure;
|
||||
# it assumes a simple course->chapter->sequence->unit->component tree.
|
||||
@set_preview_mode(True)
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_jump_to_legacy_from_nested_module(self, store_type):
|
||||
with self.store.default_store(store_type):
|
||||
def test_jump_to_legacy_from_nested_module(self):
|
||||
with self.store.default_store(ModuleStoreEnum.Type.split):
|
||||
course = CourseFactory.create()
|
||||
chapter = ItemFactory.create(category='chapter', parent_location=course.location)
|
||||
sequence = ItemFactory.create(category='sequential', parent_location=chapter.location)
|
||||
@@ -275,7 +271,6 @@ class TestJumpTo(ModuleStoreTestCase):
|
||||
self.assertRedirects(response, expected_redirect_url, status_code=302, target_status_code=302)
|
||||
|
||||
@ddt.data(
|
||||
(False, ModuleStoreEnum.Type.mongo),
|
||||
(False, ModuleStoreEnum.Type.split),
|
||||
(True, ModuleStoreEnum.Type.split),
|
||||
)
|
||||
@@ -290,8 +285,6 @@ class TestJumpTo(ModuleStoreTestCase):
|
||||
|
||||
@set_preview_mode(True)
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.mongo, False, '1'),
|
||||
(ModuleStoreEnum.Type.mongo, True, '2'),
|
||||
(ModuleStoreEnum.Type.split, False, '1'),
|
||||
(ModuleStoreEnum.Type.split, True, '2'),
|
||||
)
|
||||
@@ -1348,15 +1341,14 @@ class ProgressPageTests(ProgressPageBaseTests):
|
||||
# Assert that valid 'student_id' returns 200 status
|
||||
self._get_student_progress_page()
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_unenrolled_student_progress_for_credit_course(self, default_store):
|
||||
def test_unenrolled_student_progress_for_credit_course(self):
|
||||
"""
|
||||
Test that student progress page does not break while checking for an unenrolled student.
|
||||
Scenario: When instructor checks the progress of a student who is not enrolled in credit course.
|
||||
It should return 200 response.
|
||||
"""
|
||||
# Create a new course, a user which will not be enrolled in course, admin user for staff access
|
||||
course = CourseFactory.create(default_store=default_store)
|
||||
course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split)
|
||||
admin = AdminFactory.create()
|
||||
assert self.client.login(username=admin.username, password='test')
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ from openedx.core.lib.teams_config import TeamsConfig
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase, SharedModuleStoreTestCase,
|
||||
TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase, SharedModuleStoreTestCase,
|
||||
)
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls
|
||||
|
||||
@@ -2031,7 +2031,7 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
|
||||
sources (e.g., a mobile app), we carefully test a myriad of cases, including
|
||||
those with incomplete and malformed events.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
CATEGORY_ID = 'i4x-edx-discussion-id'
|
||||
CATEGORY_NAME = 'Discussion 1'
|
||||
@@ -2047,21 +2047,12 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
|
||||
@mock.patch.dict("common.djangoapps.student.models.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True})
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.courses_by_store = {
|
||||
ModuleStoreEnum.Type.mongo: CourseFactory.create(
|
||||
org='TestX',
|
||||
course='TR-101',
|
||||
run='Event_Transform_Test',
|
||||
default_store=ModuleStoreEnum.Type.mongo,
|
||||
),
|
||||
ModuleStoreEnum.Type.split: CourseFactory.create(
|
||||
org='TestX',
|
||||
course='TR-101S',
|
||||
run='Event_Transform_Test_Split',
|
||||
default_store=ModuleStoreEnum.Type.split,
|
||||
),
|
||||
}
|
||||
self.course = self.courses_by_store['mongo']
|
||||
self.course = CourseFactory.create(
|
||||
org='TestX',
|
||||
course='TR-101S',
|
||||
run='Event_Transform_Test_Split',
|
||||
default_store=ModuleStoreEnum.Type.split,
|
||||
)
|
||||
self.student = UserFactory.create()
|
||||
self.staff = UserFactory.create(is_staff=True)
|
||||
UserBasedRole(user=self.staff, role=CourseStaffRole.ROLE).add_course(self.course.id)
|
||||
@@ -2184,18 +2175,16 @@ class ForumThreadViewedEventTransformerTestCase(ForumsEnableMixin, UrlResetMixin
|
||||
assert 'title_truncated' in event_3_trans['event']
|
||||
assert event_3_trans['event']['title_truncated']
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_urls(self, store):
|
||||
course = self.courses_by_store[store]
|
||||
def test_urls(self):
|
||||
commentable_id = self.DUMMY_CATEGORY_ID
|
||||
thread_id = self.DUMMY_THREAD_ID
|
||||
_, event_trans = _create_and_transform_event(
|
||||
course_id=course.id,
|
||||
course_id=self.course.id,
|
||||
topic_id=commentable_id,
|
||||
thread_id=thread_id,
|
||||
)
|
||||
expected_path = '/courses/{}/discussion/forum/{}/threads/{}'.format(
|
||||
course.id, commentable_id, thread_id
|
||||
self.course.id, commentable_id, thread_id
|
||||
)
|
||||
assert event_trans['event'].get('url').endswith(expected_path)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Tests for the django comment client integration models
|
||||
from django.test.testcases import TestCase
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
TEST_DATA_MIXED_MODULESTORE,
|
||||
TEST_DATA_SPLIT_MODULESTORE,
|
||||
ModuleStoreTestCase
|
||||
)
|
||||
from xmodule.modulestore.tests.factories import ToyCourseFactory
|
||||
@@ -18,7 +18,7 @@ class RoleClassTestCase(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests for roles of the comment client service integration
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
@@ -9,10 +9,9 @@ from unittest.mock import Mock, patch
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
from django.test import RequestFactory, TestCase, override_settings
|
||||
from django.test import RequestFactory, TestCase
|
||||
from django.urls import reverse
|
||||
from edx_django_utils.cache import RequestCache
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from pytz import UTC
|
||||
|
||||
@@ -50,11 +49,9 @@ from openedx.core.djangoapps.django_comment_common.models import (
|
||||
)
|
||||
from openedx.core.djangoapps.django_comment_common.utils import seed_permissions_roles
|
||||
from openedx.core.djangoapps.util.testing import ContentGroupTestCase
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_MODULESTORE, ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, ToyCourseFactory
|
||||
from xmodule.tabs import CourseTabList
|
||||
|
||||
|
||||
class DictionaryTestCase(TestCase):
|
||||
@@ -194,13 +191,11 @@ class CoursewareContextTestCase(ModuleStoreTestCase):
|
||||
utils.add_courseware_context([thread], self.course, self.user)
|
||||
assert '/' not in thread.get('courseware_title')
|
||||
|
||||
@ddt.data((ModuleStoreEnum.Type.mongo, 2), (ModuleStoreEnum.Type.split, 1))
|
||||
@ddt.unpack
|
||||
def test_get_accessible_discussion_xblocks(self, modulestore_type, expected_discussion_xblocks):
|
||||
def test_get_accessible_discussion_xblocks(self):
|
||||
"""
|
||||
Tests that the accessible discussion xblocks having no parents do not get fetched for split modulestore.
|
||||
"""
|
||||
course = CourseFactory.create(default_store=modulestore_type)
|
||||
course = CourseFactory.create()
|
||||
|
||||
# Create a discussion xblock.
|
||||
test_discussion = self.store.create_child(self.user.id, course.location, 'discussion', 'test_discussion')
|
||||
@@ -220,7 +215,7 @@ class CoursewareContextTestCase(ModuleStoreTestCase):
|
||||
# Assert that the discussion xblock is an orphan.
|
||||
assert orphan in self.store.get_orphans(course.id)
|
||||
|
||||
assert len(get_accessible_discussion_xblocks(course, self.user)) == expected_discussion_xblocks
|
||||
assert len(get_accessible_discussion_xblocks(course, self.user)) == 1
|
||||
|
||||
|
||||
class CachedDiscussionIdMapTestCase(ModuleStoreTestCase):
|
||||
@@ -1185,7 +1180,7 @@ class IsCommentableDividedTestCase(ModuleStoreTestCase):
|
||||
Test the is_commentable_divided function.
|
||||
"""
|
||||
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
|
||||
@@ -103,9 +103,7 @@ class EdxNotesDecoratorTest(ModuleStoreTestCase):
|
||||
super().setUp()
|
||||
|
||||
ApplicationFactory(name="edx-notes")
|
||||
# Using old mongo because of locator comparison issues (see longer
|
||||
# note below in EdxNotesHelpersTest setUp.
|
||||
self.course = CourseFactory(edxnotes=True, default_store=ModuleStoreEnum.Type.mongo)
|
||||
self.course = CourseFactory(edxnotes=True, default_store=ModuleStoreEnum.Type.split)
|
||||
self.user = UserFactory()
|
||||
self.client.login(username=self.user.username, password=UserFactory._DEFAULT_PASSWORD) # lint-amnesty, pylint: disable=protected-access
|
||||
self.problem = TestProblem(self.course, self.user)
|
||||
@@ -204,11 +202,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
"""
|
||||
super().setUp()
|
||||
|
||||
# There are many tests that are comparing locators as returned from helper methods. When using
|
||||
# the split modulestore, some of those locators have version and branch information, but the
|
||||
# comparison values do not. This needs further investigation in order to enable these tests
|
||||
# with the split modulestore.
|
||||
with self.store.default_store(ModuleStoreEnum.Type.mongo):
|
||||
with self.store.default_store(ModuleStoreEnum.Type.split):
|
||||
ApplicationFactory(name="edx-notes")
|
||||
self.course = CourseFactory.create()
|
||||
self.chapter = ItemFactory.create(category="chapter", parent_location=self.course.location)
|
||||
|
||||
@@ -9,7 +9,7 @@ import ddt
|
||||
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, ItemFactory
|
||||
from xmodule.capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
|
||||
from common.djangoapps.student.tests.factories import GlobalStaffFactory
|
||||
@@ -36,8 +36,10 @@ class GradingPolicyTestMixin:
|
||||
|
||||
@classmethod
|
||||
def create_course_data(cls): # lint-amnesty, pylint: disable=missing-function-docstring
|
||||
cls.invalid_course_id = 'foo/bar/baz'
|
||||
cls.course = CourseFactory.create(display_name='An Introduction to API Testing', raw_grader=cls.raw_grader)
|
||||
cls.invalid_course_id = 'course-v1:foo+bar+baz'
|
||||
cls.course = CourseFactory.create(
|
||||
display_name='An Introduction to API Testing', grading_policy=cls.grading_policy
|
||||
)
|
||||
cls.course_id = str(cls.course.id)
|
||||
with cls.store.bulk_operations(cls.course.id, emit_signals=False):
|
||||
cls.sequential = ItemFactory.create(
|
||||
@@ -141,7 +143,7 @@ class GradingPolicyTestMixin:
|
||||
auth_header = self.get_auth_header(user)
|
||||
self.assert_get_for_course(expected_status_code=403, HTTP_AUTHORIZATION=auth_header)
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
@ddt.data(ModuleStoreEnum.Type.split)
|
||||
def test_course_keys(self, modulestore_type):
|
||||
"""
|
||||
The view should be addressable by course-keys from both module stores.
|
||||
@@ -159,25 +161,27 @@ class CourseGradingPolicyTests(GradingPolicyTestMixin, SharedModuleStoreTestCase
|
||||
"""
|
||||
Tests for CourseGradingPolicy view.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
view_name = 'grades_api:v1:course_grading_policy'
|
||||
|
||||
raw_grader = [
|
||||
{
|
||||
"min_count": 24,
|
||||
"weight": 0.2,
|
||||
"type": "Homework",
|
||||
"drop_count": 0,
|
||||
"short_label": "HW"
|
||||
},
|
||||
{
|
||||
"min_count": 4,
|
||||
"weight": 0.8,
|
||||
"type": "Exam",
|
||||
"drop_count": 0,
|
||||
"short_label": "Exam"
|
||||
}
|
||||
]
|
||||
grading_policy = {
|
||||
'GRADER': [
|
||||
{
|
||||
"min_count": 24,
|
||||
"weight": 0.2,
|
||||
"type": "Homework",
|
||||
"drop_count": 0,
|
||||
"short_label": "HW"
|
||||
},
|
||||
{
|
||||
"min_count": 4,
|
||||
"weight": 0.8,
|
||||
"type": "Exam",
|
||||
"drop_count": 0,
|
||||
"short_label": "Exam"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@@ -211,26 +215,28 @@ class CourseGradingPolicyMissingFieldsTests(GradingPolicyTestMixin, SharedModule
|
||||
"""
|
||||
Tests for CourseGradingPolicy view when fields are missing.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
view_name = 'grades_api:v1:course_grading_policy'
|
||||
|
||||
# Raw grader with missing keys
|
||||
raw_grader = [
|
||||
{
|
||||
"min_count": 24,
|
||||
"weight": 0.2,
|
||||
"type": "Homework",
|
||||
"drop_count": 0,
|
||||
"short_label": "HW"
|
||||
},
|
||||
{
|
||||
# Deleted "min_count" key
|
||||
"weight": 0.8,
|
||||
"type": "Exam",
|
||||
"drop_count": 0,
|
||||
"short_label": "Exam"
|
||||
}
|
||||
]
|
||||
grading_policy = {
|
||||
'GRADER': [
|
||||
{
|
||||
"min_count": 24,
|
||||
"weight": 0.2,
|
||||
"type": "Homework",
|
||||
"drop_count": 0,
|
||||
"short_label": "HW"
|
||||
},
|
||||
{
|
||||
# Deleted "min_count" key
|
||||
"weight": 0.8,
|
||||
"type": "Exam",
|
||||
"drop_count": 0,
|
||||
"short_label": "Exam"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
||||
@@ -8,7 +8,7 @@ from crum import set_current_request
|
||||
from xmodule.graders import ProblemScore
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase, SharedModuleStoreTestCase,
|
||||
TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase, SharedModuleStoreTestCase,
|
||||
)
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.modulestore.tests.utils import TEST_DATA_DIR
|
||||
@@ -29,7 +29,7 @@ class TestMultipleProblemTypesSubsectionScores(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Test grading of different problem types.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
SCORED_BLOCK_COUNT = 7
|
||||
ACTUAL_TOTAL_POSSIBLE = 17.0
|
||||
@@ -58,10 +58,12 @@ class TestMultipleProblemTypesSubsectionScores(SharedModuleStoreTestCase):
|
||||
For details on the contents and structure of the file, see
|
||||
`common/test/data/scoreable/README`.
|
||||
"""
|
||||
password = 'test'
|
||||
user = UserFactory.create(is_staff=False, username='test_student', password=password)
|
||||
|
||||
course_items = import_course_from_xml(
|
||||
cls.store,
|
||||
'test_user',
|
||||
user.id,
|
||||
TEST_DATA_DIR,
|
||||
source_dirs=['scoreable'],
|
||||
static_content_store=None,
|
||||
@@ -104,7 +106,7 @@ class TestVariedMetadata(ProblemSubmissionTestMixin, ModuleStoreTestCase):
|
||||
Test that changing the metadata on a block has the desired effect on the
|
||||
persisted score.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
default_problem_metadata = {
|
||||
'graded': True,
|
||||
@@ -214,7 +216,7 @@ class TestWeightedProblems(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Test scores and grades with various problem weight values.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
||||
@@ -3,7 +3,7 @@ from unittest.mock import patch
|
||||
|
||||
import ddt
|
||||
from crum import set_current_request
|
||||
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, ItemFactory
|
||||
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
@@ -67,7 +67,7 @@ class TestScoreForModule(SharedModuleStoreTestCase):
|
||||
(2/5) (3/5) (0/1) - (1/3) - (3/10)
|
||||
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
||||
@@ -153,8 +153,6 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
assert mock_block_structure_create.call_count == 1
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.mongo, 2, 41, True),
|
||||
(ModuleStoreEnum.Type.mongo, 2, 41, False),
|
||||
(ModuleStoreEnum.Type.split, 2, 41, True),
|
||||
(ModuleStoreEnum.Type.split, 2, 41, False),
|
||||
)
|
||||
@@ -167,7 +165,6 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
self._apply_recalculate_subsection_grade()
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.mongo, 2, 41),
|
||||
(ModuleStoreEnum.Type.split, 2, 41),
|
||||
)
|
||||
@ddt.unpack
|
||||
@@ -213,7 +210,6 @@ class RecalculateSubsectionGradeTest(HasCourseWithProblemsMixin, ModuleStoreTest
|
||||
)
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.mongo, 2, 41),
|
||||
(ModuleStoreEnum.Type.split, 2, 41),
|
||||
)
|
||||
@ddt.unpack
|
||||
|
||||
@@ -367,12 +367,6 @@ class GradesTransformerTestCase(CourseStructureTestCase):
|
||||
max_score=0,
|
||||
)
|
||||
|
||||
def test_course_version_not_collected_in_old_mongo(self):
|
||||
with self.store.default_store(ModuleStoreEnum.Type.mongo):
|
||||
blocks = self.build_course_with_problems()
|
||||
block_structure = get_course_blocks(self.student, blocks['course'].location, self.transformers)
|
||||
assert block_structure.get_xblock_field(blocks['course'].location, 'course_version') is None
|
||||
|
||||
def test_course_version_collected_in_split(self):
|
||||
blocks = self.build_course_with_problems()
|
||||
block_structure = get_course_blocks(self.student, blocks['course'].location, self.transformers)
|
||||
@@ -430,7 +424,6 @@ class MultiProblemModulestoreAccessTestCase(CourseStructureTestCase, SharedModul
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.split, 2, 2),
|
||||
(ModuleStoreEnum.Type.mongo, 22, 15),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_modulestore_performance(self, store_type, max_mongo_calls, min_mongo_calls):
|
||||
|
||||
@@ -33,7 +33,7 @@ from testfixtures import LogCapture
|
||||
from xmodule.fields import Date
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase, SharedModuleStoreTestCase,
|
||||
TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase, SharedModuleStoreTestCase,
|
||||
)
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
@@ -3091,7 +3091,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
|
||||
Test endpoints whereby instructors can rescore student grades,
|
||||
reset student attempts and delete state for entrance exam.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@@ -3156,7 +3156,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
|
||||
)
|
||||
self.ee_modules = [ee_module_to_reset1.module_state_key, ee_module_to_reset2.module_state_key]
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo)
|
||||
@ddt.data(ModuleStoreEnum.Type.split)
|
||||
def test_grade_histogram(self, store):
|
||||
"""
|
||||
Verify that a histogram has been created.
|
||||
@@ -3929,7 +3929,7 @@ class TestDueDateExtensions(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
"""
|
||||
Test data dumps for reporting.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@@ -4105,7 +4105,7 @@ class TestDueDateExtensionsDeletedDate(ModuleStoreTestCase, LoginEnrollmentTestC
|
||||
"""
|
||||
Tests for deleting due date extensions
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
@@ -4121,15 +4121,15 @@ class TestDueDateExtensionsDeletedDate(ModuleStoreTestCase, LoginEnrollmentTestC
|
||||
self.week2 = ItemFactory.create(due=self.due)
|
||||
self.week3 = ItemFactory.create() # No due date
|
||||
self.course.children = [
|
||||
str(self.week1.location),
|
||||
str(self.week2.location),
|
||||
str(self.week3.location)
|
||||
self.week1.location,
|
||||
self.week2.location,
|
||||
self.week3.location
|
||||
]
|
||||
self.homework = ItemFactory.create(
|
||||
parent_location=self.week1.location,
|
||||
due=self.due
|
||||
)
|
||||
self.week1.children = [str(self.homework.location)]
|
||||
self.week1.children = [self.homework.location]
|
||||
|
||||
user1 = UserFactory.create()
|
||||
StudentModule(
|
||||
|
||||
@@ -21,7 +21,7 @@ from opaque_keys.edx.locations import Location
|
||||
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
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.capa.tests.response_xml_factory import OptionResponseXMLFactory
|
||||
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
@@ -37,7 +37,7 @@ from openedx.core.lib.url_utils import quote_slashes
|
||||
TEST_COURSE_ORG = 'edx'
|
||||
TEST_COURSE_NAME = 'test_course'
|
||||
TEST_COURSE_NUMBER = '1.23x'
|
||||
TEST_COURSE_KEY = CourseKey.from_string('/'.join([TEST_COURSE_ORG, TEST_COURSE_NUMBER, TEST_COURSE_NAME]))
|
||||
TEST_COURSE_KEY = CourseKey.from_string(f'course-v1:{TEST_COURSE_ORG}+{TEST_COURSE_NUMBER}+{TEST_COURSE_NAME}')
|
||||
TEST_CHAPTER_NAME = "Section"
|
||||
TEST_SECTION_NAME = "Subsection"
|
||||
|
||||
@@ -108,7 +108,7 @@ class InstructorTaskCourseTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase)
|
||||
Base test class for InstructorTask-related tests that require
|
||||
the setup of a course.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
course = None
|
||||
current_user = None
|
||||
|
||||
@@ -273,10 +273,7 @@ class InstructorTaskModuleTestCase(InstructorTaskCourseTestCase):
|
||||
# Note that this is a capa-specific convention. The form is a version of the problem's
|
||||
# URL, modified so that it can be easily stored in html, prepended with "input-" and
|
||||
# appended with a sequence identifier for the particular response the input goes to.
|
||||
course_key = self.course.id
|
||||
return 'input_i4x-{}-{}-problem-{}_{}'.format(
|
||||
course_key.org.replace('.', '_'),
|
||||
course_key.course.replace('.', '_'),
|
||||
return 'input_{}_{}'.format(
|
||||
problem_url_name,
|
||||
response_id
|
||||
)
|
||||
|
||||
@@ -67,7 +67,6 @@ from openedx.core.djangoapps.credit.tests.factories import CreditCourseFactory
|
||||
from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme
|
||||
from openedx.core.djangoapps.util.testing import ContentGroupTestCase, TestConditionalContent
|
||||
from openedx.core.lib.teams_config import TeamsConfig
|
||||
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, check_mongo_calls # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.partitions.partitions import Group, UserPartition # lint-amnesty, pylint: disable=wrong-import-order
|
||||
@@ -369,27 +368,21 @@ class TestInstructorGradeReport(InstructorGradeReportTestCase):
|
||||
# verifies that verified passing learner is eligible for certificate
|
||||
self._verify_cell_data_for_user(verified_user.username, course.id, 'Certificate Eligible', 'Y', num_rows=2)
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.mongo, 6, 47),
|
||||
(ModuleStoreEnum.Type.split, 2, 48),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_query_counts(self, store_type, mongo_count, expected_query_count):
|
||||
with self.store.default_store(store_type):
|
||||
experiment_group_a = Group(2, 'Expériment Group A')
|
||||
experiment_group_b = Group(3, 'Expériment Group B')
|
||||
experiment_partition = UserPartition(
|
||||
1,
|
||||
'Content Expériment Configuration',
|
||||
'Group Configuration for Content Expériments',
|
||||
[experiment_group_a, experiment_group_b],
|
||||
scheme_id='random'
|
||||
)
|
||||
course = CourseFactory.create(
|
||||
cohort_config={'cohorted': True, 'auto_cohort': True, 'auto_cohort_groups': ['cohort 1', 'cohort 2']},
|
||||
user_partitions=[experiment_partition],
|
||||
teams_configuration=_TEAMS_CONFIG,
|
||||
)
|
||||
def test_query_counts(self):
|
||||
experiment_group_a = Group(2, 'Expériment Group A')
|
||||
experiment_group_b = Group(3, 'Expériment Group B')
|
||||
experiment_partition = UserPartition(
|
||||
1,
|
||||
'Content Expériment Configuration',
|
||||
'Group Configuration for Content Expériments',
|
||||
[experiment_group_a, experiment_group_b],
|
||||
scheme_id='random'
|
||||
)
|
||||
course = CourseFactory.create(
|
||||
cohort_config={'cohorted': True, 'auto_cohort': True, 'auto_cohort_groups': ['cohort 1', 'cohort 2']},
|
||||
user_partitions=[experiment_partition],
|
||||
teams_configuration=_TEAMS_CONFIG,
|
||||
)
|
||||
_ = CreditCourseFactory(course_key=course.id)
|
||||
|
||||
num_users = 5
|
||||
@@ -401,8 +394,8 @@ class TestInstructorGradeReport(InstructorGradeReportTestCase):
|
||||
RequestCache.clear_all_namespaces()
|
||||
|
||||
with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'):
|
||||
with check_mongo_calls(mongo_count):
|
||||
with self.assertNumQueries(expected_query_count):
|
||||
with check_mongo_calls(2):
|
||||
with self.assertNumQueries(48):
|
||||
CourseGradeReport.generate(None, None, course.id, {}, 'graded')
|
||||
|
||||
def test_inactive_enrollments(self):
|
||||
@@ -531,7 +524,7 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
self.assertDictContainsSubset({
|
||||
'username': 'student',
|
||||
'location': 'test_course > Section > Subsection > Problem1',
|
||||
'block_key': 'i4x://edx/1.23x/problem/Problem1',
|
||||
'block_key': 'block-v1:edx+1.23x+test_course+type@problem+block@Problem1',
|
||||
'title': 'Problem1',
|
||||
}, student_data[0])
|
||||
assert 'state' in student_data[0]
|
||||
@@ -561,7 +554,7 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
self.assertDictContainsSubset({
|
||||
'username': 'student',
|
||||
'location': 'test_course > Section > Subsection > Problem1',
|
||||
'block_key': 'i4x://edx/1.23x/problem/Problem1',
|
||||
'block_key': 'block-v1:edx+1.23x+test_course+type@problem+block@Problem1',
|
||||
'title': 'Problem1',
|
||||
'some': 'state1',
|
||||
'more': 'state1!',
|
||||
@@ -569,7 +562,7 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
self.assertDictContainsSubset({
|
||||
'username': 'student',
|
||||
'location': 'test_course > Section > Subsection > Problem1',
|
||||
'block_key': 'i4x://edx/1.23x/problem/Problem1',
|
||||
'block_key': 'block-v1:edx+1.23x+test_course+type@problem+block@Problem1',
|
||||
'title': 'Problem1',
|
||||
'some': 'state2',
|
||||
'more': 'state2!',
|
||||
@@ -602,7 +595,7 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
self.assertDictContainsSubset({
|
||||
'username': 'student',
|
||||
'location': 'test_course > Section > Subsection > Problem1',
|
||||
'block_key': 'i4x://edx/1.23x/problem/Problem1',
|
||||
'block_key': 'block-v1:edx+1.23x+test_course+type@problem+block@Problem1',
|
||||
'title': 'Problem1',
|
||||
'some': 'state1',
|
||||
'more': 'state1!',
|
||||
@@ -610,7 +603,7 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
self.assertDictContainsSubset({
|
||||
'username': 'student',
|
||||
'location': 'test_course > Section > Subsection > Problem1',
|
||||
'block_key': 'i4x://edx/1.23x/problem/Problem1',
|
||||
'block_key': 'block-v1:edx+1.23x+test_course+type@problem+block@Problem1',
|
||||
'title': 'Problem1',
|
||||
'some': 'state2',
|
||||
'more': 'state2!',
|
||||
@@ -634,9 +627,9 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
self.assertDictContainsSubset({
|
||||
'username': 'student',
|
||||
'location': 'test_course > Section > Subsection > Problem1',
|
||||
'block_key': 'i4x://edx/1.23x/problem/Problem1',
|
||||
'block_key': 'block-v1:edx+1.23x+test_course+type@problem+block@Problem1',
|
||||
'title': 'Problem1',
|
||||
'Answer ID': 'i4x-edx-1_23x-problem-Problem1_2_1',
|
||||
'Answer ID': 'Problem1_2_1',
|
||||
'Answer': 'Option 1',
|
||||
'Correct Answer': 'Option 1',
|
||||
'Question': 'The correct answer is Option 1',
|
||||
@@ -663,9 +656,9 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
self.assertDictContainsSubset({
|
||||
'username': 'student',
|
||||
'location': f'test_course > Section > Subsection > Problem{idx}',
|
||||
'block_key': f'i4x://edx/1.23x/problem/Problem{idx}',
|
||||
'block_key': f'block-v1:edx+1.23x+test_course+type@problem+block@Problem{idx}',
|
||||
'title': f'Problem{idx}',
|
||||
'Answer ID': f'i4x-edx-1_23x-problem-Problem{idx}_2_1',
|
||||
'Answer ID': f'Problem{idx}_2_1',
|
||||
'Answer': 'Option 1',
|
||||
'Correct Answer': 'Option 1',
|
||||
'Question': 'The correct answer is Option 1',
|
||||
@@ -675,8 +668,7 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
@ddt.data(
|
||||
(['problem'], 5),
|
||||
(['other'], 0),
|
||||
(['problem', 'test-category'], 10),
|
||||
(None, 10),
|
||||
(None, 5),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_build_student_data_with_filter(self, filters, filtered_count):
|
||||
@@ -688,7 +680,6 @@ class TestProblemResponsesReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
item = ItemFactory.create(
|
||||
parent_location=self.problem_section.location,
|
||||
parent=self.problem_section,
|
||||
category="test-category",
|
||||
display_name=f"Item{idx}",
|
||||
data=''
|
||||
)
|
||||
@@ -1748,7 +1739,7 @@ class TestGradeReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
metadata={'graded': True, 'format': 'Homework'},
|
||||
display_name='Subsection'
|
||||
)
|
||||
self.define_option_problem('Problem1', parent=self.problem_section, num_responses=1)
|
||||
self.define_option_problem('Problem1', parent=self.problem_section)
|
||||
self.hidden_section = ItemFactory.create(
|
||||
parent=self.chapter,
|
||||
category='sequential',
|
||||
@@ -1882,10 +1873,10 @@ class TestGradeReport(TestReportMixin, InstructorTaskModuleTestCase):
|
||||
metadata={'graded': True},
|
||||
display_name='Problem Vertical'
|
||||
)
|
||||
self.define_option_problem('Problem1', parent=vertical)
|
||||
self.define_option_problem('Problem4', parent=vertical)
|
||||
|
||||
self.submit_student_answer(student_1.username, 'Problem1', ['Option 1'])
|
||||
self.submit_student_answer(student_verified.username, 'Problem1', ['Option 1'])
|
||||
self.submit_student_answer(student_1.username, 'Problem4', ['Option 1'])
|
||||
self.submit_student_answer(student_verified.username, 'Problem4', ['Option 1'])
|
||||
result = CourseGradeReport.generate(None, None, self.course.id, {}, 'graded')
|
||||
self.assertDictContainsSubset(
|
||||
{'action_name': 'graded', 'attempted': 1, 'succeeded': 1, 'failed': 0}, result
|
||||
|
||||
@@ -7,7 +7,7 @@ from unittest.mock import patch
|
||||
|
||||
from django.test import TestCase
|
||||
from opaque_keys.edx.keys import CourseKey, UsageKey
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_MODULESTORE, SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.utils import TEST_DATA_DIR
|
||||
from xmodule.modulestore.xml_importer import import_course_from_xml
|
||||
|
||||
@@ -46,15 +46,17 @@ class CommandExecutionTestCase(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Test `manage.py resend_lti_scores` command.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.course_key = cls.store.make_course_key('edX', 'lti_provider', '3000')
|
||||
password = 'test'
|
||||
user = UserFactory.create(is_staff=False, username='test_student', password=password)
|
||||
import_course_from_xml(
|
||||
cls.store,
|
||||
'test_user',
|
||||
user.id,
|
||||
TEST_DATA_DIR,
|
||||
source_dirs=['simple'],
|
||||
static_content_store=None,
|
||||
|
||||
@@ -4,7 +4,6 @@ Tests for the LMS/lib utils
|
||||
|
||||
|
||||
from lms.lib import utils
|
||||
from xmodule.modulestore import ModuleStoreEnum # 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
|
||||
|
||||
@@ -20,30 +19,29 @@ class LmsUtilsTest(ModuleStoreTestCase):
|
||||
"""
|
||||
super().setUp()
|
||||
|
||||
with self.store.default_store(ModuleStoreEnum.Type.mongo):
|
||||
self.course = CourseFactory.create()
|
||||
self.chapter = ItemFactory.create(category="chapter", parent_location=self.course.location)
|
||||
self.sequential = ItemFactory.create(category="sequential", parent_location=self.chapter.location)
|
||||
self.vertical = ItemFactory.create(category="vertical", parent_location=self.sequential.location)
|
||||
self.html_module_1 = ItemFactory.create(category="html", parent_location=self.vertical.location)
|
||||
self.vertical_with_container = ItemFactory.create(
|
||||
category="vertical", parent_location=self.sequential.location
|
||||
)
|
||||
self.child_container = ItemFactory.create(
|
||||
category="split_test", parent_location=self.vertical_with_container.location)
|
||||
self.child_vertical = ItemFactory.create(category="vertical", parent_location=self.child_container.location)
|
||||
self.child_html_module = ItemFactory.create(category="html", parent_location=self.child_vertical.location)
|
||||
self.course = CourseFactory.create()
|
||||
self.chapter = ItemFactory.create(category="chapter", parent_location=self.course.location)
|
||||
self.sequential = ItemFactory.create(category="sequential", parent_location=self.chapter.location)
|
||||
self.vertical = ItemFactory.create(category="vertical", parent_location=self.sequential.location)
|
||||
self.html_module_1 = ItemFactory.create(category="html", parent_location=self.vertical.location)
|
||||
self.vertical_with_container = ItemFactory.create(
|
||||
category="vertical", parent_location=self.sequential.location
|
||||
)
|
||||
self.child_container = ItemFactory.create(
|
||||
category="split_test", parent_location=self.vertical_with_container.location)
|
||||
self.child_vertical = ItemFactory.create(category="vertical", parent_location=self.child_container.location)
|
||||
self.child_html_module = ItemFactory.create(category="html", parent_location=self.child_vertical.location)
|
||||
|
||||
# Read again so that children lists are accurate
|
||||
self.course = self.store.get_item(self.course.location)
|
||||
self.chapter = self.store.get_item(self.chapter.location)
|
||||
self.sequential = self.store.get_item(self.sequential.location)
|
||||
self.vertical = self.store.get_item(self.vertical.location)
|
||||
# Read again so that children lists are accurate
|
||||
self.course = self.store.get_item(self.course.location)
|
||||
self.chapter = self.store.get_item(self.chapter.location)
|
||||
self.sequential = self.store.get_item(self.sequential.location)
|
||||
self.vertical = self.store.get_item(self.vertical.location)
|
||||
|
||||
self.vertical_with_container = self.store.get_item(self.vertical_with_container.location)
|
||||
self.child_container = self.store.get_item(self.child_container.location)
|
||||
self.child_vertical = self.store.get_item(self.child_vertical.location)
|
||||
self.child_html_module = self.store.get_item(self.child_html_module.location)
|
||||
self.vertical_with_container = self.store.get_item(self.vertical_with_container.location)
|
||||
self.child_container = self.store.get_item(self.child_container.location)
|
||||
self.child_vertical = self.store.get_item(self.child_vertical.location)
|
||||
self.child_html_module = self.store.get_item(self.child_html_module.location)
|
||||
|
||||
def test_get_parent_unit(self):
|
||||
"""
|
||||
|
||||
@@ -14,7 +14,7 @@ from lms.djangoapps.lms_xblock.mixin import (
|
||||
NONSENSICAL_ACCESS_RESTRICTION
|
||||
)
|
||||
from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_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, ToyCourseFactory # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.partitions.partitions import Group, UserPartition # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
@@ -296,17 +296,15 @@ class OpenAssessmentBlockMixinTestCase(ModuleStoreTestCase):
|
||||
assert self.open_assessment.has_score
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class XBlockGetParentTest(LmsXBlockMixinTestCase):
|
||||
"""
|
||||
Test that XBlock.get_parent returns correct results with each modulestore
|
||||
backend.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_parents(self, modulestore_type):
|
||||
with self.store.default_store(modulestore_type):
|
||||
def test_parents(self):
|
||||
with self.store.default_store(ModuleStoreEnum.Type.split):
|
||||
|
||||
# setting up our own local course tree here, since it needs to be
|
||||
# created with the correct modulestore type.
|
||||
@@ -330,10 +328,9 @@ class XBlockGetParentTest(LmsXBlockMixinTestCase):
|
||||
visited = recurse(course)
|
||||
assert len(visited) == 28
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_parents_draft_content(self, modulestore_type):
|
||||
def test_parents_draft_content(self):
|
||||
# move the video to the new vertical
|
||||
with self.store.default_store(modulestore_type):
|
||||
with self.store.default_store(ModuleStoreEnum.Type.split):
|
||||
self.build_course()
|
||||
subsection = self.store.get_item(self.subsection_location)
|
||||
new_vertical = ItemFactory.create(parent=subsection, category='vertical', display_name='New Test Unit')
|
||||
|
||||
@@ -11,8 +11,7 @@ import ddt
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from rest_framework.test import APIClient
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
|
||||
@@ -72,7 +71,7 @@ class BookmarksListViewTests(BookmarksViewsTestsBase):
|
||||
GET /api/bookmarks/v1/bookmarks/?course_id={course_id1}
|
||||
POST /api/bookmarks/v1/bookmarks
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
@ddt.data(
|
||||
(1, False),
|
||||
@@ -90,9 +89,7 @@ class BookmarksListViewTests(BookmarksViewsTestsBase):
|
||||
expected order without optional fields.
|
||||
"""
|
||||
|
||||
course, __, bookmarks = self.create_course_with_bookmarks_count(
|
||||
bookmarks_count, store_type=ModuleStoreEnum.Type.mongo
|
||||
)
|
||||
course, __, bookmarks = self.create_course_with_bookmarks_count(bookmarks_count)
|
||||
|
||||
query_parameters = 'course_id={}&page_size={}'.format(
|
||||
quote(str(course.id)), 100)
|
||||
@@ -133,9 +130,7 @@ class BookmarksListViewTests(BookmarksViewsTestsBase):
|
||||
Test that requesting bookmarks for a course return results with pagination 200 code.
|
||||
"""
|
||||
|
||||
course, __, bookmarks = self.create_course_with_bookmarks_count(
|
||||
bookmarks_count, store_type=ModuleStoreEnum.Type.mongo
|
||||
)
|
||||
course, __, bookmarks = self.create_course_with_bookmarks_count(bookmarks_count)
|
||||
|
||||
page_size = 5
|
||||
query_parameters = 'course_id={}&page_size={}'.format(
|
||||
|
||||
@@ -17,7 +17,7 @@ from openedx_events.tests.utils import OpenEdxEventsTestMixin
|
||||
from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_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 ToyCourseFactory # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
from .. import cohorts
|
||||
@@ -149,7 +149,7 @@ class TestCohorts(ModuleStoreTestCase):
|
||||
"""
|
||||
Test the cohorts feature
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
@@ -648,7 +648,7 @@ class TestCohortsAndPartitionGroups(ModuleStoreTestCase):
|
||||
"""
|
||||
Test Cohorts and Partitions Groups.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
|
||||
@@ -12,7 +12,7 @@ from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartiti
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
from common.djangoapps.student.tests.factories import UserFactory
|
||||
from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_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 ToyCourseFactory # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.partitions.partitions import Group, UserPartition, UserPartitionError # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
@@ -27,7 +27,7 @@ class TestCohortPartitionScheme(ModuleStoreTestCase):
|
||||
"""
|
||||
Test the logic for linking a user to a partition group based on their cohort.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
@@ -267,7 +267,7 @@ class TestGetCohortedUserPartition(ModuleStoreTestCase):
|
||||
"""
|
||||
Test that `get_cohorted_user_partition` returns the first user_partition with scheme `CohortPartitionScheme`.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
|
||||
@@ -12,7 +12,7 @@ from unittest.mock import patch # lint-amnesty, pylint: disable=wrong-import-or
|
||||
from django.conf import settings
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.data import CertificatesDisplayBehaviors
|
||||
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 openedx.core.djangoapps.models.course_details import ABOUT_ATTRIBUTES, CourseDetails
|
||||
@@ -25,7 +25,7 @@ class CourseDetailsTestCase(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests the first course settings page (course dates, overview, etc.).
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
@@ -35,7 +35,7 @@ class CourseDetailsTestCase(ModuleStoreTestCase):
|
||||
details = CourseDetails.fetch(self.course.id)
|
||||
assert details.org == self.course.location.org, 'Org not copied into'
|
||||
assert details.course_id == self.course.location.course, 'Course_id not copied into'
|
||||
assert details.run == self.course.location.block_id, 'Course name not copied into'
|
||||
assert details.run == self.course.location.run, 'Course run not copied into'
|
||||
assert details.course_image_name == self.course.course_image
|
||||
assert details.start_date.tzinfo is not None
|
||||
assert details.end_date is None, ('end date somehow initialized ' + str(details.end_date))
|
||||
@@ -116,7 +116,7 @@ class CourseDetailsTestCase(ModuleStoreTestCase):
|
||||
jsondetails.instructor_info
|
||||
|
||||
def test_toggle_pacing_during_course_run(self):
|
||||
self.course.start = datetime.datetime.now()
|
||||
self.course.start = datetime.datetime.now(UTC)
|
||||
self.store.update_item(self.course, self.user.id)
|
||||
|
||||
details = CourseDetails.fetch(self.course.id)
|
||||
|
||||
@@ -11,7 +11,7 @@ from ddt import data, ddt, unpack
|
||||
from django.conf import settings
|
||||
from milestones import api as milestones_api
|
||||
from milestones.tests.utils import MilestonesTestCaseMixin
|
||||
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 common.djangoapps.student.tests.factories import UserFactory
|
||||
@@ -351,7 +351,7 @@ class TestGatingGradesIntegration(GradeTestBase):
|
||||
"""
|
||||
Tests the integration between the gating API and our Persistent Grades framework.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_SPLIT_MODULESTORE
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
def test_get_subsection_grade_percentage(self):
|
||||
|
||||
@@ -3,17 +3,14 @@ Tests for functionality in openedx/core/lib/courses.py.
|
||||
"""
|
||||
|
||||
|
||||
import ddt
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
from ..courses import course_image_url
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class CourseImageTestCase(ModuleStoreTestCase):
|
||||
"""Tests for course image URLs."""
|
||||
|
||||
@@ -52,13 +49,12 @@ class CourseImageTestCase(ModuleStoreTestCase):
|
||||
)
|
||||
|
||||
@override_settings(DEFAULT_COURSE_ABOUT_IMAGE_URL='test.png')
|
||||
@ddt.data(ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.mongo)
|
||||
def test_empty_image_name(self, default_store):
|
||||
def test_empty_image_name(self):
|
||||
"""
|
||||
Verify that if a course has empty `course_image`, `course_image_url` returns
|
||||
`DEFAULT_COURSE_ABOUT_IMAGE_URL` defined in the settings.
|
||||
"""
|
||||
course = CourseFactory.create(course_image='', default_store=default_store)
|
||||
course = CourseFactory.create(course_image='')
|
||||
assert '/static/test.png' == course_image_url(course)
|
||||
|
||||
def test_get_banner_image_url(self):
|
||||
|
||||
@@ -8,7 +8,6 @@ from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
|
||||
@@ -70,113 +69,63 @@ class GetCoursewareUrlTests(SharedModuleStoreTestCase):
|
||||
@classmethod
|
||||
def create_test_courses(cls):
|
||||
"""
|
||||
We build two simple course structures (one using Split, the other Old Mongo).
|
||||
Each course structure is a non-branching tree from the root Course block down
|
||||
to the Component-level problem block; that is, we make one item for each course
|
||||
hierarchy level.
|
||||
We build simple course structures.
|
||||
Course structure is a non-branching tree from the root Course block down
|
||||
to the Component-level problem block;
|
||||
|
||||
For easy access in the test functions, we return them in a dict like this:
|
||||
For easy access in the test functions, we return a dict like this:
|
||||
{
|
||||
"split": {
|
||||
"course_run": <course block for Split Mongo course>,
|
||||
"section": <chapter block in course run>
|
||||
"subsection": <sequence block in section>
|
||||
"unit": <vertical block in subsection>
|
||||
"component": <problem block in unit>
|
||||
},
|
||||
"mongo": {
|
||||
"course_run": <course block for (deprecated) Old Mongo course>,
|
||||
... etc ...
|
||||
}
|
||||
"course_run": <course block for Split Mongo course>,
|
||||
"section": <chapter block in course run>
|
||||
"subsection": <sequence block in section>
|
||||
"unit": <vertical block in subsection>
|
||||
"component": <problem block in unit>
|
||||
}
|
||||
"""
|
||||
|
||||
# Make Split Mongo course.
|
||||
with cls.store.default_store(ModuleStoreEnum.Type.split):
|
||||
course_run = CourseFactory.create(
|
||||
org='TestX',
|
||||
number='UrlHelpers',
|
||||
run='split',
|
||||
display_name='URL Helpers Test Course',
|
||||
course_run = CourseFactory.create(
|
||||
org='TestX',
|
||||
number='UrlHelpers',
|
||||
run='split',
|
||||
display_name='URL Helpers Test Course',
|
||||
)
|
||||
with cls.store.bulk_operations(course_run.id):
|
||||
section = ItemFactory.create(
|
||||
parent_location=course_run.location,
|
||||
category='chapter',
|
||||
display_name="Generated Section",
|
||||
)
|
||||
with cls.store.bulk_operations(course_run.id):
|
||||
section = ItemFactory.create(
|
||||
parent_location=course_run.location,
|
||||
category='chapter',
|
||||
display_name="Generated Section",
|
||||
)
|
||||
subsection = ItemFactory.create(
|
||||
parent_location=section.location,
|
||||
category='sequential',
|
||||
display_name="Generated Subsection",
|
||||
)
|
||||
unit = ItemFactory.create(
|
||||
parent_location=subsection.location,
|
||||
category='vertical',
|
||||
display_name="Generated Unit",
|
||||
)
|
||||
component = ItemFactory.create(
|
||||
parent_location=unit.location,
|
||||
category='problem',
|
||||
display_name="Generated Problem Component",
|
||||
)
|
||||
|
||||
# Make (deprecated) Old Mongo course.
|
||||
with cls.store.default_store(ModuleStoreEnum.Type.mongo):
|
||||
deprecated_course_run = CourseFactory.create(
|
||||
org='TestX',
|
||||
number='UrlHelpers',
|
||||
run='mongo',
|
||||
display_name='URL Helpers Test Course (Deprecated)',
|
||||
subsection = ItemFactory.create(
|
||||
parent_location=section.location,
|
||||
category='sequential',
|
||||
display_name="Generated Subsection",
|
||||
)
|
||||
unit = ItemFactory.create(
|
||||
parent_location=subsection.location,
|
||||
category='vertical',
|
||||
display_name="Generated Unit",
|
||||
)
|
||||
component = ItemFactory.create(
|
||||
parent_location=unit.location,
|
||||
category='problem',
|
||||
display_name="Generated Problem Component",
|
||||
)
|
||||
with cls.store.bulk_operations(deprecated_course_run.id):
|
||||
deprecated_section = ItemFactory.create(
|
||||
parent_location=deprecated_course_run.location,
|
||||
category='chapter',
|
||||
display_name="Generated Section",
|
||||
)
|
||||
deprecated_subsection = ItemFactory.create(
|
||||
parent_location=deprecated_section.location,
|
||||
category='sequential',
|
||||
display_name="Generated Subsection",
|
||||
)
|
||||
deprecated_unit = ItemFactory.create(
|
||||
parent_location=deprecated_subsection.location,
|
||||
category='vertical',
|
||||
display_name="Generated Unit",
|
||||
)
|
||||
deprecated_component = ItemFactory.create(
|
||||
parent_location=deprecated_unit.location,
|
||||
category='problem',
|
||||
display_name="Generated Problem Component",
|
||||
)
|
||||
|
||||
return {
|
||||
ModuleStoreEnum.Type.split: {
|
||||
'course_run': course_run,
|
||||
'section': section,
|
||||
'subsection': subsection,
|
||||
'unit': unit,
|
||||
'component': component,
|
||||
},
|
||||
ModuleStoreEnum.Type.mongo: {
|
||||
'course_run': deprecated_course_run,
|
||||
'section': deprecated_section,
|
||||
'subsection': deprecated_subsection,
|
||||
'unit': deprecated_unit,
|
||||
'component': deprecated_component,
|
||||
}
|
||||
'course_run': course_run,
|
||||
'section': section,
|
||||
'subsection': subsection,
|
||||
'unit': unit,
|
||||
'component': component,
|
||||
}
|
||||
|
||||
@ddt.data(
|
||||
(
|
||||
ModuleStoreEnum.Type.split,
|
||||
'mfe',
|
||||
'course_run',
|
||||
'http://learning-mfe/course/course-v1:TestX+UrlHelpers+split'
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.split,
|
||||
'mfe',
|
||||
'section',
|
||||
(
|
||||
@@ -185,7 +134,6 @@ class GetCoursewareUrlTests(SharedModuleStoreTestCase):
|
||||
),
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.split,
|
||||
'mfe',
|
||||
'subsection',
|
||||
(
|
||||
@@ -194,7 +142,6 @@ class GetCoursewareUrlTests(SharedModuleStoreTestCase):
|
||||
),
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.split,
|
||||
'mfe',
|
||||
'unit',
|
||||
(
|
||||
@@ -204,7 +151,6 @@ class GetCoursewareUrlTests(SharedModuleStoreTestCase):
|
||||
),
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.split,
|
||||
'mfe',
|
||||
'component',
|
||||
(
|
||||
@@ -214,58 +160,29 @@ class GetCoursewareUrlTests(SharedModuleStoreTestCase):
|
||||
),
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.split,
|
||||
'legacy',
|
||||
'course_run',
|
||||
'/courses/course-v1:TestX+UrlHelpers+split/courseware',
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.split,
|
||||
'legacy',
|
||||
'subsection',
|
||||
'/courses/course-v1:TestX+UrlHelpers+split/courseware/Generated_Section/Generated_Subsection/',
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.split,
|
||||
'legacy',
|
||||
'unit',
|
||||
'/courses/course-v1:TestX+UrlHelpers+split/courseware/Generated_Section/Generated_Subsection/1',
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.split,
|
||||
'legacy',
|
||||
'component',
|
||||
'/courses/course-v1:TestX+UrlHelpers+split/courseware/Generated_Section/Generated_Subsection/1',
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.mongo,
|
||||
'legacy',
|
||||
'course_run',
|
||||
'/courses/TestX/UrlHelpers/mongo/courseware',
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.mongo,
|
||||
'legacy',
|
||||
'subsection',
|
||||
'/courses/TestX/UrlHelpers/mongo/courseware/Generated_Section/Generated_Subsection/',
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.mongo,
|
||||
'legacy',
|
||||
'unit',
|
||||
'/courses/TestX/UrlHelpers/mongo/courseware/Generated_Section/Generated_Subsection/1',
|
||||
),
|
||||
(
|
||||
ModuleStoreEnum.Type.mongo,
|
||||
'legacy',
|
||||
'component',
|
||||
'/courses/TestX/UrlHelpers/mongo/courseware/Generated_Section/Generated_Subsection/1',
|
||||
),
|
||||
)
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_get_courseware_url(
|
||||
self,
|
||||
store_type,
|
||||
active_experience,
|
||||
structure_level,
|
||||
expected_path,
|
||||
@@ -278,10 +195,10 @@ class GetCoursewareUrlTests(SharedModuleStoreTestCase):
|
||||
|
||||
check that the expected path (URL without querystring) is returned by `get_courseware_url`.
|
||||
"""
|
||||
block = self.items[store_type][structure_level]
|
||||
block = self.items[structure_level]
|
||||
with _patch_courseware_mfe_is_active(active_experience == 'mfe') as mock_mfe_is_active:
|
||||
url = url_helpers.get_courseware_url(block.location)
|
||||
path = url.split('?')[0]
|
||||
assert path == expected_path
|
||||
course_run = self.items[store_type]['course_run']
|
||||
course_run = self.items['course_run']
|
||||
mock_mfe_is_active.assert_called_once()
|
||||
|
||||
@@ -28,9 +28,6 @@ class CompletionBatchTestCase(CompletionWaffleTestMixin, ModuleStoreTestCase):
|
||||
UNENROLLED_USERNAME = 'unenrolled_user'
|
||||
COURSE_KEY = 'course-v1:TestX+101+Test'
|
||||
BLOCK_KEY = 'block-v1:TestX+101+Test+type@problem+block@Test_Problem'
|
||||
# And for old mongo:
|
||||
COURSE_KEY_DEPRECATED = 'TestX/201/Test'
|
||||
BLOCK_KEY_DEPRECATED = 'i4x://TestX/201/problem/Test_Problem'
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
@@ -52,17 +49,6 @@ class CompletionBatchTestCase(CompletionWaffleTestMixin, ModuleStoreTestCase):
|
||||
parent=self.course, category="problem", display_name="Test Problem", publish_item=False,
|
||||
)
|
||||
assert str(self.problem.location) == self.BLOCK_KEY
|
||||
# And an old mongo course:
|
||||
self.course_deprecated = CourseFactory.create(
|
||||
org='TestX', number='201', display_name='Test',
|
||||
default_store=ModuleStoreEnum.Type.mongo,
|
||||
)
|
||||
assert str(self.course_deprecated.id) == self.COURSE_KEY_DEPRECATED
|
||||
self.problem_deprecated = ItemFactory.create(
|
||||
parent=self.course_deprecated, category="problem", display_name="Test Problem",
|
||||
publish_item=False,
|
||||
)
|
||||
assert str(self.problem_deprecated.location) == self.BLOCK_KEY_DEPRECATED
|
||||
|
||||
# Create users
|
||||
self.staff_user = UserFactory(is_staff=True)
|
||||
@@ -71,7 +57,6 @@ class CompletionBatchTestCase(CompletionWaffleTestMixin, ModuleStoreTestCase):
|
||||
|
||||
# Enrol one user in the course
|
||||
CourseEnrollmentFactory.create(user=self.enrolled_user, course_id=self.course.id)
|
||||
CourseEnrollmentFactory.create(user=self.enrolled_user, course_id=self.course_deprecated.id)
|
||||
|
||||
# Login the enrolled user by for all tests
|
||||
self.client = APIClient()
|
||||
@@ -101,16 +86,6 @@ class CompletionBatchTestCase(CompletionWaffleTestMixin, ModuleStoreTestCase):
|
||||
}
|
||||
}, 200, {'detail': 'ok'}
|
||||
),
|
||||
# Valid submission (old mongo)
|
||||
(
|
||||
{
|
||||
'username': ENROLLED_USERNAME,
|
||||
'course_key': COURSE_KEY_DEPRECATED,
|
||||
'blocks': {
|
||||
BLOCK_KEY_DEPRECATED: 1.0,
|
||||
}
|
||||
}, 200, {'detail': 'ok'}
|
||||
),
|
||||
# Blocks list can be empty, though it's a no-op
|
||||
(
|
||||
{
|
||||
@@ -222,16 +197,6 @@ class CompletionBatchTestCase(CompletionWaffleTestMixin, ModuleStoreTestCase):
|
||||
}
|
||||
}, 200, {'detail': 'ok'}
|
||||
),
|
||||
# Staff can submit completion on behalf of other users (old mongo)
|
||||
(
|
||||
{
|
||||
'username': ENROLLED_USERNAME,
|
||||
'course_key': COURSE_KEY_DEPRECATED,
|
||||
'blocks': {
|
||||
BLOCK_KEY_DEPRECATED: 1.0,
|
||||
}
|
||||
}, 200, {'detail': 'ok'}
|
||||
),
|
||||
# User must be enrolled in the course
|
||||
(
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@ from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.draft_and_published import DIRECT_ONLY_CATEGORIES
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MONGO_MODULESTORE
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
|
||||
DETACHED_BLOCK_TYPES = dict(XBlock.load_tagged_classes('detached'))
|
||||
|
||||
@@ -403,13 +403,7 @@ class DirectOnlyCategorySemantics(ModuleStoreTestCase):
|
||||
self.assertCoursePointsToBlock(block_usage_key)
|
||||
self.assertNotParentOf(block_usage_key, child_usage_key)
|
||||
|
||||
if child_published and self.store.get_modulestore_type(self.course.id) == ModuleStoreEnum.Type.mongo:
|
||||
# N.B. This block is being left as an orphan in old-mongo. This test will
|
||||
# fail when that is fixed. At that time, this condition should just be removed,
|
||||
# as SplitMongo and OldMongo will have the same semantics.
|
||||
self.assertBlockHasContent(child_usage_key, 'data', child_data)
|
||||
else:
|
||||
self.assertBlockDoesntExist(child_usage_key)
|
||||
self.assertBlockDoesntExist(child_usage_key)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@@ -444,19 +438,3 @@ class TestSplitDirectOnlyCategorySemantics(DirectOnlyCategorySemantics):
|
||||
|
||||
self.assertBlockHasContent(block_usage_key, test_data.field_name, test_data.initial,
|
||||
self.ASIDE_DATA_FIELD.field_name, self.ASIDE_DATA_FIELD.updated)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestMongoDirectOnlyCategorySemantics(DirectOnlyCategorySemantics):
|
||||
"""
|
||||
Verify DIRECT_ONLY_CATEGORY semantics against the MongoModulestore
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MONGO_MODULESTORE
|
||||
__test__ = True
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Branch.draft_preferred, ModuleStoreEnum.Branch.published_only)
|
||||
def test_course_summaries(self, branch):
|
||||
""" Test that `get_course_summaries` method in modulestore work as expected. """
|
||||
with self.store.branch_setting(branch_setting=branch):
|
||||
course_summaries = self.store.get_course_summaries()
|
||||
assert len(course_summaries) == 1
|
||||
|
||||
Reference in New Issue
Block a user