import io import os import re import time import xml.etree.ElementTree as ET from unittest import mock import pytest from webtest import Upload from wcs import fields from wcs.blocks import BlockDef from wcs.carddef import CardDef from wcs.categories import Category, DataSourceCategory, WorkflowCategory from wcs.data_sources import NamedDataSource from wcs.formdef import FormDef from wcs.qommon.errors import ConnectionError from wcs.qommon.http_request import HTTPRequest from wcs.workflows import Workflow, WorkflowBackofficeFieldsFormDef, WorkflowVariablesFieldsFormDef from wcs.wscalls import NamedWsCall from ..utilities import clean_temporary_pub, create_temporary_pub, get_app, login from .test_all import create_role, create_superuser @pytest.fixture def pub(emails): pub = create_temporary_pub() req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'}) pub.set_app_dir(req) pub.cfg['identification'] = {'methods': ['password']} pub.cfg['language'] = {'language': 'en'} pub.write_cfg() return pub def teardown_module(module): clean_temporary_pub() @pytest.fixture def formdef(pub): FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [] formdef.store() return formdef def test_forms(pub): create_superuser(pub) pub.role_class.wipe() app = login(get_app(pub)) resp = app.get('/backoffice/forms/') assert 'You first have to define roles.' in resp.text assert 'New Form' not in resp.text def test_forms_new(pub): create_superuser(pub) app = login(get_app(pub)) create_role(pub) FormDef.wipe() # create a new form resp = app.get('/backoffice/forms/') assert 'New Form' in resp.text resp = resp.click('New Form') resp.forms[0]['name'] = 'form title' resp = resp.forms[0].submit() assert resp.location == 'http://example.net/backoffice/forms/1/' resp = resp.follow() assert '
Hello World
' resp = resp.forms[0].submit() assert resp.location == 'http://example.net/backoffice/forms/1/' resp = resp.follow() assert_option_display(resp, 'Description', 'On') def test_form_enable_from_fields_page(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [] formdef.disabled = True formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') assert 'This form is currently disabled.' in resp resp = resp.click('Enable').follow() assert resp.request.path == '/backoffice/forms/1/fields/' assert 'This form is currently disabled.' not in resp def test_form_new_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') assert 'There are not yet any fields' in resp.text resp.forms[0]['label'] = 'foobar' resp.forms[0]['type'] = 'string' resp = resp.forms[0].submit() assert resp.location == 'http://example.net/backoffice/forms/1/fields/' resp = resp.follow() assert 'foobar' in resp.text assert 'Use drag and drop' in resp.text assert len(FormDef.get(1).fields) == 1 assert FormDef.get(1).fields[0].key == 'string' assert FormDef.get(1).fields[0].label == 'foobar' # add a title too resp.forms[0]['label'] = 'baz' resp.forms[0]['type'] = 'title' resp = resp.forms[0].submit() assert resp.location == 'http://example.net/backoffice/forms/1/fields/' resp = resp.follow() # check it's in the preview resp = app.get('/backoffice/forms/1/') assert resp.pyquery('.form-preview h3').text() == 'baz' def test_form_field_without_label(pub): create_superuser(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.CommentField(id='1', label=None, type='comment')] formdef.store() app = login(get_app(pub)) app.get('/backoffice/forms/1/fields/', status=200) # ok, no error def test_form_field_varname_values(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.StringField(id='1', label='1st field', type='string')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/1/') resp.forms[0]['varname'] = 'id' resp = resp.forms[0].submit('submit') assert 'this value is reserved for internal use.' in resp.text resp.forms[0]['varname'] = '0123' resp = resp.forms[0].submit('submit') assert 'must only consist of letters, numbers, or underscore' in resp.text resp.forms[0]['varname'] = 'plop' resp = resp.forms[0].submit('submit') formdef.refresh_from_storage() assert formdef.fields[0].varname == 'plop' def test_form_delete_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.StringField(id='1', label='1st field', type='string')] formdef.store() formdef.data_class().wipe() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') assert '1st field' in resp.text assert 'Use drag and drop' in resp.text assert 'Also remove all fields from the page' not in resp.text resp = resp.click(href='1/delete') assert 'You are about to remove the "1st field" field.' in resp.text assert 'Warning:' not in resp.text resp = resp.forms[0].submit() assert resp.location == 'http://example.net/backoffice/forms/1/fields/' resp = resp.follow() assert len(FormDef.get(1).fields) == 0 def test_form_delete_field_existing_data(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [ fields.StringField(id='1', label='1st field', type='string'), fields.CommentField(id='2', label='comment field', type='comment'), ] formdef.store() formdef.data_class().wipe() formdata = formdef.data_class()() formdata.just_created() formdata.data = {'1': 'hello'} formdata.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') resp = resp.click(href='1/delete') assert 'You are about to remove the "1st field" field.' in resp.text assert 'Warning:' in resp.text resp = resp.forms[0].submit() assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_2' resp = resp.follow() assert len(FormDef.get(1).fields) == 1 # check non-data fields do not show this warning resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') resp = resp.click(href='2/delete') assert 'You are about to remove the "comment field" field.' in resp.text assert 'Warning:' not in resp.text resp = resp.forms[0].submit() resp = resp.follow() assert len(FormDef.get(1).fields) == 0 def test_form_delete_page_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [ fields.PageField(id='1', label='page 1', type='page'), fields.StringField(id='2', label='field 1 1', type='string'), fields.StringField(id='3', label='field 1 2', type='string'), fields.PageField(id='4', label='page 2', type='page'), fields.PageField(id='5', label='page 3', type='page'), fields.StringField(id='6', label='field 3 1', type='string'), fields.StringField(id='7', label='field 3 2', type='string'), ] formdef.store() formdef.data_class().wipe() app = login(get_app(pub)) # delete fields from the page resp = app.get('/backoffice/forms/1/fields/1/delete') assert 'You are about to remove the "page 1" page.' in resp.text assert 'Also remove all fields from the page' in resp.text resp.forms[0]['delete_fields'] = True resp = resp.forms[0].submit() resp = resp.follow() assert len(FormDef.get(1).fields) == 4 # empty page resp = app.get('/backoffice/forms/1/fields/4/delete') assert 'You are about to remove the "page 2" page.' in resp.text assert 'Also remove all fields from the page' not in resp.text resp = resp.forms[0].submit() resp = resp.follow() assert len(FormDef.get(1).fields) == 3 # keep fields resp = app.get('/backoffice/forms/1/fields/5/delete') assert 'You are about to remove the "page 3" page.' in resp.text assert 'Also remove all fields from the page' in resp.text resp.forms[0]['delete_fields'] = False resp = resp.forms[0].submit() resp = resp.follow() assert len(FormDef.get(1).fields) == 2 def test_form_duplicate_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.StringField(id='1', label='1st field', type='string')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/') assert '1st field' in resp.text resp = resp.click(href='1/duplicate') assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_2' resp = resp.follow() assert len(FormDef.get(1).fields) == 2 assert FormDef.get(1).fields[0].label == '1st field' assert FormDef.get(1).fields[1].label == '1st field' def test_form_duplicate_page_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [ fields.PageField(id='0', label='1st page', type='page'), fields.StringField(id='1', label='1st field', type='string', varname='foobar'), fields.PageField(id='2', label='2nd page', type='page'), fields.StringField(id='3', label='2nd field', type='string', varname='baz'), ] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/') # duplicate 1st page only resp = resp.click(href='0/duplicate') assert 'Also duplicate all fields of the page' in resp.text resp = resp.form.submit().follow() assert [f.label for f in FormDef.get(1).fields] == [ '1st page', '1st field', '1st page', '2nd page', '2nd field', ] assert [str(f.id) for f in FormDef.get(1).fields] == ['0', '1', '4', '2', '3'] # duplicate 1st page and fields resp = resp.click(href='0/duplicate') assert 'Also duplicate all fields of the page' in resp.text resp.form['duplicate_fields'] = True resp = resp.form.submit().follow() assert [f.label for f in FormDef.get(1).fields] == [ '1st page', '1st field', '1st page', '1st field', '1st page', '2nd page', '2nd field', ] assert [str(f.id) for f in FormDef.get(1).fields] == ['0', '1', '5', '6', '4', '2', '3'] # duplicate copy of 1st page without fields resp = resp.click(href='4/duplicate') assert 'Also duplicate all fields of the page' not in resp.text resp = resp.form.submit().follow() assert [f.label for f in FormDef.get(1).fields] == [ '1st page', '1st field', '1st page', '1st field', '1st page', '1st page', '2nd page', '2nd field', ] assert [str(f.id) for f in FormDef.get(1).fields] == ['0', '1', '5', '6', '4', '7', '2', '3'] # duplicate last page and fields resp = resp.click(href='2/duplicate') assert 'Also duplicate all fields of the page' in resp.text resp.form['duplicate_fields'] = True resp = resp.form.submit().follow() assert [f.label for f in FormDef.get(1).fields] == [ '1st page', '1st field', '1st page', '1st field', '1st page', '1st page', '2nd page', '2nd field', '2nd page', '2nd field', ] assert [str(f.id) for f in FormDef.get(1).fields] == ['0', '1', '5', '6', '4', '7', '2', '3', '8', '9'] # duplicate last page only resp = resp.click(href='8/duplicate') assert 'Also duplicate all fields of the page' in resp.text resp = resp.form.submit().follow() assert [f.label for f in FormDef.get(1).fields] == [ '1st page', '1st field', '1st page', '1st field', '1st page', '1st page', '2nd page', '2nd field', '2nd page', '2nd field', '2nd page', ] assert [str(f.id) for f in FormDef.get(1).fields] == [ '0', '1', '5', '6', '4', '7', '2', '3', '8', '9', '10', ] def test_form_duplicate_file_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') # add a first field resp.forms[0]['label'] = 'foobar' resp.forms[0]['type'] = 'file' resp = resp.forms[0].submit() assert resp.location == 'http://example.net/backoffice/forms/%s/fields/' % formdef.id resp = resp.follow() assert 'foobar' in resp.text resp = resp.click(href='%s/duplicate' % FormDef.get(formdef.id).fields[0].id) assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_2' resp = resp.follow() def test_form_edit_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.StringField(id='1', label='1st field', type='string')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') assert '1st field' in resp.text resp = resp.click('Edit', href='1/') assert '/backoffice/forms/1/fields/#itemId_1' in resp assert resp.pyquery('.field-edit--title').text() == '1st field' assert resp.pyquery('.field-edit--subtitle').text() == 'Text (line)' assert resp.forms[0]['label'].value == '1st field' resp.forms[0]['label'] = 'changed field' resp.forms[0]['required'] = False resp = resp.forms[0].submit('submit') assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1' assert FormDef.get(1).fields[0].label == 'changed field' assert FormDef.get(1).fields[0].required is False def test_form_edit_field_advanced(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.StringField(id='1', label='1st field', type='string')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') assert '1st field' in resp.text resp = resp.click('Edit', href='1/') assert resp.forms[0]['label'].value == '1st field' assert '>Prefill' in resp.text # check the "prefill" field is in advanced panel and there's no visual marker assert resp.pyquery('#panel-advanced .PrefillSelectionWidget') assert not resp.pyquery('#tab-advanced.pk-tabs--button-marker') # complete the "prefill" field resp.forms[0]['prefill$type'] = 'String / Template' resp.forms[0]['prefill$value_string'] = 'test' resp = resp.forms[0].submit('submit') assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1' resp = resp.follow() assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'string', 'value': 'test', 'locked': False} # do the same with 'data sources' field resp = resp.click('Edit', href='1/') assert resp.forms[0]['label'].value == '1st field' assert '>Data Source' in resp.text # check the "data source" field is in advanced panel assert resp.pyquery('#panel-advanced .DataSourceSelectionWidget') # start filling the "data source" field resp.forms[0]['data_source$type'] = 'json' resp.forms[0]['data_source$value'] = 'http://example.net' resp = resp.forms[0].submit('submit') resp = resp.follow() # it is still in the advanced panel, with a visual marker resp = resp.click('Edit', href='1/') assert resp.pyquery('#panel-advanced .DataSourceSelectionWidget') assert resp.pyquery('#tab-advanced.pk-tabs--button-marker') resp = app.get('/backoffice/forms/1/fields/1/') assert resp.forms[0]['label'].value == '1st field' resp.forms[0]['prefill$type'] = 'User Field' resp.forms[0]['prefill$value_user'] = 'Email (builtin)' resp = resp.forms[0].submit('submit') assert resp.location == 'http://example.net/backoffice/forms/1/fields/' resp = resp.follow() assert ( ""1st field" is not an email field. Are you sure you want to prefill it with user's email?" in resp.text ) formdef.fields += [fields.EmailField(id='2', label='2nd field')] formdef.store() resp = app.get('/backoffice/forms/1/fields/2/') assert resp.forms[0]['label'].value == '2nd field' resp.forms[0]['prefill$type'] = 'User Field' resp.forms[0]['prefill$value_string'] = 'email' resp = resp.forms[0].submit('submit') assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_2' resp = resp.follow() assert "Are you sure you want to prefill" not in resp.text def test_form_prefill_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.StringField(id='1', label='1st field', type='string')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/1/') resp.form['prefill$type'] = 'String / Template' resp.form['prefill$value_string'] = 'test' resp = resp.form.submit('submit').follow() assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'string', 'value': 'test', 'locked': False} resp = app.get('/backoffice/forms/1/fields/1/') resp.form['prefill$type'] = 'Python Expression' resp.form['prefill$value_formula'] = 'True' resp = resp.form.submit('submit').follow() assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'formula', 'value': 'True', 'locked': False} resp = app.get('/backoffice/forms/1/fields/1/') resp.form['prefill$type'] = 'String / Template' resp.form['prefill$value_string'] = '{{form_var_toto}}' resp = resp.form.submit('submit').follow() assert FormDef.get(formdef.id).fields[0].prefill == { 'type': 'string', 'value': '{{form_var_toto}}', 'locked': False, } # check error handling resp = app.get('/backoffice/forms/1/fields/1/') resp.form['prefill$type'] = 'Python Expression' resp.form['prefill$value_formula'] = ':' resp = resp.form.submit('submit') assert 'invalid expression: unexpected EOF while parsing' in resp.text resp = app.get('/backoffice/forms/1/fields/1/') resp.form['prefill$type'] = 'String / Template' resp.form['prefill$value_string'] = '{% if %}' resp = resp.form.submit('submit') assert 'syntax error in Django template: Unexpected end of expression' in resp.text def test_form_prefill_type_options(pub): create_superuser(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.StringField(id='1', label='1st field', type='string')] formdef.store() if not pub.site_options.has_section('options'): pub.site_options.add_section('options') pub.site_options.set('options', 'disable-python-expressions', 'false') with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: pub.site_options.write(fd) app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/1/') assert resp.forms[0]['prefill$type'].options == [ ('None', True, 'None'), ('String / Template', False, 'String / Template'), ('Python Expression', False, 'Python Expression'), ('User Field', False, 'User Field'), ('Geolocation', False, 'Geolocation'), ] pub.site_options.set('options', 'disable-python-expressions', 'true') with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd: pub.site_options.write(fd) resp = app.get('/backoffice/forms/1/fields/1/') assert resp.forms[0]['prefill$type'].options == [ ('None', True, 'None'), ('String / Template', False, 'String / Template'), ('User Field', False, 'User Field'), ('Geolocation', False, 'Geolocation'), ] def test_form_edit_string_field_validation(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.StringField(id='1', label='1st field', type='string')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') assert '1st field' in resp.text resp = resp.click('Edit', href='1/') resp.form['validation$type'] = 'Regular Expression' resp.form['validation$value_regex'] = r'\d+' resp.form['validation$error_message'] = 'Foo Error' resp = resp.form.submit('submit').follow() assert FormDef.get(formdef.id).fields[0].validation == { 'type': 'regex', 'value': r'\d+', 'error_message': 'Foo Error', } resp = resp.click('Edit', href='1/') resp.form['validation$type'] = 'None' resp = resp.form.submit('submit').follow() assert FormDef.get(formdef.id).fields[0].validation is None resp = resp.click('Edit', href='1/') resp.form['validation$type'] = 'Django Condition' resp.form['validation$value_django'] = 'value|decimal < 20' resp.form['validation$error_message'] = 'Bar Error' resp = resp.form.submit('submit').follow() assert FormDef.get(formdef.id).fields[0].validation == { 'type': 'django', 'value': 'value|decimal < 20', 'error_message': 'Bar Error', } resp = resp.click('Edit', href='1/') resp.form['validation$type'] = 'Django Condition' resp.form['validation$value_django'] = '{{ value|decimal < 20 }}' resp = resp.form.submit('submit') assert 'syntax error' in resp.text def test_form_edit_item_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.ItemField(id='1', label='1st field', type='item')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') assert '1st field' in resp.text resp = resp.click('Edit', href='1/') assert resp.forms[0]['label'].value == '1st field' resp.forms[0]['label'] = 'changed field' resp.forms[0]['required'] = False resp = resp.forms[0].submit('items$add_element') # this adds a second field assert 'items$element0' in resp.form.fields assert 'items$element1' in resp.form.fields # but don't fill anything resp = resp.forms[0].submit('submit') assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1' resp = resp.follow() assert FormDef.get(1).fields[0].label == 'changed field' assert FormDef.get(1).fields[0].required is False assert FormDef.get(1).fields[0].items is None # edit and fill with one item resp = resp.click('Edit', href='1/') assert resp.forms[0]['label'].value == 'changed field' resp.forms[0]['items$element0'] = 'XXX' resp = resp.forms[0].submit('submit') assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1' assert FormDef.get(1).fields[0].items == ['XXX'] def test_form_edit_item_field_data_source(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.ItemField(id='1', label='1st field', type='item')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/1/') assert resp.form['data_source$type'].options == [ ('None', True, 'None'), ('json', False, 'JSON URL'), ('jsonp', False, 'JSONP URL'), ('python', False, 'Python Expression'), ] resp = resp.form.submit('submit').follow() data_source = NamedDataSource(name='Foobar') data_source.data_source = {'type': 'json', 'value': 'http://remote.example.net/404'} data_source.record_on_errors = True data_source.notify_on_errors = True data_source.store() resp = app.get('/backoffice/forms/1/fields/1/') assert resp.form['data_source$type'].options == [ ('None', True, 'None'), ('foobar', False, 'Foobar'), ('json', False, 'JSON URL'), ('jsonp', False, 'JSONP URL'), ('python', False, 'Python Expression'), ] resp.form['data_mode'].value = 'data-source' resp.form['data_source$type'].value = 'foobar' resp.form.submit('submit').follow() resp = app.get('/backoffice/forms/1/') assert FormDef.get(formdef.id).fields[0].data_source == {'type': 'foobar'} assert pub.loggederror_class.count() == 0 # error not recorded carddef = CardDef() carddef.name = 'Baz' carddef.store() resp = app.get('/backoffice/forms/1/fields/1/') assert resp.form['data_source$type'].options == [ ('None', False, 'None'), ('foobar', True, 'Foobar'), ('json', False, 'JSON URL'), ('jsonp', False, 'JSONP URL'), ('python', False, 'Python Expression'), ] carddef.digest_templates = {'default': 'plop'} carddef.store() resp = app.get('/backoffice/forms/1/fields/1/') assert resp.form['data_source$type'].options == [ ('None', False, 'None'), ('carddef:%s' % carddef.url_name, False, 'Baz'), ('foobar', True, 'Foobar'), ('json', False, 'JSON URL'), ('jsonp', False, 'JSONP URL'), ('python', False, 'Python Expression'), ] assert ( resp.pyquery('select#form_data_source__type option')[1].attrib['data-goto-url'] == carddef.get_admin_url() ) assert ( resp.pyquery('select#form_data_source__type option')[2].attrib['data-goto-url'] == data_source.get_admin_url() ) resp.form['data_source$type'].value = 'carddef:%s' % carddef.url_name resp = resp.form.submit('submit').follow() assert FormDef.get(formdef.id).fields[0].data_source == {'type': 'carddef:%s' % carddef.url_name} # set json source then back to none resp = app.get('/backoffice/forms/1/fields/1/') resp.form['data_source$type'].value = 'json' resp.form['data_source$value'].value = 'http://whatever' resp = resp.form.submit('submit').follow() assert FormDef.get(formdef.id).fields[0].data_source == {'type': 'json', 'value': 'http://whatever'} resp = app.get('/backoffice/forms/1/fields/1/') resp.form['data_source$type'].value = 'None' resp = resp.form.submit('submit').follow() resp = app.get('/backoffice/forms/1/') # change configuration for items resp = app.get('/backoffice/forms/1/fields/1/') resp.form['data_mode'].value = 'simple-list' resp.form['items$element0'] = 'XXX' resp = resp.form.submit('submit').follow() assert FormDef.get(1).fields[0].data_source is None assert FormDef.get(1).fields[0].items == ['XXX'] def test_form_edit_item_field_data_source_with_categories(pub): create_superuser(pub) create_role(pub) FormDef.wipe() CardDef.wipe() DataSourceCategory.wipe() NamedDataSource.wipe() data_source = NamedDataSource(name='test') data_source.store() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.ItemField(id='1', label='1st field', type='item')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/1/') assert [o[0] for o in resp.form['data_source$type'].options] == [ 'None', 'test', 'json', 'jsonp', 'python', ] cat_b = DataSourceCategory(name='Cat B') cat_b.store() data_source = NamedDataSource(name='foo bar') data_source.category_id = cat_b.id data_source.store() data_source = NamedDataSource(name='bar foo') data_source.category_id = cat_b.id data_source.store() cat_a = DataSourceCategory(name='Cat A') cat_a.store() data_source = NamedDataSource(name='foo baz') data_source.category_id = cat_a.id data_source.store() resp = app.get('/backoffice/forms/1/fields/1/') assert [o[0] for o in resp.form['data_source$type'].options] == [ 'None', 'foo_baz', 'bar_foo', 'foo_bar', 'test', 'json', 'jsonp', 'python', ] def test_form_edit_item_field_geojson_data_source(pub, http_requests): NamedDataSource.wipe() create_superuser(pub) create_role(pub) NamedDataSource.wipe() data_source = NamedDataSource(name='foobar') data_source.data_source = { 'type': 'geojson', 'value': 'http://remote.example.net/geojson', } data_source.id_property = 'id' data_source.label_template_property = '{{ text }}' data_source.cache_duration = '5' data_source.store() FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.ItemField(id='1', label='1st field', type='item')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/1/') resp.form['display_mode'] = 'map' assert resp.pyquery('option[value=foobar][data-type=geojson]') resp.form['data_mode'] = 'data-source' resp.form['data_source$type'] = 'foobar' resp.form['min_zoom'] = 'Wide area' resp.form['max_zoom'] = 'Small road' resp = resp.form.submit('submit').follow() formdef = FormDef.get(formdef.id) assert formdef.fields[0].data_source == {'type': 'foobar'} assert formdef.fields[0].min_zoom == '9' resp = app.get('/backoffice/forms/1/fields/1/') assert resp.form['min_zoom'].value == 'Wide area' def test_form_edit_items_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.ItemsField(id='1', label='1st field', type='items')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') assert '1st field' in resp.text resp = resp.click('Edit', href='1/') assert resp.forms[0]['label'].value == '1st field' assert resp.forms[0]['min_choices'].value == '0' assert resp.forms[0]['max_choices'].value == '0' resp.forms[0]['label'] = 'changed field' resp.forms[0]['required'] = False resp = resp.forms[0].submit('items$add_element') # this adds a second field assert 'items$element0' in resp.form.fields assert 'items$element1' in resp.form.fields # but don't fill anything resp = resp.forms[0].submit('submit') assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1' resp = resp.follow() assert FormDef.get(1).fields[0].label == 'changed field' assert FormDef.get(1).fields[0].required is False assert FormDef.get(1).fields[0].items is None assert FormDef.get(1).fields[0].min_choices == 0 assert FormDef.get(1).fields[0].max_choices == 0 # edit and fill with one item resp = resp.click('Edit', href='1/') assert resp.forms[0]['label'].value == 'changed field' resp.forms[0]['items$element0'] = 'XXX' resp.forms[0]['min_choices'] = 2 resp.forms[0]['max_choices'] = 5 resp = resp.forms[0].submit('submit') assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1' assert FormDef.get(1).fields[0].items == ['XXX'] assert FormDef.get(1).fields[0].min_choices == 2 assert FormDef.get(1).fields[0].max_choices == 5 # check prefilling is possible with a template or a Python expression resp = resp.follow() resp = resp.click('Edit', href='1/') assert resp.forms[0]['prefill$type'].options == [ ('None', True, 'None'), ('String / Template', False, 'String / Template'), ('Python Expression', False, 'Python Expression'), ] # change configuration for datasource resp = app.get('/backoffice/forms/1/fields/1/') resp.form['data_mode'].value = 'data-source' resp.form['data_source$type'].value = 'json' resp.form['data_source$value'].value = 'http://whatever' resp = resp.form.submit('submit').follow() assert FormDef.get(1).fields[0].data_source == {'type': 'json', 'value': 'http://whatever'} # change configuration for items resp = app.get('/backoffice/forms/1/fields/1/') resp.form['data_mode'].value = 'simple-list' resp = resp.form.submit('submit').follow() assert FormDef.get(1).fields[0].data_source is None assert FormDef.get(1).fields[0].items == ['XXX'] def test_form_edit_items_datasource(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.ItemsField(id='1', label='1st field', type='items')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') assert '1st field' in resp.text resp = app.get('/backoffice/forms/1/fields/1/') resp.form['data_mode'].value = 'data-source' resp.form['data_source$type'].value = 'json' resp.form['data_source$value'].value = 'random string' resp = resp.form.submit('submit') assert 'Value must be a full URL.' in resp.text resp.form['data_source$value'].value = 'http://whatever' resp = resp.form.submit('submit').follow() assert FormDef.get(1).fields[0].data_source == {'type': 'json', 'value': 'http://whatever'} # check template strings are ok resp = app.get('/backoffice/forms/1/fields/1/') resp.form['data_mode'].value = 'data-source' resp.form['data_source$type'].value = 'json' resp.form['data_source$value'].value = '{{url}}' resp = resp.form.submit('submit').follow() assert FormDef.get(1).fields[0].data_source == {'type': 'json', 'value': '{{url}}'} def test_form_edit_page_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/') resp = resp.click(href='fields/') assert 'There are not yet any fields' in resp.text resp.forms[0]['label'] = 'foobar' resp.forms[0]['type'] = 'page' resp = resp.forms[0].submit() assert resp.location == 'http://example.net/backoffice/forms/1/fields/' resp = resp.follow() assert 'Page #1' in resp.text assert 'foobar' in resp.text assert 'Use drag and drop' in resp.text assert len(FormDef.get(1).fields) == 1 assert FormDef.get(1).fields[0].key == 'page' assert FormDef.get(1).fields[0].label == 'foobar' resp = resp.click('Edit', href='1/') resp.form['post_conditions$element0$condition$type'] = 'python' resp.form['post_conditions$element0$condition$value_python'] = 'foo' resp.form['post_conditions$element0$error_message'] = 'bar' resp = resp.form.submit('post_conditions$add_element') # check advanced tab is open after adding a line assert resp.pyquery('[aria-selected="true"]').text() == 'Advanced' resp.form['post_conditions$element1$condition$type'] = 'python' resp.form['post_conditions$element1$condition$value_python'] = 'foo2' resp = resp.form.submit('submit') assert 'Both condition and error message are required.' in resp.text resp.form['post_conditions$element1$error_message'] = 'bar2' resp = resp.form.submit('submit').follow() assert FormDef.get(1).fields[0].post_conditions == [ {'condition': {'type': 'python', 'value': 'foo'}, 'error_message': 'bar'}, {'condition': {'type': 'python', 'value': 'foo2'}, 'error_message': 'bar2'}, ] resp = resp.click('Edit', href='1/') resp.form['post_conditions$element1$condition$type'] = 'django' resp.form['post_conditions$element1$condition$value_django'] = 'foo3' resp = resp.form.submit('submit').follow() assert FormDef.get(1).fields[0].post_conditions == [ {'condition': {'type': 'python', 'value': 'foo'}, 'error_message': 'bar'}, {'condition': {'type': 'django', 'value': 'foo3'}, 'error_message': 'bar2'}, ] # check error in expression resp = resp.click('Edit', href='1/') resp.form['post_conditions$element1$condition$type'] = 'django' resp.form['post_conditions$element1$condition$value_django'] = 'foo3 >' resp = resp.form.submit('submit') assert 'syntax error: Unexpected end of expression in if tag.' in resp.text def test_form_edit_comment_field(pub): create_superuser(pub) create_role(pub) FormDef.wipe() formdef = FormDef() formdef.name = 'form title' formdef.fields = [fields.CommentField(id='1', label='a comment field', type='comment')] formdef.store() app = login(get_app(pub)) resp = app.get('/backoffice/forms/1/fields/1/') assert 'a comment field' in resp.text assert 'WysiwygTextWidget' in resp.text # legacy, double line breaks will be converted to paragraphs formdef.fields = [fields.CommentField(id='1', type='comment', label='a comment field\n\na second line')] formdef.store() resp = app.get('/backoffice/forms/1/fields/1/') assert 'WysiwygTextWidget' in resp.text resp = resp.form.submit('submit') assert FormDef.get(formdef.id).fields[0].label == 'a comment field
\na second line
' # starting with a < formdef.fields = [ fields.CommentField(id='1', type='comment', label='a comment field\n\na second line') ] formdef.store() resp = app.get('/backoffice/forms/1/fields/1/') assert 'WysiwygTextWidget' in resp.text # legacy, ezt syntax in a non-html field will be presented as a textarea formdef.fields = [fields.CommentField(id='1', type='comment', label='[if-any toto]hello world[end]')] formdef.store() resp = app.get('/backoffice/forms/1/fields/1/') assert 'WysiwygTextWidget' not in resp.text # check a new field is created with label as HTML, enclosing label inresp = app.get('/backoffice/forms/1/fields/') resp.forms[0]['label'] = 'foobar' resp.forms[0]['type'] = 'comment' resp = resp.forms[0].submit() assert resp.location == 'http://example.net/backoffice/forms/1/fields/' assert FormDef.get(formdef.id).fields[-1].label == '
foobar
' # unless label is already given as HTML resp = app.get('/backoffice/forms/1/fields/') resp.forms[0]['label'] = '