Commit 475cf077 by Christina Roberts

Merge pull request #1393 from edx/christina/checklists-restful

Include tail from header tag in course update.
parents a6323776 0c5b511c
from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore import Location
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from lxml import html, etree from lxml import html, etree
import re import re
...@@ -39,18 +38,12 @@ def get_course_updates(location): ...@@ -39,18 +38,12 @@ def get_course_updates(location):
if course_html_parsed.tag == 'ol': if course_html_parsed.tag == 'ol':
# 0 is the newest # 0 is the newest
for idx, update in enumerate(course_html_parsed): for idx, update in enumerate(course_html_parsed):
if (len(update) == 0): if len(update) > 0:
continue content = _course_info_content(update)
elif (len(update) == 1): # make the id on the client be 1..len w/ 1 being the oldest and len being the newest
# could enforce that update[0].tag == 'h2' course_upd_collection.append({"id": location_base + "/" + str(len(course_html_parsed) - idx),
content = update[0].tail "date": update.findtext("h2"),
else: "content": content})
content = "\n".join([html.tostring(ele) for ele in update[1:]])
# make the id on the client be 1..len w/ 1 being the oldest and len being the newest
course_upd_collection.append({"id": location_base + "/" + str(len(course_html_parsed) - idx),
"date": update.findtext("h2"),
"content": content})
return course_upd_collection return course_upd_collection
...@@ -104,14 +97,22 @@ def update_course_updates(location, update, passed_id=None): ...@@ -104,14 +97,22 @@ def update_course_updates(location, update, passed_id=None):
course_updates.data = html.tostring(course_html_parsed) course_updates.data = html.tostring(course_html_parsed)
modulestore('direct').update_item(location, course_updates.data) modulestore('direct').update_item(location, course_updates.data)
if (len(new_html_parsed) == 1):
content = new_html_parsed[0].tail
else:
content = "\n".join([html.tostring(ele) for ele in new_html_parsed[1:]])
return {"id": passed_id, return {"id": passed_id,
"date": update['date'], "date": update['date'],
"content": content} "content": _course_info_content(new_html_parsed)}
def _course_info_content(html_parsed):
"""
Constructs the HTML for the course info update, not including the header.
"""
if len(html_parsed) == 1:
# could enforce that update[0].tag == 'h2'
content = html_parsed[0].tail
else:
content = html_parsed[0].tail if html_parsed[0].tail is not None else ""
content += "\n".join([html.tostring(ele) for ele in html_parsed[1:]])
return content
def delete_course_update(location, update, passed_id): def delete_course_update(location, update, passed_id):
......
...@@ -47,6 +47,14 @@ Feature: CMS.Course updates ...@@ -47,6 +47,14 @@ Feature: CMS.Course updates
Then I see the handout "Test" Then I see the handout "Test"
And I see a "saving" notification And I see a "saving" notification
Scenario: Text outside of tags is preserved
Given I have opened a new course in Studio
And I go to the course updates page
When I add a new update with the text "before <strong>middle</strong> after"
Then I should see the update "before <strong>middle</strong> after"
And when I reload the page
Then I should see the update "before <strong>middle</strong> after"
Scenario: Static links are rewritten when previewing a course update Scenario: Static links are rewritten when previewing a course update
Given I have opened a new course in Studio Given I have opened a new course in Studio
And I go to the course updates page And I go to the course updates page
......
...@@ -9,6 +9,23 @@ class CourseUpdateTest(CourseTestCase): ...@@ -9,6 +9,23 @@ class CourseUpdateTest(CourseTestCase):
'''The do all and end all of unit test cases.''' '''The do all and end all of unit test cases.'''
def test_course_update(self): def test_course_update(self):
'''Go through each interface and ensure it works.''' '''Go through each interface and ensure it works.'''
def get_response(content, date):
"""
Helper method for making call to server and returning response.
Does not supply a provided_id.
"""
payload = {'content': content,
'date': date}
url = reverse('course_info_json',
kwargs={'org': self.course.location.org,
'course': self.course.location.course,
'provided_id': ''})
resp = self.client.post(url, json.dumps(payload), "application/json")
return json.loads(resp.content)
# first get the update to force the creation # first get the update to force the creation
url = reverse('course_info', url = reverse('course_info',
kwargs={'org': self.course.location.org, kwargs={'org': self.course.location.org,
...@@ -18,17 +35,7 @@ class CourseUpdateTest(CourseTestCase): ...@@ -18,17 +35,7 @@ class CourseUpdateTest(CourseTestCase):
init_content = '<iframe width="560" height="315" src="http://www.youtube.com/embed/RocY-Jd93XU" frameborder="0">' init_content = '<iframe width="560" height="315" src="http://www.youtube.com/embed/RocY-Jd93XU" frameborder="0">'
content = init_content + '</iframe>' content = init_content + '</iframe>'
payload = {'content': content, payload = get_response(content, 'January 8, 2013')
'date': 'January 8, 2013'}
url = reverse('course_info_json',
kwargs={'org': self.course.location.org,
'course': self.course.location.course,
'provided_id': ''})
resp = self.client.post(url, json.dumps(payload), "application/json")
payload = json.loads(resp.content)
self.assertHTMLEqual(payload['content'], content) self.assertHTMLEqual(payload['content'], content)
first_update_url = reverse('course_info_json', first_update_url = reverse('course_info_json',
...@@ -48,17 +55,7 @@ class CourseUpdateTest(CourseTestCase): ...@@ -48,17 +55,7 @@ class CourseUpdateTest(CourseTestCase):
# now put in an evil update # now put in an evil update
content = '<ol/>' content = '<ol/>'
payload = {'content': content, payload = get_response(content, 'January 11, 2013')
'date': 'January 11, 2013'}
url = reverse('course_info_json',
kwargs={'org': self.course.location.org,
'course': self.course.location.course,
'provided_id': ''})
resp = self.client.post(url, json.dumps(payload), "application/json")
payload = json.loads(resp.content)
self.assertHTMLEqual(content, payload['content'], "self closing ol") self.assertHTMLEqual(content, payload['content'], "self closing ol")
url = reverse('course_info_json', url = reverse('course_info_json',
...@@ -75,6 +72,11 @@ class CourseUpdateTest(CourseTestCase): ...@@ -75,6 +72,11 @@ class CourseUpdateTest(CourseTestCase):
"application/json"), "application/json"),
'Failed to save', status_code=400) 'Failed to save', status_code=400)
# test an update with text in the tail of the header
content = 'outside <strong>inside</strong> after'
payload = get_response(content, 'June 22, 2000')
self.assertHTMLEqual(content, payload['content'], "text outside tag")
# now try to update a non-existent update # now try to update a non-existent update
url = reverse('course_info_json', url = reverse('course_info_json',
kwargs={'org': self.course.location.org, kwargs={'org': self.course.location.org,
...@@ -101,33 +103,18 @@ class CourseUpdateTest(CourseTestCase): ...@@ -101,33 +103,18 @@ class CourseUpdateTest(CourseTestCase):
# set to valid html which would break an xml parser # set to valid html which would break an xml parser
content = "<p><br><br></p>" content = "<p><br><br></p>"
payload = {'content': content, payload = get_response(content, 'January 11, 2013')
'date': 'January 11, 2013'} self.assertHTMLEqual(content, payload['content'])
url = reverse('course_info_json', kwargs={'org': self.course.location.org,
'course': self.course.location.course,
'provided_id': ''})
resp = self.client.post(url, json.dumps(payload), "application/json")
payload = json.loads(resp.content)
self.assertHTMLEqual(content, json.loads(resp.content)['content'])
# now try to delete a non-existent update # now try to delete a non-existent update
url = reverse('course_info_json', kwargs={'org': self.course.location.org, url = reverse('course_info_json', kwargs={'org': self.course.location.org,
'course': self.course.location.course, 'course': self.course.location.course,
'provided_id': '19'}) 'provided_id': '19'})
payload = {'content': content,
'date': 'January 21, 2013'}
self.assertContains(self.client.delete(url), "delete", status_code=400) self.assertContains(self.client.delete(url), "delete", status_code=400)
# now delete a real update # now delete a real update
content = 'blah blah' content = 'blah blah'
payload = {'content': content, payload = get_response(content, 'January 28, 2013')
'date': 'January 28, 2013'}
url = reverse('course_info_json', kwargs={'org': self.course.location.org,
'course': self.course.location.course,
'provided_id': ''})
resp = self.client.post(url, json.dumps(payload), "application/json")
payload = json.loads(resp.content)
this_id = payload['id'] this_id = payload['id']
self.assertHTMLEqual(content, payload['content'], "single iframe") self.assertHTMLEqual(content, payload['content'], "single iframe")
# first count the entries # first count the entries
......
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