Commit b4fe23f3 by Chris Dodge

more cleanups in CMS project

parent 3ca2bf46
import logging
import sys
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
...@@ -131,7 +128,7 @@ def remove_user_from_course_group(caller, user, location, role): ...@@ -131,7 +128,7 @@ def remove_user_from_course_group(caller, user, location, role):
raise PermissionDenied raise PermissionDenied
# see if the user is actually in that role, if not then we don't have to do anything # see if the user is actually in that role, if not then we don't have to do anything
if is_user_in_course_group_role(user, location, role) == True: if is_user_in_course_group_role(user, location, role):
groupname = get_course_groupname_for_role(location, role) groupname = get_course_groupname_for_role(location, role)
group = Group.objects.get(name=groupname) group = Group.objects.get(name=groupname)
......
...@@ -6,6 +6,7 @@ from nose.tools import assert_true, assert_equal ...@@ -6,6 +6,7 @@ from nose.tools import assert_true, assert_equal
from terrain.steps import reload_the_page from terrain.steps import reload_the_page
from selenium.common.exceptions import StaleElementReferenceException from selenium.common.exceptions import StaleElementReferenceException
############### ACTIONS #################### ############### ACTIONS ####################
@step('I select Checklists from the Tools menu$') @step('I select Checklists from the Tools menu$')
def i_select_checklists(step): def i_select_checklists(step):
......
...@@ -59,7 +59,7 @@ class Command(BaseCommand): ...@@ -59,7 +59,7 @@ class Command(BaseCommand):
discussion_items = _get_discussion_items(course) discussion_items = _get_discussion_items(course)
# now query all discussion items via get_items() and compare with the tree-traversal # now query all discussion items via get_items() and compare with the tree-traversal
queried_discussion_items = store.get_items(['i4x', course.location.org, course.location.course, queried_discussion_items = store.get_items(['i4x', course.location.org, course.location.course,
'discussion', None, None]) 'discussion', None, None])
for item in queried_discussion_items: for item in queried_discussion_items:
......
...@@ -5,7 +5,6 @@ from django.core.management.base import BaseCommand, CommandError ...@@ -5,7 +5,6 @@ from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.store_utilities import clone_course from xmodule.modulestore.store_utilities import clone_course
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.contentstore.django import contentstore from xmodule.contentstore.django import contentstore
from xmodule.modulestore import Location
from xmodule.course_module import CourseDescriptor from xmodule.course_module import CourseDescriptor
from auth.authz import _copy_course_group from auth.authz import _copy_course_group
...@@ -16,8 +15,7 @@ from auth.authz import _copy_course_group ...@@ -16,8 +15,7 @@ from auth.authz import _copy_course_group
class Command(BaseCommand): class Command(BaseCommand):
help = \ help = 'Clone a MongoDB backed course to another location'
'''Clone a MongoDB backed course to another location'''
def handle(self, *args, **options): def handle(self, *args, **options):
if len(args) != 2: if len(args) != 2:
......
...@@ -5,7 +5,6 @@ from django.core.management.base import BaseCommand, CommandError ...@@ -5,7 +5,6 @@ from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.store_utilities import delete_course from xmodule.modulestore.store_utilities import delete_course
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.contentstore.django import contentstore from xmodule.contentstore.django import contentstore
from xmodule.modulestore import Location
from xmodule.course_module import CourseDescriptor from xmodule.course_module import CourseDescriptor
from .prompt import query_yes_no from .prompt import query_yes_no
...@@ -38,7 +37,7 @@ class Command(BaseCommand): ...@@ -38,7 +37,7 @@ class Command(BaseCommand):
if query_yes_no("Deleting course {0}. Confirm?".format(loc_str), default="no"): if query_yes_no("Deleting course {0}. Confirm?".format(loc_str), default="no"):
if query_yes_no("Are you sure. This action cannot be undone!", default="no"): if query_yes_no("Are you sure. This action cannot be undone!", default="no"):
loc = CourseDescriptor.id_to_location(loc_str) loc = CourseDescriptor.id_to_location(loc_str)
if delete_course(ms, cs, loc, commit) == True: if delete_course(ms, cs, loc, commit):
print 'removing User permissions from course....' print 'removing User permissions from course....'
# in the django layer, we need to remove all the user permissions groups associated with this course # in the django layer, we need to remove all the user permissions groups associated with this course
if commit: if commit:
......
...@@ -7,7 +7,6 @@ from django.core.management.base import BaseCommand, CommandError ...@@ -7,7 +7,6 @@ from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.xml_exporter import export_to_xml from xmodule.modulestore.xml_exporter import export_to_xml
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.contentstore.django import contentstore from xmodule.contentstore.django import contentstore
from xmodule.modulestore import Location
from xmodule.course_module import CourseDescriptor from xmodule.course_module import CourseDescriptor
...@@ -15,8 +14,7 @@ unnamed_modules = 0 ...@@ -15,8 +14,7 @@ unnamed_modules = 0
class Command(BaseCommand): class Command(BaseCommand):
help = \ help = 'Import the specified data directory into the default ModuleStore'
'''Import the specified data directory into the default ModuleStore'''
def handle(self, *args, **options): def handle(self, *args, **options):
if len(args) != 2: if len(args) != 2:
......
...@@ -12,8 +12,7 @@ unnamed_modules = 0 ...@@ -12,8 +12,7 @@ unnamed_modules = 0
class Command(BaseCommand): class Command(BaseCommand):
help = \ help = 'Import the specified data directory into the default ModuleStore'
'''Import the specified data directory into the default ModuleStore'''
def handle(self, *args, **options): def handle(self, *args, **options):
if len(args) == 0: if len(args) == 0:
...@@ -28,4 +27,4 @@ class Command(BaseCommand): ...@@ -28,4 +27,4 @@ class Command(BaseCommand):
data=data_dir, data=data_dir,
courses=course_dirs) courses=course_dirs)
import_from_xml(modulestore('direct'), data_dir, course_dirs, load_error_modules=False, import_from_xml(modulestore('direct'), data_dir, course_dirs, load_error_modules=False,
static_content_store=contentstore(), verbose=True) static_content_store=contentstore(), verbose=True)
...@@ -11,8 +11,8 @@ def query_yes_no(question, default="yes"): ...@@ -11,8 +11,8 @@ def query_yes_no(question, default="yes"):
The "answer" return value is one of "yes" or "no". The "answer" return value is one of "yes" or "no".
""" """
valid = {"yes":True, "y":True, "ye":True, valid = {"yes": True, "y": True, "ye": True,
"no":False, "n":False} "no": False, "n": False}
if default is None: if default is None:
prompt = " [y/n] " prompt = " [y/n] "
elif default == "yes": elif default == "yes":
...@@ -30,5 +30,4 @@ def query_yes_no(question, default="yes"): ...@@ -30,5 +30,4 @@ def query_yes_no(question, default="yes"):
elif choice in valid: elif choice in valid:
return valid[choice] return valid[choice]
else: else:
sys.stdout.write("Please respond with 'yes' or 'no' "\ sys.stdout.write("Please respond with 'yes' or 'no' (or 'y' or 'n').\n")
"(or 'y' or 'n').\n")
from xmodule.templates import update_templates from xmodule.templates import update_templates
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
class Command(BaseCommand): class Command(BaseCommand):
help = \ help = 'Imports and updates the Studio component templates from the code pack and put in the DB'
'''Imports and updates the Studio component templates from the code pack and put in the DB'''
def handle(self, *args, **options): def handle(self, *args, **options):
update_templates() update_templates()
\ No newline at end of file
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from xmodule.modulestore.xml_importer import perform_xlint from xmodule.modulestore.xml_importer import perform_xlint
from xmodule.modulestore.django import modulestore
from xmodule.contentstore.django import contentstore
unnamed_modules = 0 unnamed_modules = 0
...@@ -9,10 +7,11 @@ unnamed_modules = 0 ...@@ -9,10 +7,11 @@ unnamed_modules = 0
class Command(BaseCommand): class Command(BaseCommand):
help = \ help = \
''' '''
Verify the structure of courseware as to it's suitability for import Verify the structure of courseware as to it's suitability for import
To run test: rake cms:xlint DATA_DIR=../data [COURSE_DIR=content-edx-101 (optional parameter)] To run test: rake cms:xlint DATA_DIR=../data [COURSE_DIR=content-edx-101 (optional parameter)]
''' '''
def handle(self, *args, **options): def handle(self, *args, **options):
if len(args) == 0: if len(args) == 0:
raise CommandError("import requires at least one argument: <data directory> [<course dir>...]") raise CommandError("import requires at least one argument: <data directory> [<course dir>...]")
......
...@@ -6,8 +6,6 @@ from django.conf import settings ...@@ -6,8 +6,6 @@ from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from path import path from path import path
from tempdir import mkdtemp_clean from tempdir import mkdtemp_clean
from datetime import timedelta
import json
from fs.osfs import OSFS from fs.osfs import OSFS
import copy import copy
from json import loads from json import loads
...@@ -39,6 +37,7 @@ TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE) ...@@ -39,6 +37,7 @@ TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE)
TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data') TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data')
TEST_DATA_MODULESTORE['direct']['OPTIONS']['fs_root'] = path('common/test/data') TEST_DATA_MODULESTORE['direct']['OPTIONS']['fs_root'] = path('common/test/data')
class MongoCollectionFindWrapper(object): class MongoCollectionFindWrapper(object):
def __init__(self, original): def __init__(self, original):
self.original = original self.original = original
...@@ -187,32 +186,31 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): ...@@ -187,32 +186,31 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
def test_get_depth_with_drafts(self): def test_get_depth_with_drafts(self):
import_from_xml(modulestore(), 'common/test/data/', ['simple']) import_from_xml(modulestore(), 'common/test/data/', ['simple'])
course = modulestore('draft').get_item(Location(['i4x', 'edX', 'simple', course = modulestore('draft').get_item(Location(['i4x', 'edX', 'simple',
'course', '2012_Fall', None]), depth=None) 'course', '2012_Fall', None]), depth=None)
# make sure no draft items have been returned # make sure no draft items have been returned
num_drafts = self._get_draft_counts(course) num_drafts = self._get_draft_counts(course)
self.assertEqual(num_drafts, 0) self.assertEqual(num_drafts, 0)
problem = modulestore('draft').get_item(Location(['i4x', 'edX', 'simple', problem = modulestore('draft').get_item(Location(['i4x', 'edX', 'simple',
'problem', 'ps01-simple', None])) 'problem', 'ps01-simple', None]))
# put into draft # put into draft
modulestore('draft').clone_item(problem.location, problem.location) modulestore('draft').clone_item(problem.location, problem.location)
# make sure we can query that item and verify that it is a draft # make sure we can query that item and verify that it is a draft
draft_problem = modulestore('draft').get_item(Location(['i4x', 'edX', 'simple', draft_problem = modulestore('draft').get_item(Location(['i4x', 'edX', 'simple',
'problem', 'ps01-simple', None])) 'problem', 'ps01-simple', None]))
self.assertTrue(getattr(draft_problem,'is_draft', False)) self.assertTrue(getattr(draft_problem, 'is_draft', False))
#now requery with depth #now requery with depth
course = modulestore('draft').get_item(Location(['i4x', 'edX', 'simple', course = modulestore('draft').get_item(Location(['i4x', 'edX', 'simple',
'course', '2012_Fall', None]), depth=None) 'course', '2012_Fall', None]), depth=None)
# make sure just one draft item have been returned # make sure just one draft item have been returned
num_drafts = self._get_draft_counts(course) num_drafts = self._get_draft_counts(course)
self.assertEqual(num_drafts, 1) self.assertEqual(num_drafts, 1)
def test_static_tab_reordering(self): def test_static_tab_reordering(self):
import_from_xml(modulestore(), 'common/test/data/', ['full']) import_from_xml(modulestore(), 'common/test/data/', ['full'])
...@@ -268,8 +266,9 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): ...@@ -268,8 +266,9 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
self.assertTrue(sequential.location.url() in chapter.children) self.assertTrue(sequential.location.url() in chapter.children)
self.client.post(reverse('delete_item'), self.client.post(reverse('delete_item'),
json.dumps({'id': sequential.location.url(), 'delete_children': 'true', 'delete_all_versions': 'true'}), json.dumps({'id': sequential.location.url(), 'delete_children': 'true',
"application/json") 'delete_all_versions': 'true'}),
"application/json")
found = False found = False
try: try:
...@@ -387,7 +386,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): ...@@ -387,7 +386,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
draft_store.clone_item(vertical.location, vertical.location) draft_store.clone_item(vertical.location, vertical.location)
for child in vertical.get_children(): for child in vertical.get_children():
draft_store.clone_item(child.location, child.location) draft_store.clone_item(child.location, child.location)
root_dir = path(mkdtemp_clean()) root_dir = path(mkdtemp_clean())
...@@ -402,7 +401,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): ...@@ -402,7 +401,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
module_store.update_children(sequential.location, sequential.children + module_store.update_children(sequential.location, sequential.children +
[private_location_no_draft.url()]) [private_location_no_draft.url()])
# read back the sequential, to make sure we have a pointer to # read back the sequential, to make sure we have a pointer to
sequential = module_store.get_item(Location(['i4x', 'edX', 'full', sequential = module_store.get_item(Location(['i4x', 'edX', 'full',
'sequential', 'Administrivia_and_Circuit_Elements', None])) 'sequential', 'Administrivia_and_Circuit_Elements', None]))
...@@ -622,9 +621,9 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -622,9 +621,9 @@ class ContentStoreTest(ModuleStoreTestCase):
# Create a course so there is something to view # Create a course so there is something to view
resp = self.client.get(reverse('index')) resp = self.client.get(reverse('index'))
self.assertContains(resp, self.assertContains(resp,
'<h1 class="title-1">My Courses</h1>', '<h1 class="title-1">My Courses</h1>',
status_code=200, status_code=200,
html=True) html=True)
def test_course_factory(self): def test_course_factory(self):
"""Test that the course factory works correctly.""" """Test that the course factory works correctly."""
...@@ -642,9 +641,9 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -642,9 +641,9 @@ class ContentStoreTest(ModuleStoreTestCase):
CourseFactory.create(display_name='Robot Super Educational Course') CourseFactory.create(display_name='Robot Super Educational Course')
resp = self.client.get(reverse('index')) resp = self.client.get(reverse('index'))
self.assertContains(resp, self.assertContains(resp,
'<span class="class-name">Robot Super Educational Course</span>', '<span class="class-name">Robot Super Educational Course</span>',
status_code=200, status_code=200,
html=True) html=True)
def test_course_overview_view_with_course(self): def test_course_overview_view_with_course(self):
"""Test viewing the course overview page with an existing course""" """Test viewing the course overview page with an existing course"""
...@@ -658,9 +657,9 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -658,9 +657,9 @@ class ContentStoreTest(ModuleStoreTestCase):
resp = self.client.get(reverse('course_index', kwargs=data)) resp = self.client.get(reverse('course_index', kwargs=data))
self.assertContains(resp, self.assertContains(resp,
'<article class="courseware-overview" data-course-id="i4x://MITx/999/course/Robot_Super_Course">', '<article class="courseware-overview" data-course-id="i4x://MITx/999/course/Robot_Super_Course">',
status_code=200, status_code=200,
html=True) html=True)
def test_clone_item(self): def test_clone_item(self):
"""Test cloning an item. E.g. creating a new section""" """Test cloning an item. E.g. creating a new section"""
...@@ -676,8 +675,7 @@ class ContentStoreTest(ModuleStoreTestCase): ...@@ -676,8 +675,7 @@ class ContentStoreTest(ModuleStoreTestCase):
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
data = parse_json(resp) data = parse_json(resp)
self.assertRegexpMatches(data['id'], self.assertRegexpMatches(data['id'], '^i4x:\/\/MITx\/999\/chapter\/([0-9]|[a-f]){32}$')
'^i4x:\/\/MITx\/999\/chapter\/([0-9]|[a-f]){32}$')
def test_capa_module(self): def test_capa_module(self):
"""Test that a problem treats markdown specially.""" """Test that a problem treats markdown specially."""
......
...@@ -23,14 +23,14 @@ class CachingTestCase(TestCase): ...@@ -23,14 +23,14 @@ class CachingTestCase(TestCase):
def test_put_and_get(self): def test_put_and_get(self):
set_cached_content(self.mockAsset) set_cached_content(self.mockAsset)
self.assertEqual(self.mockAsset.content, get_cached_content(self.unicodeLocation).content, self.assertEqual(self.mockAsset.content, get_cached_content(self.unicodeLocation).content,
'should be stored in cache with unicodeLocation') 'should be stored in cache with unicodeLocation')
self.assertEqual(self.mockAsset.content, get_cached_content(self.nonUnicodeLocation).content, self.assertEqual(self.mockAsset.content, get_cached_content(self.nonUnicodeLocation).content,
'should be stored in cache with nonUnicodeLocation') 'should be stored in cache with nonUnicodeLocation')
def test_delete(self): def test_delete(self):
set_cached_content(self.mockAsset) set_cached_content(self.mockAsset)
del_cached_content(self.nonUnicodeLocation) del_cached_content(self.nonUnicodeLocation)
self.assertEqual(None, get_cached_content(self.unicodeLocation), self.assertEqual(None, get_cached_content(self.unicodeLocation),
'should not be stored in cache with unicodeLocation') 'should not be stored in cache with unicodeLocation')
self.assertEqual(None, get_cached_content(self.nonUnicodeLocation), self.assertEqual(None, get_cached_content(self.nonUnicodeLocation),
'should not be stored in cache with nonUnicodeLocation') 'should not be stored in cache with nonUnicodeLocation')
...@@ -8,8 +8,7 @@ from django.core.urlresolvers import reverse ...@@ -8,8 +8,7 @@ from django.core.urlresolvers import reverse
from django.utils.timezone import UTC from django.utils.timezone import UTC
from xmodule.modulestore import Location from xmodule.modulestore import Location
from models.settings.course_details import (CourseDetails, from models.settings.course_details import (CourseDetails, CourseSettingsEncoder)
CourseSettingsEncoder)
from models.settings.course_grading import CourseGradingModel from models.settings.course_grading import CourseGradingModel
from contentstore.utils import get_modulestore from contentstore.utils import get_modulestore
...@@ -21,6 +20,7 @@ from xmodule.modulestore.xml_importer import import_from_xml ...@@ -21,6 +20,7 @@ from xmodule.modulestore.xml_importer import import_from_xml
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.fields import Date from xmodule.fields import Date
class CourseTestCase(ModuleStoreTestCase): class CourseTestCase(ModuleStoreTestCase):
def setUp(self): def setUp(self):
""" """
...@@ -87,16 +87,16 @@ class CourseDetailsTestCase(CourseTestCase): ...@@ -87,16 +87,16 @@ class CourseDetailsTestCase(CourseTestCase):
jsondetails.syllabus = "<a href='foo'>bar</a>" jsondetails.syllabus = "<a href='foo'>bar</a>"
# encode - decode to convert date fields and other data which changes form # encode - decode to convert date fields and other data which changes form
self.assertEqual(CourseDetails.update_from_json(jsondetails.__dict__).syllabus, self.assertEqual(CourseDetails.update_from_json(jsondetails.__dict__).syllabus,
jsondetails.syllabus, "After set syllabus") jsondetails.syllabus, "After set syllabus")
jsondetails.overview = "Overview" jsondetails.overview = "Overview"
self.assertEqual(CourseDetails.update_from_json(jsondetails.__dict__).overview, self.assertEqual(CourseDetails.update_from_json(jsondetails.__dict__).overview,
jsondetails.overview, "After set overview") jsondetails.overview, "After set overview")
jsondetails.intro_video = "intro_video" jsondetails.intro_video = "intro_video"
self.assertEqual(CourseDetails.update_from_json(jsondetails.__dict__).intro_video, self.assertEqual(CourseDetails.update_from_json(jsondetails.__dict__).intro_video,
jsondetails.intro_video, "After set intro_video") jsondetails.intro_video, "After set intro_video")
jsondetails.effort = "effort" jsondetails.effort = "effort"
self.assertEqual(CourseDetails.update_from_json(jsondetails.__dict__).effort, self.assertEqual(CourseDetails.update_from_json(jsondetails.__dict__).effort,
jsondetails.effort, "After set effort") jsondetails.effort, "After set effort")
class CourseDetailsViewTest(CourseTestCase): class CourseDetailsViewTest(CourseTestCase):
...@@ -151,8 +151,8 @@ class CourseDetailsViewTest(CourseTestCase): ...@@ -151,8 +151,8 @@ class CourseDetailsViewTest(CourseTestCase):
@staticmethod @staticmethod
def struct_to_datetime(struct_time): def struct_to_datetime(struct_time):
return datetime.datetime(struct_time.tm_year, struct_time.tm_mon, return datetime.datetime(struct_time.tm_year, struct_time.tm_mon,
struct_time.tm_mday, struct_time.tm_hour, struct_time.tm_mday, struct_time.tm_hour,
struct_time.tm_min, struct_time.tm_sec, tzinfo=UTC()) struct_time.tm_min, struct_time.tm_sec, tzinfo=UTC())
def compare_date_fields(self, details, encoded, context, field): def compare_date_fields(self, details, encoded, context, field):
if details[field] is not None: if details[field] is not None:
...@@ -249,6 +249,7 @@ class CourseGradingTest(CourseTestCase): ...@@ -249,6 +249,7 @@ class CourseGradingTest(CourseTestCase):
altered_grader = CourseGradingModel.update_grader_from_json(test_grader.course_location, test_grader.graders[1]) altered_grader = CourseGradingModel.update_grader_from_json(test_grader.course_location, test_grader.graders[1])
self.assertDictEqual(test_grader.graders[1], altered_grader, "drop_count[1] + 2") self.assertDictEqual(test_grader.graders[1], altered_grader, "drop_count[1] + 2")
class CourseMetadataEditingTest(CourseTestCase): class CourseMetadataEditingTest(CourseTestCase):
def setUp(self): def setUp(self):
CourseTestCase.setUp(self) CourseTestCase.setUp(self)
...@@ -256,7 +257,6 @@ class CourseMetadataEditingTest(CourseTestCase): ...@@ -256,7 +257,6 @@ class CourseMetadataEditingTest(CourseTestCase):
import_from_xml(modulestore(), 'common/test/data/', ['full']) import_from_xml(modulestore(), 'common/test/data/', ['full'])
self.fullcourse_location = Location(['i4x', 'edX', 'full', 'course', '6.002_Spring_2012', None]) self.fullcourse_location = Location(['i4x', 'edX', 'full', 'course', '6.002_Spring_2012', None])
def test_fetch_initial_fields(self): def test_fetch_initial_fields(self):
test_model = CourseMetadata.fetch(self.course_location) test_model = CourseMetadata.fetch(self.course_location)
self.assertIn('display_name', test_model, 'Missing editable metadata field') self.assertIn('display_name', test_model, 'Missing editable metadata field')
...@@ -272,17 +272,17 @@ class CourseMetadataEditingTest(CourseTestCase): ...@@ -272,17 +272,17 @@ class CourseMetadataEditingTest(CourseTestCase):
def test_update_from_json(self): def test_update_from_json(self):
test_model = CourseMetadata.update_from_json(self.course_location, test_model = CourseMetadata.update_from_json(self.course_location,
{ "advertised_start" : "start A", {"advertised_start": "start A",
"testcenter_info" : { "c" : "test" }, "testcenter_info": {"c": "test"},
"days_early_for_beta" : 2}) "days_early_for_beta": 2})
self.update_check(test_model) self.update_check(test_model)
# try fresh fetch to ensure persistence # try fresh fetch to ensure persistence
test_model = CourseMetadata.fetch(self.course_location) test_model = CourseMetadata.fetch(self.course_location)
self.update_check(test_model) self.update_check(test_model)
# now change some of the existing metadata # now change some of the existing metadata
test_model = CourseMetadata.update_from_json(self.course_location, test_model = CourseMetadata.update_from_json(self.course_location,
{ "advertised_start" : "start B", {"advertised_start": "start B",
"display_name" : "jolly roger"}) "display_name": "jolly roger"})
self.assertIn('display_name', test_model, 'Missing editable metadata field') self.assertIn('display_name', test_model, 'Missing editable metadata field')
self.assertEqual(test_model['display_name'], 'jolly roger', "not expected value") self.assertEqual(test_model['display_name'], 'jolly roger', "not expected value")
self.assertIn('advertised_start', test_model, 'Missing revised advertised_start metadata field') self.assertIn('advertised_start', test_model, 'Missing revised advertised_start metadata field')
...@@ -294,13 +294,12 @@ class CourseMetadataEditingTest(CourseTestCase): ...@@ -294,13 +294,12 @@ class CourseMetadataEditingTest(CourseTestCase):
self.assertIn('advertised_start', test_model, 'Missing new advertised_start metadata field') self.assertIn('advertised_start', test_model, 'Missing new advertised_start metadata field')
self.assertEqual(test_model['advertised_start'], 'start A', "advertised_start not expected value") self.assertEqual(test_model['advertised_start'], 'start A', "advertised_start not expected value")
self.assertIn('testcenter_info', test_model, 'Missing testcenter_info metadata field') self.assertIn('testcenter_info', test_model, 'Missing testcenter_info metadata field')
self.assertDictEqual(test_model['testcenter_info'], { "c" : "test" }, "testcenter_info not expected value") self.assertDictEqual(test_model['testcenter_info'], {"c": "test"}, "testcenter_info not expected value")
self.assertIn('days_early_for_beta', test_model, 'Missing days_early_for_beta metadata field') self.assertIn('days_early_for_beta', test_model, 'Missing days_early_for_beta metadata field')
self.assertEqual(test_model['days_early_for_beta'], 2, "days_early_for_beta not expected value") self.assertEqual(test_model['days_early_for_beta'], 2, "days_early_for_beta not expected value")
def test_delete_key(self): def test_delete_key(self):
test_model = CourseMetadata.delete_key(self.fullcourse_location, { 'deleteKeys' : ['doesnt_exist', 'showanswer', 'xqa_key']}) test_model = CourseMetadata.delete_key(self.fullcourse_location, {'deleteKeys': ['doesnt_exist', 'showanswer', 'xqa_key']})
# ensure no harm # ensure no harm
self.assertNotIn('graceperiod', test_model, 'blacklisted field leaked in') self.assertNotIn('graceperiod', test_model, 'blacklisted field leaked in')
self.assertIn('display_name', test_model, 'full missing editable metadata field') self.assertIn('display_name', test_model, 'full missing editable metadata field')
......
...@@ -69,4 +69,5 @@ class UrlReverseTestCase(ModuleStoreTestCase): ...@@ -69,4 +69,5 @@ class UrlReverseTestCase(ModuleStoreTestCase):
self.assertEquals( self.assertEquals(
'https://edge.edx.org/courses/edX/edX101/How_to_Create_an_edX_Course/about', 'https://edge.edx.org/courses/edX/edX101/How_to_Create_an_edX_Course/about',
utils.get_url_reverse('https://edge.edx.org/courses/edX/edX101/How_to_Create_an_edX_Course/about', course) utils.get_url_reverse('https://edge.edx.org/courses/edX/edX101/How_to_Create_an_edX_Course/about', course)
) )
\ No newline at end of file
\ No newline at end of file
import json
import shutil
from django.test.client import Client from django.test.client import Client
from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from path import path
import json
from fs.osfs import OSFS
import copy
from contentstore.utils import get_modulestore
from xmodule.modulestore import Location
from xmodule.modulestore.store_utilities import clone_course
from xmodule.modulestore.store_utilities import delete_course
from xmodule.modulestore.django import modulestore, _MODULESTORES
from xmodule.contentstore.django import contentstore
from xmodule.templates import update_templates
from xmodule.modulestore.xml_exporter import export_to_xml
from xmodule.modulestore.xml_importer import import_from_xml
from xmodule.capa_module import CapaDescriptor
from xmodule.course_module import CourseDescriptor
from xmodule.seq_module import SequenceDescriptor
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from .utils import ModuleStoreTestCase, parse_json, user, registration from .utils import ModuleStoreTestCase, parse_json, user, registration
...@@ -84,6 +61,7 @@ class ContentStoreTestCase(ModuleStoreTestCase): ...@@ -84,6 +61,7 @@ class ContentStoreTestCase(ModuleStoreTestCase):
# Now make sure that the user is now actually activated # Now make sure that the user is now actually activated
self.assertTrue(user(email).is_active) self.assertTrue(user(email).is_active)
class AuthTestCase(ContentStoreTestCase): class AuthTestCase(ContentStoreTestCase):
"""Check that various permissions-related things work""" """Check that various permissions-related things work"""
...@@ -101,9 +79,9 @@ class AuthTestCase(ContentStoreTestCase): ...@@ -101,9 +79,9 @@ class AuthTestCase(ContentStoreTestCase):
def test_public_pages_load(self): def test_public_pages_load(self):
"""Make sure pages that don't require login load without error.""" """Make sure pages that don't require login load without error."""
pages = ( pages = (
reverse('login'), reverse('login'),
reverse('signup'), reverse('signup'),
) )
for page in pages: for page in pages:
print "Checking '{0}'".format(page) print "Checking '{0}'".format(page)
self.check_page_get(page, 200) self.check_page_get(page, 200)
...@@ -136,13 +114,13 @@ class AuthTestCase(ContentStoreTestCase): ...@@ -136,13 +114,13 @@ class AuthTestCase(ContentStoreTestCase):
"""Make sure pages that do require login work.""" """Make sure pages that do require login work."""
auth_pages = ( auth_pages = (
reverse('index'), reverse('index'),
) )
# These are pages that should just load when the user is logged in # These are pages that should just load when the user is logged in
# (no data needed) # (no data needed)
simple_auth_pages = ( simple_auth_pages = (
reverse('index'), reverse('index'),
) )
# need an activated user # need an activated user
self.test_create_account() self.test_create_account()
......
...@@ -346,14 +346,14 @@ def edit_unit(request, location): ...@@ -346,14 +346,14 @@ def edit_unit(request, location):
'preview.' + settings.LMS_BASE) 'preview.' + settings.LMS_BASE)
preview_lms_link = '//{preview_lms_base}/courses/{org}/{course}/{course_name}/courseware/{section}/{subsection}/{index}'.format( preview_lms_link = '//{preview_lms_base}/courses/{org}/{course}/{course_name}/courseware/{section}/{subsection}/{index}'.format(
preview_lms_base=preview_lms_base, preview_lms_base=preview_lms_base,
lms_base=settings.LMS_BASE, lms_base=settings.LMS_BASE,
org=course.location.org, org=course.location.org,
course=course.location.course, course=course.location.course,
course_name=course.location.name, course_name=course.location.name,
section=containing_section.location.name, section=containing_section.location.name,
subsection=containing_subsection.location.name, subsection=containing_subsection.location.name,
index=index) index=index)
unit_state = compute_unit_state(item) unit_state = compute_unit_state(item)
...@@ -839,6 +839,7 @@ def upload_asset(request, org, course, coursename): ...@@ -839,6 +839,7 @@ def upload_asset(request, org, course, coursename):
response['asset_url'] = StaticContent.get_url_path_from_location(content.location) response['asset_url'] = StaticContent.get_url_path_from_location(content.location)
return response return response
@login_required @login_required
@ensure_csrf_cookie @ensure_csrf_cookie
def manage_users(request, location): def manage_users(request, location):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment