Commit 32a0a2d2 by Jean Manuel Nater

In the middle of addressing pull request comments. This is a safety commit in…

In the middle of addressing pull request comments. This is a safety commit in case I have to revert some changes I'm about to make.
parent 1b94050e
...@@ -14,10 +14,16 @@ class ModuleStoreTestCase(TestCase): ...@@ -14,10 +14,16 @@ class ModuleStoreTestCase(TestCase):
collection with templates before running the TestCase collection with templates before running the TestCase
and drops it they are finished. """ and drops it they are finished. """
def update_course(self, course, data): @staticmethod
def update_course(course, data):
""" """
Updates the version of course in the mongo modulestore Updates the version of course in the mongo modulestore
with the metadata in data and returns the updated version. 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 = xmodule.modulestore.django.modulestore()
......
...@@ -60,8 +60,8 @@ class XModuleCourseFactory(Factory): ...@@ -60,8 +60,8 @@ class XModuleCourseFactory(Factory):
if data is not None: if data is not None:
store.update_item(new_course.location, data) store.update_item(new_course.location, data)
'''update_item updates the the course as it exists in the modulestore, but doesn't #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 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) new_course = store.get_instance(new_course.id, new_course.location)
return new_course return new_course
...@@ -152,8 +152,8 @@ class XModuleItemFactory(Factory): ...@@ -152,8 +152,8 @@ class XModuleItemFactory(Factory):
if new_item.location.category not in DETACHED_CATEGORIES: if new_item.location.category not in DETACHED_CATEGORIES:
store.update_children(parent_location, parent.children + [new_item.location.url()]) 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_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 the instance we are working with, so have to refetch the item after updating it.
new_item = store.get_item(new_item.location) new_item = store.get_item(new_item.location)
return new_item return new_item
......
def check_for_get_code(code, url):
"""
Check that we got the expected code when accessing url via GET.
Returns the response.
"""
resp = self.client.get(url)
self.assertEqual(resp.status_code, code,
"got code %d for url '%s'. Expected code %d"
% (resp.status_code, url, code))
return resp
def check_for_post_code(code, url, data={}):
"""
Check that we got the expected code when accessing url via POST.
Returns the response.
"""
resp = self.client.post(url, data)
self.assertEqual(resp.status_code, code,
"got code %d for url '%s'. Expected code %d"
% (resp.status_code, url, code))
return resp
...@@ -12,7 +12,12 @@ def check_for_get_code(self, code, url): ...@@ -12,7 +12,12 @@ def check_for_get_code(self, code, url):
""" """
Check that we got the expected code when accessing url via GET. Check that we got the expected code when accessing url via GET.
Returns the HTTP response. Returns the HTTP response.
'self' is a class that subclasses TestCase.
`self` is a class that subclasses TestCase.
`code` is a status code for HTTP responses.
`url` is a url pattern for which we have to test the response.
""" """
resp = self.client.get(url) resp = self.client.get(url)
self.assertEqual(resp.status_code, code, self.assertEqual(resp.status_code, code,
...@@ -25,7 +30,11 @@ def check_for_post_code(self, code, url, data={}): ...@@ -25,7 +30,11 @@ def check_for_post_code(self, code, url, data={}):
""" """
Check that we got the expected code when accessing url via POST. Check that we got the expected code when accessing url via POST.
Returns the HTTP response. Returns the HTTP response.
'self' is a class that subclasses TestCase. `self` is a class that subclasses TestCase.
`code` is a status code for HTTP responses.
`url` is a url pattern for which we want to test the response.
""" """
resp = self.client.post(url, data) resp = self.client.post(url, data)
self.assertEqual(resp.status_code, code, self.assertEqual(resp.status_code, code,
...@@ -62,8 +71,8 @@ class LoginEnrollmentTestCase(TestCase): ...@@ -62,8 +71,8 @@ class LoginEnrollmentTestCase(TestCase):
def logout(self): def logout(self):
""" """
Logout, check that it worked. Logout; check that the HTTP response code indicates redirection
Returns an HTTP response which e as expected.
""" """
resp = self.client.get(reverse('logout'), {}) resp = self.client.get(reverse('logout'), {})
# should redirect # should redirect
...@@ -106,8 +115,8 @@ class LoginEnrollmentTestCase(TestCase): ...@@ -106,8 +115,8 @@ class LoginEnrollmentTestCase(TestCase):
def enroll(self, course, verify=False): def enroll(self, course, verify=False):
""" """
Try to enroll and return boolean indicating result. Try to enroll and return boolean indicating result.
'course' is an instance of CourseDescriptor. `course` is an instance of CourseDescriptor.
'verify' is an optional parameter specifying whether we `verify` is an optional parameter specifying whether we
want to verify that the student was successfully enrolled want to verify that the student was successfully enrolled
in the course. in the course.
""" """
...@@ -122,20 +131,12 @@ class LoginEnrollmentTestCase(TestCase): ...@@ -122,20 +131,12 @@ class LoginEnrollmentTestCase(TestCase):
self.assertTrue(result) self.assertTrue(result)
return result return result
# def enroll(self, course):
# """
# Enroll the currently logged-in user, and check that it worked.
# """
# result = self.try_enroll(course)
# self.assertTrue(result)
def unenroll(self, course): def unenroll(self, course):
""" """
Unenroll the currently logged-in user, and check that it worked. Unenroll the currently logged-in user, and check that it worked.
'course' is an instance of CourseDescriptor. `course` is an instance of CourseDescriptor.
""" """
resp = self.client.post('/change_enrollment', { resp = self.client.post(reverse('change_enrollment'), {
'enrollment_action': 'unenroll', 'enrollment_action': 'unenroll',
'course_id': course.id, 'course_id': course.id,
}) })
......
...@@ -4,11 +4,11 @@ from django.conf import settings ...@@ -4,11 +4,11 @@ from django.conf import settings
def mongo_store_config(data_dir): def mongo_store_config(data_dir):
''' """
Defines default module store using MongoModuleStore Defines default module store using MongoModuleStore.
Use of this config requires mongo to be running Use of this config requires mongo to be running.
''' """
store = { store = {
'default': { 'default': {
'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore',
...@@ -27,7 +27,9 @@ def mongo_store_config(data_dir): ...@@ -27,7 +27,9 @@ def mongo_store_config(data_dir):
def draft_mongo_store_config(data_dir): def draft_mongo_store_config(data_dir):
'''Defines default module store using DraftMongoModuleStore''' """
Defines default module store using DraftMongoModuleStore.
"""
return { return {
'default': { 'default': {
'ENGINE': 'xmodule.modulestore.mongo.DraftMongoModuleStore', 'ENGINE': 'xmodule.modulestore.mongo.DraftMongoModuleStore',
...@@ -55,7 +57,9 @@ def draft_mongo_store_config(data_dir): ...@@ -55,7 +57,9 @@ def draft_mongo_store_config(data_dir):
def xml_store_config(data_dir): def xml_store_config(data_dir):
'''Defines default module store using XMLModuleStore''' """
Defines default module store using XMLModuleStore.
"""
return { return {
'default': { 'default': {
'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore',
......
...@@ -36,15 +36,18 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -36,15 +36,18 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
# Create student accounts and activate them. # Create student accounts and activate them.
for i in range(len(self.STUDENT_INFO)): for i in range(len(self.STUDENT_INFO)):
self.create_account('u{0}'.format(i), self.STUDENT_INFO[i][0], self.STUDENT_INFO[i][1]) email, password = self.STUDENT_INFO[i]
self.activate_user(self.STUDENT_INFO[i][0]) username = 'u{0}'.format(i)
self.create_account(username, email, password)
self.activate_user(email)
def test_redirects_first_time(self): def test_redirects_first_time(self):
""" """
Verify that the first time we click on the courseware tab we are Verify that the first time we click on the courseware tab we are
redirected to the 'Welcome' section. redirected to the 'Welcome' section.
""" """
self.login(self.STUDENT_INFO[0][0], self.STUDENT_INFO[0][1]) email, password = self.STUDENT_INFO[0]
self.login(email, password)
self.enroll(self.course, True) self.enroll(self.course, True)
self.enroll(self.full, True) self.enroll(self.full, True)
...@@ -61,7 +64,8 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -61,7 +64,8 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
Verify the accordion remembers we've already visited the Welcome section Verify the accordion remembers we've already visited the Welcome section
and redirects correpondingly. and redirects correpondingly.
""" """
self.login(self.STUDENT_INFO[0][0], self.STUDENT_INFO[0][1]) email, password = self.STUDENT_INFO[0]
self.login(email, password)
self.enroll(self.course, True) self.enroll(self.course, True)
self.enroll(self.full, True) self.enroll(self.full, True)
...@@ -80,8 +84,8 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -80,8 +84,8 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
""" """
Verify the accordion remembers which chapter you were last viewing. Verify the accordion remembers which chapter you were last viewing.
""" """
email, password = self.STUDENT_INFO[0]
self.login(self.STUDENT_INFO[0][0], self.STUDENT_INFO[0][1]) self.login(email, password)
self.enroll(self.course, True) self.enroll(self.course, True)
self.enroll(self.full, True) self.enroll(self.full, True)
......
...@@ -32,28 +32,40 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -32,28 +32,40 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
@classmethod @classmethod
def _instructor_urls(self, course): def _instructor_urls(self, course):
""" """
List of urls that only instructors/staff should be able to see. `course` is an instance of CourseDescriptor whose section URLs are to be returned.
Returns a list of URLs corresponding to sections in the passed in course.
""" """
urls = [reverse(name, kwargs={'course_id': course.id}) for name in ( urls = [reverse(name, kwargs={'course_id': course.id}) for name in (
'instructor_dashboard', 'instructor_dashboard',
'gradebook', 'gradebook',
'grade_summary',)] 'grade_summary',)]
email, _ = self.ACCOUNT_INFO[0]
student_id = User.objects.get(email=email).id
urls.append(reverse('student_progress', urls.append(reverse('student_progress',
kwargs={'course_id': course.id, kwargs={'course_id': course.id,
'student_id': User.objects.get(email=self.ACCOUNT_INFO[0][0]).id})) 'student_id': student_id}))
return urls return urls
@staticmethod @staticmethod
def _reverse_urls(names, course): def _reverse_urls(names, course):
""" """
Reverse a list of course urls. Reverse a list of course urls.
`names` is a list of URL names that correspond to sections in a course.
`course` is the instance of CourseDescriptor whose section URLs are to be returned.
Returns a list URLs corresponding to section in the passed in course.
""" """
return [reverse(name, kwargs={'course_id': course.id}) return [reverse(name, kwargs={'course_id': course.id})
for name in names] for name in names]
def setUp(self): def setUp(self):
xmodule.modulestore.django._MODULESTORES = {}
self.full = CourseFactory.create(number='666', display_name='Robot_Sub_Course') self.full = CourseFactory.create(number='666', display_name='Robot_Sub_Course')
self.course = CourseFactory.create() self.course = CourseFactory.create()
...@@ -68,8 +80,9 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -68,8 +80,9 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
# Create two accounts and activate them. # Create two accounts and activate them.
for i in range(len(self.ACCOUNT_INFO)): for i in range(len(self.ACCOUNT_INFO)):
self.create_account('u{0}'.format(i), self.ACCOUNT_INFO[i][0], self.ACCOUNT_INFO[i][1]) username, email, password = 'u{0}'.format(i), self.ACCOUNT_INFO[i][0], self.ACCOUNT_INFO[i][1]
self.activate_user(self.ACCOUNT_INFO[i][0]) self.create_account(username, email, password)
self.activate_user(email)
def test_redirection_unenrolled(self): def test_redirection_unenrolled(self):
""" """
...@@ -77,7 +90,8 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -77,7 +90,8 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
instead of the 'Welcome' section after clicking on the courseware tab. instead of the 'Welcome' section after clicking on the courseware tab.
""" """
self.login(self.ACCOUNT_INFO[0][0], self.ACCOUNT_INFO[0][1]) email, password = self.ACCOUNT_INFO[0]
self.login(email, password)
response = self.client.get(reverse('courseware', response = self.client.get(reverse('courseware',
kwargs={'course_id': self.course.id})) kwargs={'course_id': self.course.id}))
self.assertRedirects(response, self.assertRedirects(response,
...@@ -90,7 +104,8 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -90,7 +104,8 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
the chapter after clicking on the courseware tab. the chapter after clicking on the courseware tab.
""" """
self.login(self.ACCOUNT_INFO[0][0], self.ACCOUNT_INFO[0][1]) email, password = self.ACCOUNT_INFO[0]
self.login(email, password)
self.enroll(self.course) self.enroll(self.course)
response = self.client.get(reverse('courseware', response = self.client.get(reverse('courseware',
...@@ -108,7 +123,8 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -108,7 +123,8 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
dashboard, the grade views, and student profile pages. dashboard, the grade views, and student profile pages.
""" """
self.login(self.ACCOUNT_INFO[0][0], self.ACCOUNT_INFO[0][1]) email, password = self.ACCOUNT_INFO[0]
self.login(email, password)
self.enroll(self.course) self.enroll(self.course)
self.enroll(self.full) self.enroll(self.full)
...@@ -127,12 +143,14 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -127,12 +143,14 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
and student profile pages for their course. and student profile pages for their course.
""" """
email, password = self.ACCOUNT_INFO[1]
# Make the instructor staff in self.course # Make the instructor staff in self.course
group_name = _course_staff_group_name(self.course.location) group_name = _course_staff_group_name(self.course.location)
group = Group.objects.create(name=group_name) group = Group.objects.create(name=group_name)
group.user_set.add(User.objects.get(email=self.ACCOUNT_INFO[1][0])) group.user_set.add(User.objects.get(email=email))
self.login(self.ACCOUNT_INFO[1][0], self.ACCOUNT_INFO[1][1]) 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.full
url = random.choice(self._instructor_urls(self.course)) url = random.choice(self._instructor_urls(self.course))
...@@ -149,10 +167,11 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -149,10 +167,11 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
staff permissions. staff permissions.
""" """
self.login(self.ACCOUNT_INFO[1][0], self.ACCOUNT_INFO[1][1]) email, password = self.ACCOUNT_INFO[1]
self.login(email, password)
# now make the instructor also staff # now make the instructor also staff
instructor = User.objects.get(email=self.ACCOUNT_INFO[1][0]) instructor = User.objects.get(email=email)
instructor.is_staff = True instructor.is_staff = True
instructor.save() instructor.save()
...@@ -202,6 +221,9 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -202,6 +221,9 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Actually do the test, relying on settings to be right. Actually do the test, relying on settings to be right.
""" """
student_email, student_password = self.ACCOUNT_INFO[0]
instructor_email, instructor_password = self.ACCOUNT_INFO[1]
# Make courses start in the future # Make courses start in the future
now = datetime.datetime.now(pytz.UTC) now = datetime.datetime.now(pytz.UTC)
tomorrow = now + datetime.timedelta(days=1) tomorrow = now + datetime.timedelta(days=1)
...@@ -300,7 +322,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -300,7 +322,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
# First, try with an enrolled student # First, try with an enrolled student
print '=== Testing student access....' print '=== Testing student access....'
self.login(self.ACCOUNT_INFO[0][0], self.ACCOUNT_INFO[0][1]) self.login(student_email, student_password)
self.enroll(self.course, True) self.enroll(self.course, True)
self.enroll(self.full, True) self.enroll(self.full, True)
...@@ -314,10 +336,10 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -314,10 +336,10 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
# Make the instructor staff in self.course # Make the instructor staff in self.course
group_name = _course_staff_group_name(self.course.location) group_name = _course_staff_group_name(self.course.location)
group = Group.objects.create(name=group_name) group = Group.objects.create(name=group_name)
group.user_set.add(User.objects.get(email=self.ACCOUNT_INFO[1][0])) group.user_set.add(User.objects.get(email=instructor_email))
self.logout() self.logout()
self.login(self.ACCOUNT_INFO[1][0], self.ACCOUNT_INFO[1][1]) self.login(instructor_email, instructor_password)
# Enroll in the classes---can't see courseware otherwise. # Enroll in the classes---can't see courseware otherwise.
self.enroll(self.course, True) self.enroll(self.course, True)
self.enroll(self.full, True) self.enroll(self.full, True)
...@@ -329,7 +351,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -329,7 +351,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
print '=== Testing staff access....' print '=== Testing staff access....'
# now also make the instructor staff # now also make the instructor staff
instructor = User.objects.get(email=self.ACCOUNT_INFO[1][0]) instructor = User.objects.get(email=instructor_email)
instructor.is_staff = True instructor.is_staff = True
instructor.save() instructor.save()
...@@ -342,6 +364,9 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -342,6 +364,9 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Actually do the test, relying on settings to be right. Actually do the test, relying on settings to be right.
""" """
student_email, student_password = self.ACCOUNT_INFO[0]
instructor_email, instructor_password = self.ACCOUNT_INFO[1]
# Make courses start in the future # Make courses start in the future
now = datetime.datetime.now(pytz.UTC) now = datetime.datetime.now(pytz.UTC)
tomorrow = now + datetime.timedelta(days=1) tomorrow = now + datetime.timedelta(days=1)
...@@ -360,7 +385,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -360,7 +385,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
print "login" print "login"
# First, try with an enrolled student # First, try with an enrolled student
print '=== Testing student access....' print '=== Testing student access....'
self.login(self.ACCOUNT_INFO[0][0], self.ACCOUNT_INFO[0][1]) self.login(student_email, student_password)
self.assertFalse(self.enroll(self.course)) self.assertFalse(self.enroll(self.course))
self.assertTrue(self.enroll(self.full)) self.assertTrue(self.enroll(self.full))
...@@ -368,18 +393,18 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -368,18 +393,18 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
# Make the instructor staff in the self.course # Make the instructor staff in the self.course
group_name = _course_staff_group_name(self.course.location) group_name = _course_staff_group_name(self.course.location)
group = Group.objects.create(name=group_name) group = Group.objects.create(name=group_name)
group.user_set.add(User.objects.get(email=self.ACCOUNT_INFO[1][0])) group.user_set.add(User.objects.get(email=instructor_email))
print "logout/login" print "logout/login"
self.logout() self.logout()
self.login(self.ACCOUNT_INFO[1][0], self.ACCOUNT_INFO[1][1]) self.login(instructor_email, instructor_password)
print "Instructor should be able to enroll in self.course" print "Instructor should be able to enroll in self.course"
self.assertTrue(self.enroll(self.course)) self.assertTrue(self.enroll(self.course))
print '=== Testing staff access....' print '=== Testing staff access....'
# now make the instructor global staff, but not in the instructor group # now make the instructor global staff, but not in the instructor group
group.user_set.remove(User.objects.get(email=self.ACCOUNT_INFO[1][0])) group.user_set.remove(User.objects.get(email=instructor_email))
instructor = User.objects.get(email=self.ACCOUNT_INFO[1][0]) instructor = User.objects.get(email=instructor_email)
instructor.is_staff = True instructor.is_staff = True
instructor.save() instructor.save()
...@@ -392,6 +417,9 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -392,6 +417,9 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Actually test beta periods, relying on settings to be right. Actually test beta periods, relying on settings to be right.
""" """
student_email, student_password = self.ACCOUNT_INFO[0]
instructor_email, instructor_password = self.ACCOUNT_INFO[1]
# trust, but verify :) # trust, but verify :)
self.assertFalse(settings.MITX_FEATURES['DISABLE_START_DATES']) self.assertFalse(settings.MITX_FEATURES['DISABLE_START_DATES'])
...@@ -408,7 +436,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -408,7 +436,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
self.course.lms.days_early_for_beta = 2 self.course.lms.days_early_for_beta = 2
# student user shouldn't see it # student user shouldn't see it
student_user = User.objects.get(email=self.ACCOUNT_INFO[0][0]) student_user = User.objects.get(email=student_email)
self.assertFalse(has_access(student_user, self.course, 'load')) self.assertFalse(has_access(student_user, self.course, 'load'))
# now add the student to the beta test group # now add the student to the beta test group
......
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