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
cd121cf4
Commit
cd121cf4
authored
Apr 19, 2014
by
Chris Dodge
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
initial implementation
parent
eda70ad7
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
121 additions
and
17 deletions
+121
-17
lms/djangoapps/api_manager/courses_urls.py
+1
-1
lms/djangoapps/api_manager/courses_views.py
+22
-5
lms/djangoapps/api_manager/tests/test_courses_views.py
+98
-11
No files found.
lms/djangoapps/api_manager/courses_urls.py
View file @
cd121cf4
...
@@ -12,6 +12,6 @@ urlpatterns = patterns(
...
@@ -12,6 +12,6 @@ urlpatterns = patterns(
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)/modules/*$'
,
'modules_list'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)/modules/*$'
,
'modules_list'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)/groups/(?P<group_id>[0-9]+)$'
,
'courses_groups_detail'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)/groups/(?P<group_id>[0-9]+)$'
,
'courses_groups_detail'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)/groups/*$'
,
'courses_groups_list'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)/groups/*$'
,
'courses_groups_list'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)/
about$'
,
'course_about
'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)/
overview$'
,
'course_overview
'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)$'
,
'courses_detail'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)$'
,
'courses_detail'
),
)
)
lms/djangoapps/api_manager/courses_views.py
View file @
cd121cf4
...
@@ -221,6 +221,7 @@ def courses_detail(request, course_id):
...
@@ -221,6 +221,7 @@ def courses_detail(request, course_id):
return
Response
(
response_data
,
status
=
status_code
)
return
Response
(
response_data
,
status
=
status_code
)
<<<<<<<
HEAD
@api_view
([
'POST'
])
@api_view
([
'POST'
])
@permission_classes
((
ApiKeyHeaderPermission
,))
@permission_classes
((
ApiKeyHeaderPermission
,))
def
courses_groups_list
(
request
,
course_id
):
def
courses_groups_list
(
request
,
course_id
):
...
@@ -302,6 +303,19 @@ def courses_groups_detail(request, course_id, group_id):
...
@@ -302,6 +303,19 @@ def courses_groups_detail(request, course_id, group_id):
def
_parse_about_html
(
html
):
def
_parse_about_html
(
html
):
=======
def
_inner_content
(
tag
):
"""
Helper method
"""
inner_content
=
None
if
tag
is
not
None
:
inner_content
=
u''
.
join
(
etree
.
tostring
(
e
)
for
e
in
tag
)
return
inner_content
def
_parse_overview_html
(
html
):
>>>>>>>
initial
implementation
"""
"""
Helper method to break up the course about HTML into components
Helper method to break up the course about HTML into components
"""
"""
...
@@ -346,11 +360,11 @@ def _parse_about_html(html):
...
@@ -346,11 +360,11 @@ def _parse_about_html(html):
if
bio_html
:
if
bio_html
:
article_data
[
'bio'
]
=
bio_html
article_data
[
'bio'
]
=
bio_html
else
:
else
:
article_data
[
'body'
]
=
etree
.
tostring
(
article
)
article_data
[
'body'
]
=
_inner_content
(
article
)
section_data
[
'articles'
]
.
append
(
article_data
)
section_data
[
'articles'
]
.
append
(
article_data
)
else
:
else
:
section_data
[
'body'
]
=
etree
.
tostring
(
section
)
section_data
[
'body'
]
=
_inner_content
(
section
)
result
.
append
(
section_data
)
result
.
append
(
section_data
)
...
@@ -359,7 +373,7 @@ def _parse_about_html(html):
...
@@ -359,7 +373,7 @@ def _parse_about_html(html):
@api_view
([
'GET'
])
@api_view
([
'GET'
])
@permission_classes
((
ApiKeyHeaderPermission
,))
@permission_classes
((
ApiKeyHeaderPermission
,))
def
course_
about
(
request
,
course_id
):
def
course_
overview
(
request
,
course_id
):
"""
"""
GET retrieves the course overview module, which - in MongoDB - is stored with the following
GET retrieves the course overview module, which - in MongoDB - is stored with the following
naming convention {"_id.org":"i4x", "_id.course":<course_num>, "_id.category":"about", "_id.name":"overview"}
naming convention {"_id.org":"i4x", "_id.course":<course_num>, "_id.category":"about", "_id.name":"overview"}
...
@@ -374,8 +388,11 @@ def course_about(request, course_id):
...
@@ -374,8 +388,11 @@ def course_about(request, course_id):
overview
=
get_course_about_section
(
course_module
,
'overview'
)
overview
=
get_course_about_section
(
course_module
,
'overview'
)
if
request
.
GET
.
get
(
'parsed'
):
if
request
.
GET
.
get
(
'parse'
)
and
request
.
GET
.
get
(
'parse'
)
in
[
'True'
,
'true'
]:
response_data
[
'sections'
]
=
_parse_about_html
(
overview
)
try
:
response_data
[
'sections'
]
=
_parse_overview_html
(
overview
)
except
:
return
Response
({
'err'
:
'could_not_parse'
},
status
=
status
.
HTTP_409_CONFLICT
)
else
:
else
:
response_data
[
'overview_html'
]
=
overview
response_data
[
'overview_html'
]
=
overview
...
...
lms/djangoapps/api_manager/tests/test_courses_views.py
View file @
cd121cf4
...
@@ -4,11 +4,15 @@
...
@@ -4,11 +4,15 @@
Run these tests @ Devstack:
Run these tests @ Devstack:
rake fasttest_lms[common/djangoapps/api_manager/tests/test_group_views.py]
rake fasttest_lms[common/djangoapps/api_manager/tests/test_group_views.py]
"""
"""
<<<<<<<
HEAD
import
simplejson
as
json
import
simplejson
as
json
import
unittest
import
unittest
=======
>>>>>>>
initial
implementation
import
uuid
import
uuid
from
django.conf
import
settings
from
textwrap
import
dedent
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.test
import
TestCase
,
Client
from
django.test
import
TestCase
,
Client
from
django.test.utils
import
override_settings
from
django.test.utils
import
override_settings
...
@@ -19,6 +23,45 @@ from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
...
@@ -19,6 +23,45 @@ from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
TEST_API_KEY
=
str
(
uuid
.
uuid4
())
TEST_API_KEY
=
str
(
uuid
.
uuid4
())
TEST_COURSE_OVERVIEW_CONTENT
=
dedent
(
"""
<section class="about">
<h2>About This Course</h2>
<p>Include your long course description here. The long course description should contain 150-400 words.</p>
<p>This is paragraph 2 of the long course description. Add more paragraphs as needed. Make sure to enclose them in paragraph tags.</p>
</section>
<section class="prerequisites">
<h2>Prerequisites</h2>
<p>Add information about course prerequisites here.</p>
</section>
<section class="course-staff">
<h2>Course Staff</h2>
<article class="teacher">
<div class="teacher-image">
<img src="/images/pl-faculty.png" align="left" style="margin:0 20 px 0" alt="Course Staff Image #1">
</div>
<h3>Staff Member #1</h3>
<p>Biography of instructor/staff member #1</p>
</article>
<article class="teacher">
<div class="teacher-image">
<img src="/images/pl-faculty.png" align="left" style="margin:0 20 px 0" alt="Course Staff Image #2">
</div>
<h3>Staff Member #2</h3>
<p>Biography of instructor/staff member #2</p>
</article>
</section>
<section class="faq">
<p>Some text here</p>
</section>
"""
)
class
SecureClient
(
Client
):
class
SecureClient
(
Client
):
""" Django test client using a "secure" connection. """
""" Django test client using a "secure" connection. """
...
@@ -34,6 +77,7 @@ class CoursesApiTests(TestCase):
...
@@ -34,6 +77,7 @@ class CoursesApiTests(TestCase):
""" Test suite for Courses API views """
""" Test suite for Courses API views """
def
setUp
(
self
):
def
setUp
(
self
):
self
.
maxDiff
=
3000
self
.
test_server_prefix
=
'https://testserver'
self
.
test_server_prefix
=
'https://testserver'
self
.
base_courses_uri
=
'/api/courses'
self
.
base_courses_uri
=
'/api/courses'
self
.
base_groups_uri
=
'/api/groups'
self
.
base_groups_uri
=
'/api/groups'
...
@@ -63,6 +107,13 @@ class CoursesApiTests(TestCase):
...
@@ -63,6 +107,13 @@ class CoursesApiTests(TestCase):
display_name
=
"Video_Resources"
display_name
=
"Video_Resources"
)
)
self
.
overview
=
ItemFactory
.
create
(
category
=
"about"
,
parent_location
=
self
.
course
.
location
,
data
=
TEST_COURSE_OVERVIEW_CONTENT
,
display_name
=
"overview"
)
self
.
test_course_id
=
self
.
course
.
id
self
.
test_course_id
=
self
.
course
.
id
self
.
test_course_name
=
self
.
course
.
display_name
self
.
test_course_name
=
self
.
course
.
display_name
self
.
test_course_number
=
self
.
course
.
number
self
.
test_course_number
=
self
.
course
.
number
...
@@ -86,6 +137,7 @@ class CoursesApiTests(TestCase):
...
@@ -86,6 +137,7 @@ class CoursesApiTests(TestCase):
response
=
self
.
client
.
get
(
uri
,
headers
=
headers
)
response
=
self
.
client
.
get
(
uri
,
headers
=
headers
)
return
response
return
response
<<<<<<<
HEAD
def
do_post
(
self
,
uri
,
data
):
def
do_post
(
self
,
uri
,
data
):
"""Submit an HTTP POST request"""
"""Submit an HTTP POST request"""
headers
=
{
headers
=
{
...
@@ -109,6 +161,8 @@ class CoursesApiTests(TestCase):
...
@@ -109,6 +161,8 @@ class CoursesApiTests(TestCase):
return
response
return
response
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
=======
>>>>>>>
initial
implementation
def
test_course_list_get
(
self
):
def
test_course_list_get
(
self
):
test_uri
=
self
.
base_courses_uri
test_uri
=
self
.
base_courses_uri
response
=
self
.
do_get
(
test_uri
)
response
=
self
.
do_get
(
test_uri
)
...
@@ -125,7 +179,6 @@ class CoursesApiTests(TestCase):
...
@@ -125,7 +179,6 @@ class CoursesApiTests(TestCase):
matched_course
=
True
matched_course
=
True
self
.
assertTrue
(
matched_course
)
self
.
assertTrue
(
matched_course
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_detail_get
(
self
):
def
test_course_detail_get
(
self
):
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
response
=
self
.
do_get
(
test_uri
)
response
=
self
.
do_get
(
test_uri
)
...
@@ -139,13 +192,11 @@ class CoursesApiTests(TestCase):
...
@@ -139,13 +192,11 @@ class CoursesApiTests(TestCase):
self
.
assertEqual
(
response
.
data
[
'uri'
],
confirm_uri
)
self
.
assertEqual
(
response
.
data
[
'uri'
],
confirm_uri
)
self
.
assertGreater
(
len
(
response
.
data
[
'modules'
]),
0
)
self
.
assertGreater
(
len
(
response
.
data
[
'modules'
]),
0
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_detail_get_notfound
(
self
):
def
test_course_detail_get_notfound
(
self
):
test_uri
=
self
.
base_courses_uri
+
'/'
+
'p29038cvp9hjwefion'
test_uri
=
self
.
base_courses_uri
+
'/'
+
'p29038cvp9hjwefion'
response
=
self
.
do_get
(
test_uri
)
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
404
)
self
.
assertEqual
(
response
.
status_code
,
404
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_chapter_list_get
(
self
):
def
test_chapter_list_get
(
self
):
test_uri
=
self
.
base_chapters_uri
test_uri
=
self
.
base_chapters_uri
response
=
self
.
do_get
(
test_uri
)
response
=
self
.
do_get
(
test_uri
)
...
@@ -161,7 +212,6 @@ class CoursesApiTests(TestCase):
...
@@ -161,7 +212,6 @@ class CoursesApiTests(TestCase):
matched_chapter
=
True
matched_chapter
=
True
self
.
assertTrue
(
matched_chapter
)
self
.
assertTrue
(
matched_chapter
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_chapter_detail_get
(
self
):
def
test_chapter_detail_get
(
self
):
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_chapter_id
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_chapter_id
response
=
self
.
do_get
(
test_uri
)
response
=
self
.
do_get
(
test_uri
)
...
@@ -172,7 +222,6 @@ class CoursesApiTests(TestCase):
...
@@ -172,7 +222,6 @@ class CoursesApiTests(TestCase):
self
.
assertEqual
(
response
.
data
[
'uri'
],
confirm_uri
)
self
.
assertEqual
(
response
.
data
[
'uri'
],
confirm_uri
)
self
.
assertGreater
(
len
(
response
.
data
[
'modules'
]),
0
)
self
.
assertGreater
(
len
(
response
.
data
[
'modules'
]),
0
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_modules_list_get
(
self
):
def
test_modules_list_get
(
self
):
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_module_id
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_module_id
response
=
self
.
do_get
(
test_uri
)
response
=
self
.
do_get
(
test_uri
)
...
@@ -188,7 +237,6 @@ class CoursesApiTests(TestCase):
...
@@ -188,7 +237,6 @@ class CoursesApiTests(TestCase):
matched_submodule
=
True
matched_submodule
=
True
self
.
assertTrue
(
matched_submodule
)
self
.
assertTrue
(
matched_submodule
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_modules_detail_get
(
self
):
def
test_modules_detail_get
(
self
):
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_module_id
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_module_id
response
=
self
.
do_get
(
test_uri
)
response
=
self
.
do_get
(
test_uri
)
...
@@ -199,13 +247,11 @@ class CoursesApiTests(TestCase):
...
@@ -199,13 +247,11 @@ class CoursesApiTests(TestCase):
self
.
assertEqual
(
response
.
data
[
'uri'
],
confirm_uri
)
self
.
assertEqual
(
response
.
data
[
'uri'
],
confirm_uri
)
self
.
assertGreater
(
len
(
response
.
data
[
'modules'
]),
0
)
self
.
assertGreater
(
len
(
response
.
data
[
'modules'
]),
0
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_modules_detail_get_notfound
(
self
):
def
test_modules_detail_get_notfound
(
self
):
test_uri
=
self
.
base_modules_uri
+
'/'
+
'2p38fp2hjfp9283'
test_uri
=
self
.
base_modules_uri
+
'/'
+
'2p38fp2hjfp9283'
response
=
self
.
do_get
(
test_uri
)
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
404
)
self
.
assertEqual
(
response
.
status_code
,
404
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_modules_list_get_filtered_submodules_for_module
(
self
):
def
test_modules_list_get_filtered_submodules_for_module
(
self
):
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_module_id
+
'/submodules?type=video'
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_module_id
+
'/submodules?type=video'
response
=
self
.
do_get
(
test_uri
)
response
=
self
.
do_get
(
test_uri
)
...
@@ -219,13 +265,11 @@ class CoursesApiTests(TestCase):
...
@@ -219,13 +265,11 @@ class CoursesApiTests(TestCase):
matched_submodule
=
True
matched_submodule
=
True
self
.
assertTrue
(
matched_submodule
)
self
.
assertTrue
(
matched_submodule
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_modules_list_get_notfound
(
self
):
def
test_modules_list_get_notfound
(
self
):
test_uri
=
self
.
base_modules_uri
+
'/2p38fp2hjfp9283/submodules?type=video'
test_uri
=
self
.
base_modules_uri
+
'/2p38fp2hjfp9283/submodules?type=video'
response
=
self
.
do_get
(
test_uri
)
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
404
)
self
.
assertEqual
(
response
.
status_code
,
404
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_groups_list_post
(
self
):
def
test_course_groups_list_post
(
self
):
data
=
{
'name'
:
self
.
test_group_name
}
data
=
{
'name'
:
self
.
test_group_name
}
...
@@ -311,3 +355,46 @@ class CoursesApiTests(TestCase):
...
@@ -311,3 +355,46 @@ class CoursesApiTests(TestCase):
test_uri
=
'{}/{}/groups/{}'
.
format
(
self
.
base_courses_uri
,
self
.
test_course_id
,
group_id
)
test_uri
=
'{}/{}/groups/{}'
.
format
(
self
.
base_courses_uri
,
self
.
test_course_id
,
group_id
)
response
=
self
.
do_get
(
test_uri
)
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
404
)
self
.
assertEqual
(
response
.
status_code
,
404
)
def
test_get_course_overview_unparsed
(
self
):
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
+
'/overview'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertGreater
(
len
(
response
.
data
),
0
)
self
.
assertEqual
(
response
.
data
[
'overview_html'
],
self
.
overview
.
data
)
def
_find_item_by_class
(
self
,
items
,
class_name
):
for
item
in
items
:
if
item
[
'class'
]
==
class_name
:
return
item
return
None
def
test_get_course_overview_parsed
(
self
):
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
+
'/overview?parse=true'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertGreater
(
len
(
response
.
data
),
0
)
sections
=
response
.
data
[
'sections'
]
self
.
assertEqual
(
len
(
sections
),
4
)
self
.
assertIsNotNone
(
self
.
_find_item_by_class
(
sections
,
'about'
))
self
.
assertIsNotNone
(
self
.
_find_item_by_class
(
sections
,
'prerequisites'
))
self
.
assertIsNotNone
(
self
.
_find_item_by_class
(
sections
,
'course-staff'
))
self
.
assertIsNotNone
(
self
.
_find_item_by_class
(
sections
,
'faq'
))
course_staff
=
self
.
_find_item_by_class
(
sections
,
'course-staff'
)
teachers
=
course_staff
[
'articles'
]
self
.
assertEqual
(
len
(
teachers
),
2
)
self
.
assertEqual
(
teachers
[
0
][
'name'
],
"Staff Member #1"
)
self
.
assertEqual
(
teachers
[
0
][
'image_src'
],
"/images/pl-faculty.png"
)
self
.
assertIn
(
"<p>Biography of instructor/staff member #1</p>"
,
teachers
[
0
][
'bio'
])
self
.
assertEqual
(
teachers
[
1
][
'name'
],
"Staff Member #2"
)
self
.
assertEqual
(
teachers
[
1
][
'image_src'
],
"/images/pl-faculty.png"
)
self
.
assertIn
(
"<p>Biography of instructor/staff member #2</p>"
,
teachers
[
1
][
'bio'
])
about
=
self
.
_find_item_by_class
(
sections
,
'about'
)
self
.
assertGreater
(
len
(
about
[
'body'
]),
0
)
prerequisites
=
self
.
_find_item_by_class
(
sections
,
'prerequisites'
)
self
.
assertGreater
(
len
(
prerequisites
[
'body'
]),
0
)
faq
=
self
.
_find_item_by_class
(
sections
,
'faq'
)
self
.
assertGreater
(
len
(
faq
[
'body'
]),
0
)
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