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
f59612ce
Commit
f59612ce
authored
Apr 20, 2014
by
chrisndodge
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #11 from edx-solutions/cdodge/sprint-H-api-work
Cdodge/sprint h api work
parents
7c581d06
49d491d0
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
510 additions
and
43 deletions
+510
-43
lms/djangoapps/api_manager/courses_urls.py
+10
-6
lms/djangoapps/api_manager/courses_views.py
+254
-0
lms/djangoapps/api_manager/groups_views.py
+2
-6
lms/djangoapps/api_manager/tests/content.py
+78
-0
lms/djangoapps/api_manager/tests/test_courses_views.py
+164
-25
lms/djangoapps/api_manager/tests/test_groups_views.py
+0
-1
lms/djangoapps/api_manager/tests/test_users_views.py
+0
-3
lms/djangoapps/courseware/views.py
+2
-2
No files found.
lms/djangoapps/api_manager/courses_urls.py
View file @
f59612ce
...
...
@@ -7,10 +7,14 @@ from django.conf.urls import patterns, url
urlpatterns
=
patterns
(
'api_manager.courses_views'
,
url
(
r'/*$^'
,
'courses_list'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)/modules/(?P<module_id>[a-zA-Z0-9/_:]+)/submodules/*$'
,
'modules_list'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)/modules/(?P<module_id>[a-zA-Z0-9/_:]+)$'
,
'modules_detail'
),
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/*$'
,
'courses_groups_list'
),
url
(
r'^(?P<course_id>[a-zA-Z0-9/_:]+)$'
,
'courses_detail'
),
url
(
r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/modules/(?P<module_id>[a-zA-Z0-9/_:]+)/submodules/*$'
,
'modules_list'
),
url
(
r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/modules/(?P<module_id>[a-zA-Z0-9/_:]+)$'
,
'modules_detail'
),
url
(
r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/modules/*$'
,
'modules_list'
),
url
(
r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/groups/(?P<group_id>[0-9]+)$'
,
'courses_groups_detail'
),
url
(
r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/groups/*$'
,
'courses_groups_list'
),
url
(
r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/overview$'
,
'course_overview'
),
url
(
r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/updates$'
,
'course_updates'
),
url
(
r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/static_tabs/(?P<tab_id>[a-zA-Z0-9/_:]+)$'
,
'static_tab_detail'
),
url
(
r'^(?P<course_id>[^/]+/[^/]+/[^/]+)/static_tabs$'
,
'static_tabs_list'
),
url
(
r'^(?P<course_id>[^/]+/[^/]+/[^/]+)$'
,
'courses_detail'
),
)
lms/djangoapps/api_manager/courses_views.py
View file @
f59612ce
...
...
@@ -2,6 +2,10 @@
from
django.contrib.auth.models
import
Group
from
django.core.exceptions
import
ObjectDoesNotExist
from
lxml
import
etree
from
StringIO
import
StringIO
from
collections
import
OrderedDict
import
logging
from
rest_framework
import
status
from
rest_framework.decorators
import
api_view
,
permission_classes
...
...
@@ -12,6 +16,10 @@ from api_manager.models import CourseGroupRelationship
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore
import
Location
,
InvalidLocationError
from
courseware.courses
import
get_course_about_section
,
get_course_info_section
from
courseware.views
import
get_static_tab_contents
log
=
logging
.
getLogger
(
__name__
)
def
_generate_base_uri
(
request
):
"""
...
...
@@ -295,3 +303,249 @@ def courses_groups_detail(request, course_id, group_id):
except
ObjectDoesNotExist
:
pass
return
Response
({},
status
=
status
.
HTTP_204_NO_CONTENT
)
def
_inner_content
(
tag
):
"""
Helper method
"""
inner_content
=
None
if
tag
is
not
None
:
inner_content
=
tag
.
text
if
tag
.
text
else
u''
inner_content
+=
u''
.
join
(
etree
.
tostring
(
e
)
for
e
in
tag
)
inner_content
+=
tag
.
tail
if
tag
.
tail
else
u''
return
inner_content
def
_parse_overview_html
(
html
):
"""
Helper method to break up the course about HTML into components
"""
result
=
{}
parser
=
etree
.
HTMLParser
()
tree
=
etree
.
parse
(
StringIO
(
html
),
parser
)
sections
=
tree
.
findall
(
'/body/section'
)
result
=
[]
for
section
in
sections
:
section_class
=
section
.
get
(
'class'
)
if
section_class
:
section_data
=
OrderedDict
()
section_data
[
'class'
]
=
section_class
articles
=
section
.
findall
(
'article'
)
if
articles
:
section_data
[
'articles'
]
=
[]
for
article
in
articles
:
article_class
=
article
.
get
(
'class'
)
if
article_class
:
article_data
=
OrderedDict
()
article_data
[
'class'
]
=
article_class
if
article_class
==
"teacher"
:
name_element
=
article
.
find
(
'h3'
)
if
name_element
is
not
None
:
article_data
[
'name'
]
=
name_element
.
text
image_element
=
article
.
find
(
"./div[@class='teacher-image']/img"
)
if
image_element
is
not
None
:
article_data
[
'image_src'
]
=
image_element
.
get
(
'src'
)
bios
=
article
.
findall
(
'p'
)
bio_html
=
''
for
bio
in
bios
:
bio_html
+=
etree
.
tostring
(
bio
)
if
bio_html
:
article_data
[
'bio'
]
=
bio_html
else
:
article_data
[
'body'
]
=
_inner_content
(
article
)
section_data
[
'articles'
]
.
append
(
article_data
)
else
:
section_data
[
'body'
]
=
_inner_content
(
section
)
result
.
append
(
section_data
)
return
result
@api_view
([
'GET'
])
@permission_classes
((
ApiKeyHeaderPermission
,))
def
course_overview
(
request
,
course_id
):
"""
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"}
"""
store
=
modulestore
()
response_data
=
OrderedDict
()
try
:
course_module
=
store
.
get_course
(
course_id
)
if
not
course_module
:
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
content
=
get_course_about_section
(
course_module
,
'overview'
)
if
request
.
GET
.
get
(
'parse'
)
and
request
.
GET
.
get
(
'parse'
)
in
[
'True'
,
'true'
]:
try
:
response_data
[
'sections'
]
=
_parse_overview_html
(
content
)
except
:
log
.
exception
(
u"Error prasing course overview. Content = {0}"
.
format
(
content
))
return
Response
({
'err'
:
'could_not_parse'
},
status
=
status
.
HTTP_409_CONFLICT
)
else
:
response_data
[
'overview_html'
]
=
content
except
InvalidLocationError
:
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
return
Response
(
response_data
)
def
_parse_updates_html
(
html
):
"""
Helper method to break up the course updates HTML into components
"""
result
=
{}
parser
=
etree
.
HTMLParser
()
tree
=
etree
.
parse
(
StringIO
(
html
),
parser
)
# get all of the individual postings
postings
=
tree
.
findall
(
'/body/ol/li'
)
result
=
[]
for
posting
in
postings
:
posting_data
=
{}
posting_date_element
=
posting
.
find
(
'h2'
)
if
posting_date_element
is
not
None
:
posting_data
[
'date'
]
=
posting_date_element
.
text
content
=
u''
for
el
in
posting
:
# note, we can't delete or skip over the date element in
# the HTML tree because there might be some tailing content
if
el
!=
posting_date_element
:
content
+=
etree
.
tostring
(
el
)
else
:
content
+=
el
.
tail
if
el
.
tail
else
u''
posting_data
[
'content'
]
=
content
.
strip
()
result
.
append
(
posting_data
)
return
result
@api_view
([
'GET'
])
@permission_classes
((
ApiKeyHeaderPermission
,))
def
course_updates
(
request
,
course_id
):
"""
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":"course_info", "_id.name":"updates"}
"""
store
=
modulestore
()
response_data
=
OrderedDict
()
try
:
course_module
=
store
.
get_course
(
course_id
)
if
not
course_module
:
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
content
=
get_course_info_section
(
request
,
course_module
,
'updates'
)
if
not
content
:
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
if
request
.
GET
.
get
(
'parse'
)
and
request
.
GET
.
get
(
'parse'
)
in
[
'True'
,
'true'
]:
try
:
response_data
[
'postings'
]
=
_parse_updates_html
(
content
)
except
:
log
.
exception
(
u"Error prasing course updates. Content = {0}"
.
format
(
content
))
return
Response
({
'err'
:
'could_not_parse'
},
status
=
status
.
HTTP_409_CONFLICT
)
else
:
response_data
[
'content'
]
=
content
except
InvalidLocationError
:
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
return
Response
(
response_data
)
@api_view
([
'GET'
])
@permission_classes
((
ApiKeyHeaderPermission
,))
def
static_tabs_list
(
request
,
course_id
):
"""
GET returns an array of Static Tabs inside of a course
"""
store
=
modulestore
()
response_data
=
OrderedDict
()
try
:
course_module
=
store
.
get_course
(
course_id
)
if
not
course_module
:
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
tabs
=
[]
for
tab
in
course_module
.
tabs
:
if
tab
.
type
==
'static_tab'
:
tab_data
=
OrderedDict
()
tab_data
[
'id'
]
=
tab
.
url_slug
tab_data
[
'name'
]
=
tab
.
name
if
request
.
GET
.
get
(
'detail'
)
and
request
.
GET
.
get
(
'detail'
)
in
[
'True'
,
'true'
]:
tab_data
[
'content'
]
=
get_static_tab_contents
(
request
,
course_module
,
tab
,
wrap_xmodule_display
=
False
)
tabs
.
append
(
tab_data
)
response_data
[
'tabs'
]
=
tabs
except
InvalidLocationError
:
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
return
Response
(
response_data
)
@api_view
([
'GET'
])
@permission_classes
((
ApiKeyHeaderPermission
,))
def
static_tab_detail
(
request
,
course_id
,
tab_id
):
"""
GET returns an array of Static Tabs inside of a course
"""
store
=
modulestore
()
response_data
=
OrderedDict
()
try
:
course_module
=
store
.
get_course
(
course_id
)
if
not
course_module
:
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
for
tab
in
course_module
.
tabs
:
if
tab
.
type
==
'static_tab'
and
tab
.
url_slug
==
tab_id
:
response_data
[
'id'
]
=
tab
.
url_slug
response_data
[
'name'
]
=
tab
.
name
response_data
[
'content'
]
=
get_static_tab_contents
(
request
,
course_module
,
tab
,
wrap_xmodule_display
=
False
)
except
InvalidLocationError
:
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
if
not
response_data
:
return
Response
({},
status
=
status
.
HTTP_404_NOT_FOUND
)
return
Response
(
response_data
)
lms/djangoapps/api_manager/groups_views.py
View file @
f59612ce
...
...
@@ -285,7 +285,6 @@ def group_courses_list(request, group_id):
base_uri
=
_generate_base_uri
(
request
)
response_data
[
'uri'
]
=
'{}/{}'
.
format
(
base_uri
,
course_id
)
store
=
modulestore
()
print
"GROUP COURSES LIST"
try
:
existing_group
=
Group
.
objects
.
get
(
id
=
group_id
)
except
ObjectDoesNotExist
:
...
...
@@ -294,17 +293,15 @@ def group_courses_list(request, group_id):
existing_course
=
store
.
get_course
(
course_id
)
except
ValueError
:
existing_course
=
None
print
existing_group
print
existing_course
if
existing_group
and
existing_course
:
try
:
existing_relationship
=
CourseGroupRelationship
.
objects
.
get
(
course_id
=
course_id
,
group
=
existing_group
)
except
ObjectDoesNotExist
:
existing_relationship
=
None
print
existing_relationship
if
existing_relationship
is
None
:
new_relationship
=
CourseGroupRelationship
.
objects
.
create
(
course_id
=
course_id
,
group
=
existing_group
)
print
new_relationship
.
__dict__
response_data
[
'group_id'
]
=
str
(
new_relationship
.
group_id
)
response_data
[
'course_id'
]
=
str
(
new_relationship
.
course_id
)
response_status
=
status
.
HTTP_201_CREATED
...
...
@@ -312,7 +309,6 @@ def group_courses_list(request, group_id):
response_data
[
'message'
]
=
"Relationship already exists."
response_status
=
status
.
HTTP_409_CONFLICT
else
:
print
request
.
DATA
response_status
=
status
.
HTTP_404_NOT_FOUND
return
Response
(
response_data
,
status
=
response_status
)
...
...
lms/djangoapps/api_manager/tests/content.py
0 → 100644
View file @
f59612ce
"""
Some test content strings. Best to keep them out of the test files because they take up a lot of
text space
"""
from
textwrap
import
dedent
TEST_COURSE_UPDATES_CONTENT
=
dedent
(
"""
<ol>
<li>
<h2>April 18, 2014</h2>
This does not have a paragraph tag around it
</li>
<li>
<h2>April 17, 2014</h2>
Some text before paragraph tag<p>This is inside paragraph tag</p>Some text after tag
</li>
<li>
<h2>April 16, 2014</h2>
Some text before paragraph tag<p>This is inside paragraph tag</p>Some text after tag<p>one more</p>
</li>
<li>
<h2>April 15, 2014</h2>
<p>A perfectly</p><p>formatted piece</p><p>of HTML</p>
</li>
</ol>
"""
)
TEST_STATIC_TAB1_CONTENT
=
dedent
(
"""
<div>This is static tab1</div>
"""
)
TEST_STATIC_TAB2_CONTENT
=
dedent
(
"""
<div>This is static tab2</div>
"""
)
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>
"""
)
lms/djangoapps/api_manager/tests/test_courses_views.py
View file @
f59612ce
...
...
@@ -8,7 +8,6 @@ import simplejson as json
import
unittest
import
uuid
from
django.conf
import
settings
from
django.core.cache
import
cache
from
django.test
import
TestCase
,
Client
from
django.test.utils
import
override_settings
...
...
@@ -16,6 +15,8 @@ from django.test.utils import override_settings
from
courseware.tests.modulestore_config
import
TEST_DATA_MIXED_MODULESTORE
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
ItemFactory
from
.content
import
TEST_COURSE_OVERVIEW_CONTENT
,
TEST_COURSE_UPDATES_CONTENT
from
.content
import
TEST_STATIC_TAB1_CONTENT
,
TEST_STATIC_TAB2_CONTENT
TEST_API_KEY
=
str
(
uuid
.
uuid4
())
...
...
@@ -34,6 +35,7 @@ class CoursesApiTests(TestCase):
""" Test suite for Courses API views """
def
setUp
(
self
):
self
.
maxDiff
=
3000
self
.
test_server_prefix
=
'https://testserver'
self
.
base_courses_uri
=
'/api/courses'
self
.
base_groups_uri
=
'/api/groups'
...
...
@@ -63,7 +65,36 @@ class CoursesApiTests(TestCase):
display_name
=
"Video_Resources"
)
self
.
overview
=
ItemFactory
.
create
(
category
=
"about"
,
parent_location
=
self
.
course
.
location
,
data
=
TEST_COURSE_OVERVIEW_CONTENT
,
display_name
=
"overview"
)
self
.
updates
=
ItemFactory
.
create
(
category
=
"course_info"
,
parent_location
=
self
.
course
.
location
,
data
=
TEST_COURSE_UPDATES_CONTENT
,
display_name
=
"updates"
)
self
.
static_tab1
=
ItemFactory
.
create
(
category
=
"static_tab"
,
parent_location
=
self
.
course
.
location
,
data
=
TEST_STATIC_TAB1_CONTENT
,
display_name
=
"syllabus"
)
self
.
static_tab2
=
ItemFactory
.
create
(
category
=
"static_tab"
,
parent_location
=
self
.
course
.
location
,
data
=
TEST_STATIC_TAB2_CONTENT
,
display_name
=
"readings"
)
self
.
test_course_id
=
self
.
course
.
id
self
.
test_bogus_course_id
=
'foo/bar/baz'
self
.
test_course_name
=
self
.
course
.
display_name
self
.
test_course_number
=
self
.
course
.
number
self
.
test_course_org
=
self
.
course
.
org
...
...
@@ -82,7 +113,6 @@ class CoursesApiTests(TestCase):
'Content-Type'
:
'application/json'
,
'X-Edx-Api-Key'
:
str
(
TEST_API_KEY
),
}
print
"GET: "
+
uri
response
=
self
.
client
.
get
(
uri
,
headers
=
headers
)
return
response
...
...
@@ -92,9 +122,6 @@ class CoursesApiTests(TestCase):
'X-Edx-Api-Key'
:
str
(
TEST_API_KEY
),
}
json_data
=
json
.
dumps
(
data
)
print
"POST: "
+
uri
print
json_data
print
""
response
=
self
.
client
.
post
(
uri
,
headers
=
headers
,
content_type
=
'application/json'
,
data
=
json_data
)
return
response
...
...
@@ -108,7 +135,6 @@ class CoursesApiTests(TestCase):
response
=
self
.
client
.
delete
(
uri
,
headers
=
headers
)
return
response
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_list_get
(
self
):
test_uri
=
self
.
base_courses_uri
response
=
self
.
do_get
(
test_uri
)
...
...
@@ -125,7 +151,6 @@ class CoursesApiTests(TestCase):
matched_course
=
True
self
.
assertTrue
(
matched_course
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_detail_get
(
self
):
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
response
=
self
.
do_get
(
test_uri
)
...
...
@@ -139,13 +164,11 @@ class CoursesApiTests(TestCase):
self
.
assertEqual
(
response
.
data
[
'uri'
],
confirm_uri
)
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
):
test_uri
=
self
.
base_courses_uri
+
'/'
+
'p29038cvp9hjwefion'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
404
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_chapter_list_get
(
self
):
test_uri
=
self
.
base_chapters_uri
response
=
self
.
do_get
(
test_uri
)
...
...
@@ -161,7 +184,6 @@ class CoursesApiTests(TestCase):
matched_chapter
=
True
self
.
assertTrue
(
matched_chapter
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_chapter_detail_get
(
self
):
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_chapter_id
response
=
self
.
do_get
(
test_uri
)
...
...
@@ -172,7 +194,6 @@ class CoursesApiTests(TestCase):
self
.
assertEqual
(
response
.
data
[
'uri'
],
confirm_uri
)
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
):
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_module_id
response
=
self
.
do_get
(
test_uri
)
...
...
@@ -188,7 +209,6 @@ class CoursesApiTests(TestCase):
matched_submodule
=
True
self
.
assertTrue
(
matched_submodule
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_modules_detail_get
(
self
):
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_module_id
response
=
self
.
do_get
(
test_uri
)
...
...
@@ -199,13 +219,11 @@ class CoursesApiTests(TestCase):
self
.
assertEqual
(
response
.
data
[
'uri'
],
confirm_uri
)
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
):
test_uri
=
self
.
base_modules_uri
+
'/'
+
'2p38fp2hjfp9283'
response
=
self
.
do_get
(
test_uri
)
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
):
test_uri
=
self
.
base_modules_uri
+
'/'
+
self
.
test_module_id
+
'/submodules?type=video'
response
=
self
.
do_get
(
test_uri
)
...
...
@@ -219,14 +237,11 @@ class CoursesApiTests(TestCase):
matched_submodule
=
True
self
.
assertTrue
(
matched_submodule
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_modules_list_get_notfound
(
self
):
test_uri
=
self
.
base_modules_uri
+
'/2p38fp2hjfp9283/submodules?type=video'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
404
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_groups_list_post
(
self
):
data
=
{
'name'
:
self
.
test_group_name
}
response
=
self
.
do_post
(
self
.
base_groups_uri
,
data
)
...
...
@@ -242,7 +257,6 @@ class CoursesApiTests(TestCase):
self
.
assertEqual
(
response
.
data
[
'course_id'
],
str
(
self
.
test_course_id
))
self
.
assertEqual
(
response
.
data
[
'group_id'
],
str
(
group_id
))
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_groups_list_post_duplicate
(
self
):
data
=
{
'name'
:
self
.
test_group_name
}
response
=
self
.
do_post
(
self
.
base_groups_uri
,
data
)
...
...
@@ -254,14 +268,12 @@ class CoursesApiTests(TestCase):
response
=
self
.
do_post
(
test_uri
,
data
)
self
.
assertEqual
(
response
.
status_code
,
409
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_group_courses_list_post_invalid_resources
(
self
):
test_uri
=
self
.
base_courses_uri
+
'/1239878976/groups'
data
=
{
'group_id'
:
"98723896"
}
response
=
self
.
do_post
(
test_uri
,
data
)
self
.
assertEqual
(
response
.
status_code
,
404
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_groups_detail_get
(
self
):
data
=
{
'name'
:
self
.
test_group_name
}
response
=
self
.
do_post
(
self
.
base_groups_uri
,
data
)
...
...
@@ -276,7 +288,6 @@ class CoursesApiTests(TestCase):
self
.
assertEqual
(
response
.
data
[
'course_id'
],
self
.
test_course_id
)
self
.
assertEqual
(
response
.
data
[
'group_id'
],
str
(
group_id
))
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_groups_detail_delete
(
self
):
data
=
{
'name'
:
self
.
test_group_name
}
response
=
self
.
do_post
(
self
.
base_groups_uri
,
data
)
...
...
@@ -291,19 +302,16 @@ class CoursesApiTests(TestCase):
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
404
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_groups_detail_delete_invalid_course
(
self
):
test_uri
=
'{}/
123987102/groups/123124'
.
format
(
self
.
base_courses_uri
)
test_uri
=
'{}/
{}/groups/123124'
.
format
(
self
.
base_courses_uri
,
self
.
test_bogus_course_id
)
response
=
self
.
do_delete
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
204
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_groups_detail_delete_invalid_group
(
self
):
test_uri
=
'{}/{}/groups/123124'
.
format
(
self
.
base_courses_uri
,
self
.
test_course_id
)
response
=
self
.
do_delete
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
204
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
def
test_course_groups_detail_get_undefined
(
self
):
data
=
{
'name'
:
self
.
test_group_name
}
response
=
self
.
do_post
(
self
.
base_groups_uri
,
data
)
...
...
@@ -311,3 +319,134 @@ class CoursesApiTests(TestCase):
test_uri
=
'{}/{}/groups/{}'
.
format
(
self
.
base_courses_uri
,
self
.
test_course_id
,
group_id
)
response
=
self
.
do_get
(
test_uri
)
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
)
def
test_get_course_updates
(
self
):
# first try raw without any parsing
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
+
'/updates'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertGreater
(
len
(
response
.
data
),
0
)
self
.
assertEqual
(
response
.
data
[
'content'
],
self
.
updates
.
data
)
# then try parsed
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
+
'/updates?parse=True'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertGreater
(
len
(
response
.
data
),
0
)
postings
=
response
.
data
[
'postings'
]
self
.
assertEqual
(
len
(
postings
),
4
)
self
.
assertEqual
(
postings
[
0
][
'date'
],
'April 18, 2014'
)
self
.
assertEqual
(
postings
[
0
][
'content'
],
'This does not have a paragraph tag around it'
)
self
.
assertEqual
(
postings
[
1
][
'date'
],
'April 17, 2014'
)
self
.
assertEqual
(
postings
[
1
][
'content'
],
'Some text before paragraph tag<p>This is inside paragraph tag</p>Some text after tag'
)
self
.
assertEqual
(
postings
[
2
][
'date'
],
'April 16, 2014'
)
self
.
assertEqual
(
postings
[
2
][
'content'
],
'Some text before paragraph tag<p>This is inside paragraph tag</p>Some text after tag<p>one more</p>'
)
self
.
assertEqual
(
postings
[
3
][
'date'
],
'April 15, 2014'
)
self
.
assertEqual
(
postings
[
3
][
'content'
],
'<p>A perfectly</p><p>formatted piece</p><p>of HTML</p>'
)
def
test_static_tab_list
(
self
):
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
+
'/static_tabs'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertGreater
(
len
(
response
.
data
),
0
)
tabs
=
response
.
data
[
'tabs'
]
self
.
assertEqual
(
len
(
tabs
),
2
)
self
.
assertEqual
(
tabs
[
0
][
'name'
],
u'syllabus'
)
self
.
assertEqual
(
tabs
[
0
][
'id'
],
u'syllabus'
)
self
.
assertEqual
(
tabs
[
1
][
'name'
],
u'readings'
)
self
.
assertEqual
(
tabs
[
1
][
'id'
],
u'readings'
)
# now try when we get the details on the tabs
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
+
'/static_tabs?detail=true'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertGreater
(
len
(
response
.
data
),
0
)
tabs
=
response
.
data
[
'tabs'
]
self
.
assertEqual
(
tabs
[
0
][
'name'
],
u'syllabus'
)
self
.
assertEqual
(
tabs
[
0
][
'id'
],
u'syllabus'
)
self
.
assertEqual
(
tabs
[
0
][
'content'
],
self
.
static_tab1
.
data
)
self
.
assertEqual
(
tabs
[
1
][
'name'
],
u'readings'
)
self
.
assertEqual
(
tabs
[
1
][
'id'
],
u'readings'
)
self
.
assertEqual
(
tabs
[
1
][
'content'
],
self
.
static_tab2
.
data
)
#try a bogus course_id to test failure case
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_bogus_course_id
+
'/static_tabs'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
404
)
def
test_static_tab_detail
(
self
):
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
+
'/static_tabs/syllabus'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertGreater
(
len
(
response
.
data
),
0
)
tab
=
response
.
data
self
.
assertEqual
(
tab
[
'name'
],
u'syllabus'
)
self
.
assertEqual
(
tab
[
'id'
],
u'syllabus'
)
self
.
assertEqual
(
tab
[
'content'
],
self
.
static_tab1
.
data
)
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
+
'/static_tabs/readings'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertGreater
(
len
(
response
.
data
),
0
)
tab
=
response
.
data
self
.
assertEqual
(
tab
[
'name'
],
u'readings'
)
self
.
assertEqual
(
tab
[
'id'
],
u'readings'
)
self
.
assertEqual
(
tab
[
'content'
],
self
.
static_tab2
.
data
)
# try a bogus courseId
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_bogus_course_id
+
'/static_tabs/syllabus'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
404
)
# try a not found item
test_uri
=
self
.
base_courses_uri
+
'/'
+
self
.
test_course_id
+
'/static_tabs/bogus'
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
404
)
lms/djangoapps/api_manager/tests/test_groups_views.py
View file @
f59612ce
...
...
@@ -564,7 +564,6 @@ class GroupsApiTests(TestCase):
response
=
self
.
do_post
(
test_uri
,
data
)
self
.
assertEqual
(
response
.
status_code
,
201
)
test_uri
=
'{}/{}/courses/{}'
.
format
(
self
.
base_groups_uri
,
group_id
,
self
.
test_course_id
)
print
test_uri
response
=
self
.
do_get
(
test_uri
)
self
.
assertEqual
(
response
.
status_code
,
200
)
confirm_uri
=
'{}{}/{}/courses/{}'
.
format
(
...
...
lms/djangoapps/api_manager/tests/test_users_views.py
View file @
f59612ce
...
...
@@ -51,9 +51,6 @@ class UsersApiTests(TestCase):
'X-Edx-Api-Key'
:
str
(
TEST_API_KEY
),
}
json_data
=
json
.
dumps
(
data
)
print
"POST: "
+
uri
print
json_data
print
""
response
=
self
.
client
.
post
(
uri
,
headers
=
headers
,
content_type
=
'application/json'
,
data
=
json_data
)
return
response
...
...
lms/djangoapps/courseware/views.py
View file @
f59612ce
...
...
@@ -773,7 +773,7 @@ def notification_image_for_tab(course_tab, user, course):
return
None
def
get_static_tab_contents
(
request
,
course
,
tab
):
def
get_static_tab_contents
(
request
,
course
,
tab
,
wrap_xmodule_display
=
True
):
"""
Returns the contents for the given static tab
"""
...
...
@@ -788,7 +788,7 @@ def get_static_tab_contents(request, course, tab):
course
.
id
,
request
.
user
,
modulestore
()
.
get_instance
(
course
.
id
,
loc
),
depth
=
0
)
tab_module
=
get_module
(
request
.
user
,
request
,
loc
,
field_data_cache
,
course
.
id
,
static_asset_path
=
course
.
static_asset_path
request
.
user
,
request
,
loc
,
field_data_cache
,
course
.
id
,
static_asset_path
=
course
.
static_asset_path
,
wrap_xmodule_display
=
wrap_xmodule_display
)
logging
.
debug
(
'course_module = {0}'
.
format
(
tab_module
))
...
...
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