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
edx
edx-platform
Commits
cb3140e9
Commit
cb3140e9
authored
Jul 21, 2015
by
tlindaliu
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #8782 from edx/lliu/courseware-access
Add courseware_access field to mobile API
parents
9d574b4e
5aeccd52
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
104 additions
and
7 deletions
+104
-7
lms/djangoapps/mobile_api/users/serializers.py
+17
-0
lms/djangoapps/mobile_api/users/tests.py
+87
-7
No files found.
lms/djangoapps/mobile_api/users/serializers.py
View file @
cb3140e9
...
...
@@ -4,8 +4,12 @@ Serializer for user API
from
rest_framework
import
serializers
from
rest_framework.reverse
import
reverse
from
django.template
import
defaultfilters
from
courseware.access
import
has_access
from
student.models
import
CourseEnrollment
,
User
from
certificates.models
import
certificate_status_for_student
,
CertificateStatuses
from
xmodule.course_module
import
DEFAULT_START_DATE
class
CourseOverviewField
(
serializers
.
RelatedField
):
...
...
@@ -35,12 +39,24 @@ class CourseOverviewField(serializers.RelatedField):
course_updates_url
=
None
course_handouts_url
=
None
if
course_overview
.
advertised_start
is
not
None
:
start_type
=
"string"
start_display
=
course_overview
.
advertised_start
elif
course_overview
.
start
!=
DEFAULT_START_DATE
:
start_type
=
"timestamp"
start_display
=
defaultfilters
.
date
(
course_overview
.
start
,
"DATE_FORMAT"
)
else
:
start_type
=
"empty"
start_display
=
None
return
{
"id"
:
course_id
,
"name"
:
course_overview
.
display_name
,
"number"
:
course_overview
.
display_number_with_default
,
"org"
:
course_overview
.
display_org_with_default
,
"start"
:
course_overview
.
start
,
"start_display"
:
start_display
,
"start_type"
:
start_type
,
"end"
:
course_overview
.
end
,
"course_image"
:
course_overview
.
course_image_url
,
"social_urls"
:
{
...
...
@@ -53,6 +69,7 @@ class CourseOverviewField(serializers.RelatedField):
"course_updates"
:
course_updates_url
,
"course_handouts"
:
course_handouts_url
,
"subscription_id"
:
course_overview
.
clean_id
(
padding_char
=
'_'
),
"courseware_access"
:
has_access
(
request
.
user
,
'load_mobile'
,
course_overview
)
.
to_json
()
if
request
else
None
}
...
...
lms/djangoapps/mobile_api/users/tests.py
View file @
cb3140e9
...
...
@@ -2,12 +2,28 @@
Tests for users API
"""
import
datetime
import
ddt
from
mock
import
patch
import
pytz
from
django.conf
import
settings
from
django.utils
import
timezone
from
django.template
import
defaultfilters
from
xmodule.modulestore.tests.factories
import
ItemFactory
,
CourseFactory
from
student.models
import
CourseEnrollment
from
certificates.models
import
CertificateStatuses
from
certificates.tests.factories
import
GeneratedCertificateFactory
from
courseware.access_response
import
(
MilestoneError
,
StartDateError
,
VisibilityError
,
)
from
student.models
import
CourseEnrollment
from
util.milestones_helpers
import
(
set_prerequisite_courses
,
seed_milestone_relationship_types
,
)
from
xmodule.course_module
import
DEFAULT_START_DATE
from
xmodule.modulestore.tests.factories
import
ItemFactory
,
CourseFactory
from
..
import
errors
from
..testutils
import
MobileAPITestCase
,
MobileAuthTestMixin
,
MobileAuthUserTestMixin
,
MobileCourseAccessTestMixin
...
...
@@ -43,6 +59,7 @@ class TestUserInfoApi(MobileAPITestCase, MobileAuthTestMixin):
self
.
assertTrue
(
self
.
username
in
response
[
'location'
])
@ddt.ddt
class
TestUserEnrollmentApi
(
MobileAPITestCase
,
MobileAuthUserTestMixin
,
MobileCourseAccessTestMixin
):
"""
Tests for /api/mobile/v0.5/users/<user_name>/course_enrollments/
...
...
@@ -50,6 +67,9 @@ class TestUserEnrollmentApi(MobileAPITestCase, MobileAuthUserTestMixin, MobileCo
REVERSE_INFO
=
{
'name'
:
'courseenrollment-detail'
,
'params'
:
[
'username'
]}
ALLOW_ACCESS_TO_UNRELEASED_COURSE
=
True
ALLOW_ACCESS_TO_MILESTONE_COURSE
=
True
NEXT_WEEK
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
+
datetime
.
timedelta
(
days
=
7
)
LAST_WEEK
=
datetime
.
datetime
.
now
(
pytz
.
UTC
)
-
datetime
.
timedelta
(
days
=
7
)
ADVERTISED_START
=
"Spring 2016"
def
verify_success
(
self
,
response
):
super
(
TestUserEnrollmentApi
,
self
)
.
verify_success
(
response
)
...
...
@@ -73,18 +93,78 @@ class TestUserEnrollmentApi(MobileAPITestCase, MobileAuthUserTestMixin, MobileCo
num_courses
=
3
courses
=
[]
for
course_
num
in
range
(
num_courses
):
for
course_
index
in
range
(
num_courses
):
courses
.
append
(
CourseFactory
.
create
(
mobile_available
=
True
))
self
.
enroll
(
courses
[
course_
num
]
.
id
)
self
.
enroll
(
courses
[
course_
index
]
.
id
)
# verify courses are returned in the order of enrollment, with most recently enrolled first.
response
=
self
.
api_response
()
for
course_
num
in
range
(
num_courses
):
for
course_
index
in
range
(
num_courses
):
self
.
assertEqual
(
response
.
data
[
course_
num
][
'course'
][
'id'
],
# pylint: disable=no-member
unicode
(
courses
[
num_courses
-
course_
num
-
1
]
.
id
)
response
.
data
[
course_
index
][
'course'
][
'id'
],
# pylint: disable=no-member
unicode
(
courses
[
num_courses
-
course_
index
-
1
]
.
id
)
)
@patch.dict
(
settings
.
FEATURES
,
{
'ENABLE_PREREQUISITE_COURSES'
:
True
,
'MILESTONES_APP'
:
True
,
'DISABLE_START_DATES'
:
False
}
)
def
test_courseware_access
(
self
):
seed_milestone_relationship_types
()
self
.
login
()
course_with_prereq
=
CourseFactory
.
create
(
start
=
self
.
LAST_WEEK
,
mobile_available
=
True
)
prerequisite_course
=
CourseFactory
.
create
()
set_prerequisite_courses
(
course_with_prereq
.
id
,
[
unicode
(
prerequisite_course
.
id
)])
# Create list of courses with various expected courseware_access responses and corresponding expected codes
courses
=
[
course_with_prereq
,
CourseFactory
.
create
(
start
=
self
.
NEXT_WEEK
,
mobile_available
=
True
),
CourseFactory
.
create
(
visible_to_staff_only
=
True
,
mobile_available
=
True
),
CourseFactory
.
create
(
start
=
self
.
LAST_WEEK
,
mobile_available
=
True
,
visible_to_staff_only
=
False
),
]
expected_error_codes
=
[
MilestoneError
()
.
error_code
,
# 'unfulfilled_milestones'
StartDateError
(
self
.
NEXT_WEEK
)
.
error_code
,
# 'course_not_started'
VisibilityError
()
.
error_code
,
# 'not_visible_to_user'
None
,
]
# Enroll in all the courses
for
course
in
courses
:
self
.
enroll
(
course
.
id
)
# Verify courses have the correct response through error code. Last enrolled course is first course in response
response
=
self
.
api_response
()
for
course_index
in
range
(
len
(
courses
)):
result
=
response
.
data
[
course_index
][
'course'
][
'courseware_access'
]
# pylint: disable=no-member
self
.
assertEqual
(
result
[
'error_code'
],
expected_error_codes
[::
-
1
][
course_index
])
if
result
[
'error_code'
]
is
not
None
:
self
.
assertFalse
(
result
[
'has_access'
])
@ddt.data
(
(
NEXT_WEEK
,
ADVERTISED_START
,
ADVERTISED_START
,
"string"
),
(
NEXT_WEEK
,
None
,
defaultfilters
.
date
(
NEXT_WEEK
,
"DATE_FORMAT"
),
"timestamp"
),
(
DEFAULT_START_DATE
,
ADVERTISED_START
,
ADVERTISED_START
,
"string"
),
(
DEFAULT_START_DATE
,
None
,
None
,
"empty"
)
)
@ddt.unpack
@patch.dict
(
'django.conf.settings.FEATURES'
,
{
'DISABLE_START_DATES'
:
False
})
def
test_start_type_and_display
(
self
,
start
,
advertised_start
,
expected_display
,
expected_type
):
"""
Tests that the correct start_type and start_display are returned in the
case the course has not started
"""
self
.
login
()
course
=
CourseFactory
.
create
(
start
=
start
,
advertised_start
=
advertised_start
,
mobile_available
=
True
)
self
.
enroll
(
course
.
id
)
response
=
self
.
api_response
()
self
.
assertEqual
(
response
.
data
[
0
][
'course'
][
'start_type'
],
expected_type
)
# pylint: disable=no-member
self
.
assertEqual
(
response
.
data
[
0
][
'course'
][
'start_display'
],
expected_display
)
# pylint: disable=no-member
def
test_no_certificate
(
self
):
self
.
login_and_enroll
()
...
...
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