Commit a51c7711 authored by Jérome Perrin's avatar Jérome Perrin

Formulator: Fix MultiItemsWidget values being escaped twice

This was breaking for cases where values contained characters used for
markup such as <> or & and also for the special case of None which is
used to render disabled items.
parent 2b6afa33
...@@ -50,6 +50,7 @@ from Products.ERP5Form.Form import field_value_cache ...@@ -50,6 +50,7 @@ from Products.ERP5Form.Form import field_value_cache
from Products.ERP5Form.Form import getFieldValue from Products.ERP5Form.Form import getFieldValue
from Products.ERP5Form import ProxyField from Products.ERP5Form import ProxyField
from DateTime import DateTime from DateTime import DateTime
import lxml.html
from Products.Formulator.Widget import NSMAP from Products.Formulator.Widget import NSMAP
ODG_XML_WRAPPING_XPATH = 'draw:text-box/text:p/text:span' ODG_XML_WRAPPING_XPATH = 'draw:text-box/text:p/text:span'
...@@ -534,6 +535,8 @@ class TestListField(ERP5TypeTestCase): ...@@ -534,6 +535,8 @@ class TestListField(ERP5TypeTestCase):
def afterSetUp(self): def afterSetUp(self):
self.field = ListField('test_field') self.field = ListField('test_field')
self.field.values['items'] = [('My first Line', '1'), ('My Second Line', '2')]
self.field.values['default'] = '2'
self.widget = self.field.widget self.widget = self.field.widget
self.createCategories() self.createCategories()
self.tic() self.tic()
...@@ -553,9 +556,6 @@ class TestListField(ERP5TypeTestCase): ...@@ -553,9 +556,6 @@ class TestListField(ERP5TypeTestCase):
int_index=2) int_index=2)
def test_render_odt(self): def test_render_odt(self):
items = [('My first Line', '1'), ('My Second Line', '2')]
self.field.values['items'] = items
self.field.values['default'] = '2'
element = self.field.render_odt(as_string=False) element = self.field.render_odt(as_string=False)
self.assertEqual('{%(text)s}p' % NSMAP, element.tag) self.assertEqual('{%(text)s}p' % NSMAP, element.tag)
self.assertEqual('My Second Line', element.text) self.assertEqual('My Second Line', element.text)
...@@ -565,6 +565,44 @@ class TestListField(ERP5TypeTestCase): ...@@ -565,6 +565,44 @@ class TestListField(ERP5TypeTestCase):
element = self.field.render_odt(as_string=False) element = self.field.render_odt(as_string=False)
self.assertEqual('??? (3)', element.text) self.assertEqual('??? (3)', element.text)
def test_render(self):
select, input_element, = lxml.html.fragments_fromstring(self.field.render()) # pylint:disable=unbalanced-tuple-unpacking
# listfields render an input to confirm that the field was posted
# in the form's action script
self.assertEqual(input_element.name, 'default_field_test_field:int')
self.assertEqual(input_element.type, 'hidden')
self.assertEqual(select.tag, 'select')
first, second = select
self.assertEqual(first.tag, 'option')
self.assertEqual(first.text_content(), 'My first Line')
self.assertEqual(first.attrib['value'], '1')
self.assertEqual(second.tag, 'option')
self.assertEqual(second.text_content(), 'My Second Line')
self.assertEqual(second.attrib['value'], '2',)
self.assertTrue(second.attrib['selected'])
def test_render_escape_html(self):
self.field.values['default'] = ''
self.field.values['items'] = [
('<script>alert("text content")</script>', '<script>alert("value")</script>'),]
(script, ), _, = lxml.html.fragments_fromstring(self.field.render()) # pylint:disable=unbalanced-tuple-unpacking
self.assertEqual(script.attrib['value'], '<script>alert("value")</script>')
self.assertEqual(script.text_content(), '<script>alert("text content")</script>')
# selected
self.field.values['default'] = self.field.values['items'][0][1]
(script, ), _, = lxml.html.fragments_fromstring(self.field.render()) # pylint:disable=unbalanced-tuple-unpacking
self.assertEqual(script.attrib['value'], '<script>alert("value")</script>')
self.assertEqual(script.text_content(), '<script>alert("text content")</script>')
def test_render_disabled(self):
self.field.values['default'] = ''
# None items are rendered as disabled
self.field.values['items'] = [('Disabled', None)]
(disabled, ), _, = lxml.html.fragments_fromstring(self.field.render()) # pylint:disable=unbalanced-tuple-unpacking
self.assertTrue(disabled.attrib['disabled'])
self.assertFalse(disabled.attrib.get('value'))
def test_listField_value_order(self): def test_listField_value_order(self):
'''This test check the list field value order '''This test check the list field value order
...@@ -606,6 +644,46 @@ class TestMultiListField(ERP5TypeTestCase): ...@@ -606,6 +644,46 @@ class TestMultiListField(ERP5TypeTestCase):
self.field.values['items'] = [('A', 'a',), ('B', 'b')] self.field.values['items'] = [('A', 'a',), ('B', 'b')]
self.field.values['default'] = ['a', 'b'] self.field.values['default'] = ['a', 'b']
def test_render(self):
select, input_element, = lxml.html.fragments_fromstring(self.field.render()) # pylint:disable=unbalanced-tuple-unpacking
# listfields render an input to confirm that the field was posted
# in the form's action script
self.assertEqual(input_element.name, 'default_field_test_field:int')
self.assertEqual(input_element.type, 'hidden')
self.assertEqual(select.tag, 'select')
first, second = select
self.assertEqual(first.tag, 'option')
self.assertEqual(first.text_content(), 'A')
self.assertEqual(first.attrib['value'], 'a')
self.assertTrue(second.attrib['selected'])
self.assertEqual(second.tag, 'option')
self.assertEqual(second.text_content(), 'B')
self.assertEqual(second.attrib['value'], 'b',)
self.assertTrue(second.attrib['selected'])
def test_render_escape_html(self):
self.field.values['default'] = []
self.field.values['items'] = [
('<script>alert("text content")</script>', '<script>alert("value")</script>')]
(script, ), _, = lxml.html.fragments_fromstring(self.field.render()) # pylint:disable=unbalanced-tuple-unpacking
self.assertEqual(script.attrib['value'], '<script>alert("value")</script>')
self.assertEqual(script.text_content(), '<script>alert("text content")</script>')
# selected
self.field.values['default'] = [self.field.values['items'][0][1]]
(script, ), _, = lxml.html.fragments_fromstring(self.field.render()) # pylint:disable=unbalanced-tuple-unpacking
self.assertEqual(script.attrib['value'], '<script>alert("value")</script>')
self.assertEqual(script.text_content(), '<script>alert("text content")</script>')
def test_render_disabled(self):
# None items are rendered as disabled
self.field.values['default'] = []
self.field.values['items'] = [('Disabled', None)]
(disabled, ), _, = lxml.html.fragments_fromstring(self.field.render()) # pylint:disable=unbalanced-tuple-unpacking
self.assertTrue(disabled.attrib['disabled'])
self.assertFalse(disabled.attrib.get('value'))
def test_render_view(self): def test_render_view(self):
self.assertEqual('A<br />\nB', self.field.render_view(value=['a', 'b'])) self.assertEqual('A<br />\nB', self.field.render_view(value=['a', 'b']))
......
...@@ -1027,7 +1027,7 @@ class MultiItemsWidget(ItemsWidget): ...@@ -1027,7 +1027,7 @@ class MultiItemsWidget(ItemsWidget):
if item_value in value: if item_value in value:
rendered_item = self.render_selected_item( rendered_item = self.render_selected_item(
escape(ustr(item_text)), escape(ustr(item_text)),
escape(ustr(item_value)), item_value,
key, key,
css_class, css_class,
extra_item) extra_item)
...@@ -1037,7 +1037,7 @@ class MultiItemsWidget(ItemsWidget): ...@@ -1037,7 +1037,7 @@ class MultiItemsWidget(ItemsWidget):
else: else:
rendered_item = self.render_item( rendered_item = self.render_item(
escape(ustr(item_text)), escape(ustr(item_text)),
escape(ustr(item_value)), item_value,
key, key,
css_class, css_class,
extra_item) extra_item)
......
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