Merge pull request #1393 from edx/christina/checklists-restful
Include tail from header tag in course update.
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
from xmodule.modulestore import Location
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from lxml import html, etree
|
||||
import re
|
||||
@@ -39,18 +38,12 @@ def get_course_updates(location):
|
||||
if course_html_parsed.tag == 'ol':
|
||||
# 0 is the newest
|
||||
for idx, update in enumerate(course_html_parsed):
|
||||
if (len(update) == 0):
|
||||
continue
|
||||
elif (len(update) == 1):
|
||||
# could enforce that update[0].tag == 'h2'
|
||||
content = update[0].tail
|
||||
else:
|
||||
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})
|
||||
if len(update) > 0:
|
||||
content = _course_info_content(update)
|
||||
# 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
|
||||
|
||||
@@ -104,14 +97,22 @@ def update_course_updates(location, update, passed_id=None):
|
||||
course_updates.data = html.tostring(course_html_parsed)
|
||||
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,
|
||||
"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):
|
||||
|
||||
@@ -47,6 +47,14 @@ Feature: CMS.Course updates
|
||||
Then I see the handout "Test"
|
||||
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
|
||||
Given I have opened a new course in Studio
|
||||
And I go to the course updates page
|
||||
|
||||
@@ -9,6 +9,23 @@ class CourseUpdateTest(CourseTestCase):
|
||||
'''The do all and end all of unit test cases.'''
|
||||
def test_course_update(self):
|
||||
'''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
|
||||
url = reverse('course_info',
|
||||
kwargs={'org': self.course.location.org,
|
||||
@@ -18,17 +35,7 @@ class CourseUpdateTest(CourseTestCase):
|
||||
|
||||
init_content = '<iframe width="560" height="315" src="http://www.youtube.com/embed/RocY-Jd93XU" frameborder="0">'
|
||||
content = init_content + '</iframe>'
|
||||
payload = {'content': content,
|
||||
'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)
|
||||
|
||||
payload = get_response(content, 'January 8, 2013')
|
||||
self.assertHTMLEqual(payload['content'], content)
|
||||
|
||||
first_update_url = reverse('course_info_json',
|
||||
@@ -48,17 +55,7 @@ class CourseUpdateTest(CourseTestCase):
|
||||
|
||||
# now put in an evil update
|
||||
content = '<ol/>'
|
||||
payload = {'content': content,
|
||||
'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)
|
||||
|
||||
payload = get_response(content, 'January 11, 2013')
|
||||
self.assertHTMLEqual(content, payload['content'], "self closing ol")
|
||||
|
||||
url = reverse('course_info_json',
|
||||
@@ -75,6 +72,11 @@ class CourseUpdateTest(CourseTestCase):
|
||||
"application/json"),
|
||||
'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
|
||||
url = reverse('course_info_json',
|
||||
kwargs={'org': self.course.location.org,
|
||||
@@ -101,33 +103,18 @@ class CourseUpdateTest(CourseTestCase):
|
||||
|
||||
# set to valid html which would break an xml parser
|
||||
content = "<p><br><br></p>"
|
||||
payload = {'content': content,
|
||||
'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, json.loads(resp.content)['content'])
|
||||
payload = get_response(content, 'January 11, 2013')
|
||||
self.assertHTMLEqual(content, payload['content'])
|
||||
|
||||
# now try to delete a non-existent update
|
||||
url = reverse('course_info_json', kwargs={'org': self.course.location.org,
|
||||
'course': self.course.location.course,
|
||||
'provided_id': '19'})
|
||||
payload = {'content': content,
|
||||
'date': 'January 21, 2013'}
|
||||
self.assertContains(self.client.delete(url), "delete", status_code=400)
|
||||
|
||||
# now delete a real update
|
||||
content = 'blah blah'
|
||||
payload = {'content': content,
|
||||
'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)
|
||||
payload = get_response(content, 'January 28, 2013')
|
||||
this_id = payload['id']
|
||||
self.assertHTMLEqual(content, payload['content'], "single iframe")
|
||||
# first count the entries
|
||||
|
||||
Reference in New Issue
Block a user