Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
edx-platform
Commits
dc280977
Commit
dc280977
authored
Nov 28, 2017
by
Albert St. Aubin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated tests WIP
parent
242e058f
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
188 additions
and
44 deletions
+188
-44
common/djangoapps/entitlements/api/v1/tests/test_views.py
+125
-0
common/djangoapps/entitlements/api/v1/views.py
+62
-28
common/djangoapps/entitlements/models.py
+0
-15
common/djangoapps/student/tests/test_views.py
+1
-1
No files found.
common/djangoapps/entitlements/api/v1/tests/test_views.py
View file @
dc280977
...
@@ -7,6 +7,9 @@ from django.core.urlresolvers import reverse
...
@@ -7,6 +7,9 @@ from django.core.urlresolvers import reverse
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
entitlements.tests.factories
import
CourseEntitlementFactory
from
entitlements.models
import
CourseEntitlement
from
entitlements.api.v1.serializers
import
CourseEntitlementSerializer
from
student.tests.factories
import
CourseEnrollmentFactory
,
UserFactory
,
TEST_PASSWORD
from
student.tests.factories
import
CourseEnrollmentFactory
,
UserFactory
,
TEST_PASSWORD
# Entitlements is not in CMS' INSTALLED_APPS so these imports will error during test collection
# Entitlements is not in CMS' INSTALLED_APPS so these imports will error during test collection
...
@@ -151,6 +154,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
...
@@ -151,6 +154,7 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
entitlement
=
CourseEntitlementFactory
()
entitlement
=
CourseEntitlementFactory
()
CourseEntitlementFactory
.
create_batch
(
2
)
CourseEntitlementFactory
.
create_batch
(
2
)
CourseEntitlementFactory
()
url
=
reverse
(
self
.
ENTITLEMENTS_DETAILS_PATH
,
args
=
[
str
(
entitlement
.
uuid
)])
url
=
reverse
(
self
.
ENTITLEMENTS_DETAILS_PATH
,
args
=
[
str
(
entitlement
.
uuid
)])
response
=
self
.
client
.
get
(
response
=
self
.
client
.
get
(
...
@@ -195,3 +199,124 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
...
@@ -195,3 +199,124 @@ class EntitlementViewSetTest(ModuleStoreTestCase):
course_entitlement
.
refresh_from_db
()
course_entitlement
.
refresh_from_db
()
assert
course_entitlement
.
expired_at
is
not
None
assert
course_entitlement
.
expired_at
is
not
None
assert
course_entitlement
.
enrollment_course_run
is
None
assert
course_entitlement
.
enrollment_course_run
is
None
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
@patch
(
"openedx.core.djangoapps.catalog.utils.get_course_runs_for_course"
)
class
EntitlementEnrollmentViewSetTest
(
ModuleStoreTestCase
):
ENTITLEMENTS_ENROLLMENT_NAMESPACE
=
'entitlements_api:v1:enrollments'
def
setUp
(
self
):
super
(
EntitlementEnrollmentViewSetTest
,
self
)
.
setUp
()
self
.
user
=
UserFactory
()
self
.
client
.
login
(
username
=
self
.
user
.
username
,
password
=
TEST_PASSWORD
)
self
.
course
=
CourseFactory
.
create
(
org
=
'edX'
,
number
=
'DemoX'
,
display_name
=
'Demo_Course'
)
self
.
course2
=
CourseFactory
.
create
(
org
=
'edX'
,
number
=
'DemoX2'
,
display_name
=
'Demo_Course 2'
)
def
test_user_can_enroll
(
self
,
mock_get_course_runs
):
course_entitlement
=
CourseEntitlementFactory
(
user
=
self
.
user
)
url
=
reverse
(
self
.
ENTITLEMENTS_ENROLLMENT_NAMESPACE
,
args
=
[
str
(
course_entitlement
.
uuid
)]
)
assert
course_entitlement
.
enrollment_course_run
is
None
mock_get_course_runs
.
method
.
return_value
=
[
{
'key'
:
str
(
self
.
course
.
id
)}
]
data
=
{
'course_run_id'
:
str
(
self
.
course
.
id
)
}
response
=
self
.
client
.
post
(
url
,
data
=
json
.
dumps
(
data
),
content_type
=
'application/json'
,
)
course_entitlement
.
refresh_from_db
()
assert
response
.
status_code
==
201
assert
CourseEnrollment
.
is_enrolled
(
self
.
user
,
self
.
course
.
id
)
assert
course_entitlement
.
enrollment_course_run
is
not
None
def
test_user_can_unenroll
(
self
,
mock_get_course_runs
):
course_entitlement
=
CourseEntitlementFactory
(
user
=
self
.
user
)
url
=
reverse
(
self
.
ENTITLEMENTS_ENROLLMENT_NAMESPACE
,
args
=
[
str
(
course_entitlement
.
uuid
)]
)
assert
course_entitlement
.
enrollment_course_run
is
None
mock_get_course_runs
.
return_value
=
[
{
'key'
:
str
(
self
.
course
.
id
)}
]
data
=
{
'course_run_id'
:
str
(
self
.
course
.
id
)
}
response
=
self
.
client
.
post
(
url
,
data
=
json
.
dumps
(
data
),
content_type
=
'application/json'
,
)
course_entitlement
.
refresh_from_db
()
assert
response
.
status_code
==
201
assert
CourseEnrollment
.
is_enrolled
(
self
.
user
,
self
.
course
.
id
)
response
=
self
.
client
.
delete
(
url
,
content_type
=
'application/json'
,
)
assert
response
.
status_code
==
204
course_entitlement
.
refresh_from_db
()
assert
not
CourseEnrollment
.
is_enrolled
(
self
.
user
,
self
.
course
.
id
)
assert
course_entitlement
.
enrollment_course_run
is
None
def
test_user_can_switch
(
self
,
mock_get_course_runs
):
course_entitlement
=
CourseEntitlementFactory
(
user
=
self
.
user
)
url
=
reverse
(
self
.
ENTITLEMENTS_ENROLLMENT_NAMESPACE
,
args
=
[
str
(
course_entitlement
.
uuid
)]
)
assert
course_entitlement
.
enrollment_course_run
is
None
mock_get_course_runs
.
return_value
=
[
{
'key'
:
str
(
self
.
course
.
id
)},
{
'key'
:
str
(
self
.
course2
.
id
)}
]
data
=
{
'course_run_id'
:
str
(
self
.
course
.
id
)
}
response
=
self
.
client
.
post
(
url
,
data
=
json
.
dumps
(
data
),
content_type
=
'application/json'
,
)
course_entitlement
.
refresh_from_db
()
assert
response
.
status_code
==
201
assert
CourseEnrollment
.
is_enrolled
(
self
.
user
,
self
.
course
.
id
)
data
=
{
'course_run_id'
:
str
(
self
.
course2
.
id
)
}
response
=
self
.
client
.
post
(
url
,
data
=
json
.
dumps
(
data
),
content_type
=
'application/json'
,
)
assert
response
.
status_code
==
201
course_entitlement
.
refresh_from_db
()
assert
CourseEnrollment
.
is_enrolled
(
self
.
user
,
self
.
course2
.
id
)
assert
course_entitlement
.
enrollment_course_run
is
not
None
print
course_entitlement
.
enrollment_course_run
.
course_id
common/djangoapps/entitlements/api/v1/views.py
View file @
dc280977
...
@@ -3,9 +3,13 @@ import logging
...
@@ -3,9 +3,13 @@ import logging
from
django.utils
import
timezone
from
django.utils
import
timezone
from
django_filters.rest_framework
import
DjangoFilterBackend
from
django_filters.rest_framework
import
DjangoFilterBackend
from
edx_rest_framework_extensions.authentication
import
JwtAuthentication
from
edx_rest_framework_extensions.authentication
import
JwtAuthentication
from
opaque_keys.edx.keys
import
CourseKey
from
rest_framework
import
permissions
,
viewsets
,
status
from
rest_framework
import
permissions
,
viewsets
,
status
from
rest_framework.response
import
Response
from
rest_framework.response
import
Response
from
rest_framework.authentication
import
SessionAuthentication
from
rest_framework.authentication
import
SessionAuthentication
from
student.models
import
CourseEnrollmentException
# from enrollment.errors import CourseEnrollmentError, CourseEnrollmentExistsError, CourseModeNotFoundError
# from openedx.core.lib.exceptions import CourseNotFoundError
from
openedx.core.djangoapps.catalog.utils
import
get_course_runs_for_course
from
openedx.core.djangoapps.catalog.utils
import
get_course_runs_for_course
from
entitlements.api.v1.filters
import
CourseEntitlementFilter
from
entitlements.api.v1.filters
import
CourseEntitlementFilter
...
@@ -22,8 +26,9 @@ log = logging.getLogger(__name__)
...
@@ -22,8 +26,9 @@ log = logging.getLogger(__name__)
class
EntitlementViewSet
(
viewsets
.
ModelViewSet
):
class
EntitlementViewSet
(
viewsets
.
ModelViewSet
):
authentication_classes
=
(
JwtAuthentication
,
SessionAuthenticationCrossDomainCsrf
,)
authentication_classes
=
(
JwtAuthentication
,
SessionAuthentication
,)
permission_classes
=
(
permissions
.
IsAuthenticated
,
IsAdminOrAuthenticatedReadOnly
,)
permission_classes
=
(
permissions
.
IsAuthenticated
,
permissions
.
IsAdminUser
,)
queryset
=
CourseEntitlement
.
objects
.
all
()
.
select_related
(
'user'
)
lookup_value_regex
=
'[0-9a-f-]+'
lookup_value_regex
=
'[0-9a-f-]+'
lookup_field
=
'uuid'
lookup_field
=
'uuid'
serializer_class
=
CourseEntitlementSerializer
serializer_class
=
CourseEntitlementSerializer
...
@@ -71,12 +76,36 @@ class EntitlementEnrollmentViewSet(viewsets.GenericViewSet):
...
@@ -71,12 +76,36 @@ class EntitlementEnrollmentViewSet(viewsets.GenericViewSet):
queryset
=
CourseEntitlement
.
objects
.
all
()
queryset
=
CourseEntitlement
.
objects
.
all
()
serializer_class
=
CourseEntitlementSerializer
serializer_class
=
CourseEntitlementSerializer
def
_verify_course_run_for_entitlement
(
self
,
entitlement
,
course_session_id
):
course_run_valid
=
False
course_runs
=
get_course_runs_for_course
(
entitlement
.
course_uuid
)
for
run
in
course_runs
:
if
course_session_id
==
run
.
get
(
'key'
,
''
):
course_run_valid
=
True
break
return
course_run_valid
def
_enroll_entitlement
(
self
,
entitlement
,
course_session_key
,
user
):
def
_enroll_entitlement
(
self
,
entitlement
,
course_session_key
,
user
):
enrollment
=
CourseEnrollment
.
enroll
(
try
:
user
=
user
,
enrollment
=
CourseEnrollment
.
enroll
(
course_key
=
course_session_key
,
user
=
user
,
mode
=
entitlement
.
mode
,
course_key
=
course_session_key
,
)
mode
=
entitlement
.
mode
,
)
except
CourseEnrollmentException
:
message
=
(
'Course Entitlement Enroll for {username} failed for course: {course_id}, '
'mode: {mode}, and entitlement: {entitlement}'
)
.
format
(
username
=
user
.
username
,
course_id
=
course_session_key
,
mode
=
entitlement
.
mode
,
entitlement
=
entitlement
.
uuid
)
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
'message'
:
message
}
)
CourseEntitlement
.
set_enrollment
(
entitlement
,
enrollment
)
CourseEntitlement
.
set_enrollment
(
entitlement
,
enrollment
)
...
@@ -103,37 +132,42 @@ class EntitlementEnrollmentViewSet(viewsets.GenericViewSet):
...
@@ -103,37 +132,42 @@ class EntitlementEnrollmentViewSet(viewsets.GenericViewSet):
)
)
# Verify the course run ID is of the same type as the Course entitlement.
# Verify the course run ID is of the same type as the Course entitlement.
course_run_valid
=
False
course_run_valid
=
self
.
_verify_course_run_for_entitlement
(
entitlement
,
course_session_id
)
course_runs
=
get_course_runs_for_course
(
entitlement
.
course_uuid
)
for
run
in
course_runs
:
if
course_session_id
==
run
.
get
(
'key'
,
''
):
course_run_valid
=
True
if
not
course_run_valid
:
if
not
course_run_valid
:
return
Response
(
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
"The Course Run ID is not a match for this Course Entitlement."
data
=
{
'message'
:
"The Course Run ID is not a match for this Course Entitlement."
}
)
)
# Determine if this is a Switch session or a simple enroll and handle both.
# Determine if this is a Switch session or a simple enroll and handle both.
try
:
course_run_string
=
CourseKey
.
from_string
(
course_session_id
)
except
CourseKey
.
InvalidKeyError
:
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
,
data
=
{
'message'
:
u"Invalid '{course_id}'"
.
format
(
course_id
=
course_session_id
)
}
)
if
entitlement
.
enrollment_course_run
is
None
:
if
entitlement
.
enrollment_course_run
is
None
:
self
.
_enroll_entitlement
(
self
.
_enroll_entitlement
(
entitlement
=
entitlement
,
entitlement
=
entitlement
,
course_session_key
=
CourseKey
.
from_string
(
course_session_id
),
course_session_key
=
course_run_string
,
user
=
request
.
user
)
elif
entitlement
.
enrollment_course_run
.
course_id
!=
course_session_id
:
self
.
_unenroll_entitlement
(
entitlement
=
entitlement
,
course_session_key
=
entitlement
.
enrollment_course_run
.
course_id
,
user
=
request
.
user
)
self
.
_enroll_entitlement
(
entitlement
=
entitlement
,
course_session_key
=
course_run_string
,
user
=
request
.
user
user
=
request
.
user
)
)
else
:
if
entitlement
.
enrollment_course_run
.
course_id
!=
course_session_id
:
self
.
_unenroll_entitlement
(
entitlement
=
entitlement
,
course_session_key
=
entitlement
.
enrollment_course_run
.
course_id
,
user
=
request
.
user
)
self
.
_enroll_entitlement
(
entitlement
=
entitlement
,
course_session_key
=
CourseKey
.
from_string
(
course_session_id
),
user
=
request
.
user
)
return
Response
(
return
Response
(
status
=
status
.
HTTP_201_CREATED
,
status
=
status
.
HTTP_201_CREATED
,
...
@@ -157,7 +191,7 @@ class EntitlementEnrollmentViewSet(viewsets.GenericViewSet):
...
@@ -157,7 +191,7 @@ class EntitlementEnrollmentViewSet(viewsets.GenericViewSet):
)
)
if
entitlement
.
enrollment_course_run
is
None
:
if
entitlement
.
enrollment_course_run
is
None
:
return
Response
()
return
Response
(
status
=
status
.
HTTP_204_NO_CONTENT
)
self
.
_unenroll_entitlement
(
self
.
_unenroll_entitlement
(
entitlement
=
entitlement
,
entitlement
=
entitlement
,
...
...
common/djangoapps/entitlements/models.py
View file @
dc280977
...
@@ -26,21 +26,6 @@ class CourseEntitlement(TimeStampedModel):
...
@@ -26,21 +26,6 @@ class CourseEntitlement(TimeStampedModel):
order_number
=
models
.
CharField
(
max_length
=
128
,
null
=
True
)
order_number
=
models
.
CharField
(
max_length
=
128
,
null
=
True
)
@classmethod
@classmethod
def
get_active_user_course_entitlements
(
cls
,
user
,
course_uuid
):
"""
Returns all the available sessions for a given course.
"""
try
:
entitlement
=
cls
.
objects
.
get
(
user
=
user
,
course_uuid
=
course_uuid
,
)
return
entitlement
except
cls
.
DoesNotExist
:
return
None
@classmethod
def
set_enrollment
(
cls
,
entitlement
,
enrollment
):
def
set_enrollment
(
cls
,
entitlement
,
enrollment
):
"""
"""
Fulfills an entitlement by specifying a session.
Fulfills an entitlement by specifying a session.
...
...
common/djangoapps/student/tests/test_views.py
View file @
dc280977
...
@@ -319,7 +319,7 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin):
...
@@ -319,7 +319,7 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin):
If we remove the prerequisite and access the dashboard again, the prerequisite
If we remove the prerequisite and access the dashboard again, the prerequisite
should not appear.
should not appear.
"""
"""
self
.
pre_requisite_course
=
CourseFactory
.
create
(
org
=
'edx'
,
number
=
'999'
,
display_name
=
'Pre requisite Course'
)
self
.
pre_requisite_course
=
CourseFactory
.
create
(
org
=
'edx'
,
number
=
'999'
,
display_name
=
'Pre requisite Course'
)
self
.
course
=
CourseFactory
.
create
(
self
.
course
=
CourseFactory
.
create
(
org
=
'edx'
,
org
=
'edx'
,
number
=
'998'
,
number
=
'998'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment