Merge pull request #11042 from edx/jeskew/xml_removal
Remove XML modulestore code from most tests.
This commit is contained in:
@@ -29,10 +29,6 @@ class TestArgParsing(unittest.TestCase):
|
||||
with self.assertRaises(CommandError):
|
||||
self.command.handle("foo", "user@foo.org", "org", "course", "run")
|
||||
|
||||
def test_xml_store(self):
|
||||
with self.assertRaises(CommandError):
|
||||
self.command.handle(ModuleStoreEnum.Type.xml, "user@foo.org", "org", "course", "run")
|
||||
|
||||
def test_nonexistent_user_id(self):
|
||||
errstring = "No user 99 found"
|
||||
with self.assertRaisesRegexp(CommandError, errstring):
|
||||
|
||||
@@ -124,15 +124,6 @@ class MixedWithOptionsTestCase(MixedSplitTestCase):
|
||||
'DOC_STORE_CONFIG': DOC_STORE_CONFIG,
|
||||
'OPTIONS': modulestore_options
|
||||
},
|
||||
{
|
||||
'NAME': 'xml',
|
||||
'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore',
|
||||
'OPTIONS': {
|
||||
'data_dir': DATA_DIR,
|
||||
'default_class': 'xmodule.hidden_module.HiddenDescriptor',
|
||||
'xblock_mixins': modulestore_options['xblock_mixins'],
|
||||
}
|
||||
},
|
||||
],
|
||||
'xblock_mixins': modulestore_options['xblock_mixins'],
|
||||
}
|
||||
|
||||
@@ -34,9 +34,7 @@ from embargo.exceptions import InvalidAccessPoint
|
||||
from mock import patch
|
||||
|
||||
|
||||
# Since we don't need any XML course fixtures, use a modulestore configuration
|
||||
# that disables the XML modulestore.
|
||||
MODULESTORE_CONFIG = mixed_store_config(settings.COMMON_TEST_DATA_ROOT, {}, include_xml=False)
|
||||
MODULESTORE_CONFIG = mixed_store_config(settings.COMMON_TEST_DATA_ROOT, {})
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
|
||||
@@ -163,9 +163,7 @@ def replace_static_urls(text, data_directory=None, course_id=None, static_asset_
|
||||
if settings.DEBUG and finders.find(rest, True):
|
||||
return original
|
||||
# if we're running with a MongoBacked store course_namespace is not None, then use studio style urls
|
||||
elif (not static_asset_path) \
|
||||
and course_id \
|
||||
and modulestore().get_modulestore_type(course_id) != ModuleStoreEnum.Type.xml:
|
||||
elif (not static_asset_path) and course_id:
|
||||
# first look in the static file pipeline and see if we are trying to reference
|
||||
# a piece of static content which is in the edx-platform repo (e.g. JS associated with an xmodule)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
|
||||
from student.tests.factories import UserFactory, CourseEnrollmentFactory
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_MODULESTORE
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
# This import is for an lms djangoapp.
|
||||
@@ -90,7 +90,7 @@ class TestStudentDashboardEmailViewXMLBacked(SharedModuleStoreTestCase):
|
||||
"""
|
||||
Check for email view on student dashboard, with XML backed course.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
super(TestStudentDashboardEmailViewXMLBacked, self).setUp()
|
||||
|
||||
@@ -649,7 +649,6 @@ def dashboard(request):
|
||||
show_email_settings_for = frozenset(
|
||||
enrollment.course_id for enrollment in course_enrollments if (
|
||||
settings.FEATURES['ENABLE_INSTRUCTOR_EMAIL'] and
|
||||
modulestore().get_modulestore_type(enrollment.course_id) != ModuleStoreEnum.Type.xml and
|
||||
CourseAuthorization.instructor_email_enabled(enrollment.course_id)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -175,7 +175,7 @@ class CourseFields(object):
|
||||
scope=Scope.settings
|
||||
)
|
||||
textbooks = TextbookList(
|
||||
help=_("List of pairs of (title, url) for textbooks used in this course"),
|
||||
help=_("List of Textbook objects with (title, url) for textbooks used in this course"),
|
||||
default=[],
|
||||
scope=Scope.content
|
||||
)
|
||||
|
||||
@@ -55,7 +55,6 @@ class ModuleStoreEnum(object):
|
||||
"""
|
||||
split = 'split'
|
||||
mongo = 'mongo'
|
||||
xml = 'xml'
|
||||
|
||||
class RevisionOption(object):
|
||||
"""
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
MixedModuleStore allows for aggregation between multiple modulestores.
|
||||
|
||||
In this way, courses can be served up both - say - XMLModuleStore or MongoModuleStore
|
||||
In this way, courses can be served up via either SplitMongoModuleStore or MongoModuleStore.
|
||||
|
||||
"""
|
||||
|
||||
@@ -169,15 +169,6 @@ class MixedModuleStore(ModuleStoreDraftAndPublished, ModuleStoreWriteBase):
|
||||
|
||||
for store_settings in stores:
|
||||
key = store_settings['NAME']
|
||||
is_xml = 'XMLModuleStore' in store_settings['ENGINE']
|
||||
if is_xml:
|
||||
# restrict xml to only load courses in mapping
|
||||
store_settings['OPTIONS']['course_ids'] = [
|
||||
course_key.to_deprecated_string()
|
||||
for course_key, store_key in self.mappings.iteritems()
|
||||
if store_key == key
|
||||
]
|
||||
|
||||
store = create_modulestore_instance(
|
||||
store_settings['ENGINE'],
|
||||
self.contentstore,
|
||||
|
||||
@@ -29,13 +29,13 @@ from openedx.core.djangoapps.bookmarks.signals import trigger_update_xblocks_cac
|
||||
|
||||
class StoreConstructors(object):
|
||||
"""Enumeration of store constructor types."""
|
||||
draft, split, xml = range(3)
|
||||
draft, split = range(2)
|
||||
|
||||
|
||||
def mixed_store_config(data_dir, mappings, include_xml=False, xml_source_dirs=None, store_order=None):
|
||||
def mixed_store_config(data_dir, mappings, store_order=None):
|
||||
"""
|
||||
Return a `MixedModuleStore` configuration, which provides
|
||||
access to both Mongo- and XML-backed courses.
|
||||
access to both Mongo-backed courses.
|
||||
|
||||
Args:
|
||||
data_dir (string): the directory from which to load XML-backed courses.
|
||||
@@ -51,26 +51,15 @@ def mixed_store_config(data_dir, mappings, include_xml=False, xml_source_dirs=No
|
||||
|
||||
Keyword Args:
|
||||
|
||||
include_xml (boolean): If True, include an XML modulestore in the configuration.
|
||||
xml_source_dirs (list): The directories containing XML courses to load from disk.
|
||||
|
||||
note: For the courses to be loaded into the XML modulestore and accessible do the following:
|
||||
* include_xml should be True
|
||||
* xml_source_dirs should be the list of directories (relative to data_dir)
|
||||
containing the courses you want to load
|
||||
* mappings should be configured, pointing the xml courses to the xml modulestore
|
||||
|
||||
store_order (list): List of StoreConstructors providing order of modulestores
|
||||
to use in creating courses.
|
||||
"""
|
||||
if store_order is None:
|
||||
store_order = [StoreConstructors.draft, StoreConstructors.split]
|
||||
|
||||
if include_xml and StoreConstructors.xml not in store_order:
|
||||
store_order.append(StoreConstructors.xml)
|
||||
|
||||
store_constructors = {
|
||||
StoreConstructors.split: split_mongo_store_config(data_dir)['default'],
|
||||
StoreConstructors.draft: draft_mongo_store_config(data_dir)['default'],
|
||||
StoreConstructors.xml: xml_store_config(data_dir, source_dirs=xml_source_dirs)['default'],
|
||||
}
|
||||
|
||||
store = {
|
||||
@@ -140,28 +129,6 @@ def split_mongo_store_config(data_dir):
|
||||
return store
|
||||
|
||||
|
||||
def xml_store_config(data_dir, source_dirs=None):
|
||||
"""
|
||||
Defines default module store using XMLModuleStore.
|
||||
|
||||
Note: you should pass in a list of source_dirs that you care about,
|
||||
otherwise all courses in the data_dir will be processed.
|
||||
"""
|
||||
store = {
|
||||
'default': {
|
||||
'NAME': 'xml',
|
||||
'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore',
|
||||
'OPTIONS': {
|
||||
'data_dir': data_dir,
|
||||
'default_class': 'xmodule.hidden_module.HiddenDescriptor',
|
||||
'source_dirs': source_dirs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return store
|
||||
|
||||
|
||||
@patch('xmodule.modulestore.django.create_modulestore_instance', autospec=True)
|
||||
def drop_mongo_collections(mock_create):
|
||||
"""
|
||||
@@ -180,39 +147,25 @@ def drop_mongo_collections(mock_create):
|
||||
|
||||
TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT
|
||||
|
||||
# This is an XML only modulestore with only the toy course loaded
|
||||
TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR, source_dirs=['toy'])
|
||||
|
||||
# This modulestore will provide both a mixed mongo editable modulestore, and
|
||||
# an XML store with just the toy course loaded.
|
||||
TEST_DATA_MIXED_TOY_MODULESTORE = mixed_store_config(
|
||||
TEST_DATA_DIR, {'edX/toy/2012_Fall': 'xml', }, include_xml=True, xml_source_dirs=['toy']
|
||||
)
|
||||
|
||||
# This modulestore will provide both a mixed mongo editable modulestore, and
|
||||
# an XML store with common/test/data/2014 loaded, which is a course that is closed.
|
||||
TEST_DATA_MIXED_CLOSED_MODULESTORE = mixed_store_config(
|
||||
TEST_DATA_DIR, {'edX/detached_pages/2014': 'xml', }, include_xml=True, xml_source_dirs=['2014']
|
||||
)
|
||||
|
||||
# This modulestore will provide both a mixed mongo editable modulestore, and
|
||||
# an XML store with common/test/data/graded loaded, which is a course that is graded.
|
||||
TEST_DATA_MIXED_GRADED_MODULESTORE = mixed_store_config(
|
||||
TEST_DATA_DIR, {'edX/graded/2012_Fall': 'xml', }, include_xml=True, xml_source_dirs=['graded']
|
||||
# This modulestore will provide a mixed mongo editable modulestore.
|
||||
# If your test uses the 'toy' course, use the the ToyCourseFactory to construct it.
|
||||
# If your test needs a closed course to test against, import the common/test/data/2014
|
||||
# test course into this modulestore.
|
||||
# If your test needs a graded course to test against, import the common/test/data/graded
|
||||
# test course into this modulestore.
|
||||
TEST_DATA_MIXED_MODULESTORE = mixed_store_config(
|
||||
TEST_DATA_DIR, {}
|
||||
)
|
||||
|
||||
# All store requests now go through mixed
|
||||
# Use this modulestore if you specifically want to test mongo and not a mocked modulestore.
|
||||
# This modulestore definition below will not load any xml courses.
|
||||
TEST_DATA_MONGO_MODULESTORE = mixed_store_config(mkdtemp_clean(), {}, include_xml=False)
|
||||
TEST_DATA_MONGO_MODULESTORE = mixed_store_config(mkdtemp_clean(), {})
|
||||
|
||||
# All store requests now go through mixed
|
||||
# Use this modulestore if you specifically want to test split-mongo and not a mocked modulestore.
|
||||
# This modulestore definition below will not load any xml courses.
|
||||
TEST_DATA_SPLIT_MODULESTORE = mixed_store_config(
|
||||
mkdtemp_clean(),
|
||||
{},
|
||||
include_xml=False,
|
||||
store_order=[StoreConstructors.split, StoreConstructors.draft]
|
||||
)
|
||||
|
||||
@@ -265,7 +218,7 @@ class SharedModuleStoreTestCase(TestCase):
|
||||
In Django 1.8, we will be able to use setUpTestData() to do class level init
|
||||
for Django ORM models that will get cleaned up properly.
|
||||
"""
|
||||
MODULESTORE = mixed_store_config(mkdtemp_clean(), {}, include_xml=False)
|
||||
MODULESTORE = mixed_store_config(mkdtemp_clean(), {})
|
||||
# Tell Django to clean out all databases, not just default
|
||||
multi_db = True
|
||||
|
||||
@@ -429,7 +382,7 @@ class ModuleStoreTestCase(TestCase):
|
||||
your `setUp()` method.
|
||||
"""
|
||||
|
||||
MODULESTORE = mixed_store_config(mkdtemp_clean(), {}, include_xml=False)
|
||||
MODULESTORE = mixed_store_config(mkdtemp_clean(), {})
|
||||
# Tell Django to clean out all databases, not just default
|
||||
multi_db = True
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ from xmodule.modulestore import prefer_xmodules, ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.sample_courses import default_block_info_tree, TOY_BLOCK_INFO_TREE
|
||||
from xmodule.tabs import CourseTab
|
||||
from xmodule.x_module import DEPRECATION_VSCOMPAT_EVENT
|
||||
from xmodule.course_module import Textbook
|
||||
|
||||
|
||||
class Dummy(object):
|
||||
@@ -190,7 +191,7 @@ class ToyCourseFactory(SampleCourseFactory):
|
||||
|
||||
fields = {
|
||||
'block_info_tree': TOY_BLOCK_INFO_TREE,
|
||||
'textbooks': [["Textbook", "path/to/a/text_book"]],
|
||||
'textbooks': [Textbook("Textbook", "path/to/a/text_book")],
|
||||
'wiki_slug': "toy",
|
||||
'graded': True,
|
||||
'discussion_topics': {"General": {"id": "i4x-edX-toy-course-2012_Fall"}},
|
||||
|
||||
@@ -74,9 +74,6 @@ class CommonMixedModuleStoreSetup(CourseComparisonTest):
|
||||
RENDER_TEMPLATE = lambda t_n, d, ctx=None, nsp='main': ''
|
||||
|
||||
MONGO_COURSEID = 'MITx/999/2013_Spring'
|
||||
XML_COURSEID1 = 'edX/toy/2012_Fall'
|
||||
XML_COURSEID2 = 'edX/simple/2012_Fall'
|
||||
BAD_COURSE_ID = 'edX/simple'
|
||||
|
||||
modulestore_options = {
|
||||
'default_class': DEFAULT_CLASS,
|
||||
@@ -91,11 +88,6 @@ class CommonMixedModuleStoreSetup(CourseComparisonTest):
|
||||
'collection': COLLECTION,
|
||||
'asset_collection': ASSET_COLLECTION,
|
||||
}
|
||||
MAPPINGS = {
|
||||
XML_COURSEID1: 'xml',
|
||||
XML_COURSEID2: 'xml',
|
||||
BAD_COURSE_ID: 'xml',
|
||||
}
|
||||
OPTIONS = {
|
||||
'stores': [
|
||||
{
|
||||
@@ -110,15 +102,6 @@ class CommonMixedModuleStoreSetup(CourseComparisonTest):
|
||||
'DOC_STORE_CONFIG': DOC_STORE_CONFIG,
|
||||
'OPTIONS': modulestore_options
|
||||
},
|
||||
{
|
||||
'NAME': ModuleStoreEnum.Type.xml,
|
||||
'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore',
|
||||
'OPTIONS': {
|
||||
'data_dir': DATA_DIR,
|
||||
'default_class': 'xmodule.hidden_module.HiddenDescriptor',
|
||||
'xblock_mixins': modulestore_options['xblock_mixins'],
|
||||
}
|
||||
},
|
||||
],
|
||||
'xblock_mixins': modulestore_options['xblock_mixins'],
|
||||
}
|
||||
@@ -157,7 +140,7 @@ class CommonMixedModuleStoreSetup(CourseComparisonTest):
|
||||
self.addTypeEqualityFunc(BlockUsageLocator, '_compare_ignore_version')
|
||||
self.addTypeEqualityFunc(CourseLocator, '_compare_ignore_version')
|
||||
# define attrs which get set in initdb to quell pylint
|
||||
self.writable_chapter_location = self.store = self.fake_location = self.xml_chapter_location = None
|
||||
self.writable_chapter_location = self.store = self.fake_location = None
|
||||
self.course_locations = {}
|
||||
|
||||
self.user_id = ModuleStoreEnum.UserID.test
|
||||
@@ -257,10 +240,11 @@ class CommonMixedModuleStoreSetup(CourseComparisonTest):
|
||||
return self.store.has_changes(self.store.get_item(location))
|
||||
|
||||
# pylint: disable=dangerous-default-value
|
||||
def _initialize_mixed(self, mappings=MAPPINGS, contentstore=None):
|
||||
def _initialize_mixed(self, mappings=None, contentstore=None):
|
||||
"""
|
||||
initializes the mixed modulestore.
|
||||
"""
|
||||
mappings = mappings or {}
|
||||
self.store = MixedModuleStore(
|
||||
contentstore, create_modulestore_instance=create_modulestore_instance,
|
||||
mappings=mappings,
|
||||
@@ -281,25 +265,14 @@ class CommonMixedModuleStoreSetup(CourseComparisonTest):
|
||||
break
|
||||
self._initialize_mixed()
|
||||
|
||||
# convert to CourseKeys
|
||||
self.course_locations = {
|
||||
course_id: CourseLocator.from_string(course_id)
|
||||
for course_id in [self.MONGO_COURSEID, self.XML_COURSEID1, self.XML_COURSEID2]
|
||||
}
|
||||
# and then to the root UsageKey
|
||||
self.course_locations = {
|
||||
course_id: course_key.make_usage_key('course', course_key.run)
|
||||
for course_id, course_key in self.course_locations.iteritems()
|
||||
}
|
||||
|
||||
mongo_course_key = self.course_locations[self.MONGO_COURSEID].course_key
|
||||
self.fake_location = self.store.make_course_key(mongo_course_key.org, mongo_course_key.course, mongo_course_key.run).make_usage_key('vertical', 'fake')
|
||||
|
||||
self.xml_chapter_location = self.course_locations[self.XML_COURSEID1].replace(
|
||||
category='chapter', name='Overview'
|
||||
)
|
||||
|
||||
self._create_course(self.course_locations[self.MONGO_COURSEID].course_key)
|
||||
test_course_key = CourseLocator.from_string(self.MONGO_COURSEID)
|
||||
test_course_key = test_course_key.make_usage_key('course', test_course_key.run).course_key
|
||||
self.fake_location = self.store.make_course_key(
|
||||
test_course_key.org,
|
||||
test_course_key.course,
|
||||
test_course_key.run
|
||||
).make_usage_key('vertical', 'fake')
|
||||
self._create_course(test_course_key)
|
||||
|
||||
self.assertEquals(default, self.store.get_modulestore_type(self.course.id))
|
||||
|
||||
@@ -346,12 +319,6 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
Make sure we get back the store type we expect for given mappings
|
||||
"""
|
||||
self.initdb(default_ms)
|
||||
self.assertEqual(self.store.get_modulestore_type(
|
||||
self._course_key_from_string(self.XML_COURSEID1)), ModuleStoreEnum.Type.xml
|
||||
)
|
||||
self.assertEqual(self.store.get_modulestore_type(
|
||||
self._course_key_from_string(self.XML_COURSEID2)), ModuleStoreEnum.Type.xml
|
||||
)
|
||||
self.assertEqual(self.store.get_modulestore_type(
|
||||
self._course_key_from_string(self.MONGO_COURSEID)), default_ms
|
||||
)
|
||||
@@ -401,15 +368,10 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
self.initdb(default_ms)
|
||||
self._create_block_hierarchy()
|
||||
|
||||
self.assertTrue(self.store.has_item(self.course_locations[self.XML_COURSEID1]))
|
||||
|
||||
with check_mongo_calls(max_find.pop(0), max_send):
|
||||
self.assertTrue(self.store.has_item(self.problem_x1a_1))
|
||||
|
||||
# try negative cases
|
||||
self.assertFalse(self.store.has_item(
|
||||
self.course_locations[self.XML_COURSEID1].replace(name='not_findable', category='problem')
|
||||
))
|
||||
with check_mongo_calls(max_find.pop(0), max_send):
|
||||
self.assertFalse(self.store.has_item(self.fake_location))
|
||||
|
||||
@@ -429,16 +391,10 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
self.initdb(default_ms)
|
||||
self._create_block_hierarchy()
|
||||
|
||||
self.assertIsNotNone(self.store.get_item(self.course_locations[self.XML_COURSEID1]))
|
||||
|
||||
with check_mongo_calls(max_find.pop(0), max_send):
|
||||
self.assertIsNotNone(self.store.get_item(self.problem_x1a_1))
|
||||
|
||||
# try negative cases
|
||||
with self.assertRaises(ItemNotFoundError):
|
||||
self.store.get_item(
|
||||
self.course_locations[self.XML_COURSEID1].replace(name='not_findable', category='problem')
|
||||
)
|
||||
with check_mongo_calls(max_find.pop(0), max_send):
|
||||
with self.assertRaises(ItemNotFoundError):
|
||||
self.store.get_item(self.fake_location)
|
||||
@@ -457,12 +413,6 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
self.initdb(default_ms)
|
||||
self._create_block_hierarchy()
|
||||
|
||||
course_locn = self.course_locations[self.XML_COURSEID1]
|
||||
# NOTE: use get_course if you just want the course. get_items is expensive
|
||||
modules = self.store.get_items(course_locn.course_key, qualifiers={'category': 'course'})
|
||||
self.assertEqual(len(modules), 1)
|
||||
self.assertEqual(modules[0].location, course_locn)
|
||||
|
||||
course_locn = self.course_locations[self.MONGO_COURSEID]
|
||||
with check_mongo_calls(max_find, max_send):
|
||||
modules = self.store.get_items(course_locn.course_key, qualifiers={'category': 'problem'})
|
||||
@@ -545,18 +495,10 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
@ddt.unpack
|
||||
def test_update_item(self, default_ms, max_find, max_send):
|
||||
"""
|
||||
Update should fail for r/o dbs and succeed for r/w ones
|
||||
Update should succeed for r/w dbs
|
||||
"""
|
||||
self.initdb(default_ms)
|
||||
self._create_block_hierarchy()
|
||||
course = self.store.get_course(self.course_locations[self.XML_COURSEID1].course_key)
|
||||
# if following raised, then the test is really a noop, change it
|
||||
self.assertFalse(course.show_calculator, "Default changed making test meaningless")
|
||||
course.show_calculator = True
|
||||
with self.assertRaises(NotImplementedError): # ensure it doesn't allow writing
|
||||
self.store.update_item(course, self.user_id)
|
||||
|
||||
# now do it for a r/w db
|
||||
problem = self.store.get_item(self.problem_x1a_1)
|
||||
# if following raised, then the test is really a noop, change it
|
||||
self.assertNotEqual(problem.max_attempts, 2, "Default changed making test meaningless")
|
||||
@@ -953,10 +895,6 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
if default_ms == ModuleStoreEnum.Type.mongo and mongo_uses_error_check(self.store):
|
||||
max_find += 1
|
||||
|
||||
# r/o try deleting the chapter (is here to ensure it can't be deleted)
|
||||
with self.assertRaises(NotImplementedError):
|
||||
self.store.delete_item(self.xml_chapter_location, self.user_id)
|
||||
|
||||
with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.writable_chapter_location.course_key):
|
||||
with check_mongo_calls(max_find, max_send):
|
||||
self.store.delete_item(self.writable_chapter_location, self.user_id)
|
||||
@@ -1075,14 +1013,12 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
@ddt.unpack
|
||||
def test_get_courses(self, default_ms, max_find, max_send):
|
||||
self.initdb(default_ms)
|
||||
# we should have 3 total courses across all stores
|
||||
# we should have one course across all stores
|
||||
with check_mongo_calls(max_find, max_send):
|
||||
courses = self.store.get_courses()
|
||||
course_ids = [course.location for course in courses]
|
||||
self.assertEqual(len(courses), 3, "Not 3 courses: {}".format(course_ids))
|
||||
self.assertEqual(len(courses), 1, "Not one course: {}".format(course_ids))
|
||||
self.assertIn(self.course_locations[self.MONGO_COURSEID], course_ids)
|
||||
self.assertIn(self.course_locations[self.XML_COURSEID1], course_ids)
|
||||
self.assertIn(self.course_locations[self.XML_COURSEID2], course_ids)
|
||||
|
||||
with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred):
|
||||
draft_courses = self.store.get_courses(remove_branch=True)
|
||||
@@ -1111,30 +1047,6 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
mongo_course = self.store.get_course(self.course_locations[self.MONGO_COURSEID].course_key)
|
||||
self.assertEqual(len(mongo_course.children), 1)
|
||||
|
||||
def test_xml_get_courses(self):
|
||||
"""
|
||||
Test that the xml modulestore only loaded the courses from the maps.
|
||||
"""
|
||||
self.initdb(ModuleStoreEnum.Type.mongo)
|
||||
xml_store = self.store._get_modulestore_by_type(ModuleStoreEnum.Type.xml) # pylint: disable=protected-access
|
||||
courses = xml_store.get_courses()
|
||||
self.assertEqual(len(courses), 2)
|
||||
course_ids = [course.id for course in courses]
|
||||
self.assertIn(self.course_locations[self.XML_COURSEID1].course_key, course_ids)
|
||||
self.assertIn(self.course_locations[self.XML_COURSEID2].course_key, course_ids)
|
||||
# this course is in the directory from which we loaded courses but not in the map
|
||||
self.assertNotIn("edX/toy/TT_2012_Fall", course_ids)
|
||||
|
||||
def test_xml_no_write(self):
|
||||
"""
|
||||
Test that the xml modulestore doesn't allow write ops.
|
||||
"""
|
||||
self.initdb(ModuleStoreEnum.Type.mongo)
|
||||
xml_store = self.store._get_modulestore_by_type(ModuleStoreEnum.Type.xml) # pylint: disable=protected-access
|
||||
# the important thing is not which exception it raises but that it raises an exception
|
||||
with self.assertRaises(AttributeError):
|
||||
xml_store.create_course("org", "course", "run", self.user_id)
|
||||
|
||||
# draft is 2: find out which ms owns course, get item
|
||||
# split: active_versions, structure, definition (to load course wiki string)
|
||||
@ddt.data((ModuleStoreEnum.Type.mongo, 2, 0), (ModuleStoreEnum.Type.split, 3, 0))
|
||||
@@ -1149,9 +1061,6 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
course = self.store.get_item(self.course_locations[self.MONGO_COURSEID])
|
||||
self.assertEqual(course.id, self.course_locations[self.MONGO_COURSEID].course_key)
|
||||
|
||||
course = self.store.get_item(self.course_locations[self.XML_COURSEID1])
|
||||
self.assertEqual(course.id, self.course_locations[self.XML_COURSEID1].course_key)
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_get_library(self, default_ms):
|
||||
"""
|
||||
@@ -1190,9 +1099,6 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
parent = self.store.get_parent_location(self.problem_x1a_1)
|
||||
self.assertEqual(parent, self.vertical_x1a)
|
||||
|
||||
parent = self.store.get_parent_location(self.xml_chapter_location)
|
||||
self.assertEqual(parent, self.course_locations[self.XML_COURSEID1])
|
||||
|
||||
def verify_get_parent_locations_results(self, expected_results):
|
||||
"""
|
||||
Verifies the results of calling get_parent_locations matches expected_results.
|
||||
@@ -1373,34 +1279,6 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
with self.assertRaises(NoPathToItem):
|
||||
path_to_location(self.store, orphan)
|
||||
|
||||
def test_xml_path_to_location(self):
|
||||
"""
|
||||
Make sure that path_to_location works: should be passed a modulestore
|
||||
with the toy and simple courses loaded.
|
||||
"""
|
||||
# only needs course_locations set
|
||||
self.initdb(ModuleStoreEnum.Type.mongo)
|
||||
course_key = self.course_locations[self.XML_COURSEID1].course_key
|
||||
video_key = course_key.make_usage_key('video', 'Welcome')
|
||||
chapter_key = course_key.make_usage_key('chapter', 'Overview')
|
||||
should_work = (
|
||||
(video_key,
|
||||
(course_key, "Overview", "Welcome", None, None, video_key)),
|
||||
(chapter_key,
|
||||
(course_key, "Overview", None, None, None, chapter_key)),
|
||||
)
|
||||
|
||||
for location, expected in should_work:
|
||||
self.assertEqual(path_to_location(self.store, location), expected)
|
||||
|
||||
not_found = (
|
||||
course_key.make_usage_key('video', 'WelcomeX'),
|
||||
course_key.make_usage_key('course', 'NotHome'),
|
||||
)
|
||||
for location in not_found:
|
||||
with self.assertRaises(ItemNotFoundError):
|
||||
path_to_location(self.store, location)
|
||||
|
||||
def test_navigation_index(self):
|
||||
"""
|
||||
Make sure that navigation_index correctly parses the various position values that we might get from calls to
|
||||
@@ -1652,15 +1530,6 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
Test the get_courses_for_wiki method
|
||||
"""
|
||||
self.initdb(default_ms)
|
||||
# Test XML wikis
|
||||
wiki_courses = self.store.get_courses_for_wiki('toy')
|
||||
self.assertEqual(len(wiki_courses), 1)
|
||||
self.assertIn(self.course_locations[self.XML_COURSEID1].course_key, wiki_courses)
|
||||
|
||||
wiki_courses = self.store.get_courses_for_wiki('simple')
|
||||
self.assertEqual(len(wiki_courses), 1)
|
||||
self.assertIn(self.course_locations[self.XML_COURSEID2].course_key, wiki_courses)
|
||||
|
||||
# Test Mongo wiki
|
||||
with check_mongo_calls(max_find, max_send):
|
||||
wiki_courses = self.store.get_courses_for_wiki('999')
|
||||
@@ -1995,14 +1864,13 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
wiki_courses = self.store.get_courses_for_wiki('999')
|
||||
self.assertEqual(len(wiki_courses), 0)
|
||||
|
||||
# but there should be two courses with wiki_slug 'simple'
|
||||
# but there should be one course with wiki_slug 'simple'
|
||||
wiki_courses = self.store.get_courses_for_wiki('simple')
|
||||
self.assertEqual(len(wiki_courses), 2)
|
||||
self.assertEqual(len(wiki_courses), 1)
|
||||
self.assertIn(
|
||||
self.course_locations[self.MONGO_COURSEID].course_key.replace(branch=None),
|
||||
wiki_courses
|
||||
)
|
||||
self.assertIn(self.course_locations[self.XML_COURSEID2].course_key, wiki_courses)
|
||||
|
||||
# configure mongo course to use unique wiki_slug.
|
||||
mongo_course = self.store.get_course(self.course_locations[self.MONGO_COURSEID].course_key)
|
||||
@@ -2017,15 +1885,11 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
)
|
||||
# and NOT retriveable with its old wiki_slug
|
||||
wiki_courses = self.store.get_courses_for_wiki('simple')
|
||||
self.assertEqual(len(wiki_courses), 1)
|
||||
self.assertEqual(len(wiki_courses), 0)
|
||||
self.assertNotIn(
|
||||
self.course_locations[self.MONGO_COURSEID].course_key.replace(branch=None),
|
||||
wiki_courses
|
||||
)
|
||||
self.assertIn(
|
||||
self.course_locations[self.XML_COURSEID2].course_key,
|
||||
wiki_courses
|
||||
)
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_branch_setting(self, default_ms):
|
||||
@@ -2120,13 +1984,10 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
self.assertEquals(store.get_modulestore_type(), store_type)
|
||||
|
||||
# verify store used for creating a course
|
||||
try:
|
||||
course = self.store.create_course("org", "course{}".format(uuid4().hex[:5]), "run", self.user_id)
|
||||
self.assertEquals(course.system.modulestore.get_modulestore_type(), store_type)
|
||||
except NotImplementedError:
|
||||
self.assertEquals(store_type, ModuleStoreEnum.Type.xml)
|
||||
course = self.store.create_course("org", "course{}".format(uuid4().hex[:5]), "run", self.user_id)
|
||||
self.assertEquals(course.system.modulestore.get_modulestore_type(), store_type)
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.xml)
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_default_store(self, default_ms):
|
||||
"""
|
||||
Test the default store context manager
|
||||
@@ -2148,9 +2009,6 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
self.verify_default_store(ModuleStoreEnum.Type.mongo)
|
||||
with self.store.default_store(ModuleStoreEnum.Type.split):
|
||||
self.verify_default_store(ModuleStoreEnum.Type.split)
|
||||
with self.store.default_store(ModuleStoreEnum.Type.xml):
|
||||
self.verify_default_store(ModuleStoreEnum.Type.xml)
|
||||
self.verify_default_store(ModuleStoreEnum.Type.split)
|
||||
self.verify_default_store(ModuleStoreEnum.Type.mongo)
|
||||
|
||||
def test_default_store_fake(self):
|
||||
@@ -2205,25 +2063,6 @@ class TestMixedModuleStore(CommonMixedModuleStoreSetup):
|
||||
dest_store = self.store._get_modulestore_by_type(destination_modulestore)
|
||||
self.assertCoursesEqual(source_store, source_course_key, dest_store, dest_course_id)
|
||||
|
||||
def test_clone_xml_split(self):
|
||||
"""
|
||||
Can clone xml courses to split; so, test it.
|
||||
"""
|
||||
with MongoContentstoreBuilder().build() as contentstore:
|
||||
# initialize the mixed modulestore
|
||||
self._initialize_mixed(contentstore=contentstore, mappings={self.XML_COURSEID2: 'xml', })
|
||||
source_course_key = CourseKey.from_string(self.XML_COURSEID2)
|
||||
with self.store.default_store(ModuleStoreEnum.Type.split):
|
||||
dest_course_id = CourseLocator("org.other", "course.other", "run.other")
|
||||
self.store.clone_course(
|
||||
source_course_key, dest_course_id, ModuleStoreEnum.UserID.test
|
||||
)
|
||||
|
||||
# pylint: disable=protected-access
|
||||
source_store = self.store._get_modulestore_by_type(ModuleStoreEnum.Type.xml)
|
||||
dest_store = self.store._get_modulestore_by_type(ModuleStoreEnum.Type.split)
|
||||
self.assertCoursesEqual(source_store, source_course_key, dest_store, dest_course_id)
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_bulk_operations_signal_firing(self, default):
|
||||
""" Signals should be fired right before bulk_operations() exits. """
|
||||
|
||||
@@ -31,10 +31,6 @@ class TestXMLModuleStore(unittest.TestCase):
|
||||
"""
|
||||
Test around the XML modulestore
|
||||
"""
|
||||
def test_xml_modulestore_type(self):
|
||||
store = XMLModuleStore(DATA_DIR, source_dirs=[])
|
||||
self.assertEqual(store.get_modulestore_type(), ModuleStoreEnum.Type.xml)
|
||||
|
||||
@patch('xmodule.tabs.CourseTabList.initialize_default', Mock())
|
||||
def test_unicode_chars_in_xml_content(self):
|
||||
# edX/full/6.002_Spring_2012 has non-ASCII chars, and during
|
||||
|
||||
@@ -875,7 +875,8 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
Args:
|
||||
course_key: just for signature compatibility
|
||||
"""
|
||||
return ModuleStoreEnum.Type.xml
|
||||
# return ModuleStoreEnum.Type.xml
|
||||
return None
|
||||
|
||||
def get_courses_for_wiki(self, wiki_slug, **kwargs):
|
||||
"""
|
||||
@@ -893,7 +894,7 @@ class XMLModuleStore(ModuleStoreReadBase):
|
||||
|
||||
Returns the course count
|
||||
"""
|
||||
return {ModuleStoreEnum.Type.xml: True}
|
||||
return {'xml': True}
|
||||
|
||||
@contextmanager
|
||||
def branch_setting(self, branch_setting, course_id=None): # pylint: disable=unused-argument
|
||||
|
||||
@@ -279,9 +279,7 @@ class CourseExportManager(ExportManager):
|
||||
policy = {'course/' + courselike.location.name: own_metadata(courselike)}
|
||||
course_policy.write(dumps(policy, cls=EdxJSONEncoder, sort_keys=True, indent=4))
|
||||
|
||||
# xml backed courses don't support drafts!
|
||||
if courselike.runtime.modulestore.get_modulestore_type() != ModuleStoreEnum.Type.xml:
|
||||
_export_drafts(self.modulestore, self.courselike_key, export_fs, xml_centric_courselike_key)
|
||||
_export_drafts(self.modulestore, self.courselike_key, export_fs, xml_centric_courselike_key)
|
||||
|
||||
|
||||
class LibraryExportManager(ExportManager):
|
||||
|
||||
@@ -100,11 +100,4 @@ class CourseAuthorizationAdminForm(forms.ModelForm):
|
||||
msg += 'Please recheck that you have supplied a valid course id.'
|
||||
raise forms.ValidationError(msg)
|
||||
|
||||
# Now, try and discern if it is a Studio course - HTML editor doesn't work with XML courses
|
||||
is_studio_course = modulestore().get_modulestore_type(course_key) != ModuleStoreEnum.Type.xml
|
||||
if not is_studio_course:
|
||||
msg = "Course Email feature is only available for courses authored in Studio. "
|
||||
msg += '"{0}" appears to be an XML backed course.'.format(course_key.to_deprecated_string())
|
||||
raise forms.ValidationError(msg)
|
||||
|
||||
return course_key
|
||||
|
||||
@@ -8,7 +8,6 @@ from nose.plugins.attrib import attr
|
||||
|
||||
from bulk_email.models import CourseAuthorization, CourseEmailTemplate
|
||||
from bulk_email.forms import CourseAuthorizationAdminForm, CourseEmailTemplateForm
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
@@ -127,32 +126,6 @@ class CourseAuthorizationFormTest(ModuleStoreTestCase):
|
||||
form.save()
|
||||
|
||||
|
||||
class CourseAuthorizationXMLFormTest(ModuleStoreTestCase):
|
||||
"""Check that XML courses cannot be authorized for email."""
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
|
||||
@patch.dict(settings.FEATURES, {'ENABLE_INSTRUCTOR_EMAIL': True, 'REQUIRE_COURSE_EMAIL_AUTH': True})
|
||||
def test_xml_course_authorization(self):
|
||||
course_id = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall')
|
||||
# Assert this is an XML course
|
||||
self.assertEqual(modulestore().get_modulestore_type(course_id), ModuleStoreEnum.Type.xml)
|
||||
|
||||
form_data = {'course_id': course_id.to_deprecated_string(), 'email_enabled': True}
|
||||
form = CourseAuthorizationAdminForm(data=form_data)
|
||||
# Validation shouldn't work
|
||||
self.assertFalse(form.is_valid())
|
||||
|
||||
msg = u"Course Email feature is only available for courses authored in Studio. "
|
||||
msg += u'"{0}" appears to be an XML backed course.'.format(course_id.to_deprecated_string())
|
||||
self.assertEquals(msg, form._errors['course_id'][0]) # pylint: disable=protected-access
|
||||
|
||||
with self.assertRaisesRegexp(
|
||||
ValueError,
|
||||
"The CourseAuthorization could not be created because the data didn't validate."
|
||||
):
|
||||
form.save()
|
||||
|
||||
|
||||
class CourseEmailTemplateFormTest(ModuleStoreTestCase):
|
||||
"""Test the CourseEmailTemplateForm that is used in the Django admin subsystem."""
|
||||
|
||||
|
||||
@@ -453,10 +453,8 @@ def get_studio_url(course, page):
|
||||
Args:
|
||||
course (CourseDescriptor)
|
||||
"""
|
||||
is_studio_course = course.course_edit_method == "Studio"
|
||||
is_mongo_course = modulestore().get_modulestore_type(course.id) != ModuleStoreEnum.Type.xml
|
||||
studio_link = None
|
||||
if is_studio_course and is_mongo_course:
|
||||
if course.course_edit_method == "Studio":
|
||||
studio_link = get_cms_course_link(course, page)
|
||||
return studio_link
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
|
||||
from course_modes.models import CourseMode
|
||||
from track.tests import EventTrackingTestCase
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_CLOSED_MODULESTORE
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_MODULESTORE
|
||||
from xmodule.modulestore.tests.utils import TEST_DATA_DIR
|
||||
from xmodule.modulestore.xml_importer import import_course_from_xml
|
||||
|
||||
from student.models import CourseEnrollment
|
||||
from student.tests.factories import AdminFactory, CourseEnrollmentAllowedFactory, UserFactory
|
||||
@@ -199,16 +201,32 @@ class AboutTestCaseXML(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
"""
|
||||
Tests for the course about page
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_CLOSED_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
# The following XML test course (which lives at common/test/data/2014)
|
||||
# is closed; we're testing that an about page still appears when
|
||||
# the course is already closed
|
||||
xml_course_id = SlashSeparatedCourseKey('edX', 'detached_pages', '2014')
|
||||
def setUp(self):
|
||||
"""
|
||||
Set up the tests
|
||||
"""
|
||||
super(AboutTestCaseXML, self).setUp()
|
||||
|
||||
# this text appears in that course's about page
|
||||
# common/test/data/2014/about/overview.html
|
||||
xml_data = "about page 463139"
|
||||
# The following test course (which lives at common/test/data/2014)
|
||||
# is closed; we're testing that an about page still appears when
|
||||
# the course is already closed
|
||||
self.xml_course_id = self.store.make_course_key('edX', 'detached_pages', '2014')
|
||||
import_course_from_xml(
|
||||
self.store,
|
||||
'test_user',
|
||||
TEST_DATA_DIR,
|
||||
source_dirs=['2014'],
|
||||
static_content_store=None,
|
||||
target_id=self.xml_course_id,
|
||||
raise_on_failure=True,
|
||||
create_if_not_present=True,
|
||||
)
|
||||
|
||||
# this text appears in that course's about page
|
||||
# common/test/data/2014/about/overview.html
|
||||
self.xml_data = "about page 463139"
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
|
||||
def test_logged_in_xml(self):
|
||||
|
||||
@@ -17,9 +17,11 @@ from util.date_utils import strftime_localized
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
ModuleStoreTestCase,
|
||||
SharedModuleStoreTestCase,
|
||||
TEST_DATA_SPLIT_MODULESTORE
|
||||
TEST_DATA_SPLIT_MODULESTORE,
|
||||
TEST_DATA_MIXED_MODULESTORE
|
||||
)
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_CLOSED_MODULESTORE
|
||||
from xmodule.modulestore.tests.utils import TEST_DATA_DIR
|
||||
from xmodule.modulestore.xml_importer import import_course_from_xml
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls
|
||||
from student.models import CourseEnrollment
|
||||
from student.tests.factories import AdminFactory
|
||||
@@ -212,16 +214,32 @@ class CourseInfoTestCaseXML(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
"""
|
||||
Tests for the Course Info page for an XML course
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_CLOSED_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
# The following XML test course (which lives at common/test/data/2014)
|
||||
# is closed; we're testing that a course info page still appears when
|
||||
# the course is already closed
|
||||
xml_course_key = SlashSeparatedCourseKey('edX', 'detached_pages', '2014')
|
||||
def setUp(self):
|
||||
"""
|
||||
Set up the tests
|
||||
"""
|
||||
super(CourseInfoTestCaseXML, self).setUp()
|
||||
|
||||
# this text appears in that course's course info page
|
||||
# common/test/data/2014/info/updates.html
|
||||
xml_data = "course info 463139"
|
||||
# The following test course (which lives at common/test/data/2014)
|
||||
# is closed; we're testing that a course info page still appears when
|
||||
# the course is already closed
|
||||
self.xml_course_key = self.store.make_course_key('edX', 'detached_pages', '2014')
|
||||
import_course_from_xml(
|
||||
self.store,
|
||||
'test_user',
|
||||
TEST_DATA_DIR,
|
||||
source_dirs=['2014'],
|
||||
static_content_store=None,
|
||||
target_id=self.xml_course_key,
|
||||
raise_on_failure=True,
|
||||
create_if_not_present=True,
|
||||
)
|
||||
|
||||
# this text appears in that course's course info page
|
||||
# common/test/data/2014/info/updates.html
|
||||
self.xml_data = "course info 463139"
|
||||
|
||||
@mock.patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
|
||||
def test_logged_in_xml(self):
|
||||
|
||||
@@ -33,8 +33,9 @@ from xmodule.modulestore.django import _get_modulestore_branch_setting, modulest
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.xml_importer import import_course_from_xml
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls
|
||||
from xmodule.modulestore.tests.factories import (
|
||||
CourseFactory, ItemFactory, check_mongo_calls
|
||||
)
|
||||
from xmodule.tests.xml import factories as xml
|
||||
from xmodule.tests.xml import XModuleXmlImportTest
|
||||
|
||||
@@ -303,30 +304,6 @@ class CoursesRenderTest(ModuleStoreTestCase):
|
||||
self.assertIn("this module is temporarily unavailable", course_about)
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
class XmlCoursesRenderTest(ModuleStoreTestCase):
|
||||
"""Test methods related to rendering courses content for an XML course."""
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
|
||||
toy_course_key = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall')
|
||||
|
||||
def test_get_course_info_section_render(self):
|
||||
course = get_course_by_id(self.toy_course_key)
|
||||
request = get_request_for_user(UserFactory.create())
|
||||
|
||||
# Test render works okay. Note the href is different in XML courses.
|
||||
course_info = get_course_info_section(request, request.user, course, 'handouts')
|
||||
self.assertEqual(course_info, "<a href='/static/toy/handouts/sample_handout.txt'>Sample</a>")
|
||||
|
||||
# Test when render raises an exception
|
||||
with mock.patch('courseware.courses.get_module') as mock_module_render:
|
||||
mock_module_render.return_value = mock.MagicMock(
|
||||
render=mock.Mock(side_effect=Exception('Render failed!'))
|
||||
)
|
||||
course_info = get_course_info_section(request, request.user, course, 'handouts')
|
||||
self.assertIn("this module is temporarily unavailable", course_info)
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
@ddt.ddt
|
||||
class CourseInstantiationTests(ModuleStoreTestCase):
|
||||
|
||||
@@ -43,13 +43,13 @@ from openedx.core.lib.courses import course_image_url
|
||||
from openedx.core.lib.gating import api as gating_api
|
||||
from student.models import anonymous_id_for_user
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
TEST_DATA_MIXED_TOY_MODULESTORE,
|
||||
TEST_DATA_XML_MODULESTORE,
|
||||
SharedModuleStoreTestCase)
|
||||
ModuleStoreTestCase,
|
||||
SharedModuleStoreTestCase,
|
||||
TEST_DATA_MIXED_MODULESTORE
|
||||
)
|
||||
from xmodule.lti_module import LTIDescriptor
|
||||
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 ItemFactory, CourseFactory, ToyCourseFactory, check_mongo_calls
|
||||
from xmodule.x_module import XModuleDescriptor, XModule, STUDENT_VIEW, CombinedSystem
|
||||
|
||||
@@ -1369,17 +1369,6 @@ class ViewInStudioTest(ModuleStoreTestCase):
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
self.child_module = self._get_module(course.id, child_descriptor, child_descriptor.location)
|
||||
|
||||
def setup_xml_course(self):
|
||||
"""
|
||||
Define the XML backed course to use.
|
||||
Toy courses are already loaded in XML and mixed modulestores.
|
||||
"""
|
||||
course_key = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall')
|
||||
location = course_key.make_usage_key('chapter', 'Overview')
|
||||
descriptor = modulestore().get_item(location)
|
||||
|
||||
self.module = self._get_module(course_key, descriptor, location)
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
class MongoViewInStudioTest(ViewInStudioTest):
|
||||
@@ -1414,7 +1403,7 @@ class MongoViewInStudioTest(ViewInStudioTest):
|
||||
class MixedViewInStudioTest(ViewInStudioTest):
|
||||
"""Test the 'View in Studio' link visibility in a mixed mongo backed course."""
|
||||
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def test_view_in_studio_link_mongo_backed(self):
|
||||
"""Mixed mongo courses that are mongo backed should see 'View in Studio' links."""
|
||||
@@ -1428,24 +1417,6 @@ class MixedViewInStudioTest(ViewInStudioTest):
|
||||
result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context)
|
||||
self.assertNotIn('View Unit in Studio', result_fragment.content)
|
||||
|
||||
def test_view_in_studio_link_xml_backed(self):
|
||||
"""Course in XML only modulestore should not see 'View in Studio' links."""
|
||||
self.setup_xml_course()
|
||||
result_fragment = self.module.render(STUDENT_VIEW, context=self.default_context)
|
||||
self.assertNotIn('View Unit in Studio', result_fragment.content)
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
class XmlViewInStudioTest(ViewInStudioTest):
|
||||
"""Test the 'View in Studio' link visibility in an xml backed course."""
|
||||
MODULESTORE = TEST_DATA_XML_MODULESTORE
|
||||
|
||||
def test_view_in_studio_link_xml_backed(self):
|
||||
"""Course in XML only modulestore should not see 'View in Studio' links."""
|
||||
self.setup_xml_course()
|
||||
result_fragment = self.module.render(STUDENT_VIEW)
|
||||
self.assertNotIn('View Unit in Studio', result_fragment.content)
|
||||
|
||||
|
||||
@XBlock.tag("detached")
|
||||
class DetachedXBlock(XBlock):
|
||||
|
||||
@@ -27,10 +27,13 @@ from util.milestones_helpers import (
|
||||
from milestones.tests.utils import MilestonesTestCaseMixin
|
||||
from xmodule import tabs as xmodule_tabs
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
TEST_DATA_MIXED_TOY_MODULESTORE, TEST_DATA_MIXED_CLOSED_MODULESTORE,
|
||||
SharedModuleStoreTestCase)
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
ModuleStoreTestCase,
|
||||
SharedModuleStoreTestCase,
|
||||
TEST_DATA_MIXED_MODULESTORE
|
||||
)
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.modulestore.tests.utils import TEST_DATA_DIR
|
||||
from xmodule.modulestore.xml_importer import import_course_from_xml
|
||||
|
||||
|
||||
class TabTestCase(SharedModuleStoreTestCase):
|
||||
@@ -225,7 +228,7 @@ class TextbooksTestCase(TabTestCase):
|
||||
class StaticTabDateTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase):
|
||||
"""Test cases for Static Tab Dates."""
|
||||
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@@ -237,10 +240,6 @@ class StaticTabDateTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase):
|
||||
)
|
||||
cls.course.tabs.append(xmodule_tabs.CourseTab.load('static_tab', name='New Tab', url_slug='new_tab'))
|
||||
cls.course.save()
|
||||
cls.toy_course_key = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall')
|
||||
|
||||
def setUp(self):
|
||||
super(StaticTabDateTestCase, self).setUp()
|
||||
|
||||
def test_logged_in(self):
|
||||
self.setup_user()
|
||||
@@ -263,13 +262,13 @@ class StaticTabDateTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase):
|
||||
|
||||
def test_get_static_tab_contents(self):
|
||||
self.setup_user()
|
||||
course = get_course_by_id(self.toy_course_key)
|
||||
course = get_course_by_id(self.course.id)
|
||||
request = get_request_for_user(self.user)
|
||||
tab = xmodule_tabs.CourseTabList.get_tab_by_slug(course.tabs, 'resources')
|
||||
tab = xmodule_tabs.CourseTabList.get_tab_by_slug(course.tabs, 'new_tab')
|
||||
|
||||
# Test render works okay
|
||||
tab_content = get_static_tab_contents(request, course, tab)
|
||||
self.assertIn(self.toy_course_key.to_deprecated_string(), tab_content)
|
||||
self.assertIn(self.course.id.to_deprecated_string(), tab_content)
|
||||
self.assertIn('static_tab', tab_content)
|
||||
|
||||
# Test when render raises an exception
|
||||
@@ -287,17 +286,33 @@ class StaticTabDateTestCaseXML(LoginEnrollmentTestCase, ModuleStoreTestCase):
|
||||
Tests for the static tab dates of an XML course
|
||||
"""
|
||||
|
||||
MODULESTORE = TEST_DATA_MIXED_CLOSED_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
# The following XML test course (which lives at common/test/data/2014)
|
||||
# is closed; we're testing that tabs still appear when
|
||||
# the course is already closed
|
||||
xml_course_key = SlashSeparatedCourseKey('edX', 'detached_pages', '2014')
|
||||
def setUp(self):
|
||||
"""
|
||||
Set up the tests
|
||||
"""
|
||||
super(StaticTabDateTestCaseXML, self).setUp()
|
||||
|
||||
# this text appears in the test course's tab
|
||||
# common/test/data/2014/tabs/8e4cce2b4aaf4ba28b1220804619e41f.html
|
||||
xml_data = "static 463139"
|
||||
xml_url = "8e4cce2b4aaf4ba28b1220804619e41f"
|
||||
# The following XML test course (which lives at common/test/data/2014)
|
||||
# is closed; we're testing that tabs still appear when
|
||||
# the course is already closed
|
||||
self.xml_course_key = self.store.make_course_key('edX', 'detached_pages', '2014')
|
||||
import_course_from_xml(
|
||||
self.store,
|
||||
'test_user',
|
||||
TEST_DATA_DIR,
|
||||
source_dirs=['2014'],
|
||||
static_content_store=None,
|
||||
target_id=self.xml_course_key,
|
||||
raise_on_failure=True,
|
||||
create_if_not_present=True,
|
||||
)
|
||||
|
||||
# this text appears in the test course's tab
|
||||
# common/test/data/2014/tabs/8e4cce2b4aaf4ba28b1220804619e41f.html
|
||||
self.xml_data = "static 463139"
|
||||
self.xml_url = "8e4cce2b4aaf4ba28b1220804619e41f"
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
|
||||
def test_logged_in_xml(self):
|
||||
@@ -321,7 +336,7 @@ class EntranceExamsTabsTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase, Mi
|
||||
"""
|
||||
Validate tab behavior when dealing with Entrance Exams
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_CLOSED_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'ENTRANCE_EXAMS': True, 'MILESTONES_APP': True})
|
||||
def setUp(self):
|
||||
@@ -428,7 +443,7 @@ class TextBookCourseViewsTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest
|
||||
"""
|
||||
Validate tab behavior when dealing with textbooks.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
||||
@@ -51,7 +51,7 @@ from util.url import reload_django_url_config
|
||||
from util.views import ensure_valid_course_key
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_MODULESTORE
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls
|
||||
from openedx.core.djangoapps.credit.api import set_credit_requirements
|
||||
@@ -63,7 +63,7 @@ class TestJumpTo(ModuleStoreTestCase):
|
||||
"""
|
||||
Check the jumpto link for a course.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
super(TestJumpTo, self).setUp()
|
||||
|
||||
@@ -10,12 +10,13 @@ from nose.plugins.attrib import attr
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
|
||||
from courseware.tests.helpers import LoginEnrollmentTestCase
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_XML_MODULESTORE as XML_MODULESTORE
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_TOY_MODULESTORE as TOY_MODULESTORE
|
||||
from lms.djangoapps.lms_xblock.field_data import LmsFieldData
|
||||
from xmodule.error_module import ErrorDescriptor
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
ModuleStoreTestCase, TEST_DATA_MIXED_MODULESTORE
|
||||
)
|
||||
from xmodule.modulestore.tests.factories import ToyCourseFactory
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
@@ -122,34 +123,17 @@ class PageLoaderTestCase(LoginEnrollmentTestCase):
|
||||
self.assertNotIsInstance(descriptor, ErrorDescriptor)
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
class TestXmlCoursesLoad(ModuleStoreTestCase, PageLoaderTestCase):
|
||||
"""
|
||||
Check that all pages in test courses load properly from XML.
|
||||
"""
|
||||
MODULESTORE = XML_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
super(TestXmlCoursesLoad, self).setUp()
|
||||
self.setup_user()
|
||||
|
||||
def test_toy_course_loads(self):
|
||||
# Load one of the XML based courses
|
||||
# Our test mapping rules allow the MixedModuleStore
|
||||
# to load this course from XML, not Mongo.
|
||||
self.check_all_pages_load(SlashSeparatedCourseKey('edX', 'toy', '2012_Fall'))
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
class TestMongoCoursesLoad(ModuleStoreTestCase, PageLoaderTestCase):
|
||||
"""
|
||||
Check that all pages in test courses load properly from Mongo.
|
||||
"""
|
||||
MODULESTORE = TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
super(TestMongoCoursesLoad, self).setUp()
|
||||
self.setup_user()
|
||||
self.toy_course_key = ToyCourseFactory.create().id
|
||||
|
||||
@mock.patch('xmodule.course_module.requests.get')
|
||||
def test_toy_textbooks_loads(self, mock_get):
|
||||
@@ -158,8 +142,7 @@ class TestMongoCoursesLoad(ModuleStoreTestCase, PageLoaderTestCase):
|
||||
<entry page="5" page_label="ii" name="Table of Contents"/>
|
||||
</table_of_contents>
|
||||
""").strip()
|
||||
|
||||
location = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall').make_usage_key('course', '2012_Fall')
|
||||
location = self.toy_course_key.make_usage_key('course', '2012_Fall')
|
||||
course = self.store.get_item(location)
|
||||
self.assertGreater(len(course.textbooks), 0)
|
||||
|
||||
|
||||
@@ -491,23 +491,7 @@ class Courses(SysadminDashboardView):
|
||||
escape(str(err))
|
||||
)
|
||||
|
||||
is_xml_course = (modulestore().get_modulestore_type(course_key) == ModuleStoreEnum.Type.xml)
|
||||
if course_found and is_xml_course:
|
||||
cdir = course.data_dir
|
||||
self.def_ms.courses.pop(cdir)
|
||||
|
||||
# now move the directory (don't actually delete it)
|
||||
new_dir = "{course_dir}_deleted_{timestamp}".format(
|
||||
course_dir=cdir,
|
||||
timestamp=int(time.time())
|
||||
)
|
||||
os.rename(settings.DATA_DIR / cdir, settings.DATA_DIR / new_dir)
|
||||
|
||||
self.msg += (u"<font color='red'>Deleted "
|
||||
u"{0} = {1} ({2})</font>".format(
|
||||
cdir, course.id, course.display_name))
|
||||
|
||||
elif course_found and not is_xml_course:
|
||||
if course_found:
|
||||
# delete course that is stored with mongodb backend
|
||||
self.def_ms.delete_course(course.id, request.user.id)
|
||||
# don't delete user permission groups, though
|
||||
|
||||
@@ -5,9 +5,11 @@ from django.test.testcases import TestCase
|
||||
from nose.plugins.attrib import attr
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
import django_comment_common.models as models
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
TEST_DATA_MIXED_MODULESTORE, ModuleStoreTestCase
|
||||
)
|
||||
from xmodule.modulestore.tests.factories import ToyCourseFactory
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
@@ -15,7 +17,7 @@ class RoleClassTestCase(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests for roles of the comment client service integration
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
super(RoleClassTestCase, self).setUp()
|
||||
@@ -23,7 +25,7 @@ class RoleClassTestCase(ModuleStoreTestCase):
|
||||
# For course ID, syntax edx/classname/classdate is important
|
||||
# because xmodel.course_module.id_to_location looks for a string to split
|
||||
|
||||
self.course_id = CourseKey.from_string("edX/toy/2012_Fall")
|
||||
self.course_id = ToyCourseFactory.create().id
|
||||
self.student_role = models.Role.objects.get_or_create(name="Student",
|
||||
course_id=self.course_id)[0]
|
||||
self.student_role.add_permission("delete_thread")
|
||||
|
||||
@@ -25,8 +25,8 @@ from openedx.core.djangoapps.content.course_structures.models import CourseStruc
|
||||
from openedx.core.djangoapps.util.testing import ContentGroupTestCase
|
||||
from student.roles import CourseStaffRole
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, ToyCourseFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MIXED_MODULESTORE
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from lms.djangoapps.teams.tests.factories import CourseTeamFactory
|
||||
@@ -1248,14 +1248,14 @@ class IsCommentableCohortedTestCase(ModuleStoreTestCase):
|
||||
Test the is_commentable_cohorted function.
|
||||
"""
|
||||
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Make sure that course is reloaded every time--clear out the modulestore.
|
||||
"""
|
||||
super(IsCommentableCohortedTestCase, self).setUp()
|
||||
self.toy_course_key = CourseLocator("edX", "toy", "2012_Fall", deprecated=True)
|
||||
self.toy_course_key = ToyCourseFactory.create().id
|
||||
|
||||
def test_is_commentable_cohorted(self):
|
||||
course = modulestore().get_course(self.toy_course_key)
|
||||
|
||||
@@ -12,7 +12,7 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
|
||||
from bulk_email.models import CourseAuthorization
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
TEST_DATA_MIXED_TOY_MODULESTORE, SharedModuleStoreTestCase
|
||||
TEST_DATA_MIXED_MODULESTORE, SharedModuleStoreTestCase
|
||||
)
|
||||
from student.tests.factories import AdminFactory
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
@@ -112,7 +112,7 @@ class TestNewInstructorDashboardEmailViewXMLBacked(SharedModuleStoreTestCase):
|
||||
Check for email view on the new instructor dashboard
|
||||
"""
|
||||
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
||||
@@ -66,10 +66,9 @@ def bulk_email_is_enabled_for_course(course_id):
|
||||
"""
|
||||
|
||||
bulk_email_enabled_globally = (settings.FEATURES['ENABLE_INSTRUCTOR_EMAIL'] is True)
|
||||
is_studio_course = (modulestore().get_modulestore_type(course_id) != ModuleStoreEnum.Type.xml)
|
||||
bulk_email_enabled_for_course = CourseAuthorization.instructor_email_enabled(course_id)
|
||||
|
||||
if bulk_email_enabled_globally and is_studio_course and bulk_email_enabled_for_course:
|
||||
if bulk_email_enabled_globally and bulk_email_enabled_for_course:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -745,14 +745,6 @@ MODULESTORE = {
|
||||
'fs_root': DATA_DIR,
|
||||
'render_template': 'edxmako.shortcuts.render_to_string',
|
||||
}
|
||||
},
|
||||
{
|
||||
'NAME': 'xml',
|
||||
'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore',
|
||||
'OPTIONS': {
|
||||
'data_dir': DATA_DIR,
|
||||
'default_class': 'xmodule.hidden_module.HiddenDescriptor',
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import ddt
|
||||
from xblock.validation import ValidationMessage
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ToyCourseFactory, ItemFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MIXED_MODULESTORE
|
||||
from xmodule.partitions.partitions import Group, UserPartition
|
||||
|
||||
|
||||
@@ -157,21 +157,17 @@ class XBlockGetParentTest(LmsXBlockMixinTestCase):
|
||||
Test that XBlock.get_parent returns correct results with each modulestore
|
||||
backend.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split, ModuleStoreEnum.Type.xml)
|
||||
@ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
def test_parents(self, modulestore_type):
|
||||
with self.store.default_store(modulestore_type):
|
||||
|
||||
# setting up our own local course tree here, since it needs to be
|
||||
# created with the correct modulestore type.
|
||||
|
||||
if modulestore_type == 'xml':
|
||||
course_key = self.store.make_course_key('edX', 'toy', '2012_Fall')
|
||||
else:
|
||||
course_key = ToyCourseFactory.create(run='2012_Fall_copy').id
|
||||
course_key = ToyCourseFactory.create().id
|
||||
course = self.store.get_course(course_key)
|
||||
|
||||
self.assertIsNone(course.get_parent())
|
||||
|
||||
def recurse(parent):
|
||||
|
||||
@@ -16,7 +16,8 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
from student.models import CourseEnrollment
|
||||
from student.tests.factories import UserFactory
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_TOY_MODULESTORE, ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_MODULESTORE, ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import ToyCourseFactory
|
||||
|
||||
from ..models import CourseUserGroup, CourseCohort, CourseUserGroupPartitionGroup
|
||||
from .. import cohorts
|
||||
@@ -138,14 +139,14 @@ class TestCohorts(ModuleStoreTestCase):
|
||||
"""
|
||||
Test the cohorts feature
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Make sure that course is reloaded every time--clear out the modulestore.
|
||||
"""
|
||||
super(TestCohorts, self).setUp()
|
||||
self.toy_course_key = SlashSeparatedCourseKey("edX", "toy", "2012_Fall")
|
||||
self.toy_course_key = ToyCourseFactory.create().id
|
||||
|
||||
def _create_cohort(self, course_id, cohort_name, assignment_type):
|
||||
"""
|
||||
@@ -732,7 +733,7 @@ class TestCohortsAndPartitionGroups(ModuleStoreTestCase):
|
||||
"""
|
||||
Test Cohorts and Partitions Groups.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
@@ -740,7 +741,7 @@ class TestCohortsAndPartitionGroups(ModuleStoreTestCase):
|
||||
"""
|
||||
super(TestCohortsAndPartitionGroups, self).setUp()
|
||||
|
||||
self.test_course_key = SlashSeparatedCourseKey("edX", "toy", "2012_Fall")
|
||||
self.test_course_key = ToyCourseFactory.create().id
|
||||
self.course = modulestore().get_course(self.test_course_key)
|
||||
|
||||
self.first_cohort = CohortFactory(course_id=self.course.id, name="FirstCohort")
|
||||
|
||||
@@ -15,7 +15,8 @@ from courseware.tests.test_masquerade import StaffMasqueradeTestCase
|
||||
from student.tests.factories import UserFactory
|
||||
from xmodule.partitions.partitions import Group, UserPartition, UserPartitionError
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, TEST_DATA_MIXED_MODULESTORE
|
||||
from xmodule.modulestore.tests.factories import ToyCourseFactory
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
|
||||
from openedx.core.djangoapps.user_api.partition_schemes import RandomUserPartitionScheme
|
||||
@@ -31,7 +32,7 @@ class TestCohortPartitionScheme(ModuleStoreTestCase):
|
||||
"""
|
||||
Test the logic for linking a user to a partition group based on their cohort.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
@@ -40,7 +41,7 @@ class TestCohortPartitionScheme(ModuleStoreTestCase):
|
||||
"""
|
||||
super(TestCohortPartitionScheme, self).setUp()
|
||||
|
||||
self.course_key = SlashSeparatedCourseKey("edX", "toy", "2012_Fall")
|
||||
self.course_key = ToyCourseFactory.create().id
|
||||
self.course = modulestore().get_course(self.course_key)
|
||||
config_course_cohorts(self.course, is_cohorted=True)
|
||||
|
||||
@@ -278,7 +279,7 @@ class TestGetCohortedUserPartition(ModuleStoreTestCase):
|
||||
"""
|
||||
Test that `get_cohorted_user_partition` returns the first user_partition with scheme `CohortPartitionScheme`.
|
||||
"""
|
||||
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
|
||||
MODULESTORE = TEST_DATA_MIXED_MODULESTORE
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
@@ -286,7 +287,7 @@ class TestGetCohortedUserPartition(ModuleStoreTestCase):
|
||||
and a student for each test.
|
||||
"""
|
||||
super(TestGetCohortedUserPartition, self).setUp()
|
||||
self.course_key = SlashSeparatedCourseKey("edX", "toy", "2012_Fall")
|
||||
self.course_key = ToyCourseFactory.create().id
|
||||
self.course = modulestore().get_course(self.course_key)
|
||||
self.student = UserFactory.create()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ from xmodule.modulestore import ModuleStoreEnum
|
||||
def course_image_url(course):
|
||||
"""Try to look up the image url for the course. If it's not found,
|
||||
log an error and return the dead link"""
|
||||
if course.static_asset_path or modulestore().get_modulestore_type(course.id) == ModuleStoreEnum.Type.xml:
|
||||
if course.static_asset_path:
|
||||
# If we are a static course with the course_image attribute
|
||||
# set different than the default, return that path so that
|
||||
# courses can use custom course image paths, otherwise just
|
||||
|
||||
@@ -300,10 +300,9 @@ def add_staff_markup(user, has_instructor_access, disable_staff_debug_info, bloc
|
||||
# TODO: make this more general, eg use an XModule attribute instead
|
||||
if isinstance(block, VerticalBlock) and (not context or not context.get('child_of_vertical', False)):
|
||||
# check that the course is a mongo backed Studio course before doing work
|
||||
is_mongo_course = modulestore().get_modulestore_type(block.location.course_key) != ModuleStoreEnum.Type.xml
|
||||
is_studio_course = block.course_edit_method == "Studio"
|
||||
|
||||
if is_studio_course and is_mongo_course:
|
||||
if is_studio_course:
|
||||
# build edit link to unit in CMS. Can't use reverse here as lms doesn't load cms's urls.py
|
||||
edit_link = "//" + settings.CMS_BASE + '/container/' + unicode(block.location)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user