Update tests to allow LMS tests to use published branch setting.
Conflicts: cms/djangoapps/contentstore/views/tests/test_container_page.py common/djangoapps/external_auth/tests/test_shib.py common/djangoapps/student/tests/test_login.py common/lib/xmodule/xmodule/modulestore/tests/django_utils.py common/lib/xmodule/xmodule/modulestore/tests/factories.py common/lib/xmodule/xmodule/modulestore/xml_importer.py lms/djangoapps/branding/tests.py lms/djangoapps/courseware/tests/test_submitting_problems.py lms/djangoapps/courseware/tests/test_video_handlers.py lms/djangoapps/instructor_task/tests/test_base.py lms/djangoapps/instructor_task/tests/test_integration.py
This commit is contained in:
@@ -89,7 +89,7 @@ class CourseTestCase(ModuleStoreTestCase):
|
||||
"""
|
||||
Create a non-staff user, log them in (if authenticate=True), and return the client, user to use for testing.
|
||||
"""
|
||||
nonstaff, password = super(CourseTestCase, self).create_non_staff_authed_user_client()
|
||||
nonstaff, password = self.create_non_staff_user()
|
||||
|
||||
client = Client()
|
||||
if authenticate:
|
||||
|
||||
@@ -20,16 +20,11 @@ class ContainerPageTestCase(StudioPageTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ContainerPageTestCase, self).setUp()
|
||||
self.vertical = ItemFactory.create(parent_location=self.sequential.location,
|
||||
category='vertical', display_name='Unit')
|
||||
self.html = ItemFactory.create(parent_location=self.vertical.location,
|
||||
category="html", display_name="HTML")
|
||||
self.child_container = ItemFactory.create(parent_location=self.vertical.location,
|
||||
category='split_test', display_name='Split Test')
|
||||
self.child_vertical = ItemFactory.create(parent_location=self.child_container.location,
|
||||
category='vertical', display_name='Child Vertical')
|
||||
self.video = ItemFactory.create(parent_location=self.child_vertical.location,
|
||||
category="video", display_name="My Video")
|
||||
self.vertical = self._create_item(self.sequential.location, 'vertical', 'Unit')
|
||||
self.html = self._create_item(self.vertical.location, "html", "HTML")
|
||||
self.child_container = self._create_item(self.vertical.location, 'split_test', 'Split Test')
|
||||
self.child_vertical = self._create_item(self.child_container.location, 'vertical', 'Child Vertical')
|
||||
self.video = self._create_item(self.child_vertical.location, "video", "My Video")
|
||||
self.store = modulestore()
|
||||
|
||||
def test_container_html(self):
|
||||
@@ -51,14 +46,8 @@ class ContainerPageTestCase(StudioPageTestCase):
|
||||
Create the scenario of an xblock with children (non-vertical) on the container page.
|
||||
This should create a container page that is a child of another container page.
|
||||
"""
|
||||
draft_container = ItemFactory.create(
|
||||
parent_location=self.child_container.location,
|
||||
category="wrapper", display_name="Wrapper"
|
||||
)
|
||||
ItemFactory.create(
|
||||
parent_location=draft_container.location,
|
||||
category="html", display_name="Child HTML"
|
||||
)
|
||||
draft_container = self._create_item(self.child_container.location, "wrapper", "Wrapper")
|
||||
self._create_item(draft_container.location, "html", "Child HTML")
|
||||
|
||||
def test_container_html(xblock):
|
||||
self._test_html_content(
|
||||
@@ -135,8 +124,7 @@ class ContainerPageTestCase(StudioPageTestCase):
|
||||
"""
|
||||
Verify that a public container rendered as a child of the container page returns the expected HTML.
|
||||
"""
|
||||
empty_child_container = ItemFactory.create(parent_location=self.vertical.location,
|
||||
category='split_test', display_name='Split Test')
|
||||
empty_child_container = self._create_item(self.vertical.location, 'split_test', 'Split Test')
|
||||
published_empty_child_container = self.store.publish(empty_child_container.location, self.user.id)
|
||||
self.validate_preview_html(published_empty_child_container, self.reorderable_child_view,
|
||||
can_reorder=False, can_edit=False, can_add=False)
|
||||
@@ -145,7 +133,18 @@ class ContainerPageTestCase(StudioPageTestCase):
|
||||
"""
|
||||
Verify that a draft container rendered as a child of the container page returns the expected HTML.
|
||||
"""
|
||||
empty_child_container = ItemFactory.create(parent_location=self.vertical.location,
|
||||
category='split_test', display_name='Split Test')
|
||||
empty_child_container = self._create_item(self.vertical.location, 'split_test', 'Split Test')
|
||||
self.validate_preview_html(empty_child_container, self.reorderable_child_view,
|
||||
can_reorder=True, can_edit=True, can_add=False)
|
||||
|
||||
def _create_item(self, parent_location, category, display_name, **kwargs):
|
||||
"""
|
||||
creates an item in the module store, without publishing it.
|
||||
"""
|
||||
return ItemFactory.create(
|
||||
parent_location=parent_location,
|
||||
category=category,
|
||||
display_name=display_name,
|
||||
publish_item=False,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@@ -35,7 +35,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
|
||||
"""
|
||||
self.staff_pwd = super(ContentStoreToyCourseTest, self).setUp()
|
||||
self.staff_usr = self.user
|
||||
self.non_staff_usr, self.non_staff_pwd = self.create_non_staff_authed_user_client()
|
||||
self.non_staff_usr, self.non_staff_pwd = self.create_non_staff_user()
|
||||
|
||||
self.client = Client()
|
||||
self.contentstore = contentstore()
|
||||
|
||||
@@ -18,6 +18,7 @@ from django.utils.importlib import import_module
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, mixed_store_config
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
|
||||
from external_auth.models import ExternalAuthMap
|
||||
@@ -80,6 +81,7 @@ class ShibSPTest(ModuleStoreTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ShibSPTest, self).setUp(create_user=False)
|
||||
self.test_user_id = ModuleStoreEnum.UserID.test
|
||||
|
||||
@unittest.skipUnless(settings.FEATURES.get('AUTH_USE_SHIB'), "AUTH_USE_SHIB not set")
|
||||
def test_exception_shib_login(self):
|
||||
@@ -376,13 +378,21 @@ class ShibSPTest(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests that the correct course specific login and registration urls work for shib
|
||||
"""
|
||||
course = CourseFactory.create(org='MITx', number='999', display_name='Robot Super Course')
|
||||
course = CourseFactory.create(
|
||||
org='MITx',
|
||||
number='999',
|
||||
display_name='Robot Super Course',
|
||||
user_id=self.test_user_id,
|
||||
)
|
||||
|
||||
# Test for cases where course is found
|
||||
for domain in ["", "shib:https://idp.stanford.edu/"]:
|
||||
# set domains
|
||||
course.enrollment_domain = domain
|
||||
self.store.update_item(course, self.user.id)
|
||||
|
||||
# temporarily set the branch to draft-preferred so we can update the course
|
||||
with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, course.id):
|
||||
course.enrollment_domain = domain
|
||||
self.store.update_item(course, self.test_user_id)
|
||||
|
||||
# setting location to test that GET params get passed through
|
||||
login_request = self.request_factory.get('/course_specific_login/MITx/999/Robot_Super_Course' +
|
||||
@@ -449,13 +459,21 @@ class ShibSPTest(ModuleStoreTestCase):
|
||||
"""
|
||||
|
||||
# create 2 course, one with limited enrollment one without
|
||||
shib_course = CourseFactory.create(org='Stanford', number='123', display_name='Shib Only')
|
||||
shib_course.enrollment_domain = 'shib:https://idp.stanford.edu/'
|
||||
self.store.update_item(shib_course, self.user.id)
|
||||
shib_course = CourseFactory.create(
|
||||
org='Stanford',
|
||||
number='123',
|
||||
display_name='Shib Only',
|
||||
enrollment_domain='shib:https://idp.stanford.edu/',
|
||||
user_id=self.test_user_id,
|
||||
)
|
||||
|
||||
open_enroll_course = CourseFactory.create(org='MITx', number='999', display_name='Robot Super Course')
|
||||
open_enroll_course.enrollment_domain = ''
|
||||
self.store.update_item(open_enroll_course, self.user.id)
|
||||
open_enroll_course = CourseFactory.create(
|
||||
org='MITx',
|
||||
number='999',
|
||||
display_name='Robot Super Course',
|
||||
enrollment_domain='',
|
||||
user_id=self.test_user_id,
|
||||
)
|
||||
|
||||
# create 3 kinds of students, external_auth matching shib_course, external_auth not matching, no external auth
|
||||
shib_student = UserFactory.create()
|
||||
@@ -519,9 +537,13 @@ class ShibSPTest(ModuleStoreTestCase):
|
||||
student.save()
|
||||
extauth.save()
|
||||
|
||||
course = CourseFactory.create(org='Stanford', number='123', display_name='Shib Only')
|
||||
course.enrollment_domain = 'shib:https://idp.stanford.edu/'
|
||||
self.store.update_item(course, self.user.id)
|
||||
course = CourseFactory.create(
|
||||
org='Stanford',
|
||||
number='123',
|
||||
display_name='Shib Only',
|
||||
enrollment_domain='shib:https://idp.stanford.edu/',
|
||||
user_id=self.test_user_id,
|
||||
)
|
||||
|
||||
# use django test client for sessions and url processing
|
||||
# no enrollment before trying
|
||||
|
||||
@@ -346,10 +346,19 @@ class ExternalAuthShibTest(ModuleStoreTestCase):
|
||||
"""
|
||||
def setUp(self):
|
||||
super(ExternalAuthShibTest, self).setUp()
|
||||
self.course = CourseFactory.create(org='Stanford', number='456', display_name='NO SHIB')
|
||||
self.shib_course = CourseFactory.create(org='Stanford', number='123', display_name='Shib Only')
|
||||
self.shib_course.enrollment_domain = 'shib:https://idp.stanford.edu/'
|
||||
self.store.update_item(self.shib_course, self.user.id)
|
||||
self.course = CourseFactory.create(
|
||||
org='Stanford',
|
||||
number='456',
|
||||
display_name='NO SHIB',
|
||||
user_id=self.user.id,
|
||||
)
|
||||
self.shib_course = CourseFactory.create(
|
||||
org='Stanford',
|
||||
number='123',
|
||||
display_name='Shib Only',
|
||||
enrollment_domain='shib:https://idp.stanford.edu/',
|
||||
user_id=self.user.id,
|
||||
)
|
||||
self.user_w_map = UserFactory.create(email='withmap@stanford.edu')
|
||||
self.extauth = ExternalAuthMap(external_id='withmap@stanford.edu',
|
||||
external_email='withmap@stanford.edu',
|
||||
|
||||
@@ -129,6 +129,13 @@ class ModuleStoreTestCase(TestCase):
|
||||
your `setUp()` method.
|
||||
"""
|
||||
def setUp(self, **kwargs):
|
||||
"""
|
||||
Creates a test User if `create_user` is True.
|
||||
Returns the password for the test User.
|
||||
|
||||
Args:
|
||||
create_user - specifies whether or not to create a test User. Default is True.
|
||||
"""
|
||||
super(ModuleStoreTestCase, self).setUp()
|
||||
|
||||
self.store = modulestore()
|
||||
@@ -151,20 +158,21 @@ class ModuleStoreTestCase(TestCase):
|
||||
|
||||
return password
|
||||
|
||||
def create_non_staff_authed_user_client(self):
|
||||
def create_non_staff_user(self):
|
||||
"""
|
||||
Create a non-staff user, log them in (if authenticate=True), and return the client, user to use for testing.
|
||||
Creates a non-staff test user.
|
||||
Returns the non-staff test user and its password.
|
||||
"""
|
||||
uname = 'teststudent'
|
||||
password = 'foo'
|
||||
nonstaff = User.objects.create_user(uname, 'test+student@edx.org', password)
|
||||
nonstaff_user = User.objects.create_user(uname, 'test+student@edx.org', password)
|
||||
|
||||
# Note that we do not actually need to do anything
|
||||
# for registration if we directly mark them active.
|
||||
nonstaff.is_active = True
|
||||
nonstaff.is_staff = False
|
||||
nonstaff.save()
|
||||
return nonstaff, password
|
||||
nonstaff_user.is_active = True
|
||||
nonstaff_user.is_staff = False
|
||||
nonstaff_user.save()
|
||||
return nonstaff_user, password
|
||||
|
||||
def update_course(self, course, user_id):
|
||||
"""
|
||||
|
||||
@@ -56,18 +56,19 @@ class CourseFactory(XModuleFactory):
|
||||
|
||||
location = Location(org, number, run, 'course', name)
|
||||
|
||||
# Write the data to the mongo datastore
|
||||
new_course = store.create_xmodule(location, metadata=kwargs.get('metadata', None))
|
||||
with store.branch_setting(ModuleStoreEnum.Branch.draft_preferred):
|
||||
# Write the data to the mongo datastore
|
||||
new_course = store.create_xmodule(location, metadata=kwargs.get('metadata', None))
|
||||
|
||||
# The rest of kwargs become attributes on the course:
|
||||
for k, v in kwargs.iteritems():
|
||||
setattr(new_course, k, v)
|
||||
# The rest of kwargs become attributes on the course:
|
||||
for k, v in kwargs.iteritems():
|
||||
setattr(new_course, k, v)
|
||||
|
||||
# Save the attributes we just set
|
||||
new_course.save()
|
||||
# Update the data in the mongo datastore
|
||||
store.update_item(new_course, user_id)
|
||||
return new_course
|
||||
# Save the attributes we just set
|
||||
new_course.save()
|
||||
# Update the data in the mongo datastore
|
||||
store.update_item(new_course, user_id)
|
||||
return new_course
|
||||
|
||||
|
||||
class ItemFactory(XModuleFactory):
|
||||
@@ -129,6 +130,8 @@ class ItemFactory(XModuleFactory):
|
||||
|
||||
:boilerplate: (optional) the boilerplate for overriding field values
|
||||
|
||||
:publish_item: (optional) whether or not to publish the item (default is True)
|
||||
|
||||
:target_class: is ignored
|
||||
"""
|
||||
|
||||
@@ -145,6 +148,7 @@ class ItemFactory(XModuleFactory):
|
||||
metadata = kwargs.pop('metadata', {})
|
||||
location = kwargs.pop('location')
|
||||
user_id = kwargs.pop('user_id', ModuleStoreEnum.UserID.test)
|
||||
publish_item = kwargs.pop('publish_item', True)
|
||||
|
||||
assert isinstance(location, Location)
|
||||
assert location != parent_location
|
||||
@@ -154,47 +158,55 @@ class ItemFactory(XModuleFactory):
|
||||
# This code was based off that in cms/djangoapps/contentstore/views.py
|
||||
parent = kwargs.pop('parent', None) or store.get_item(parent_location)
|
||||
|
||||
if 'boilerplate' in kwargs:
|
||||
template_id = kwargs.pop('boilerplate')
|
||||
clz = XBlock.load_class(category, select=prefer_xmodules)
|
||||
template = clz.get_template(template_id)
|
||||
assert template is not None
|
||||
metadata.update(template.get('metadata', {}))
|
||||
if not isinstance(data, basestring):
|
||||
data.update(template.get('data'))
|
||||
with store.branch_setting(ModuleStoreEnum.Branch.draft_preferred):
|
||||
|
||||
# replace the display name with an optional parameter passed in from the caller
|
||||
if display_name is not None:
|
||||
metadata['display_name'] = display_name
|
||||
runtime = parent.runtime if parent else None
|
||||
store.create_and_save_xmodule(location, user_id, metadata=metadata, definition_data=data, runtime=runtime)
|
||||
if 'boilerplate' in kwargs:
|
||||
template_id = kwargs.pop('boilerplate')
|
||||
clz = XBlock.load_class(category, select=prefer_xmodules)
|
||||
template = clz.get_template(template_id)
|
||||
assert template is not None
|
||||
metadata.update(template.get('metadata', {}))
|
||||
if not isinstance(data, basestring):
|
||||
data.update(template.get('data'))
|
||||
|
||||
module = store.get_item(location)
|
||||
# replace the display name with an optional parameter passed in from the caller
|
||||
if display_name is not None:
|
||||
metadata['display_name'] = display_name
|
||||
runtime = parent.runtime if parent else None
|
||||
store.create_and_save_xmodule(location, user_id, metadata=metadata, definition_data=data, runtime=runtime)
|
||||
|
||||
for attr, val in kwargs.items():
|
||||
setattr(module, attr, val)
|
||||
# Save the attributes we just set
|
||||
module.save()
|
||||
module = store.get_item(location)
|
||||
|
||||
store.update_item(module, user_id)
|
||||
for attr, val in kwargs.items():
|
||||
setattr(module, attr, val)
|
||||
# Save the attributes we just set
|
||||
module.save()
|
||||
|
||||
if 'detached' not in module._class_tags:
|
||||
parent.children.append(location)
|
||||
store.update_item(parent, user_id)
|
||||
store.update_item(module, user_id)
|
||||
|
||||
# VS[compat] cdodge: This is a hack because static_tabs also have references from the course module, so
|
||||
# if we add one then we need to also add it to the policy information (i.e. metadata)
|
||||
# we should remove this once we can break this reference from the course to static tabs
|
||||
if category == 'static_tab':
|
||||
course = store.get_course(location.course_key)
|
||||
course.tabs.append(
|
||||
StaticTab(
|
||||
name=display_name,
|
||||
url_slug=location.name,
|
||||
# VS[compat] cdodge: This is a hack because static_tabs also have references from the course module, so
|
||||
# if we add one then we need to also add it to the policy information (i.e. metadata)
|
||||
# we should remove this once we can break this reference from the course to static tabs
|
||||
if category == 'static_tab':
|
||||
course = store.get_course(location.course_key)
|
||||
course.tabs.append(
|
||||
StaticTab(
|
||||
name=display_name,
|
||||
url_slug=location.name,
|
||||
)
|
||||
)
|
||||
)
|
||||
store.update_item(course, user_id)
|
||||
store.update_item(course, user_id)
|
||||
|
||||
# parent and publish the item, so it can be accessed
|
||||
if 'detached' not in module._class_tags:
|
||||
parent.children.append(location)
|
||||
store.update_item(parent, user_id)
|
||||
if publish_item:
|
||||
store.publish(parent.location, user_id)
|
||||
elif publish_item:
|
||||
store.publish(location, user_id)
|
||||
|
||||
# return the published item
|
||||
return store.get_item(location)
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import xblock
|
||||
from xmodule.tabs import CourseTabList
|
||||
from xmodule.modulestore.exceptions import InvalidLocationError
|
||||
from xmodule.modulestore.mongo.base import MongoRevisionKey
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -159,165 +160,167 @@ def import_from_xml(
|
||||
# of course modules. It will be left as a TBD to implement that
|
||||
# method on XmlModuleStore.
|
||||
course_items = []
|
||||
for course_key in xml_module_store.modules.keys():
|
||||
|
||||
if target_course_id is not None:
|
||||
dest_course_id = target_course_id
|
||||
else:
|
||||
dest_course_id = course_key
|
||||
with store.branch_setting(ModuleStoreEnum.Branch.draft_preferred):
|
||||
for course_key in xml_module_store.modules.keys():
|
||||
|
||||
# Creates a new course if it doesn't already exist
|
||||
if create_new_course_if_not_present and not store.has_course(dest_course_id, ignore_case=True):
|
||||
try:
|
||||
store.create_course(dest_course_id.org, dest_course_id.offering, user_id)
|
||||
except InvalidLocationError:
|
||||
# course w/ same org and course exists
|
||||
log.debug(
|
||||
"Skipping import of course with id, {0},"
|
||||
"since it collides with an existing one".format(dest_course_id)
|
||||
)
|
||||
continue
|
||||
if target_course_id is not None:
|
||||
dest_course_id = target_course_id
|
||||
else:
|
||||
dest_course_id = course_key
|
||||
|
||||
with store.bulk_write_operations(dest_course_id):
|
||||
course_data_path = None
|
||||
|
||||
if verbose:
|
||||
log.debug("Scanning {0} for course module...".format(course_key))
|
||||
|
||||
# Quick scan to get course module as we need some info from there.
|
||||
# Also we need to make sure that the course module is committed
|
||||
# first into the store
|
||||
for module in xml_module_store.modules[course_key].itervalues():
|
||||
if module.scope_ids.block_type == 'course':
|
||||
course_data_path = path(data_dir) / module.data_dir
|
||||
|
||||
log.debug(u'======> IMPORTING course {course_key}'.format(
|
||||
course_key=course_key,
|
||||
))
|
||||
|
||||
if not do_import_static:
|
||||
# for old-style xblock where this was actually linked to kvs
|
||||
module.static_asset_path = module.data_dir
|
||||
module.save()
|
||||
log.debug('course static_asset_path={path}'.format(
|
||||
path=module.static_asset_path
|
||||
))
|
||||
|
||||
log.debug('course data_dir={0}'.format(module.data_dir))
|
||||
|
||||
course = _import_module_and_update_references(
|
||||
module, store, user_id,
|
||||
course_key,
|
||||
dest_course_id,
|
||||
do_import_static=do_import_static
|
||||
# Creates a new course if it doesn't already exist
|
||||
if create_new_course_if_not_present and not store.has_course(dest_course_id, ignore_case=True):
|
||||
try:
|
||||
store.create_course(dest_course_id.org, dest_course_id.offering, user_id)
|
||||
except InvalidLocationError:
|
||||
# course w/ same org and course exists
|
||||
log.debug(
|
||||
"Skipping import of course with id, {0},"
|
||||
"since it collides with an existing one".format(dest_course_id)
|
||||
)
|
||||
|
||||
for entry in course.pdf_textbooks:
|
||||
for chapter in entry.get('chapters', []):
|
||||
if StaticContent.is_c4x_path(chapter.get('url', '')):
|
||||
asset_key = StaticContent.get_location_from_path(chapter['url'])
|
||||
chapter['url'] = StaticContent.get_static_path_from_location(asset_key)
|
||||
|
||||
# Original wiki_slugs had value location.course. To make them unique this was changed to 'org.course.name'.
|
||||
# If we are importing into a course with a different course_id and wiki_slug is equal to either of these default
|
||||
# values then remap it so that the wiki does not point to the old wiki.
|
||||
if course_key != course.id:
|
||||
original_unique_wiki_slug = u'{0}.{1}.{2}'.format(
|
||||
course_key.org,
|
||||
course_key.course,
|
||||
course_key.run
|
||||
)
|
||||
if course.wiki_slug == original_unique_wiki_slug or course.wiki_slug == course_key.course:
|
||||
course.wiki_slug = u'{0}.{1}.{2}'.format(
|
||||
course.id.org,
|
||||
course.id.course,
|
||||
course.id.run,
|
||||
)
|
||||
|
||||
# cdodge: more hacks (what else). Seems like we have a
|
||||
# problem when importing a course (like 6.002) which
|
||||
# does not have any tabs defined in the policy file.
|
||||
# The import goes fine and then displays fine in LMS,
|
||||
# but if someone tries to add a new tab in the CMS, then
|
||||
# the LMS barfs because it expects that -- if there are
|
||||
# *any* tabs -- then there at least needs to be
|
||||
# some predefined ones
|
||||
if course.tabs is None or len(course.tabs) == 0:
|
||||
CourseTabList.initialize_default(course)
|
||||
|
||||
store.update_item(course, user_id)
|
||||
|
||||
course_items.append(course)
|
||||
break
|
||||
|
||||
# TODO: shouldn't this raise an exception if course wasn't found?
|
||||
|
||||
# then import all the static content
|
||||
if static_content_store is not None and do_import_static:
|
||||
# first pass to find everything in /static/
|
||||
import_static_content(
|
||||
course_data_path, static_content_store,
|
||||
dest_course_id, subpath='static', verbose=verbose
|
||||
)
|
||||
|
||||
elif verbose and not do_import_static:
|
||||
log.debug(
|
||||
"Skipping import of static content, "
|
||||
"since do_import_static={0}".format(do_import_static)
|
||||
)
|
||||
|
||||
# no matter what do_import_static is, import "static_import" directory
|
||||
|
||||
# This is needed because the "about" pages (eg "overview") are
|
||||
# loaded via load_extra_content, and do not inherit the lms
|
||||
# metadata from the course module, and thus do not get
|
||||
# "static_content_store" properly defined. Static content
|
||||
# referenced in those extra pages thus need to come through the
|
||||
# c4x:// contentstore, unfortunately. Tell users to copy that
|
||||
# content into the "static_import" subdir.
|
||||
|
||||
simport = 'static_import'
|
||||
if os.path.exists(course_data_path / simport):
|
||||
import_static_content(
|
||||
course_data_path, static_content_store,
|
||||
dest_course_id, subpath=simport, verbose=verbose
|
||||
)
|
||||
|
||||
# now loop through all the modules
|
||||
for module in xml_module_store.modules[course_key].itervalues():
|
||||
if module.scope_ids.block_type == 'course':
|
||||
# we've already saved the course module up at the top
|
||||
# of the loop so just skip over it in the inner loop
|
||||
continue
|
||||
|
||||
if verbose:
|
||||
log.debug('importing module location {loc}'.format(
|
||||
loc=module.location
|
||||
))
|
||||
with store.bulk_write_operations(dest_course_id):
|
||||
course_data_path = None
|
||||
|
||||
_import_module_and_update_references(
|
||||
module, store,
|
||||
if verbose:
|
||||
log.debug("Scanning {0} for course module...".format(course_key))
|
||||
|
||||
# Quick scan to get course module as we need some info from there.
|
||||
# Also we need to make sure that the course module is committed
|
||||
# first into the store
|
||||
for module in xml_module_store.modules[course_key].itervalues():
|
||||
if module.scope_ids.block_type == 'course':
|
||||
course_data_path = path(data_dir) / module.data_dir
|
||||
|
||||
log.debug(u'======> IMPORTING course {course_key}'.format(
|
||||
course_key=course_key,
|
||||
))
|
||||
|
||||
if not do_import_static:
|
||||
# for old-style xblock where this was actually linked to kvs
|
||||
module.static_asset_path = module.data_dir
|
||||
module.save()
|
||||
log.debug('course static_asset_path={path}'.format(
|
||||
path=module.static_asset_path
|
||||
))
|
||||
|
||||
log.debug('course data_dir={0}'.format(module.data_dir))
|
||||
|
||||
course = _import_module_and_update_references(
|
||||
module, store, user_id,
|
||||
course_key,
|
||||
dest_course_id,
|
||||
do_import_static=do_import_static
|
||||
)
|
||||
|
||||
for entry in course.pdf_textbooks:
|
||||
for chapter in entry.get('chapters', []):
|
||||
if StaticContent.is_c4x_path(chapter.get('url', '')):
|
||||
asset_key = StaticContent.get_location_from_path(chapter['url'])
|
||||
chapter['url'] = StaticContent.get_static_path_from_location(asset_key)
|
||||
|
||||
# Original wiki_slugs had value location.course. To make them unique this was changed to 'org.course.name'.
|
||||
# If we are importing into a course with a different course_id and wiki_slug is equal to either of these default
|
||||
# values then remap it so that the wiki does not point to the old wiki.
|
||||
if course_key != course.id:
|
||||
original_unique_wiki_slug = u'{0}.{1}.{2}'.format(
|
||||
course_key.org,
|
||||
course_key.course,
|
||||
course_key.run
|
||||
)
|
||||
if course.wiki_slug == original_unique_wiki_slug or course.wiki_slug == course_key.course:
|
||||
course.wiki_slug = u'{0}.{1}.{2}'.format(
|
||||
course.id.org,
|
||||
course.id.course,
|
||||
course.id.run,
|
||||
)
|
||||
|
||||
# cdodge: more hacks (what else). Seems like we have a
|
||||
# problem when importing a course (like 6.002) which
|
||||
# does not have any tabs defined in the policy file.
|
||||
# The import goes fine and then displays fine in LMS,
|
||||
# but if someone tries to add a new tab in the CMS, then
|
||||
# the LMS barfs because it expects that -- if there are
|
||||
# *any* tabs -- then there at least needs to be
|
||||
# some predefined ones
|
||||
if course.tabs is None or len(course.tabs) == 0:
|
||||
CourseTabList.initialize_default(course)
|
||||
|
||||
store.update_item(course, user_id)
|
||||
|
||||
course_items.append(course)
|
||||
break
|
||||
|
||||
# TODO: shouldn't this raise an exception if course wasn't found?
|
||||
|
||||
# then import all the static content
|
||||
if static_content_store is not None and do_import_static:
|
||||
# first pass to find everything in /static/
|
||||
import_static_content(
|
||||
course_data_path, static_content_store,
|
||||
dest_course_id, subpath='static', verbose=verbose
|
||||
)
|
||||
|
||||
elif verbose and not do_import_static:
|
||||
log.debug(
|
||||
"Skipping import of static content, "
|
||||
"since do_import_static={0}".format(do_import_static)
|
||||
)
|
||||
|
||||
# no matter what do_import_static is, import "static_import" directory
|
||||
|
||||
# This is needed because the "about" pages (eg "overview") are
|
||||
# loaded via load_extra_content, and do not inherit the lms
|
||||
# metadata from the course module, and thus do not get
|
||||
# "static_content_store" properly defined. Static content
|
||||
# referenced in those extra pages thus need to come through the
|
||||
# c4x:// contentstore, unfortunately. Tell users to copy that
|
||||
# content into the "static_import" subdir.
|
||||
|
||||
simport = 'static_import'
|
||||
if os.path.exists(course_data_path / simport):
|
||||
import_static_content(
|
||||
course_data_path, static_content_store,
|
||||
dest_course_id, subpath=simport, verbose=verbose
|
||||
)
|
||||
|
||||
# now loop through all the modules
|
||||
for module in xml_module_store.modules[course_key].itervalues():
|
||||
if module.scope_ids.block_type == 'course':
|
||||
# we've already saved the course module up at the top
|
||||
# of the loop so just skip over it in the inner loop
|
||||
continue
|
||||
|
||||
if verbose:
|
||||
log.debug('importing module location {loc}'.format(
|
||||
loc=module.location
|
||||
))
|
||||
|
||||
_import_module_and_update_references(
|
||||
module, store,
|
||||
user_id,
|
||||
course_key,
|
||||
dest_course_id,
|
||||
do_import_static=do_import_static,
|
||||
runtime=course.runtime
|
||||
)
|
||||
|
||||
# finally, publish the course
|
||||
store.publish(course.location, user_id)
|
||||
|
||||
# now import any DRAFT items
|
||||
_import_course_draft(
|
||||
xml_module_store,
|
||||
store,
|
||||
user_id,
|
||||
course_data_path,
|
||||
course_key,
|
||||
dest_course_id,
|
||||
do_import_static=do_import_static,
|
||||
runtime=course.runtime
|
||||
course.runtime
|
||||
)
|
||||
|
||||
# finally, publish the course
|
||||
store.publish(course.location, user_id)
|
||||
|
||||
# now import any DRAFT items
|
||||
_import_course_draft(
|
||||
xml_module_store,
|
||||
store,
|
||||
user_id,
|
||||
course_data_path,
|
||||
course_key,
|
||||
dest_course_id,
|
||||
course.runtime
|
||||
)
|
||||
|
||||
return xml_module_store, course_items
|
||||
|
||||
|
||||
|
||||
@@ -30,10 +30,11 @@ class AnonymousIndexPageTest(ModuleStoreTestCase):
|
||||
def setUp(self):
|
||||
super(AnonymousIndexPageTest, self).setUp()
|
||||
self.factory = RequestFactory()
|
||||
self.course = CourseFactory.create()
|
||||
self.course.days_early_for_beta = 5
|
||||
self.course.enrollment_start = datetime.datetime.now(UTC) + datetime.timedelta(days=3)
|
||||
self.store.update_item(self.course, self.user.id)
|
||||
self.course = CourseFactory.create(
|
||||
days_early_for_beta=5,
|
||||
enrollment_start=datetime.datetime.now(UTC)+datetime.timedelta(days=3),
|
||||
user_id=self.user.id,
|
||||
)
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_STARTDATE)
|
||||
def test_none_user_index_access_with_startdate_fails(self):
|
||||
|
||||
@@ -3,7 +3,7 @@ import textwrap
|
||||
from lettuce import world, steps
|
||||
from nose.tools import assert_in, assert_equals, assert_true
|
||||
|
||||
from common import i_am_registered_for_the_course, visit_scenario_item, publish
|
||||
from common import i_am_registered_for_the_course, visit_scenario_item
|
||||
|
||||
DATA_TEMPLATE = textwrap.dedent("""\
|
||||
<annotatable>
|
||||
@@ -78,9 +78,6 @@ class AnnotatableSteps(object):
|
||||
display_name="Test Annotation Module",
|
||||
data=DATA_TEMPLATE.format("\n".join(ANNOTATION_TEMPLATE.format(i) for i in xrange(count)))
|
||||
)
|
||||
|
||||
publish(world.scenario_dict['ANNOTATION_VERTICAL'].location)
|
||||
|
||||
self.annotations_count = count
|
||||
|
||||
def view_component(self, step):
|
||||
@@ -125,7 +122,6 @@ class AnnotatableSteps(object):
|
||||
)
|
||||
)
|
||||
)
|
||||
publish(world.scenario_dict['ANNOTATION_VERTICAL'].location)
|
||||
|
||||
def click_reply(self, step, problem):
|
||||
r"""I click "Reply to annotation" on passage (?P<problem>\d+)$"""
|
||||
|
||||
@@ -134,10 +134,6 @@ def section_location(course_num):
|
||||
return world.scenario_dict['SECTION'].location.replace(course=course_num)
|
||||
|
||||
|
||||
def publish(location):
|
||||
modulestore().publish(location, '**replace_user**')
|
||||
|
||||
|
||||
def visit_scenario_item(item_key):
|
||||
"""
|
||||
Go to the courseware page containing the item stored in `world.scenario_dict`
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from lettuce import world, steps
|
||||
from nose.tools import assert_in, assert_true # pylint: disable=no-name-in-module
|
||||
|
||||
from common import i_am_registered_for_the_course, visit_scenario_item, publish
|
||||
from common import i_am_registered_for_the_course, visit_scenario_item
|
||||
from problems_setup import add_problem_to_course, answer_problem
|
||||
|
||||
@steps
|
||||
@@ -67,9 +67,6 @@ class ConditionalSteps(object):
|
||||
data='<html><div class="hidden-contents">Hidden Contents</p></html>'
|
||||
)
|
||||
|
||||
publish(world.scenario_dict['VERTICAL'].location)
|
||||
|
||||
|
||||
def setup_problem_attempts(self, step, not_attempted=None):
|
||||
r'that the conditioned problem has (?P<not_attempted>not )?been attempted$'
|
||||
visit_scenario_item('CONDITION_SOURCE')
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
from lettuce import world, steps
|
||||
from nose.tools import assert_in, assert_equals, assert_true
|
||||
|
||||
from common import i_am_registered_for_the_course, visit_scenario_item, publish
|
||||
from common import i_am_registered_for_the_course, visit_scenario_item
|
||||
from problems_setup import add_problem_to_course, answer_problem
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ from django.test.utils import override_settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.conf import settings
|
||||
|
||||
from xmodule.modulestore.mongo.base import MongoRevisionKey
|
||||
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, ItemFactory
|
||||
from xmodule.x_module import STUDENT_VIEW
|
||||
@@ -160,7 +161,8 @@ class TestLTIModuleListing(ModuleStoreTestCase):
|
||||
parent_location=self.section2.location,
|
||||
display_name="lti draft",
|
||||
category="lti",
|
||||
location=self.course.id.make_usage_key('lti', 'lti_published').replace(revision=MongoRevisionKey.draft),
|
||||
location=self.course.id.make_usage_key('lti', 'lti_published'),
|
||||
publish_item=False,
|
||||
)
|
||||
|
||||
def expected_handler_url(self, handler):
|
||||
|
||||
@@ -12,6 +12,7 @@ from webob import Request
|
||||
from xmodule.contentstore.content import StaticContent
|
||||
from xmodule.contentstore.django import contentstore
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.x_module import STUDENT_VIEW
|
||||
from . import BaseTestXmodule
|
||||
from .test_video_xml import SOURCE_XML
|
||||
@@ -411,7 +412,8 @@ class TestTranscriptTranslationGetDispatch(TestVideo):
|
||||
self.course.static_asset_path = 'dummy/static'
|
||||
self.course.save()
|
||||
store = modulestore()
|
||||
store.update_item(self.course, self.user.id)
|
||||
with store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.course.id):
|
||||
store.update_item(self.course, self.user.id)
|
||||
|
||||
# Test youtube style en
|
||||
request = Request.blank('/translation/en?videoId=12345')
|
||||
|
||||
@@ -13,6 +13,7 @@ from django.contrib.auth.models import User
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from capa.tests.response_xml_factory import OptionResponseXMLFactory
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
@@ -207,8 +208,10 @@ class InstructorTaskModuleTestCase(InstructorTaskCourseTestCase):
|
||||
problem_xml = factory.build_xml(**factory_args)
|
||||
location = InstructorTaskTestCase.problem_location(problem_url_name)
|
||||
item = self.module_store.get_item(location)
|
||||
item.data = problem_xml
|
||||
self.module_store.update_item(item, self.user.id)
|
||||
with self.module_store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, location.course_key):
|
||||
item.data = problem_xml
|
||||
self.module_store.update_item(item, self.user.id)
|
||||
self.module_store.publish(location, self.user.id)
|
||||
|
||||
def get_student_module(self, username, descriptor):
|
||||
"""Get StudentModule object for test course, given the `username` and the problem's `descriptor`."""
|
||||
|
||||
@@ -17,6 +17,7 @@ from django.core.urlresolvers import reverse
|
||||
from capa.tests.response_xml_factory import (CodeResponseXMLFactory,
|
||||
CustomResponseXMLFactory)
|
||||
from xmodule.modulestore.tests.factories import ItemFactory
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
|
||||
from courseware.model_data import StudentModule
|
||||
|
||||
@@ -297,7 +298,9 @@ class TestRescoringTask(TestIntegrationTask):
|
||||
InstructorTaskModuleTestCase.problem_location(problem_url_name)
|
||||
)
|
||||
descriptor.data = problem_xml
|
||||
self.module_store.update_item(descriptor, self.user.id)
|
||||
with self.module_store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, descriptor.location.course_key):
|
||||
self.module_store.update_item(descriptor, self.user.id)
|
||||
self.module_store.publish(descriptor.location, self.user.id)
|
||||
else:
|
||||
# Use "per-student" rerandomization so that check-problem can be called more than once.
|
||||
# Using "always" means we cannot check a problem twice, but we want to call once to get the
|
||||
|
||||
@@ -109,7 +109,6 @@ STATICFILES_DIRS += [
|
||||
if os.path.isdir(COMMON_TEST_DATA_ROOT / course_dir)
|
||||
]
|
||||
|
||||
MODULESTORE_BRANCH = 'draft-preferred'
|
||||
update_module_store_settings(
|
||||
MODULESTORE,
|
||||
module_store_options={
|
||||
|
||||
Reference in New Issue
Block a user