Commit ffd6d894 by Akiva Leffert

Update course enrollments API to allow beta users to see a course.

Also adds me as an author
JIRA: https://openedx.atlassian.net/browse/MA-76
parent 8b73de91
...@@ -179,3 +179,4 @@ Henry Tareque <henry.tareque@gmail.com> ...@@ -179,3 +179,4 @@ Henry Tareque <henry.tareque@gmail.com>
Eugeny Kolpakov <eugeny.kolpakov@gmail.com> Eugeny Kolpakov <eugeny.kolpakov@gmail.com>
Omar Al-Ithawi <oithawi@qrf.org> Omar Al-Ithawi <oithawi@qrf.org>
Louis Pilfold <louis@lpil.uk> Louis Pilfold <louis@lpil.uk>
Akiva Leffert <akiva@edx.org>
""" """
Tests for users API Tests for users API
""" """
import ddt
from rest_framework.test import APITestCase from rest_framework.test import APITestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
...@@ -8,8 +10,10 @@ from courseware.tests.factories import UserFactory ...@@ -8,8 +10,10 @@ from courseware.tests.factories import UserFactory
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from mobile_api.users.serializers import CourseEnrollmentSerializer from mobile_api.users.serializers import CourseEnrollmentSerializer
from student.models import CourseEnrollment from student.models import CourseEnrollment
from student import auth
@ddt.ddt
class TestUserApi(ModuleStoreTestCase, APITestCase): class TestUserApi(ModuleStoreTestCase, APITestCase):
""" """
Test the user info API Test the user info API
...@@ -25,44 +29,70 @@ class TestUserApi(ModuleStoreTestCase, APITestCase): ...@@ -25,44 +29,70 @@ class TestUserApi(ModuleStoreTestCase, APITestCase):
super(TestUserApi, self).tearDown() super(TestUserApi, self).tearDown()
self.client.logout() self.client.logout()
def _enroll(self): def _enrollment_url(self):
"""
api url that gets the current user's course enrollments
"""
return reverse('courseenrollment-detail', kwargs={'username': self.user.username})
def _enroll(self, course):
""" """
enroll test user in test course enroll test user in test course
""" """
resp = self.client.post(reverse('change_enrollment'), { resp = self.client.post(reverse('change_enrollment'), {
'enrollment_action': 'enroll', 'enrollment_action': 'enroll',
'course_id': self.course.id.to_deprecated_string(), 'course_id': course.id.to_deprecated_string(),
'check_access': True, 'check_access': True,
}) })
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
def test_user_enrollments(self): def _verify_single_course_enrollment(self, course):
url = reverse('courseenrollment-detail', kwargs={'username': self.user.username}) """
check that enrolling in course adds us to it
"""
url = self._enrollment_url()
self.client.login(username=self.username, password=self.password) self.client.login(username=self.username, password=self.password)
self._enroll(course)
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, []) # pylint: disable=E1103
self._enroll() courses = response.data # pylint: disable=maybe-no-member
self.assertEqual(len(courses), 1)
found_course = courses[0]['course']
self.assertTrue('video_outline' in found_course)
self.assertTrue('course_handouts' in found_course)
self.assertEqual(found_course['id'], unicode(course.id))
self.assertEqual(courses[0]['mode'], 'honor')
def test_non_mobile_enrollments(self):
url = self._enrollment_url()
non_mobile_course = CourseFactory.create(mobile_available=False)
self.client.login(username=self.username, password=self.password)
self._enroll(non_mobile_course)
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, []) # pylint: disable=maybe-no-member
courses = response.data # pylint: disable=E1103 @ddt.data(auth.CourseBetaTesterRole, auth.CourseStaffRole, auth.CourseInstructorRole)
def test_privileged_enrollments(self, role):
non_mobile_course = CourseFactory.create(mobile_available=False)
role(non_mobile_course.id).add_users(self.user)
self.assertTrue(len(courses), 1) self._verify_single_course_enrollment(non_mobile_course)
course = courses[0]['course']
self.assertTrue('video_outline' in course) def test_mobile_enrollments(self):
self.assertTrue('course_handouts' in course) self._verify_single_course_enrollment(self.course)
self.assertEqual(course['id'], self.course.id.to_deprecated_string())
self.assertEqual(courses[0]['mode'], 'honor')
def test_user_overview(self): def test_user_overview(self):
self.client.login(username=self.username, password=self.password) self.client.login(username=self.username, password=self.password)
url = reverse('user-detail', kwargs={'username': self.user.username}) url = reverse('user-detail', kwargs={'username': self.user.username})
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
data = response.data # pylint: disable=E1103 data = response.data # pylint: disable=maybe-no-member
self.assertEqual(data['username'], self.user.username) self.assertEqual(data['username'], self.user.username)
self.assertEqual(data['email'], self.user.email) self.assertEqual(data['email'], self.user.email)
...@@ -89,7 +119,7 @@ class TestUserApi(ModuleStoreTestCase, APITestCase): ...@@ -89,7 +119,7 @@ class TestUserApi(ModuleStoreTestCase, APITestCase):
def test_course_serializer(self): def test_course_serializer(self):
self.client.login(username=self.username, password=self.password) self.client.login(username=self.username, password=self.password)
self._enroll() self._enroll(self.course)
serialized = CourseEnrollmentSerializer(CourseEnrollment.enrollments_for_user(self.user)[0]).data # pylint: disable=E1101 serialized = CourseEnrollmentSerializer(CourseEnrollment.enrollments_for_user(self.user)[0]).data # pylint: disable=E1101
self.assertEqual(serialized['course']['video_outline'], None) self.assertEqual(serialized['course']['video_outline'], None)
self.assertEqual(serialized['course']['name'], self.course.display_name) self.assertEqual(serialized['course']['name'], self.course.display_name)
...@@ -8,8 +8,10 @@ from rest_framework.authentication import OAuth2Authentication, SessionAuthentic ...@@ -8,8 +8,10 @@ from rest_framework.authentication import OAuth2Authentication, SessionAuthentic
from rest_framework.decorators import api_view, authentication_classes, permission_classes from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from courseware.access import has_access from courseware import access
from student.models import CourseEnrollment, User from student.models import CourseEnrollment, User
from student.roles import CourseBetaTesterRole
from student import auth
from .serializers import CourseEnrollmentSerializer, UserSerializer from .serializers import CourseEnrollmentSerializer, UserSerializer
...@@ -119,12 +121,18 @@ def my_user_info(request): ...@@ -119,12 +121,18 @@ def my_user_info(request):
def mobile_course_enrollments(enrollments, user): def mobile_course_enrollments(enrollments, user):
""" """
Return enrollments only if courses are mobile_available (or if the user has staff access) Return enrollments only if courses are mobile_available (or if the user has
enrollments is a list of CourseEnrollments. privileged (beta, staff, instructor) access)
:param enrollments is a list of CourseEnrollments.
""" """
for enr in enrollments: for enr in enrollments:
course = enr.course course = enr.course
# Implicitly includes instructor role via the following has_access check
role = CourseBetaTesterRole(course.id)
# The course doesn't always really exist -- we can have bad data in the enrollments # The course doesn't always really exist -- we can have bad data in the enrollments
# pointing to non-existent (or removed) courses, in which case `course` is None. # pointing to non-existent (or removed) courses, in which case `course` is None.
if course and (course.mobile_available or has_access(user, 'staff', course)): if course and (course.mobile_available or auth.has_access(user, role) or access.has_access(user, 'staff', course)):
yield enr yield enr
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