wcs/tests/test_widgets.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1436 lines
51 KiB
Python
Raw Normal View History

import copy
import datetime
import shutil
import mechanize
import pytest
from pyquery import PyQuery
from quixote import cleanup, get_response
from quixote.http_request import parse_query
from wcs.qommon import sessions
from wcs.qommon.form import (
CheckboxesWidget,
CompositeWidget,
ComputedExpressionWidget,
ConditionWidget,
DateWidget,
EmailWidget,
FileWithPreviewWidget,
Form,
MapWidget,
MiniRichTextWidget,
OptGroup,
PasswordEntryWidget,
RichTextWidget,
SingleSelectHintWidget,
SingleSelectWidget,
SingleSelectWidgetWithOther,
StringWidget,
TableListRowsWidget,
TableWidget,
TextWidget,
WcsExtraStringWidget,
WidgetDict,
WysiwygTextWidget,
)
from wcs.qommon.http_request import HTTPRequest
from wcs.wf.profile import ProfileUpdateRowWidget
2021-04-01 16:47:57 +02:00
from .utilities import create_temporary_pub
def setup_module(module):
cleanup()
global pub, req
pub = create_temporary_pub()
req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
req.language = None
pub._set_request(req)
def teardown_module(module):
shutil.rmtree(pub.APP_DIR)
class MockHtmlForm:
def __init__(self, widget):
2014-10-03 16:53:35 +02:00
widget = copy.deepcopy(widget)
form = Form(method='post', use_tokens=False, enctype='application/x-www-form-urlencoded')
form.widgets.append(widget)
self.as_html = str(form.render())
response = mechanize._response.test_html_response(self.as_html, headers=[], url='')
factory = mechanize.Browser()
factory.set_response(response)
self.factory = factory
self.form = list(factory.forms())[0]
def set_form_value(self, name, value):
self.form.set_value(value, name)
def set_form_hidden_value(self, name, value):
self.form.find_control(name).readonly = False
self.form.set_value(value, name)
def get_parsed_query(self):
return parse_query(self.form._request_data()[1], 'utf-8')
def mock_form_submission(req, widget, html_vars=None, click=None, hidden_html_vars=None):
html_vars = html_vars or {}
hidden_html_vars = hidden_html_vars or {}
form = MockHtmlForm(widget)
for k, v in html_vars.items():
form.set_form_value(k, v)
for k, v in hidden_html_vars.items():
form.set_form_hidden_value(k, v)
if click is not None:
request = form.form.click(click)
req.form = parse_query(request.data, 'utf-8')
else:
req.form = form.get_parsed_query()
def test_stringwidget_values():
widget = StringWidget('test')
form = MockHtmlForm(widget)
assert 'name="test"' in form.as_html
req.form = {}
assert widget.parse() is None
widget = StringWidget('test', value='foo')
req.form = {}
assert widget.parse() == 'foo'
widget = StringWidget('test', value='foo')
mock_form_submission(req, widget, {'test': ''})
assert widget.parse() is None
widget = StringWidget('test', value='foo')
mock_form_submission(req, widget, {'test': 'bar'})
assert widget.parse() == 'bar'
def test_stringwidget_strip():
widget = StringWidget('test', value='foo')
mock_form_submission(req, widget, {'test': ' bar '})
assert widget.parse() == 'bar'
def test_stringwidget_required():
widget = StringWidget('test', value='foo', required=True)
mock_form_submission(req, widget, {'test': ''})
assert widget.has_error()
widget = StringWidget('test', value='foo', required=True)
mock_form_submission(req, widget, {'test': 'bar'})
assert not widget.has_error()
assert widget.parse() == 'bar'
def test_stringwidget_readonly():
widget = StringWidget('test', value='foo', required=True)
assert 'readonly' not in str(widget.render())
widget = StringWidget('test', value='foo', required=True, readonly=False)
assert 'readonly' not in str(widget.render())
widget = StringWidget('test', value='foo', required=True, readonly=True)
assert 'readonly="readonly"' in str(widget.render())
def test_aria_hint_error():
widget = StringWidget('test', value='foo')
assert 'aria-describedby' not in str(widget.render())
widget = StringWidget('test', value='foo', hint='hint')
assert 'aria-describedby="form_hint_test"' in str(widget.render())
widget.set_error('plop')
assert 'aria-describedby="form_hint_test form_error_test"' in str(widget.render())
widget = StringWidget('test', value='foo')
widget.set_error('plop')
assert 'aria-describedby="form_error_test"' in str(widget.render())
def test_table_list_rows():
widget = TableListRowsWidget('test', columns=['a', 'b', 'c'])
form = MockHtmlForm(widget)
req.form = {}
for row in range(5):
for col in range(3):
assert 'test$element%d$col%d' % (row, col) in form.as_html
widget = TableListRowsWidget('test', columns=['a', 'b', 'c'])
form = MockHtmlForm(widget)
mock_form_submission(req, widget, {'test$element0$col0': 'bar', 'test$element1$col1': 'foo'})
assert widget.parse() == [['bar', None, None], [None, 'foo', None]]
def test_table_list_rows_add_row():
widget = TableListRowsWidget('test', columns=['a', 'b', 'c'])
form = MockHtmlForm(widget)
req.form = {}
mock_form_submission(req, widget, click='test$add_element')
widget = TableListRowsWidget('test', columns=['a', 'b', 'c'])
form = MockHtmlForm(widget)
for row in range(6): # one more row
for col in range(3):
assert 'test$element%d$col%d' % (row, col) in form.as_html
def test_table_list_rows_required():
req.form = {}
widget = TableListRowsWidget('test', columns=['a', 'b', 'c'], required=True)
mock_form_submission(req, widget)
widget = TableListRowsWidget('test', columns=['a', 'b', 'c'], required=True)
assert widget.has_error()
req.form = {}
widget = TableListRowsWidget('test', columns=['a', 'b', 'c'], required=True)
mock_form_submission(req, widget, click='test$add_element')
widget = TableListRowsWidget('test', columns=['a', 'b', 'c'], required=True)
assert not widget.has_error()
2014-10-03 16:53:35 +02:00
def test_table_list_rows_set_many_values():
widget = TableListRowsWidget('test', columns=['a', 'b', 'c'])
form = MockHtmlForm(widget)
req.form = {}
widget = TableListRowsWidget('test', columns=['a', 'b', 'c'])
widget.set_value([(str(x), None, None) for x in range(10)])
form = MockHtmlForm(widget)
for row in range(10):
for col in range(3):
assert 'test$element%d$col%d' % (row, col) in form.as_html
2021-04-02 14:14:55 +02:00
assert 'test$element%d$col%d' % (10, 0) not in form.as_html
mock_form_submission(req, widget, click='test$add_element')
widget = TableListRowsWidget('test', columns=['a', 'b', 'c'])
form = MockHtmlForm(widget)
assert 'test$element%d$col%d' % (10, 0) in form.as_html
2014-10-03 16:53:35 +02:00
def test_table_widget():
req.form = {}
widget = TableWidget('test', columns=['a', 'b', 'c'], rows=['A', 'B'])
widget.set_value([['0'], ['1']])
assert widget.get_widget('c-0-0').value == '0'
assert widget.get_widget('c-0-1').value is None
assert widget.get_widget('c-1-0').value == '1'
assert widget.get_widget('c-1-1').value is None
form = MockHtmlForm(widget)
assert 'value="0"' in form.as_html
assert 'value="1"' in form.as_html
mock_form_submission(req, widget, {'test$c-0-0': 'X', 'test$c-0-1': 'Y'})
assert widget.parse() == [['X', 'Y', None], ['1', None, None]]
2014-10-03 16:53:35 +02:00
def test_passwordentry_widget_success():
widget = PasswordEntryWidget('test')
form = MockHtmlForm(widget)
assert 'name="test$pwd1"' in form.as_html
req.form = {}
assert widget.parse() is None
widget = PasswordEntryWidget('test', value={'cleartext': 'foo'}, formats=['cleartext'])
2014-10-03 16:53:35 +02:00
req.form = {}
assert widget.parse() == {'cleartext': 'foo'}
2014-10-03 16:53:35 +02:00
widget = PasswordEntryWidget('test', formats=['cleartext'])
2014-10-03 16:53:35 +02:00
req.form = {}
mock_form_submission(req, widget, {'test$pwd1': ''})
assert widget.parse() is None
widget = PasswordEntryWidget('test', formats=['cleartext'])
2014-10-03 16:53:35 +02:00
req.form = {}
mock_form_submission(req, widget, {'test$pwd1': 'foo', 'test$pwd2': 'foo'})
assert widget.parse() == {'cleartext': 'foo'}
2014-10-03 16:53:35 +02:00
widget = PasswordEntryWidget('test', formats=['cleartext'], confirmation=False)
req.form = {}
mock_form_submission(req, widget, {'test$pwd1': 'foo'})
assert widget.parse() == {'cleartext': 'foo'}
2014-10-03 16:53:35 +02:00
def test_passwordentry_widget_errors():
# mismatch
widget = PasswordEntryWidget('test', formats=['cleartext'])
2014-10-03 16:53:35 +02:00
req.form = {}
mock_form_submission(req, widget, {'test$pwd1': 'foo', 'test$pwd2': 'bar'})
assert widget.parse() is None
assert widget.has_error() is True
# too short
widget = PasswordEntryWidget('test', formats=['cleartext'], min_length=4)
2014-10-03 16:53:35 +02:00
req.form = {}
mock_form_submission(req, widget, {'test$pwd1': 'foo', 'test$pwd2': 'foo'})
assert widget.parse() is None
assert widget.has_error() is True
# uppercases
widget = PasswordEntryWidget('test', formats=['cleartext'], count_uppercase=1)
2014-10-03 16:53:35 +02:00
req.form = {}
mock_form_submission(req, widget, {'test$pwd1': 'foo', 'test$pwd2': 'foo'})
assert widget.parse() is None
assert widget.has_error() is True
# digits
widget = PasswordEntryWidget('test', formats=['cleartext'], count_digit=1)
2014-10-03 16:53:35 +02:00
req.form = {}
mock_form_submission(req, widget, {'test$pwd1': 'foo', 'test$pwd2': 'foo'})
assert widget.parse() is None
assert widget.has_error() is True
# specials
widget = PasswordEntryWidget('test', formats=['cleartext'], count_special=1)
2014-10-03 16:53:35 +02:00
req.form = {}
mock_form_submission(req, widget, {'test$pwd1': 'foo', 'test$pwd2': 'foo'})
assert widget.parse() is None
assert widget.has_error() is True
def test_textwidget():
widget = TextWidget('test')
form = MockHtmlForm(widget)
assert 'name="test"' in form.as_html
req.form = {}
assert widget.parse() is None
widget = TextWidget('test', value='foo')
req.form = {}
assert widget.parse() == 'foo'
widget = TextWidget('test', value='foo')
mock_form_submission(req, widget, {'test': ''})
assert widget.parse() is None
widget = TextWidget('test', value='foo')
mock_form_submission(req, widget, {'test': 'bar'})
assert widget.parse() == 'bar'
widget = TextWidget('test', value='foo', maxlength=10)
mock_form_submission(req, widget, {'test': 'bar'})
assert not widget.has_error()
assert widget.parse() == 'bar'
widget = TextWidget('test', value='foo', maxlength=10)
mock_form_submission(req, widget, {'test': 'bar' * 10})
assert widget.has_error()
assert widget.get_error() == 'too many characters (limit is 10)'
def test_emailwidget():
pub.cfg = {'emails': {'check_domain_with_dns': True}}
get_response().javascript_code_parts = []
widget = EmailWidget('test')
form = MockHtmlForm(widget)
assert 'name="test"' in form.as_html
assert 'WCS_WELL_KNOWN_DOMAINS' in ''.join(get_response().javascript_code_parts)
req.form = {}
assert widget.parse() is None
for good_email in ('foo@localhost', 'foo.bar@localhost', 'foo+bar@localhost', 'foo_bar@localhost'):
widget = EmailWidget('test')
mock_form_submission(req, widget, {'test': good_email})
assert not widget.has_error()
assert widget.parse() == good_email
widget = EmailWidget('test')
mock_form_submission(req, widget, {'test': 'foo'})
assert widget.has_error()
widget = EmailWidget('test')
mock_form_submission(req, widget, {'test': 'foo@localhost@test'})
assert widget.has_error()
widget = EmailWidget('test')
mock_form_submission(req, widget, {'test': 'foo@localhost..localdomain'})
assert widget.has_error()
widget = EmailWidget('test')
mock_form_submission(req, widget, {'test': 'foö@localhost'})
assert widget.has_error()
def test_date_widget():
widget = DateWidget('test')
form = MockHtmlForm(widget)
assert 'name="test"' in form.as_html
req.form = {}
assert widget.parse() is None
pub.cfg['language'] = {'language': 'en'}
widget = DateWidget('test')
mock_form_submission(req, widget, {'test': '2014-1-20'})
assert not widget.has_error()
assert widget.parse() == '2014-01-20'
# check two-digit years
widget = DateWidget('test')
mock_form_submission(req, widget, {'test': '14-1-20'})
assert not widget.has_error()
assert widget.parse() == '2014-01-20'
widget = DateWidget('test', maximum_date='1/1/2014') # accept "fr" format
mock_form_submission(req, widget, {'test': '2014-1-20'})
assert widget.has_error()
with pub.with_language('fr'):
pub.cfg['language'] = {'language': 'fr'}
widget = DateWidget('test')
mock_form_submission(req, widget, {'test': '20/1/2014'})
assert not widget.has_error()
assert widget.parse() == '20/01/2014'
mock_form_submission(req, widget, {'test': '2014-1-20'})
assert not widget.has_error()
assert widget.parse() == '20/01/2014'
# prevent typo in years (too far in the past of future)
widget = DateWidget('test')
mock_form_submission(req, widget, {'test': '20/1/2123'})
assert widget.has_error()
widget = DateWidget('test')
mock_form_submission(req, widget, {'test': '20/1/1123'})
assert widget.has_error()
widget = DateWidget('test')
mock_form_submission(req, widget, {'test': '20/1/1789'})
assert not widget.has_error()
assert widget.parse() == '20/01/1789'
widget = DateWidget('test', minimum_date='1/1/2014')
mock_form_submission(req, widget, {'test': '20/1/2014'})
assert not widget.has_error()
widget = DateWidget('test', minimum_date='1/1/2014')
mock_form_submission(req, widget, {'test': '20/1/2013'})
assert widget.has_error()
widget = DateWidget('test', maximum_date='1/1/2014')
mock_form_submission(req, widget, {'test': '20/1/2013'})
assert not widget.has_error()
widget = DateWidget('test', maximum_date='1/1/2014')
mock_form_submission(req, widget, {'test': '20/1/2014'})
assert widget.has_error()
widget = DateWidget('test', maximum_date='2014-1-1') # accept "C" format
mock_form_submission(req, widget, {'test': '20/1/2014'})
assert widget.has_error()
yesterday = (datetime.date.today() - datetime.timedelta(days=1)).strftime(widget.get_format_string())
tomorrow = (datetime.date.today() + datetime.timedelta(days=1)).strftime(widget.get_format_string())
widget = DateWidget('test', minimum_is_future=True)
mock_form_submission(req, widget, {'test': tomorrow})
assert not widget.has_error()
widget = DateWidget('test', minimum_is_future=True)
mock_form_submission(req, widget, {'test': yesterday})
assert widget.has_error()
widget = DateWidget('test', date_in_the_past=True)
mock_form_submission(req, widget, {'test': tomorrow})
assert widget.has_error()
widget = DateWidget('test', date_in_the_past=True)
mock_form_submission(req, widget, {'test': yesterday})
assert not widget.has_error()
def test_wysiwygwidget():
widget = WysiwygTextWidget('test')
form = MockHtmlForm(widget)
assert 'name="test"' in form.as_html
req.form = {}
assert widget.parse() is None
widget = WysiwygTextWidget('test')
mock_form_submission(req, widget, {'test': 'bla bla bla'})
assert not widget.has_error()
assert widget.parse() == 'bla bla bla'
widget = WysiwygTextWidget('test')
mock_form_submission(req, widget, {'test': '<p>bla bla bla</p>'})
assert not widget.has_error()
assert widget.parse() == '<p>bla bla bla</p>'
2021-02-04 10:37:40 +01:00
widget = WysiwygTextWidget('test')
mock_form_submission(req, widget, {'test': '<a href="#">a</a>'})
assert not widget.has_error()
assert widget.parse() == '<a href="#" rel="nofollow">a</a>'
widget = WysiwygTextWidget('test')
mock_form_submission(req, widget, {'test': '<a href="javascript:alert()">a</a>'})
assert not widget.has_error()
assert widget.parse() == '<a>a</a>' # javascript: got filtered
# check comments are kept
widget = WysiwygTextWidget('test')
mock_form_submission(req, widget, {'test': '<p>hello</p><!-- world --><p>.</p>'})
assert not widget.has_error()
assert widget.parse() == '<p>hello</p><!-- world --><p>.</p>'
# check <script> are kept
widget = WysiwygTextWidget('test')
mock_form_submission(req, widget, {'test': '<p>hello</p><script>alert("test")</script>'})
assert not widget.has_error()
assert widget.parse() == '<p>hello</p><script>alert("test")</script>'
# check <style> are kept
widget = WysiwygTextWidget('test')
mock_form_submission(req, widget, {'test': '<p>hello</p><style>p { color: blue; }</style>'})
assert not widget.has_error()
assert widget.parse() == '<p>hello</p><style>p { color: blue; }</style>'
# check django syntax is kept intact
widget = WysiwygTextWidget('test')
mock_form_submission(
req,
widget,
{'test': '<a href="{% if 1 > 2 %}héllo{% endif %}">{% if 2 > 1 %}{{plop|date:"Y"}}{% endif %}</a>'},
)
assert not widget.has_error()
assert (
widget.parse()
== '<a href="{% if 1 > 2 %}héllo{% endif %}" rel="nofollow">{% if 2 > 1 %}{{plop|date:"Y"}}{% endif %}</a>'
2021-02-04 10:37:40 +01:00
)
# make sure it is kept intact even after ckeditor escaped characters
widget = WysiwygTextWidget('test')
mock_form_submission(
req,
widget,
{
'test': '<a href="{% if 1 &gt; 2 %}héllo{% endif %}" rel="nofollow">{% if 2 &gt; 1 %}{{plop|date:&quot;Y&quot;}}{% endif %}</a>'
2021-02-04 10:37:40 +01:00
},
)
assert not widget.has_error()
assert (
widget.parse()
== '<a href="{% if 1 > 2 %}héllo{% endif %}" rel="nofollow">{% if 2 > 1 %}{{plop|date:"Y"}}{% endif %}</a>'
2021-02-04 10:37:40 +01:00
)
def test_wysiwygwidget_img():
# check <img> are considered even if there's no text content
widget = WysiwygTextWidget('test')
mock_form_submission(req, widget, {'test': '<p><img src="/test/"></p>'})
assert widget.parse() == '<p><img src="/test/"></p>'
def test_mini_rich_text_widget():
widget = MiniRichTextWidget('test')
form = MockHtmlForm(widget)
assert 'data-godo-schema="basic"' in form.as_html
def test_rich_text_widget():
widget = RichTextWidget('test')
form = MockHtmlForm(widget)
assert 'data-godo-schema="full"' in form.as_html
def test_select_hint_widget():
widget = SingleSelectHintWidget(
'test', options=[('apple', 'Apple', 'apple'), ('pear', 'Pear', 'pear'), ('peach', 'Peach', 'peach')]
)
assert widget.has_valid_options()
widget = SingleSelectHintWidget(
'test',
options=[('apple', 'Apple', 'apple'), ('pear', 'Pear', 'pear'), ('peach', 'Peach', 'peach')],
options_with_attributes=[
('apple', 'Apple', 'apple', {}),
('pear', 'Pear', 'pear', {'disabled': True}),
('peach', 'Peach', 'peach', {}),
2021-02-04 10:37:40 +01:00
],
)
assert widget.has_valid_options()
mock_form_submission(req, widget, {'test': ['apple']})
assert widget.parse() == 'apple'
with pytest.raises(AttributeError):
# mechanize will
# raise AttributeError(
# "insufficient non-disabled items with name %s" % name)
# as the item is disabled
mock_form_submission(req, widget, {'test': ['pear']})
widget = SingleSelectHintWidget(
'test',
options=[('apple', 'Apple', 'apple'), ('pear', 'Pear', 'pear'), ('peach', 'Peach', 'peach')],
options_with_attributes=[
('apple', 'Apple', 'apple', {'disabled': True}),
('pear', 'Pear', 'pear', {'disabled': True}),
('peach', 'Peach', 'peach', {'disabled': True}),
2021-02-04 10:37:40 +01:00
],
)
assert not widget.has_valid_options()
# test readonly only includes the selected value
req.form = {}
widget = SingleSelectHintWidget(
'test', options=[('apple', 'Apple', 'apple'), ('pear', 'Pear', 'pear'), ('peach', 'Peach', 'peach')]
)
widget.readonly = 'readonly'
widget.attrs['readonly'] = 'readonly'
assert 'apple' in str(widget.render()) and 'pear' in str(widget.render())
widget.set_value('pear')
assert 'apple' not in str(widget.render()) and 'pear' in str(widget.render())
assert 'readonly="readonly"' not in str(widget.render())
def test_select_widget():
# test with optgroups
widget = SingleSelectWidget(
'test',
options=[
OptGroup('foo'),
('apple', 'Apple', 'apple'),
OptGroup('bar'),
('pear', 'Pear', 'pear'),
('peach', 'Peach', 'peach'),
],
)
assert widget.get_allowed_values() == ['apple', 'pear', 'peach']
assert (
'<optgroup label="foo">'
'<option value="apple">Apple</option>'
'</optgroup>'
'<optgroup label="bar">'
'<option value="pear">Pear</option>'
'<option value="peach">Peach</option>'
'</optgroup>'
) in ''.join(p.strip() for p in str(widget.render()).split('\n'))
# first option is not optgroup
widget = SingleSelectWidget(
'test',
options=[
('apple', 'Apple', 'apple'),
OptGroup('bar'),
('pear', 'Pear', 'pear'),
('peach', 'Peach', 'peach'),
],
)
assert widget.get_allowed_values() == ['apple', 'pear', 'peach']
assert (
'<option value="apple">Apple</option>'
'<optgroup label="bar">'
'<option value="pear">Pear</option>'
'<option value="peach">Peach</option>'
'</optgroup>'
) in ''.join(p.strip() for p in str(widget.render()).split('\n'))
# only one optgroup and no options
widget = SingleSelectWidget(
'test',
options=[
OptGroup('bar'),
],
)
assert widget.get_allowed_values() == []
assert ('<optgroup label="bar">' '</optgroup>') in ''.join(
p.strip() for p in str(widget.render()).split('\n')
2021-02-04 10:37:40 +01:00
)
def test_select_or_other_widget():
widget = SingleSelectWidgetWithOther(
'test', options=[('apple', 'Apple'), ('pear', 'Pear'), ('peach', 'Peach')]
)
form = MockHtmlForm(widget)
assert '__other' in form.as_html
assert 'Other:' in form.as_html
assert widget.parse() is None
widget = SingleSelectWidgetWithOther(
'test', options=[('apple', 'Apple'), ('pear', 'Pear'), ('peach', 'Peach')], other_label='Alternative:'
)
form = MockHtmlForm(widget)
assert '__other' in form.as_html
assert 'Alternative:' in form.as_html
widget = SingleSelectWidgetWithOther(
'test', options=[('apple', 'Apple'), ('pear', 'Pear'), ('peach', 'Peach')]
)
mock_form_submission(req, widget, {'test$choice': ['apple']})
assert widget.parse() == 'apple'
widget = SingleSelectWidgetWithOther(
'test', options=[('apple', 'Apple'), ('pear', 'Pear'), ('peach', 'Peach')]
)
mock_form_submission(req, widget, {'test$choice': ['__other'], 'test$other': 'Apricot'})
assert widget.parse() == 'Apricot'
def test_checkboxes_widget():
widget = CheckboxesWidget(
'test', options=[('apple', 'Apple', 'apple'), ('pear', 'Pear', 'pear'), ('peach', 'Peach', 'peach')]
)
mock_form_submission(req, widget, {'test$elementpeach': ['yes'], 'test$elementpear': ['yes']})
assert widget.parse() == ['pear', 'peach']
def test_composite_widget():
widget = CompositeWidget('compotest')
widget.add(StringWidget, name='str1')
widget.add(StringWidget, name='str2', required=True)
req.form = {'compotest$str1': 'foo1', 'compotest$str2': 'foo2'}
assert not widget.has_error()
assert len(widget.widgets) == 2
assert widget.widgets[0].parse() == 'foo1'
assert widget.widgets[1].parse() == 'foo2'
widget = CompositeWidget('compotest')
widget.add(StringWidget, name='str1')
widget.add(StringWidget, name='str2', required=True)
req.form = {'compotest$str1': 'alone'}
assert widget.has_error()
assert not widget.widgets[0].has_error()
assert widget.widgets[0].parse() == 'alone'
assert widget.widgets[1].has_error()
assert 'required' in widget.widgets[1].get_error()
req.session = sessions.Session(id=1) # needed by FileWithPreviewWidget
widget = CompositeWidget('compotest')
widget.add(StringWidget, name='str1')
widget.add(FileWithPreviewWidget, name='')
assert 'class="FileWithPreviewWidget widget file-upload-widget"' in str(
widget.render_content_as_tr()
) # extra_css_class is present
def test_computed_expression_widget():
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_template': 'hello world', 'test$type': ['template']})
assert widget.parse() == 'hello world'
assert not widget.has_error()
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_template': '', 'test$type': ['template']})
assert widget.parse() is None
assert not widget.has_error()
# python value left empty
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_python': '', 'test$type': ['python']})
assert not widget.has_error()
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$type': ['python']})
assert not widget.has_error()
# but field marqued as required
widget = ComputedExpressionWidget('test', required=True)
mock_form_submission(req, widget, {'test$value_python': '', 'test$type': ['python']})
assert widget.has_error()
# invalid values
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_python': 'hello world', 'test$type': ['python']})
assert widget.has_error()
assert widget.get_error().startswith('syntax error')
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_python': '=3', 'test$type': ['python']})
assert widget.has_error()
assert widget.get_error().startswith('syntax error')
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_python': '{{form_var_foo}}', 'test$type': ['python']})
assert widget.has_error()
assert 'Python expression cannot contain {{' in widget.get_error()
widget = ComputedExpressionWidget('test')
mock_form_submission(
req, widget, {'test$value_template': '{{ form_var_xxx }}', 'test$type': ['template']}
)
assert not widget.has_error()
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_template': '{% if True %}', 'test$type': ['template']})
assert widget.has_error()
assert widget.get_error().startswith('syntax error in Django template')
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_template': '[form_var_xxx]', 'test$type': ['template']})
assert not widget.has_error()
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_template': '[end]', 'test$type': ['template']})
assert widget.has_error()
assert widget.get_error().startswith('syntax error in ezt template')
def test_wcsextrastringwidget():
widget = WcsExtraStringWidget('test', value='foo', required=True)
mock_form_submission(req, widget, {'test': ''})
assert widget.has_error()
widget = WcsExtraStringWidget('test', value='foo', required=True)
mock_form_submission(req, widget, {'test': 'bar'})
assert not widget.has_error()
assert widget.parse() == 'bar'
def test_wcsextrastringwidget_regex_validation():
# check regex validation
class FakeField:
pass
2021-02-04 10:37:40 +01:00
fakefield = FakeField()
fakefield.validation = {'type': 'regex', 'value': r'\d+'}
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '123'})
assert not widget.has_error()
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '123 ab'})
assert widget.has_error()
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': 'cdab 12'})
assert widget.has_error()
fakefield.validation = {'type': 'regex', 'value': r'\d+(\.\d{1,2})?'}
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '12'})
assert not widget.has_error()
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '12.34'})
assert not widget.has_error()
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '12,34'})
assert widget.has_error()
assert widget.error == 'invalid value'
widget = WcsExtraStringWidget('test', value='foo', required=False)
fakefield.validation = {
'type': 'regex',
'value': r'\d+(\.\d{1,2})?',
'error_message': 'Foo Bar Custom Error',
}
widget.field = fakefield
mock_form_submission(req, widget, {'test': '12,34'})
assert widget.has_error()
assert widget.error == 'Foo Bar Custom Error'
def test_wcsextrastringwidget_builtin_validation():
class FakeField:
pass
2021-02-04 10:37:40 +01:00
fakefield = FakeField()
fakefield.validation = {'type': 'digits'}
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '12'})
assert not widget.has_error()
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': 'az'})
assert widget.has_error()
assert widget.error == 'Only digits are allowed'
fakefield.validation = {'type': 'zipcode-fr'}
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '12345'})
assert not widget.has_error()
# and check it gets a special HTML inputmode
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
assert 'inputmode="numeric"' in str(widget.render())
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '1234'})
assert widget.has_error()
assert widget.error == 'Invalid zip code'
def test_wcsextrastringwidget_phone():
class FakeField:
pass
2021-02-04 10:37:40 +01:00
fakefield = FakeField()
fakefield.validation = {'type': 'phone'}
# check validation
for valid_case in ('0123456789', '+321234566', '02/123.45.67', '+33(0)2 34 56 78 90'):
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': valid_case})
assert not widget.has_error()
for invalid_case in ('az', '123 az', 'aZ 1234'):
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': invalid_case})
assert widget.has_error()
assert widget.error == 'Invalid phone number'
# and check it gets a special HTML input type
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
assert 'type="tel"' in str(widget.render())
def test_wcsextrastringwidget_phone_fr():
class FakeField:
pass
2021-02-04 10:37:40 +01:00
fakefield = FakeField()
# check validation
fakefield.validation = {'type': 'phone-fr'}
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '0123456789'})
assert not widget.has_error()
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '01 23 45 67 89'})
assert not widget.has_error()
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': 'az'})
assert widget.has_error()
assert widget.error == 'Invalid phone number'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '0123'})
assert widget.has_error()
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '01234567890123'})
assert widget.has_error()
# and check it gets a special HTML input type
assert 'type="tel"' in str(widget.render())
def test_wcsextrastringwidget_siren_validation():
class FakeField:
pass
2021-02-04 10:37:40 +01:00
fakefield = FakeField()
fakefield.validation = {'type': 'siren-fr'}
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '443170139'})
assert not widget.has_error()
assert widget.value == '443170139'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': ' 443 170 139'})
assert not widget.has_error()
assert widget.value == '443170139'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '443170130'})
assert widget.has_error()
assert widget.error == 'Invalid SIREN code'
assert widget.value == '443170130'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '44317013900036'})
assert widget.has_error()
assert widget.value == '44317013900036'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': 'XXX170130'})
assert widget.has_error()
assert widget.value == 'XXX170130'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': 'XXX 170 130'})
assert widget.has_error()
assert widget.value == 'XXX 170 130' # do not normalize invalid value
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '443170¹39'})
assert widget.has_error()
assert widget.value == '443170¹39'
def test_wcsextrastringwidget_siret_validation():
class FakeField:
pass
2021-02-04 10:37:40 +01:00
fakefield = FakeField()
fakefield.validation = {'type': 'siret-fr'}
# regular case
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '44317013900036'})
assert not widget.has_error()
assert widget.value == '44317013900036'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '443 170 139 00036'})
assert not widget.has_error()
assert widget.value == '44317013900036' # normalized
assert not widget.has_error()
# special case la poste
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '35600000000048'})
assert not widget.has_error()
assert widget.value == '35600000000048'
# failing cases
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '44317013900037'})
assert widget.has_error()
assert widget.error == 'Invalid SIRET code'
assert widget.value == '44317013900037'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': 'ABC17013900037'})
assert widget.has_error()
assert widget.value == 'ABC17013900037'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '443170139'})
assert widget.has_error()
assert widget.value == '443170139'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '443 170 139'})
assert widget.has_error()
assert widget.value == '443 170 139' # do not normalize invalid value
def test_wcsextrastringwidget_nir_validation():
class FakeField:
pass
2021-02-04 10:37:40 +01:00
fakefield = FakeField()
fakefield.validation = {'type': 'nir-fr'}
# regular cases
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
# https://fr.wikipedia.org/wiki/Num%C3%A9ro_de_s%C3%A9curit%C3%A9_sociale_en_France#/media/Fichier:CarteVitale2.jpg
mock_form_submission(req, widget, {'test': '269054958815780'})
assert not widget.has_error()
assert widget.value == '269054958815780'
# corsica
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '269052A58815717'})
assert not widget.has_error()
assert widget.value == '269052A58815717'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '269052B58815744'})
assert not widget.has_error()
assert widget.value == '269052B58815744'
# accept spaces, but remove them
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '2 69 05 2B588 157 44'})
assert not widget.has_error()
assert widget.value == '269052B58815744'
# failing cases
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '42'})
assert widget.has_error()
assert widget.error == 'Invalid NIR'
assert widget.value == '42'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '269054958815700'})
assert widget.has_error()
assert widget.value == '269054958815700'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': 'hello 789012345'})
assert widget.has_error()
assert widget.value == 'hello 789012345'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '069054958815780'})
assert widget.has_error()
assert widget.value == '069054958815780'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '269004958815780'})
assert widget.has_error()
assert widget.value == '269004958815780'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '269054900015780'})
assert widget.has_error()
assert widget.value == '269054900015780'
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '269054958800080'})
assert widget.has_error()
assert widget.value == '269054958800080'
def test_wcsextrastringwidget_belgian_nrn_validation():
class FakeField:
pass
fakefield = FakeField()
fakefield.validation = {'type': 'nrn-be'}
# regular cases
for value in ('85073003328', '17073003384', '40000095579', '00000100364', '40000100133'):
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': value})
assert not widget.has_error()
# failing cases
for value in (
'8507300332', # too short
'850730033281', # too long
'8507300332A', # not just digits
'85143003377', # invalid month
'85073203365', # invalid day
'85073003329', # invalid checksum (<2000)
'17073003385', # invalid checksum (≥2000)
):
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': value})
assert widget.has_error()
def test_wcsextrastringwidget_iban_validation():
class FakeField:
pass
2021-02-04 10:37:40 +01:00
fakefield = FakeField()
fakefield.validation = {'type': 'iban'}
# regular cases
for iban in [
'BE71 0961 2345 6769', # Belgium
'be71 0961 2345 6769', # Lowercase
' BE71 0961 2345 6769 ', # Extra padding
'FR76 3000 6000 0112 3456 7890 189', # France
'FR27 2004 1000 0101 2345 6Z02 068', # France (having letter)
'DE91 1000 0000 0123 4567 89', # Germany
'GR96 0810 0010 0000 0123 4567 890', # Greece
'RO09 BCYP 0000 0012 3456 7890', # Romania
'SA44 2000 0001 2345 6789 1234', # Saudi Arabia
'ES79 2100 0813 6101 2345 6789', # Spain
'CH56 0483 5012 3456 7800 9', # Switzerland
'GB98 MIDL 0700 9312 3456 78', # United Kingdom
]:
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': iban.replace(' ', '')})
assert not widget.has_error()
widget._parse(req)
assert widget.value == iban.upper().replace(' ', '').strip()
# failing cases
for iban in [
'42',
'FR76 2004 1000 0101 2345 6Z02 068',
'FR76 2004 1000 0101 2345 6%02 068',
'FR76 hello 234 6789 1234 6789 123',
'FRxx 2004 1000 0101 2345 6Z02 068',
'FR76 3000 6000 011² 3456 7890 189', # ²
'XX12',
'XX12 0000 00',
'FR76',
'FR76 0000 0000 0000 0000 0000 000',
'FR76 1234 4567',
]:
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': iban.replace(' ', '')})
assert widget.has_error()
assert widget.error == 'Invalid IBAN'
def test_wcsextrastringwidget_time():
class FakeField:
pass
fakefield = FakeField()
fakefield.validation = {'type': 'time'}
# check validation
for valid_case in ('00:00', '23:59'):
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': valid_case})
assert not widget.has_error()
for invalid_case in ('az', '0000', '24:00', '23:60', 'a00:00', '00:00a'):
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': invalid_case})
assert widget.has_error()
assert widget.error == 'Invalid time'
# and check it gets a special HTML input type
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
assert 'type="time"' in str(widget.render())
def test_wcsextrastringwidget_django_validation():
class FakeField:
pass
2021-02-04 10:37:40 +01:00
fakefield = FakeField()
fakefield.validation = {'type': 'django', 'value': 'value|decimal and value|decimal < 20'}
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '12'})
assert not widget.has_error()
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': '35'})
assert widget.has_error()
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': 'az'})
assert widget.has_error()
assert widget.error == 'invalid value'
widget = WcsExtraStringWidget('test', value='foo', required=False)
fakefield.validation = {
'type': 'django',
'value': 'value|decimal and value|decimal < 20',
'error_message': 'Foo Bar Custom Error',
}
widget.field = fakefield
mock_form_submission(req, widget, {'test': 'az'})
assert widget.has_error()
assert widget.error == 'Foo Bar Custom Error'
pub.substitutions.feed(pub)
fakefield.validation = {'type': 'django', 'value': 'value|decimal == today.year'}
widget = WcsExtraStringWidget('test', value='foo', required=False)
widget.field = fakefield
mock_form_submission(req, widget, {'test': str(datetime.date.today().year)})
assert not widget.has_error()
def test_widgetdict_widget():
widget = WidgetDict('test', value={'a': None, 'b': None, 'c': None})
mock_form_submission(
req,
widget,
{
'test$element0key': 'a',
'test$element0value': 'value-a',
'test$element1key': 'c',
'test$element1value': 'value-c',
'test$element2key': 'b',
'test$element2value': 'value-b',
2021-02-04 10:37:40 +01:00
},
)
assert widget.parse() == {'a': 'value-a', 'b': 'value-b', 'c': 'value-c'}
# on rendering, elements are ordered by their key name
html_frags = str(widget.render_content()).split()
assert (
html_frags.index('name="test$element0key"')
< html_frags.index('name="test$element2key"') # a
< html_frags.index('name="test$element1key"') # b
) # c
def test_map_widget():
widget = MapWidget('test', title='Map')
form = MockHtmlForm(widget)
assert 'name="test$latlng"' in form.as_html
req.form = {}
assert widget.parse() is None
widget = MapWidget('test', title='Map')
mock_form_submission(req, widget, hidden_html_vars={'test$latlng': '1.23;2.34'})
assert not widget.has_error()
assert widget.parse() == '1.23;2.34'
assert '<label' in str(widget.render())
2021-04-02 14:14:55 +02:00
assert '<label ' not in str(widget.render_widget_content())
2023-01-30 18:23:11 +01:00
widget = MapWidget('test', title='Map')
mock_form_submission(req, widget, hidden_html_vars={'test$latlng': 'blah'})
assert widget.has_error()
pub.load_site_options()
pub.site_options.set('options', 'map-bounds-top-left', '1.23;2.34')
pub.site_options.set('options', 'map-bounds-bottom-right', '2.34;3.45')
widget = MapWidget('test', title='Map')
assert 'data-max-bounds-lat1=' in str(widget.render())
assert 'data-max-bounds-lat2=' in str(widget.render())
assert 'data-max-bounds-lng1=' in str(widget.render())
assert 'data-max-bounds-lng2=' in str(widget.render())
def test_profile_fields_sorting():
widget = ProfileUpdateRowWidget('profile')
assert [f[1] for f in widget.get_widgets()[0].options] == ['Email', 'Name']
def test_computed_expression_widget_no_python():
pub.load_site_options()
pub.site_options.set('options', 'disable-python-expressions', 'true')
widget = ComputedExpressionWidget('test')
form = Form(method='post', use_tokens=False, enctype='application/x-www-form-urlencoded')
form.widgets.append(widget)
assert '$type' not in str(form.render())
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_template': 'hello world'})
assert widget.parse() == 'hello world'
assert not widget.has_error()
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_template': ''})
assert widget.parse() is None
assert not widget.has_error()
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_template': '{{ form_var_xxx }}'})
assert not widget.has_error()
widget = ComputedExpressionWidget('test')
mock_form_submission(req, widget, {'test$value_template': '{% if True %}'})
assert widget.has_error()
assert widget.get_error().startswith('syntax error in Django template')
pub.site_options.set('options', 'disable-python-expressions', 'false')
def test_condition_widget():
widget = ConditionWidget('test')
form = Form(method='post', use_tokens=False, enctype='application/x-www-form-urlencoded')
form.widgets.append(widget)
assert '$type' in str(form.render())
widget = ConditionWidget('test')
mock_form_submission(req, widget, {'test$value_django': 'hello == 1'})
assert widget.parse() == {'type': 'django', 'value': 'hello == 1'}
assert not widget.has_error()
widget = ConditionWidget('test')
mock_form_submission(req, widget, {'test$value_django': ''})
assert widget.parse() is None
assert not widget.has_error()
widget = ConditionWidget('test')
mock_form_submission(req, widget, {'test$value_django': '{{ form_var_xxx }}'})
assert widget.has_error()
assert widget.get_error() == "syntax error: Could not parse the remainder: '{{' from '{{'"
widget = ConditionWidget('test')
mock_form_submission(req, widget, {'test$value_python': 'hello == 1', 'test$type': ['python']})
assert widget.parse() == {'type': 'python', 'value': 'hello == 1'}
assert not widget.has_error()
widget = ConditionWidget('test')
mock_form_submission(req, widget, {'test$value_python': 'hello~', 'test$type': ['python']})
assert widget.has_error()
assert widget.get_error().startswith('syntax error:')
def test_condition_widget_no_python():
pub.load_site_options()
pub.site_options.set('options', 'disable-python-expressions', 'true')
widget = ConditionWidget('test')
form = Form(method='post', use_tokens=False, enctype='application/x-www-form-urlencoded')
form.widgets.append(widget)
assert '$type' not in str(form.render())
widget = ConditionWidget('test')
mock_form_submission(req, widget, {'test$value_django': 'hello == 1'})
assert widget.parse() == {'type': 'django', 'value': 'hello == 1'}
assert not widget.has_error()
widget = ConditionWidget('test')
mock_form_submission(req, widget, {'test$value_django': ''})
assert widget.parse() is None
assert not widget.has_error()
widget = ConditionWidget('test')
mock_form_submission(req, widget, {'test$value_django': '{{ form_var_xxx }}'})
assert widget.has_error()
assert widget.get_error() == "syntax error: Could not parse the remainder: '{{' from '{{'"
pub.site_options.set('options', 'disable-python-expressions', 'false')
def test_emoji_button():
# textual button
form = Form(use_tokens=False)
form.add_submit('submit', 'Submit')
assert PyQuery(str(form.render()))('button').attr.name == 'submit'
assert not PyQuery(str(form.render()))('button').attr['aria-label']
assert PyQuery(str(form.render()))('button').text() == 'Submit'
# emoji + text
form = Form(use_tokens=False)
form.add_submit('submit', '✅ Submit')
assert PyQuery(str(form.render()))('button').attr.name == 'submit'
assert PyQuery(str(form.render()))('button').attr['aria-label'] == 'Submit'
assert PyQuery(str(form.render()))('button').text() == '✅ Submit'
# single emoji (do not do this) (no empty aria-label)
form = Form(use_tokens=False)
form.add_submit('submit', '')
assert PyQuery(str(form.render()))('button').attr.name == 'submit'
assert not PyQuery(str(form.render()))('button').attr['aria-label']
assert PyQuery(str(form.render()))('button').text() == ''