Commit f59612ce by chrisndodge

Merge pull request #11 from edx-solutions/cdodge/sprint-H-api-work

Cdodge/sprint h api work
parents 7c581d06 49d491d0
......@@ -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'),
)
......@@ -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)
......@@ -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)
......
"""
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>
""")
......@@ -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)
......@@ -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(
......
......@@ -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
......
......@@ -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))
......
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