Commit 7f017d0c by Jean Manuel Nater

Addressed pull request feedback

parent c4c68f51
......@@ -357,7 +357,6 @@ def change_enrollment(request):
return HttpResponseBadRequest("Course id not specified")
if action == "enroll":
# Make sure the course exists
# We don't do this check on unenroll, or a bad course id can't be unenrolled from
try:
......@@ -366,6 +365,7 @@ def change_enrollment(request):
log.warning("User {0} tried to enroll in non-existent course {1}"
.format(user.username, course_id))
return HttpResponseBadRequest("Course id is invalid")
if not has_access(user, course, 'enroll'):
return HttpResponseBadRequest("Enrollment is closed")
......
......@@ -17,30 +17,24 @@ class ModuleStoreTestCase(TestCase):
@staticmethod
def update_course(course, data):
"""
Updates the version of course in the mongo modulestore
with the metadata in data and returns the updated version.
Updates the version of course in the modulestore
with the metadata in 'data' and returns the updated version.
'course' is an instance of CourseDescriptor for which we want
to update metadata.
'data' is a dictionary with an entry for each CourseField we want to update.
"""
store = xmodule.modulestore.django.modulestore()
store.update_item(course.location, data)
store.update_metadata(course.location, data)
updated_course = store.get_instance(course.id, course.location)
return updated_course
@staticmethod
def flush_mongo_except_templates():
'''
Delete everything in the module store except templates
'''
"""
Delete everything in the module store except templates.
"""
modulestore = xmodule.modulestore.django.modulestore()
# This query means: every item in the collection
......@@ -52,11 +46,11 @@ class ModuleStoreTestCase(TestCase):
@staticmethod
def load_templates_if_necessary():
'''
"""
Load templates into the direct modulestore only if they do not already exist.
We need the templates, because they are copied to create
XModules such as sections and problems
'''
XModules such as sections and problems.
"""
modulestore = xmodule.modulestore.django.modulestore('direct')
# Count the number of templates
......@@ -68,9 +62,9 @@ class ModuleStoreTestCase(TestCase):
@classmethod
def setUpClass(cls):
'''
Flush the mongo store and set up templates
'''
"""
Flush the mongo store and set up templates.
"""
# Use a uuid to differentiate
# the mongo collections on jenkins.
......@@ -88,9 +82,9 @@ class ModuleStoreTestCase(TestCase):
@classmethod
def tearDownClass(cls):
'''
Revert to the old modulestore settings
'''
"""
Revert to the old modulestore settings.
"""
# Clean up by dropping the collection
modulestore = xmodule.modulestore.django.modulestore()
......@@ -102,9 +96,9 @@ class ModuleStoreTestCase(TestCase):
settings.MODULESTORE = cls.orig_modulestore
def _pre_setup(self):
'''
Remove everything but the templates before each test
'''
"""
Remove everything but the templates before each test.
"""
# Flush anything that is not a template
ModuleStoreTestCase.flush_mongo_except_templates()
......@@ -116,9 +110,9 @@ class ModuleStoreTestCase(TestCase):
super(ModuleStoreTestCase, self)._pre_setup()
def _post_teardown(self):
'''
Flush everything we created except the templates
'''
"""
Flush everything we created except the templates.
"""
# Flush anything that is not a template
ModuleStoreTestCase.flush_mongo_except_templates()
......
......@@ -60,8 +60,8 @@ class XModuleCourseFactory(Factory):
if data is not None:
store.update_item(new_course.location, data)
#update_item updates the the course as it exists in the modulestore, but doesn't
#update the instance we are working with, so have to refetch the course after updating it.
# update_item updates the the course as it exists in the modulestore, but doesn't
# update the instance we are working with, so have to refetch the course after updating it.
new_course = store.get_instance(new_course.id, new_course.location)
return new_course
......@@ -152,8 +152,8 @@ class XModuleItemFactory(Factory):
if new_item.location.category not in DETACHED_CATEGORIES:
store.update_children(parent_location, parent.children + [new_item.location.url()])
#update_children updates the the item as it exists in the modulestore, but doesn't
#update the instance we are working with, so have to refetch the item after updating it.
# update_children updates the the item as it exists in the modulestore, but doesn't
# update the instance we are working with, so have to refetch the item after updating it.
new_item = store.get_item(new_item.location)
return new_item
......
......@@ -526,7 +526,6 @@ def _adjust_start_date_for_beta_testers(user, descriptor):
start_as_datetime = descriptor.lms.start
delta = timedelta(descriptor.lms.days_early_for_beta)
effective = start_as_datetime - delta
# ...and back to time_struct
return effective
......
......@@ -48,7 +48,6 @@ class LoginEnrollmentTestCase(TestCase):
Provides support for user creation,
activation, login, and course enrollment.
"""
def setup_user(self):
"""
Create a user account, activate, and log in.
......@@ -67,8 +66,8 @@ class LoginEnrollmentTestCase(TestCase):
"""
Login, check that the corresponding view's response has a 200 status code.
"""
resp = resp = self.client.post(reverse('login'),
{'email': email, 'password': password})
resp = self.client.post(reverse('login'),
{'email': email, 'password': password})
self.assertEqual(resp.status_code, 200)
data = json.loads(resp.content)
self.assertTrue(data['success'])
......@@ -78,15 +77,14 @@ class LoginEnrollmentTestCase(TestCase):
Logout; check that the HTTP response code indicates redirection
as expected.
"""
resp = self.client.get(reverse('logout'), {})
# should redirect
self.assertEqual(resp.status_code, 302)
check_for_get_code(self, 302, reverse('logout'))
def create_account(self, username, email, password):
"""
Create the account and check that it worked.
"""
resp = self.client.post(reverse('create_account'), {
resp = check_for_post_code(self, 200, reverse('create_account'), {
'username': username,
'email': email,
'password': password,
......@@ -94,10 +92,8 @@ class LoginEnrollmentTestCase(TestCase):
'terms_of_service': 'true',
'honor_code': 'true',
})
self.assertEqual(resp.status_code, 200)
data = json.loads(resp.content)
self.assertEqual(data['success'], True)
# Check both that the user is created, and inactive
self.assertFalse(User.objects.get(email=email).is_active)
......@@ -107,12 +103,8 @@ class LoginEnrollmentTestCase(TestCase):
No error checking.
"""
activation_key = Registration.objects.get(user__email=email).activation_key
# and now we try to activate
url = reverse('activate', kwargs={'key': activation_key})
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
check_for_get_code(self, 200, reverse('activate', kwargs={'key': activation_key}))
# Now make sure that the user is now actually activated
self.assertTrue(User.objects.get(email=email).is_active)
......@@ -128,8 +120,6 @@ class LoginEnrollmentTestCase(TestCase):
'enrollment_action': 'enroll',
'course_id': course.id,
})
print ('Enrollment in %s result status code: %s'
% (course.location.url(), str(resp.status_code)))
result = resp.status_code == 200
if verify:
self.assertTrue(result)
......@@ -140,8 +130,5 @@ class LoginEnrollmentTestCase(TestCase):
Unenroll the currently logged-in user, and check that it worked.
`course` is an instance of CourseDescriptor.
"""
resp = self.client.post(reverse('change_enrollment'), {
'enrollment_action': 'unenroll',
'course_id': course.id,
})
self.assertEqual(resp.status_code, 200)
check_for_post_code(self, 200, reverse('change_enrollment'), {'enrollment_action': 'unenroll',
'course_id': course.id})
......@@ -16,7 +16,7 @@ def mongo_store_config(data_dir):
'default_class': 'xmodule.raw_module.RawDescriptor',
'host': 'localhost',
'db': 'test_xmodule',
'collection': 'modulestore_%s' % uuid4().hex,
'collection': 'modulestore',
'fs_root': data_dir,
'render_template': 'mitxmako.shortcuts.render_to_string'
}
......@@ -30,28 +30,24 @@ def draft_mongo_store_config(data_dir):
"""
Defines default module store using DraftMongoModuleStore.
"""
modulestore_options = {
'default_class': 'xmodule.raw_module.RawDescriptor',
'host': 'localhost',
'db': 'xmodule',
'collection': 'modulestore_%s' % uuid4().hex,
'fs_root': data_dir,
'render_template': 'mitxmako.shortcuts.render_to_string'
}
return {
'default': {
'ENGINE': 'xmodule.modulestore.mongo.DraftMongoModuleStore',
'OPTIONS': {
'default_class': 'xmodule.raw_module.RawDescriptor',
'host': 'localhost',
'db': 'test_xmodule',
'collection': 'modulestore_%s' % uuid4().hex,
'fs_root': data_dir,
'render_template': 'mitxmako.shortcuts.render_to_string',
}
'OPTIONS': modulestore_options
},
'direct': {
'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore',
'OPTIONS': {
'default_class': 'xmodule.raw_module.RawDescriptor',
'host': 'localhost',
'db': 'test_xmodule',
'collection': 'modulestore_%s' % uuid4().hex,
'fs_root': data_dir,
'render_template': 'mitxmako.shortcuts.render_to_string',
}
'OPTIONS': modulestore_options
}
}
......
......@@ -20,8 +20,8 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
def setUp(self):
self.course = CourseFactory.create()
self.full = CourseFactory.create(display_name='Robot_Sub_Course')
self.test_course = CourseFactory.create(display_name='Robot_Sub_Course')
self.course = CourseFactory.create(display_name='Robot_Super_Course')
self.chapter0 = ItemFactory.create(parent_location=self.course.location,
display_name='Overview')
self.chapter9 = ItemFactory.create(parent_location=self.course.location,
......@@ -46,7 +46,7 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
email, password = self.STUDENT_INFO[0]
self.login(email, password)
self.enroll(self.course, True)
self.enroll(self.full, True)
self.enroll(self.test_course, True)
resp = self.client.get(reverse('courseware',
kwargs={'course_id': self.course.id}))
......@@ -64,7 +64,7 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
email, password = self.STUDENT_INFO[0]
self.login(email, password)
self.enroll(self.course, True)
self.enroll(self.full, True)
self.enroll(self.test_course, True)
self.client.get(reverse('courseware_section', kwargs={'course_id': self.course.id,
'chapter': 'Overview',
......@@ -84,7 +84,7 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
email, password = self.STUDENT_INFO[0]
self.login(email, password)
self.enroll(self.course, True)
self.enroll(self.full, True)
self.enroll(self.test_course, True)
# Now we directly navigate to a section in a chapter other than 'Overview'.
check_for_get_code(self, 200, reverse('courseware_section',
......
......@@ -4,7 +4,6 @@ import pytz
from mock import patch
from django.contrib.auth.models import User, Group
from django.conf import settings
from django.core.urlresolvers import reverse
from django.test.utils import override_settings
......@@ -20,7 +19,6 @@ from helpers import LoginEnrollmentTestCase, check_for_get_code
from modulestore_config import TEST_DATA_MONGO_MODULESTORE
#@patch.dict(access_settings.MITX_FEATURES, {'DISABLE_START_DATES': True})
@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE)
class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
"""
......@@ -50,17 +48,14 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
`course` is an instance of CourseDescriptor.
"""
print '=== Checking non-staff access for {0}'.format(course.id)
urls = [reverse('about_course', kwargs={'course_id': course.id}), reverse('courses')]
for url in urls:
print 'checking for 200 on {0}'.format(url)
check_for_get_code(self, 200, url)
def _check_non_staff_dark(self, course):
"""
Check that non-staff don't have access to dark urls.
"""
print '=== Checking non-staff access for {0}'.format(course.id)
names = ['courseware', 'instructor_dashboard', 'progress']
urls = self._reverse_urls(names, course)
......@@ -70,15 +65,12 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
for index, book in enumerate(course.textbooks)
])
for url in urls:
print 'checking for 404 on {0}'.format(url)
check_for_get_code(self, 404, url)
def _check_staff(self, course):
"""
Check that access is right for staff in course.
"""
print '=== Checking staff access for {0}'.format(course.id)
names = ['about_course', 'instructor_dashboard', 'progress']
urls = self._reverse_urls(names, course)
urls.extend([
......@@ -87,7 +79,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
for index, book in enumerate(course.textbooks)
])
for url in urls:
print 'checking for 200 on {0}'.format(url)
check_for_get_code(self, 200, url)
# The student progress tab is not accessible to a student
......@@ -99,7 +90,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
url = reverse('student_progress',
kwargs={'course_id': course.id,
'student_id': User.objects.get(email=self.ACCOUNT_INFO[0][0]).id})
print 'checking for 404 on view-as-student: {0}'.format(url)
check_for_get_code(self, 404, url)
# The courseware url should redirect, not 200
......@@ -108,11 +98,12 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
def setUp(self):
self.full = CourseFactory.create(number='666', display_name='Robot_Sub_Course')
self.course = CourseFactory.create()
self.course = CourseFactory.create(number='999', display_name='Robot_Super_Course')
self.overview_chapter = ItemFactory.create(display_name='Overview')
self.courseware_chapter = ItemFactory.create(display_name='courseware')
self.sub_courseware_chapter = ItemFactory.create(parent_location=self.full.location,
self.test_course = CourseFactory.create(number='666', display_name='Robot_Sub_Course')
self.sub_courseware_chapter = ItemFactory.create(parent_location=self.test_course.location,
display_name='courseware')
self.sub_overview_chapter = ItemFactory.create(parent_location=self.sub_courseware_chapter.location,
display_name='Overview')
......@@ -130,7 +121,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Verify unenrolled student is redirected to the 'about' section of the chapter
instead of the 'Welcome' section after clicking on the courseware tab.
"""
email, password = self.ACCOUNT_INFO[0]
self.login(email, password)
response = self.client.get(reverse('courseware',
......@@ -144,7 +134,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Verify enrolled student is redirected to the 'Welcome' section of
the chapter after clicking on the courseware tab.
"""
email, password = self.ACCOUNT_INFO[0]
self.login(email, password)
self.enroll(self.course)
......@@ -163,19 +152,17 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Verify non-staff cannot load the instructor
dashboard, the grade views, and student profile pages.
"""
email, password = self.ACCOUNT_INFO[0]
self.login(email, password)
self.enroll(self.course)
self.enroll(self.full)
self.enroll(self.test_course)
urls = [reverse('instructor_dashboard', kwargs={'course_id': self.course.id}),
reverse('instructor_dashboard', kwargs={'course_id': self.full.id})]
reverse('instructor_dashboard', kwargs={'course_id': self.test_course.id})]
# Shouldn't be able to get to the instructor pages
for url in urls:
print 'checking for 404 on {0}'.format(url)
check_for_get_code(self, 404, url)
def test_instructor_course_access(self):
......@@ -183,7 +170,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Verify instructor can load the instructor dashboard, the grade views,
and student profile pages for their course.
"""
email, password = self.ACCOUNT_INFO[1]
# Make the instructor staff in self.course
......@@ -193,13 +179,11 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
self.login(email, password)
# Now should be able to get to self.course, but not self.full
# Now should be able to get to self.course, but not self.test_course
url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id})
print 'checking for 200 on {0}'.format(url)
check_for_get_code(self, 200, url)
url = reverse('instructor_dashboard', kwargs={'course_id': self.full.id})
print 'checking for 404 on {0}'.format(url)
url = reverse('instructor_dashboard', kwargs={'course_id': self.test_course.id})
check_for_get_code(self, 404, url)
def test_instructor_as_staff_access(self):
......@@ -207,7 +191,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Verify the instructor can load staff pages if he is given
staff permissions.
"""
email, password = self.ACCOUNT_INFO[1]
self.login(email, password)
......@@ -218,18 +201,11 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
# and now should be able to load both
urls = [reverse('instructor_dashboard', kwargs={'course_id': self.course.id}),
reverse('instructor_dashboard', kwargs={'course_id': self.full.id})]
reverse('instructor_dashboard', kwargs={'course_id': self.test_course.id})]
for url in urls:
print 'checking for 200 on {0}'.format(url)
check_for_get_code(self, 200, url)
def test_dark_launch(self):
"""
Make sure that before course start, students can't access course
pages, but instructors can.
"""
@patch.dict(access_settings.MITX_FEATURES, {'DISABLE_START_DATES': False})
def test_dark_launch_enrolled_student(self):
"""
......@@ -243,24 +219,23 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
now = datetime.datetime.now(pytz.UTC)
tomorrow = now + datetime.timedelta(days=1)
course_data = {'start': tomorrow}
full_data = {'start': tomorrow}
test_course_data = {'start': tomorrow}
self.course = self.update_course(self.course, course_data)
self.full = self.update_course(self.full, full_data)
self.test_course = self.update_course(self.test_course, test_course_data)
self.assertFalse(self.course.has_started())
self.assertFalse(self.full.has_started())
self.assertFalse(self.test_course.has_started())
# First, try with an enrolled student
print '=== Testing student access....'
self.login(student_email, student_password)
self.enroll(self.course, True)
self.enroll(self.full, True)
self.enroll(self.test_course, True)
# shouldn't be able to get to anything except the light pages
self._check_non_staff_light(self.course)
self._check_non_staff_dark(self.course)
self._check_non_staff_light(self.full)
self._check_non_staff_dark(self.full)
self._check_non_staff_light(self.test_course)
self._check_non_staff_dark(self.test_course)
@patch.dict(access_settings.MITX_FEATURES, {'DISABLE_START_DATES': False})
def test_dark_launch_instructor(self):
......@@ -268,17 +243,15 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Make sure that before course start instructors can access the
page for their course.
"""
instructor_email, instructor_password = self.ACCOUNT_INFO[1]
now = datetime.datetime.now(pytz.UTC)
tomorrow = now + datetime.timedelta(days=1)
course_data = {'start': tomorrow}
full_data = {'start': tomorrow}
test_course_data = {'start': tomorrow}
self.course = self.update_course(self.course, course_data)
self.full = self.update_course(self.full, full_data)
self.test_course = self.update_course(self.test_course, test_course_data)
print '=== Testing course instructor access....'
# Make the instructor staff in self.course
group_name = _course_staff_group_name(self.course.location)
group = Group.objects.create(name=group_name)
......@@ -287,11 +260,11 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
self.login(instructor_email, instructor_password)
# Enroll in the classes---can't see courseware otherwise.
self.enroll(self.course, True)
self.enroll(self.full, True)
self.enroll(self.test_course, True)
# should now be able to get to everything for self.course
self._check_non_staff_light(self.full)
self._check_non_staff_dark(self.full)
self._check_non_staff_light(self.test_course)
self._check_non_staff_dark(self.test_course)
self._check_staff(self.course)
@patch.dict(access_settings.MITX_FEATURES, {'DISABLE_START_DATES': False})
......@@ -300,21 +273,19 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Make sure that before course start staff can access
course pages.
"""
instructor_email, instructor_password = self.ACCOUNT_INFO[1]
now = datetime.datetime.now(pytz.UTC)
tomorrow = now + datetime.timedelta(days=1)
course_data = {'start': tomorrow}
full_data = {'start': tomorrow}
test_course_data = {'start': tomorrow}
self.course = self.update_course(self.course, course_data)
self.full = self.update_course(self.full, full_data)
self.test_course = self.update_course(self.test_course, test_course_data)
self.login(instructor_email, instructor_password)
self.enroll(self.course, True)
self.enroll(self.full, True)
self.enroll(self.test_course, True)
print '=== Testing staff access....'
# now also make the instructor staff
instructor = User.objects.get(email=instructor_email)
instructor.is_staff = True
......@@ -322,14 +293,13 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
# and now should be able to load both
self._check_staff(self.course)
self._check_staff(self.full)
self._check_staff(self.test_course)
@patch.dict(access_settings.MITX_FEATURES, {'DISABLE_START_DATES': False})
def test_enrollment_period(self):
"""
Check that enrollment periods work.
"""
student_email, student_password = self.ACCOUNT_INFO[0]
instructor_email, instructor_password = self.ACCOUNT_INFO[1]
......@@ -340,34 +310,27 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
yesterday = now - datetime.timedelta(days=1)
course_data = {'enrollment_start': tomorrow, 'enrollment_end': nextday}
full_data = {'enrollment_start': yesterday, 'enrollment_end': tomorrow}
test_course_data = {'enrollment_start': yesterday, 'enrollment_end': tomorrow}
print "changing"
# self.course's enrollment period hasn't started
self.course = self.update_course(self.course, course_data)
# full course's has
self.full = self.update_course(self.full, full_data)
# test_course course's has
self.test_course = self.update_course(self.test_course, test_course_data)
print "login"
# First, try with an enrolled student
print '=== Testing student access....'
self.login(student_email, student_password)
self.assertFalse(self.enroll(self.course))
self.assertTrue(self.enroll(self.full))
self.assertTrue(self.enroll(self.test_course))
print '=== Testing course instructor access....'
# Make the instructor staff in the self.course
group_name = _course_staff_group_name(self.course.location)
group = Group.objects.create(name=group_name)
group.user_set.add(User.objects.get(email=instructor_email))
print "logout/login"
self.logout()
self.login(instructor_email, instructor_password)
print "Instructor should be able to enroll in self.course"
self.assertTrue(self.enroll(self.course))
print '=== Testing staff access....'
# now make the instructor global staff, but not in the instructor group
group.user_set.remove(User.objects.get(email=instructor_email))
instructor = User.objects.get(email=instructor_email)
......@@ -383,7 +346,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
"""
Check that beta-test access works.
"""
student_email, student_password = self.ACCOUNT_INFO[0]
instructor_email, instructor_password = self.ACCOUNT_INFO[1]
......
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