Commit 820e7711 by Calen Pennington

Add failing test for [LMS-1528]

Also cleans up test_view_authentication to use user factories for
various user classes
parent 0c2c6811
...@@ -14,7 +14,7 @@ from student.tests.factories import RegistrationFactory # Imported to re-export ...@@ -14,7 +14,7 @@ from student.tests.factories import RegistrationFactory # Imported to re-export
from student.tests.factories import UserProfileFactory as StudentUserProfileFactory from student.tests.factories import UserProfileFactory as StudentUserProfileFactory
from courseware.models import StudentModule, XModuleUserStateSummaryField from courseware.models import StudentModule, XModuleUserStateSummaryField
from courseware.models import XModuleStudentInfoField, XModuleStudentPrefsField from courseware.models import XModuleStudentInfoField, XModuleStudentPrefsField
from courseware.roles import CourseInstructorRole, CourseStaffRole from courseware.roles import CourseInstructorRole, CourseStaffRole, CourseBetaTesterRole, GlobalStaff
from xmodule.modulestore import Location from xmodule.modulestore import Location
...@@ -54,6 +54,32 @@ class StaffFactory(UserFactory): ...@@ -54,6 +54,32 @@ class StaffFactory(UserFactory):
CourseStaffRole(extracted).add_users(self) CourseStaffRole(extracted).add_users(self)
class BetaTesterFactory(UserFactory):
"""
Given a course Location, returns a User object with beta-tester
permissions for `course`.
"""
last_name = "Beta-Tester"
@post_generation
def course(self, create, extracted, **kwargs):
if extracted is None:
raise ValueError("Must specify a course location for a course staff user")
CourseBetaTesterRole(extracted).add_users(self)
class GlobalStaffFactory(UserFactory):
"""
Returns a User object with global staff access
"""
last_name = "GlobalStaff"
@post_generation
def set_staff(self, create, extracted, **kwargs):
GlobalStaff().add_users(self)
class StudentModuleFactory(DjangoModelFactory): class StudentModuleFactory(DjangoModelFactory):
FACTORY_FOR = StudentModule FACTORY_FOR = StudentModule
......
import datetime import datetime
import pytz import pytz
import unittest
from mock import patch from mock import patch
...@@ -9,14 +10,16 @@ from django.test.utils import override_settings ...@@ -9,14 +10,16 @@ from django.test.utils import override_settings
# Need access to internal func to put users in the right group # Need access to internal func to put users in the right group
from courseware.access import has_access from courseware.access import has_access
from courseware.roles import CourseBetaTesterRole, CourseInstructorRole, CourseStaffRole, GlobalStaff
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from student.tests.factories import UserFactory, CourseEnrollmentFactory
from courseware.tests.helpers import LoginEnrollmentTestCase, check_for_get_code from courseware.tests.helpers import LoginEnrollmentTestCase, check_for_get_code
from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE
from courseware.tests.factories import BetaTesterFactory, StaffFactory, GlobalStaffFactory, InstructorFactory
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
...@@ -89,13 +92,16 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -89,13 +92,16 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
# user (the student), and the requesting user (the prof) # user (the student), and the requesting user (the prof)
url = reverse('student_progress', url = 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': self.enrolled_user.id})
check_for_get_code(self, 404, url) check_for_get_code(self, 404, url)
# The courseware url should redirect, not 200 # The courseware url should redirect, not 200
url = self._reverse_urls(['courseware'], course)[0] url = self._reverse_urls(['courseware'], course)[0]
check_for_get_code(self, 302, url) check_for_get_code(self, 302, url)
def login(self, user):
return super(TestViewAuth, self).login(user.email, 'test')
def setUp(self): def setUp(self):
self.course = CourseFactory.create(number='999', display_name='Robot_Super_Course') self.course = CourseFactory.create(number='999', display_name='Robot_Super_Course')
...@@ -110,19 +116,22 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -110,19 +116,22 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
self.welcome_section = ItemFactory.create(parent_location=self.overview_chapter.location, self.welcome_section = ItemFactory.create(parent_location=self.overview_chapter.location,
display_name='Welcome') display_name='Welcome')
# Create two accounts and activate them. self.unenrolled_user = UserFactory(last_name="Unenrolled")
for i in range(len(self.ACCOUNT_INFO)):
username, email, password = 'u{0}'.format(i), self.ACCOUNT_INFO[i][0], self.ACCOUNT_INFO[i][1] self.enrolled_user = UserFactory(last_name="Enrolled")
self.create_account(username, email, password) CourseEnrollmentFactory(user=self.enrolled_user, course_id=self.course.id)
self.activate_user(email) CourseEnrollmentFactory(user=self.enrolled_user, course_id=self.test_course.id)
self.staff_user = StaffFactory(course=self.course.location)
self.instructor_user = InstructorFactory(course=self.course.location)
self.global_staff_user = GlobalStaffFactory()
def test_redirection_unenrolled(self): def test_redirection_unenrolled(self):
""" """
Verify unenrolled student is redirected to the 'about' section of the chapter Verify unenrolled student is redirected to the 'about' section of the chapter
instead of the 'Welcome' section after clicking on the courseware tab. instead of the 'Welcome' section after clicking on the courseware tab.
""" """
email, password = self.ACCOUNT_INFO[0] self.login(self.unenrolled_user)
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,
...@@ -134,9 +143,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -134,9 +143,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Verify enrolled student is redirected to the 'Welcome' section of Verify enrolled student is redirected to the 'Welcome' section of
the chapter after clicking on the courseware tab. the chapter after clicking on the courseware tab.
""" """
email, password = self.ACCOUNT_INFO[0] self.login(self.enrolled_user)
self.login(email, password)
self.enroll(self.course)
response = self.client.get(reverse('courseware', response = self.client.get(reverse('courseware',
kwargs={'course_id': self.course.id})) kwargs={'course_id': self.course.id}))
...@@ -152,11 +159,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -152,11 +159,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Verify non-staff cannot load the instructor Verify non-staff cannot load the instructor
dashboard, the grade views, and student profile pages. dashboard, the grade views, and student profile pages.
""" """
email, password = self.ACCOUNT_INFO[0] self.login(self.enrolled_user)
self.login(email, password)
self.enroll(self.course)
self.enroll(self.test_course)
urls = [reverse('instructor_dashboard', kwargs={'course_id': self.course.id}), urls = [reverse('instructor_dashboard', kwargs={'course_id': self.course.id}),
reverse('instructor_dashboard', kwargs={'course_id': self.test_course.id})] reverse('instructor_dashboard', kwargs={'course_id': self.test_course.id})]
...@@ -165,17 +168,26 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -165,17 +168,26 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
for url in urls: for url in urls:
check_for_get_code(self, 404, url) check_for_get_code(self, 404, url)
def test_instructor_course_access(self): def test_staff_course_access(self):
""" """
Verify instructor can load the instructor dashboard, the grade views, Verify instructor can load the instructor dashboard, the grade views,
and student profile pages for their course. and student profile pages for their course.
""" """
email, password = self.ACCOUNT_INFO[1] self.login(self.staff_user)
# Make the instructor staff in self.course # Now should be able to get to self.course, but not self.test_course
CourseInstructorRole(self.course.location).add_users(User.objects.get(email=email)) url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id})
check_for_get_code(self, 200, url)
url = reverse('instructor_dashboard', kwargs={'course_id': self.test_course.id})
check_for_get_code(self, 404, url)
self.login(email, password) def test_instructor_course_access(self):
"""
Verify instructor can load the instructor dashboard, the grade views,
and student profile pages for their course.
"""
self.login(self.instructor_user)
# Now should be able to get to self.course, but not self.test_course # Now should be able to get to self.course, but not self.test_course
url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id}) url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id})
...@@ -184,18 +196,11 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -184,18 +196,11 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
url = reverse('instructor_dashboard', kwargs={'course_id': self.test_course.id}) url = reverse('instructor_dashboard', kwargs={'course_id': self.test_course.id})
check_for_get_code(self, 404, url) check_for_get_code(self, 404, url)
def test_instructor_as_staff_access(self): def test_global_staff_access(self):
""" """
Verify the instructor can load staff pages if he is given Verify the global staff user can access any course.
staff permissions.
""" """
email, password = self.ACCOUNT_INFO[1] self.login(self.global_staff_user)
self.login(email, password)
# now make the instructor also staff
instructor = User.objects.get(email=email)
instructor.is_staff = True
instructor.save()
# and now should be able to load both # and now should be able to load both
urls = [reverse('instructor_dashboard', kwargs={'course_id': self.course.id}), urls = [reverse('instructor_dashboard', kwargs={'course_id': self.course.id}),
...@@ -211,8 +216,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -211,8 +216,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
pages. pages.
""" """
student_email, student_password = self.ACCOUNT_INFO[0]
# 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)
...@@ -225,9 +228,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -225,9 +228,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
self.assertFalse(self.test_course.has_started()) self.assertFalse(self.test_course.has_started())
# First, try with an enrolled student # First, try with an enrolled student
self.login(student_email, student_password) self.login(self.enrolled_user)
self.enroll(self.course, True)
self.enroll(self.test_course, True)
# shouldn't be able to get to anything except the light pages # shouldn't be able to get to anything except the light pages
self._check_non_staff_light(self.course) self._check_non_staff_light(self.course)
...@@ -241,8 +242,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -241,8 +242,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
Make sure that before course start instructors can access the Make sure that before course start instructors can access the
page for their course. page for their course.
""" """
instructor_email, instructor_password = self.ACCOUNT_INFO[1]
now = datetime.datetime.now(pytz.UTC) now = datetime.datetime.now(pytz.UTC)
tomorrow = now + datetime.timedelta(days=1) tomorrow = now + datetime.timedelta(days=1)
course_data = {'start': tomorrow} course_data = {'start': tomorrow}
...@@ -250,11 +249,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -250,11 +249,7 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
self.course = self.update_course(self.course, course_data) self.course = self.update_course(self.course, course_data)
self.test_course = self.update_course(self.test_course, test_course_data) self.test_course = self.update_course(self.test_course, test_course_data)
# Make the instructor staff in self.course self.login(self.instructor_user)
CourseStaffRole(self.course.location).add_users(User.objects.get(email=instructor_email))
self.logout()
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.test_course, True) self.enroll(self.test_course, True)
...@@ -265,13 +260,11 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -265,13 +260,11 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
self._check_staff(self.course) self._check_staff(self.course)
@patch.dict('courseware.access.settings.MITX_FEATURES', {'DISABLE_START_DATES': False}) @patch.dict('courseware.access.settings.MITX_FEATURES', {'DISABLE_START_DATES': False})
def test_dark_launch_staff(self): def test_dark_launch_global_staff(self):
""" """
Make sure that before course start staff can access Make sure that before course start staff can access
course pages. course pages.
""" """
instructor_email, instructor_password = self.ACCOUNT_INFO[1]
now = datetime.datetime.now(pytz.UTC) now = datetime.datetime.now(pytz.UTC)
tomorrow = now + datetime.timedelta(days=1) tomorrow = now + datetime.timedelta(days=1)
course_data = {'start': tomorrow} course_data = {'start': tomorrow}
...@@ -279,15 +272,10 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -279,15 +272,10 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
self.course = self.update_course(self.course, course_data) self.course = self.update_course(self.course, course_data)
self.test_course = self.update_course(self.test_course, test_course_data) self.test_course = self.update_course(self.test_course, test_course_data)
self.login(instructor_email, instructor_password) self.login(self.global_staff_user)
self.enroll(self.course, True) self.enroll(self.course, True)
self.enroll(self.test_course, True) self.enroll(self.test_course, True)
# now also make the instructor staff
instructor = User.objects.get(email=instructor_email)
instructor.is_staff = True
instructor.save()
# and now should be able to load both # and now should be able to load both
self._check_staff(self.course) self._check_staff(self.course)
self._check_staff(self.test_course) self._check_staff(self.test_course)
...@@ -297,9 +285,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -297,9 +285,6 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
""" """
Check that enrollment periods work. Check that enrollment periods work.
""" """
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)
...@@ -315,52 +300,54 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase): ...@@ -315,52 +300,54 @@ class TestViewAuth(ModuleStoreTestCase, LoginEnrollmentTestCase):
self.test_course = self.update_course(self.test_course, test_course_data) self.test_course = self.update_course(self.test_course, test_course_data)
# First, try with an enrolled student # First, try with an enrolled student
self.login(student_email, student_password) self.login(self.unenrolled_user)
self.assertFalse(self.enroll(self.course)) self.assertFalse(self.enroll(self.course))
self.assertTrue(self.enroll(self.test_course)) self.assertTrue(self.enroll(self.test_course))
# Make the instructor staff in the self.course
instructor_role = CourseInstructorRole(self.course.location)
instructor_role.add_users(User.objects.get(email=instructor_email))
self.logout() self.logout()
self.login(instructor_email, instructor_password) self.login(self.instructor_user)
self.assertTrue(self.enroll(self.course)) self.assertTrue(self.enroll(self.course))
# now make the instructor global staff, but not in the instructor group
instructor_role.remove_users(User.objects.get(email=instructor_email))
GlobalStaff().add_users(User.objects.get(email=instructor_email))
# unenroll and try again # unenroll and try again
self.unenroll(self.course) self.login(self.global_staff_user)
self.assertTrue(self.enroll(self.course)) self.assertTrue(self.enroll(self.course))
@patch.dict('courseware.access.settings.MITX_FEATURES', {'DISABLE_START_DATES': False})
def test_beta_period(self):
"""
Check that beta-test access works.
"""
student_email, student_password = self.ACCOUNT_INFO[0]
instructor_email, instructor_password = self.ACCOUNT_INFO[1]
# Make courses start in the future @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
class TestBetatesterAccess(ModuleStoreTestCase):
def setUp(self):
now = datetime.datetime.now(pytz.UTC) now = datetime.datetime.now(pytz.UTC)
tomorrow = now + datetime.timedelta(days=1) tomorrow = now + datetime.timedelta(days=1)
course_data = {'start': tomorrow}
# self.course's hasn't started self.course = CourseFactory(days_early_for_beta=2, start=tomorrow)
self.course = self.update_course(self.course, course_data) self.content = ItemFactory(parent=self.course)
self.assertFalse(self.course.has_started())
self.normal_student = UserFactory()
self.beta_tester = BetaTesterFactory(course=self.course.location)
# but should be accessible for beta testers @patch.dict('courseware.access.settings.MITX_FEATURES', {'DISABLE_START_DATES': False})
self.course.days_early_for_beta = 2 def test_course_beta_period(self):
"""
Check that beta-test access works for courses.
"""
self.assertFalse(self.course.has_started())
# student user shouldn't see it # student user shouldn't see it
student_user = User.objects.get(email=student_email) self.assertFalse(has_access(self.normal_student, self.course, 'load'))
self.assertFalse(has_access(student_user, self.course, 'load'))
# now add the student to the beta test group # now the student should see it
CourseBetaTesterRole(self.course.location).add_users(student_user) self.assertTrue(has_access(self.beta_tester, self.course, 'load'))
@unittest.expectedFailure
@patch.dict('courseware.access.settings.MITX_FEATURES', {'DISABLE_START_DATES': False})
def test_content_beta_period(self):
"""
Check that beta-test access works for content.
"""
# student user shouldn't see it
self.assertFalse(has_access(self.normal_student, self.content, 'load'))
# now the student should see it # now the student should see it
self.assertTrue(has_access(student_user, self.course, 'load')) self.assertTrue(has_access(self.beta_tester, self.content, 'load'))
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