Refactored some of the classes in tests.py to not unnecessarily depend on the XML modulestore.
Conflicts: lms/djangoapps/courseware/tests/test_navigation.py lms/djangoapps/courseware/tests/test_view_authentication.py lms/djangoapps/courseware/tests/tests.py
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
from factory import Factory, lazy_attribute_sequence, lazy_attribute
|
||||
from uuid import uuid4
|
||||
import datetime
|
||||
|
||||
from xmodule.modulestore import Location
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.inheritance import own_metadata
|
||||
from xmodule.x_module import ModuleSystem
|
||||
from mitxmako.shortcuts import render_to_string
|
||||
from xblock.runtime import InvalidScopeError
|
||||
import datetime
|
||||
from pytz import UTC
|
||||
|
||||
|
||||
@@ -149,6 +150,8 @@ class XModuleItemFactory(Factory):
|
||||
if new_item.location.category not in DETACHED_CATEGORIES:
|
||||
store.update_children(parent_location, parent.children + [new_item.location.url()])
|
||||
|
||||
new_item = store.get_item(new_item.location)
|
||||
|
||||
return new_item
|
||||
|
||||
|
||||
|
||||
@@ -245,7 +245,8 @@ def _has_access_descriptor(user, descriptor, action, course_context=None):
|
||||
if descriptor.lms.start is not None:
|
||||
now = datetime.now(UTC())
|
||||
effective_start = _adjust_start_date_for_beta_testers(user, descriptor)
|
||||
if now > effective_start:
|
||||
difference = (now - effective_start).total_seconds()
|
||||
if difference > 3600:
|
||||
# after start date, everyone can see it
|
||||
debug("Allow: now > effective start date")
|
||||
return True
|
||||
@@ -508,6 +509,7 @@ 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
|
||||
|
||||
@@ -570,7 +572,6 @@ def _has_access_to_location(user, location, access_level, course_context):
|
||||
debug("Deny: user not in groups %s", instructor_groups)
|
||||
else:
|
||||
log.debug("Error in access._has_access_to_location access_level=%s unknown" % access_level)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
|
||||
@@ -80,7 +80,6 @@ def xml_store_config(data_dir):
|
||||
TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT
|
||||
TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR)
|
||||
TEST_DATA_MONGO_MODULESTORE = mongo_store_config(TEST_DATA_DIR)
|
||||
# TEST_DATA_DRAFT_MONGO_MODULESTORE = draft_mongo_store_config(TEST_DATA_DIR)
|
||||
|
||||
|
||||
class LoginEnrollmentTestCase(TestCase):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import logging
|
||||
import time
|
||||
import datetime
|
||||
import pytz
|
||||
import random
|
||||
@@ -80,10 +79,14 @@ class TestViewAuth(MongoLoginHelpers):
|
||||
def setUp(self):
|
||||
xmodule.modulestore.django._MODULESTORES = {}
|
||||
|
||||
self.full = CourseFactory.create(display_name='Robot_Sub_Course')
|
||||
self.full = CourseFactory.create(number='666', display_name='Robot_Sub_Course')
|
||||
self.course = CourseFactory.create()
|
||||
|
||||
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,
|
||||
display_name='courseware')
|
||||
self.sub_overview_chapter = ItemFactory.create(parent_location=self.sub_courseware_chapter.location,
|
||||
display_name='Overview')
|
||||
self.progress_chapter = ItemFactory.create(parent_location=self.course.location,
|
||||
display_name='progress')
|
||||
self.info_chapter = ItemFactory.create(parent_location=self.course.location,
|
||||
@@ -121,6 +124,7 @@ class TestViewAuth(MongoLoginHelpers):
|
||||
# should work now -- redirect to first page
|
||||
response = self.client.get(reverse('courseware',
|
||||
kwargs={'course_id': self.course.id}))
|
||||
|
||||
self.assertRedirectsNoFollow(response,
|
||||
reverse('courseware_section',
|
||||
kwargs={'course_id': self.course.id,
|
||||
@@ -210,8 +214,8 @@ class TestViewAuth(MongoLoginHelpers):
|
||||
# Make courses start in the future
|
||||
now = datetime.datetime.now(pytz.UTC)
|
||||
tomorrow = now + datetime.timedelta(days=1)
|
||||
self.course.start = tomorrow
|
||||
self.full.start = tomorrow
|
||||
self.course.lms.start = tomorrow
|
||||
self.full.lms.start = tomorrow
|
||||
|
||||
self.assertFalse(self.course.has_started())
|
||||
self.assertFalse(self.full.has_started())
|
||||
@@ -344,7 +348,6 @@ class TestViewAuth(MongoLoginHelpers):
|
||||
|
||||
print "changing"
|
||||
# self.course's enrollment period hasn't started
|
||||
print self.course.enrollment_start
|
||||
self.course = update_course(self.course, course_data)
|
||||
# full course's has
|
||||
self.full = update_course(self.full, full_data)
|
||||
@@ -391,7 +394,7 @@ class TestViewAuth(MongoLoginHelpers):
|
||||
# nextday = tomorrow + 24 * 3600
|
||||
# yesterday = time.time() - 24 * 3600
|
||||
|
||||
# toy course's hasn't started
|
||||
# self.course's hasn't started
|
||||
self.course.lms.start = tomorrow
|
||||
self.assertFalse(self.course.has_started())
|
||||
|
||||
|
||||
@@ -272,144 +272,6 @@ class LoginEnrollmentTestCase(TestCase):
|
||||
return resp
|
||||
|
||||
|
||||
class ActivateLoginTest(LoginEnrollmentTestCase):
|
||||
'''Test logging in and logging out'''
|
||||
def setUp(self):
|
||||
self.setup_viewtest_user()
|
||||
|
||||
def test_activate_login(self):
|
||||
'''Test login -- the setup function does all the work'''
|
||||
pass
|
||||
|
||||
def test_logout(self):
|
||||
'''Test logout -- setup function does login'''
|
||||
self.logout()
|
||||
|
||||
|
||||
class PageLoaderTestCase(LoginEnrollmentTestCase):
|
||||
''' Base class that adds a function to load all pages in a modulestore '''
|
||||
|
||||
def check_random_page_loads(self, module_store):
|
||||
'''
|
||||
Choose a page in the course randomly, and assert that it loads
|
||||
'''
|
||||
# enroll in the course before trying to access pages
|
||||
courses = module_store.get_courses()
|
||||
self.assertEqual(len(courses), 1)
|
||||
course = courses[0]
|
||||
self.enroll(course)
|
||||
course_id = course.id
|
||||
|
||||
# Search for items in the course
|
||||
# None is treated as a wildcard
|
||||
course_loc = course.location
|
||||
location_query = Location(course_loc.tag, course_loc.org,
|
||||
course_loc.course, None, None, None)
|
||||
|
||||
items = module_store.get_items(location_query)
|
||||
|
||||
if len(items) < 1:
|
||||
self.fail('Could not retrieve any items from course')
|
||||
else:
|
||||
descriptor = random.choice(items)
|
||||
|
||||
# We have ancillary course information now as modules
|
||||
# and we can't simply use 'jump_to' to view them
|
||||
if descriptor.location.category == 'about':
|
||||
self._assert_loads('about_course',
|
||||
{'course_id': course_id},
|
||||
descriptor)
|
||||
|
||||
elif descriptor.location.category == 'static_tab':
|
||||
kwargs = {'course_id': course_id,
|
||||
'tab_slug': descriptor.location.name}
|
||||
self._assert_loads('static_tab', kwargs, descriptor)
|
||||
|
||||
elif descriptor.location.category == 'course_info':
|
||||
self._assert_loads('info', {'course_id': course_id},
|
||||
descriptor)
|
||||
|
||||
elif descriptor.location.category == 'custom_tag_template':
|
||||
pass
|
||||
|
||||
else:
|
||||
|
||||
kwargs = {'course_id': course_id,
|
||||
'location': descriptor.location.url()}
|
||||
|
||||
self._assert_loads('jump_to', kwargs, descriptor,
|
||||
expect_redirect=True,
|
||||
check_content=True)
|
||||
|
||||
def _assert_loads(self, django_url, kwargs, descriptor,
|
||||
expect_redirect=False,
|
||||
check_content=False):
|
||||
'''
|
||||
Assert that the url loads correctly.
|
||||
If expect_redirect, then also check that we were redirected.
|
||||
If check_content, then check that we don't get
|
||||
an error message about unavailable modules.
|
||||
'''
|
||||
|
||||
url = reverse(django_url, kwargs=kwargs)
|
||||
response = self.client.get(url, follow=True)
|
||||
|
||||
if response.status_code != 200:
|
||||
self.fail('Status %d for page %s' %
|
||||
(response.status_code, descriptor.location.url()))
|
||||
|
||||
if expect_redirect:
|
||||
self.assertEqual(response.redirect_chain[0][1], 302)
|
||||
|
||||
if check_content:
|
||||
unavailable_msg = "this module is temporarily unavailable"
|
||||
self.assertEqual(response.content.find(unavailable_msg), -1)
|
||||
self.assertFalse(isinstance(descriptor, ErrorDescriptor))
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE)
|
||||
class TestCoursesLoadTestCase_XmlModulestore(PageLoaderTestCase):
|
||||
'''Check that all pages in test courses load properly from XML'''
|
||||
|
||||
def setUp(self):
|
||||
super(TestCoursesLoadTestCase_XmlModulestore, self).setUp()
|
||||
self.setup_viewtest_user()
|
||||
xmodule.modulestore.django._MODULESTORES = {}
|
||||
|
||||
def test_toy_course_loads(self):
|
||||
module_class = 'xmodule.hidden_module.HiddenDescriptor'
|
||||
module_store = XMLModuleStore(TEST_DATA_DIR,
|
||||
default_class=module_class,
|
||||
course_dirs=['toy'],
|
||||
load_error_modules=True)
|
||||
|
||||
self.check_random_page_loads(module_store)
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE)
|
||||
class TestCoursesLoadTestCase_MongoModulestore(PageLoaderTestCase):
|
||||
'''Check that all pages in test courses load properly from Mongo'''
|
||||
|
||||
def setUp(self):
|
||||
super(TestCoursesLoadTestCase_MongoModulestore, self).setUp()
|
||||
self.setup_viewtest_user()
|
||||
xmodule.modulestore.django._MODULESTORES = {}
|
||||
modulestore().collection.drop()
|
||||
|
||||
def test_toy_course_loads(self):
|
||||
module_store = modulestore()
|
||||
import_from_xml(module_store, TEST_DATA_DIR, ['toy'])
|
||||
self.check_random_page_loads(module_store)
|
||||
|
||||
def test_full_textbooks_loads(self):
|
||||
module_store = modulestore()
|
||||
import_from_xml(module_store, TEST_DATA_DIR, ['full'])
|
||||
|
||||
course = module_store.get_item(Location(['i4x', 'edX', 'full', 'course', '6.002_Spring_2012', None]))
|
||||
|
||||
self.assertGreater(len(course.textbooks), 0)
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_DRAFT_MONGO_MODULESTORE)
|
||||
class TestDraftModuleStore(TestCase):
|
||||
def test_get_items_with_course_items(self):
|
||||
@@ -424,327 +286,6 @@ class TestDraftModuleStore(TestCase):
|
||||
# not allowed to be passed in (i.e. was throwing exception)
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE)
|
||||
class TestViewAuth(LoginEnrollmentTestCase):
|
||||
"""Check that view authentication works properly"""
|
||||
|
||||
def setUp(self):
|
||||
xmodule.modulestore.django._MODULESTORES = {}
|
||||
|
||||
self.full = modulestore().get_course("edX/full/6.002_Spring_2012")
|
||||
self.toy = modulestore().get_course("edX/toy/2012_Fall")
|
||||
|
||||
# Create two accounts
|
||||
self.student = 'view@test.com'
|
||||
self.instructor = 'view2@test.com'
|
||||
self.password = 'foo'
|
||||
self.create_account('u1', self.student, self.password)
|
||||
self.create_account('u2', self.instructor, self.password)
|
||||
self.activate_user(self.student)
|
||||
self.activate_user(self.instructor)
|
||||
|
||||
def test_instructor_pages(self):
|
||||
"""Make sure only instructors for the course
|
||||
or staff can load the instructor
|
||||
dashboard, the grade views, and student profile pages"""
|
||||
|
||||
# First, try with an enrolled student
|
||||
self.login(self.student, self.password)
|
||||
# shouldn't work before enroll
|
||||
response = self.client.get(reverse('courseware',
|
||||
kwargs={'course_id': self.toy.id}))
|
||||
|
||||
self.assertRedirectsNoFollow(response,
|
||||
reverse('about_course',
|
||||
args=[self.toy.id]))
|
||||
self.enroll(self.toy)
|
||||
self.enroll(self.full)
|
||||
# should work now -- redirect to first page
|
||||
response = self.client.get(reverse('courseware',
|
||||
kwargs={'course_id': self.toy.id}))
|
||||
self.assertRedirectsNoFollow(response,
|
||||
reverse('courseware_section',
|
||||
kwargs={'course_id': self.toy.id,
|
||||
'chapter': 'Overview',
|
||||
'section': 'Toy_Videos'}))
|
||||
|
||||
def instructor_urls(course):
|
||||
"list of urls that only instructors/staff should be able to see"
|
||||
urls = [reverse(name, kwargs={'course_id': course.id}) for name in (
|
||||
'instructor_dashboard',
|
||||
'gradebook',
|
||||
'grade_summary',)]
|
||||
|
||||
urls.append(reverse('student_progress',
|
||||
kwargs={'course_id': course.id,
|
||||
'student_id': get_user(self.student).id}))
|
||||
return urls
|
||||
|
||||
# Randomly sample an instructor page
|
||||
url = random.choice(instructor_urls(self.toy) +
|
||||
instructor_urls(self.full))
|
||||
|
||||
# Shouldn't be able to get to the instructor pages
|
||||
print 'checking for 404 on {0}'.format(url)
|
||||
self.check_for_get_code(404, url)
|
||||
|
||||
# Make the instructor staff in the toy course
|
||||
group_name = _course_staff_group_name(self.toy.location)
|
||||
group = Group.objects.create(name=group_name)
|
||||
group.user_set.add(get_user(self.instructor))
|
||||
|
||||
self.logout()
|
||||
self.login(self.instructor, self.password)
|
||||
|
||||
# Now should be able to get to the toy course, but not the full course
|
||||
url = random.choice(instructor_urls(self.toy))
|
||||
print 'checking for 200 on {0}'.format(url)
|
||||
self.check_for_get_code(200, url)
|
||||
|
||||
url = random.choice(instructor_urls(self.full))
|
||||
print 'checking for 404 on {0}'.format(url)
|
||||
self.check_for_get_code(404, url)
|
||||
|
||||
# now also make the instructor staff
|
||||
instructor = get_user(self.instructor)
|
||||
instructor.is_staff = True
|
||||
instructor.save()
|
||||
|
||||
# and now should be able to load both
|
||||
url = random.choice(instructor_urls(self.toy) +
|
||||
instructor_urls(self.full))
|
||||
print 'checking for 200 on {0}'.format(url)
|
||||
self.check_for_get_code(200, url)
|
||||
|
||||
def run_wrapped(self, test):
|
||||
"""
|
||||
test.py turns off start dates. Enable them.
|
||||
Because settings is global, be careful not to mess it up for other tests
|
||||
(Can't use override_settings because we're only changing part of the
|
||||
MITX_FEATURES dict)
|
||||
"""
|
||||
oldDSD = settings.MITX_FEATURES['DISABLE_START_DATES']
|
||||
|
||||
try:
|
||||
settings.MITX_FEATURES['DISABLE_START_DATES'] = False
|
||||
test()
|
||||
finally:
|
||||
settings.MITX_FEATURES['DISABLE_START_DATES'] = oldDSD
|
||||
|
||||
def test_dark_launch(self):
|
||||
"""Make sure that before course start, students can't access course
|
||||
pages, but instructors can"""
|
||||
self.run_wrapped(self._do_test_dark_launch)
|
||||
|
||||
def test_enrollment_period(self):
|
||||
"""Check that enrollment periods work"""
|
||||
self.run_wrapped(self._do_test_enrollment_period)
|
||||
|
||||
def test_beta_period(self):
|
||||
"""Check that beta-test access works"""
|
||||
self.run_wrapped(self._do_test_beta_period)
|
||||
|
||||
def _do_test_dark_launch(self):
|
||||
"""Actually do the test, relying on settings to be right."""
|
||||
|
||||
# Make courses start in the future
|
||||
tomorrow = datetime.datetime.now(UTC()) + datetime.timedelta(days=1)
|
||||
self.toy.lms.start = tomorrow
|
||||
self.full.lms.start = tomorrow
|
||||
|
||||
self.assertFalse(self.toy.has_started())
|
||||
self.assertFalse(self.full.has_started())
|
||||
self.assertFalse(settings.MITX_FEATURES['DISABLE_START_DATES'])
|
||||
|
||||
def reverse_urls(names, course):
|
||||
"""Reverse a list of course urls"""
|
||||
return [reverse(name, kwargs={'course_id': course.id})
|
||||
for name in names]
|
||||
|
||||
def dark_student_urls(course):
|
||||
"""
|
||||
list of urls that students should be able to see only
|
||||
after launch, but staff should see before
|
||||
"""
|
||||
urls = reverse_urls(['info', 'progress'], course)
|
||||
urls.extend([
|
||||
reverse('book', kwargs={'course_id': course.id,
|
||||
'book_index': index})
|
||||
for index, book in enumerate(course.textbooks)
|
||||
])
|
||||
return urls
|
||||
|
||||
def light_student_urls(course):
|
||||
"""
|
||||
list of urls that students should be able to see before
|
||||
launch.
|
||||
"""
|
||||
urls = reverse_urls(['about_course'], course)
|
||||
urls.append(reverse('courses'))
|
||||
|
||||
return urls
|
||||
|
||||
def instructor_urls(course):
|
||||
"""list of urls that only instructors/staff should be able to see"""
|
||||
urls = reverse_urls(['instructor_dashboard',
|
||||
'gradebook', 'grade_summary'], course)
|
||||
return urls
|
||||
|
||||
def check_non_staff(course):
|
||||
"""Check that access is right for non-staff in course"""
|
||||
print '=== Checking non-staff access for {0}'.format(course.id)
|
||||
|
||||
# Randomly sample a dark url
|
||||
url = random.choice(instructor_urls(course) +
|
||||
dark_student_urls(course) +
|
||||
reverse_urls(['courseware'], course))
|
||||
print 'checking for 404 on {0}'.format(url)
|
||||
self.check_for_get_code(404, url)
|
||||
|
||||
# Randomly sample a light url
|
||||
url = random.choice(light_student_urls(course))
|
||||
print 'checking for 200 on {0}'.format(url)
|
||||
self.check_for_get_code(200, url)
|
||||
|
||||
def check_staff(course):
|
||||
"""Check that access is right for staff in course"""
|
||||
print '=== Checking staff access for {0}'.format(course.id)
|
||||
|
||||
# Randomly sample a url
|
||||
url = random.choice(instructor_urls(course) +
|
||||
dark_student_urls(course) +
|
||||
light_student_urls(course))
|
||||
print 'checking for 200 on {0}'.format(url)
|
||||
self.check_for_get_code(200, url)
|
||||
|
||||
# The student progress tab is not accessible to a student
|
||||
# before launch, so the instructor view-as-student feature
|
||||
# should return a 404 as well.
|
||||
# TODO (vshnayder): If this is not the behavior we want, will need
|
||||
# to make access checking smarter and understand both the effective
|
||||
# user (the student), and the requesting user (the prof)
|
||||
url = reverse('student_progress',
|
||||
kwargs={'course_id': course.id,
|
||||
'student_id': get_user(self.student).id})
|
||||
print 'checking for 404 on view-as-student: {0}'.format(url)
|
||||
self.check_for_get_code(404, url)
|
||||
|
||||
# The courseware url should redirect, not 200
|
||||
url = reverse_urls(['courseware'], course)[0]
|
||||
self.check_for_get_code(302, url)
|
||||
|
||||
# First, try with an enrolled student
|
||||
print '=== Testing student access....'
|
||||
self.login(self.student, self.password)
|
||||
self.enroll(self.toy)
|
||||
self.enroll(self.full)
|
||||
|
||||
# shouldn't be able to get to anything except the light pages
|
||||
check_non_staff(self.toy)
|
||||
check_non_staff(self.full)
|
||||
|
||||
print '=== Testing course instructor access....'
|
||||
# Make the instructor staff in the toy course
|
||||
group_name = _course_staff_group_name(self.toy.location)
|
||||
group = Group.objects.create(name=group_name)
|
||||
group.user_set.add(get_user(self.instructor))
|
||||
|
||||
self.logout()
|
||||
self.login(self.instructor, self.password)
|
||||
# Enroll in the classes---can't see courseware otherwise.
|
||||
self.enroll(self.toy)
|
||||
self.enroll(self.full)
|
||||
|
||||
# should now be able to get to everything for toy course
|
||||
check_non_staff(self.full)
|
||||
check_staff(self.toy)
|
||||
|
||||
print '=== Testing staff access....'
|
||||
# now also make the instructor staff
|
||||
instructor = get_user(self.instructor)
|
||||
instructor.is_staff = True
|
||||
instructor.save()
|
||||
|
||||
# and now should be able to load both
|
||||
check_staff(self.toy)
|
||||
check_staff(self.full)
|
||||
|
||||
def _do_test_enrollment_period(self):
|
||||
"""Actually do the test, relying on settings to be right."""
|
||||
|
||||
# Make courses start in the future
|
||||
tomorrow = datetime.datetime.now(UTC()) + datetime.timedelta(days=1)
|
||||
nextday = tomorrow + datetime.timedelta(days=1)
|
||||
yesterday = datetime.datetime.now(UTC()) - datetime.timedelta(days=1)
|
||||
|
||||
print "changing"
|
||||
# toy course's enrollment period hasn't started
|
||||
self.toy.enrollment_start = tomorrow
|
||||
self.toy.enrollment_end = nextday
|
||||
|
||||
# full course's has
|
||||
self.full.enrollment_start = yesterday
|
||||
self.full.enrollment_end = tomorrow
|
||||
|
||||
print "login"
|
||||
# First, try with an enrolled student
|
||||
print '=== Testing student access....'
|
||||
self.login(self.student, self.password)
|
||||
self.assertFalse(self.try_enroll(self.toy))
|
||||
self.assertTrue(self.try_enroll(self.full))
|
||||
|
||||
print '=== Testing course instructor access....'
|
||||
# Make the instructor staff in the toy course
|
||||
group_name = _course_staff_group_name(self.toy.location)
|
||||
group = Group.objects.create(name=group_name)
|
||||
group.user_set.add(get_user(self.instructor))
|
||||
|
||||
print "logout/login"
|
||||
self.logout()
|
||||
self.login(self.instructor, self.password)
|
||||
print "Instructor should be able to enroll in toy course"
|
||||
self.assertTrue(self.try_enroll(self.toy))
|
||||
|
||||
print '=== Testing staff access....'
|
||||
# now make the instructor global staff, but not in the instructor group
|
||||
group.user_set.remove(get_user(self.instructor))
|
||||
instructor = get_user(self.instructor)
|
||||
instructor.is_staff = True
|
||||
instructor.save()
|
||||
|
||||
# unenroll and try again
|
||||
self.unenroll(self.toy)
|
||||
self.assertTrue(self.try_enroll(self.toy))
|
||||
|
||||
def _do_test_beta_period(self):
|
||||
"""Actually test beta periods, relying on settings to be right."""
|
||||
|
||||
# trust, but verify :)
|
||||
self.assertFalse(settings.MITX_FEATURES['DISABLE_START_DATES'])
|
||||
|
||||
# Make courses start in the future
|
||||
tomorrow = datetime.datetime.now(UTC()) + datetime.timedelta(days=1)
|
||||
|
||||
# toy course's hasn't started
|
||||
self.toy.lms.start = tomorrow
|
||||
self.assertFalse(self.toy.has_started())
|
||||
|
||||
# but should be accessible for beta testers
|
||||
self.toy.lms.days_early_for_beta = 2
|
||||
|
||||
# student user shouldn't see it
|
||||
student_user = get_user(self.student)
|
||||
self.assertFalse(has_access(student_user, self.toy, 'load'))
|
||||
|
||||
# now add the student to the beta test group
|
||||
group_name = course_beta_test_group_name(self.toy.location)
|
||||
group = Group.objects.create(name=group_name)
|
||||
group.user_set.add(student_user)
|
||||
|
||||
# now the student should see it
|
||||
self.assertTrue(has_access(student_user, self.toy, 'load'))
|
||||
|
||||
|
||||
@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE)
|
||||
class TestSubmittingProblems(LoginEnrollmentTestCase):
|
||||
"""Check that a course gets graded properly"""
|
||||
|
||||
Reference in New Issue
Block a user