913 lines
32 KiB
Python
913 lines
32 KiB
Python
import io
|
|
import time
|
|
import xml.etree.ElementTree as ET
|
|
|
|
import pytest
|
|
|
|
from wcs.blocks import BlockDef
|
|
from wcs.carddef import CardDef
|
|
from wcs.categories import Category
|
|
from wcs.formdef import FormDef, FormdefImportError, fields
|
|
from wcs.qommon.misc import indent_xml as indent
|
|
from wcs.workflows import Workflow
|
|
|
|
from .utilities import clean_temporary_pub, create_temporary_pub
|
|
|
|
|
|
@pytest.fixture
|
|
def pub(request):
|
|
return create_temporary_pub()
|
|
|
|
|
|
def teardown_module(module):
|
|
clean_temporary_pub()
|
|
|
|
|
|
def export_to_indented_xml(formdef, include_id=False):
|
|
formdef_xml = ET.fromstring(ET.tostring(formdef.export_to_xml(include_id=include_id)))
|
|
indent(formdef_xml)
|
|
return formdef_xml
|
|
|
|
|
|
def assert_compare_formdef(formdef1, formdef2, include_id=False):
|
|
assert ET.tostring(export_to_indented_xml(formdef1, include_id=include_id)) == ET.tostring(
|
|
export_to_indented_xml(formdef2, include_id=include_id)
|
|
)
|
|
assert formdef1.export_to_json(include_id=include_id, indent=2) == formdef2.export_to_json(
|
|
include_id=include_id, indent=2
|
|
)
|
|
|
|
|
|
def assert_xml_import_export_works(formdef, include_id=False):
|
|
formdef_xml = formdef.export_to_xml(include_id=include_id)
|
|
formdef2 = FormDef.import_from_xml_tree(formdef_xml, include_id=include_id)
|
|
assert_compare_formdef(formdef, formdef2, include_id=include_id)
|
|
return formdef2
|
|
|
|
|
|
def assert_json_import_export_works(formdef, include_id=False):
|
|
formdef2 = FormDef.import_from_json(
|
|
io.StringIO(formdef.export_to_json(include_id=include_id)), include_id=include_id
|
|
)
|
|
assert_compare_formdef(formdef, formdef2, include_id=include_id)
|
|
return formdef2
|
|
|
|
|
|
def test_empty(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'empty'
|
|
assert_xml_import_export_works(formdef)
|
|
assert_json_import_export_works(formdef)
|
|
|
|
|
|
def test_text_attributes(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.url_name = 'foo'
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert f2.url_name == formdef.url_name
|
|
f2 = assert_json_import_export_works(formdef)
|
|
assert f2.url_name == formdef.url_name
|
|
|
|
|
|
def test_empty_description_tag(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'empty'
|
|
assert_xml_import_export_works(formdef)
|
|
export = ET.tostring(export_to_indented_xml(formdef))
|
|
# add empty description tag
|
|
export = export.replace(b'<name>empty</name>', b'<name>empty</name><description></description>')
|
|
formdef2 = FormDef.import_from_xml_tree(ET.fromstring(export))
|
|
assert not formdef2.description
|
|
|
|
|
|
def test_empty_display_locations_tag(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.TitleField(label='title', display_locations=[]),
|
|
fields.SubtitleField(label='subtitle', display_locations=[]),
|
|
fields.TextField(label='string', display_locations=[]),
|
|
]
|
|
|
|
formdef_xml = formdef.export_to_xml()
|
|
f1 = formdef_xml.findall('fields/field')[0]
|
|
f2 = formdef_xml.findall('fields/field')[1]
|
|
f3 = formdef_xml.findall('fields/field')[2]
|
|
assert '<display_locations />' in str(ET.tostring(f1))
|
|
assert '<display_locations />' in str(ET.tostring(f2))
|
|
assert '<display_locations />' in str(ET.tostring(f3))
|
|
|
|
formdef2 = assert_xml_import_export_works(formdef)
|
|
assert formdef2.fields[0].display_locations == []
|
|
assert formdef2.fields[1].display_locations == []
|
|
assert formdef2.fields[2].display_locations == []
|
|
formdef2_xml = formdef2.export_to_xml()
|
|
f1 = formdef2_xml.findall('fields/field')[0]
|
|
f2 = formdef2_xml.findall('fields/field')[1]
|
|
f3 = formdef2_xml.findall('fields/field')[2]
|
|
assert '<display_locations />' in str(ET.tostring(f1))
|
|
assert '<display_locations />' in str(ET.tostring(f2))
|
|
assert '<display_locations />' in str(ET.tostring(f3))
|
|
|
|
|
|
def test_boolean_attributes(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.url_name = 'foo'
|
|
formdef.confirmation = True
|
|
formdef.enable_tracking_codes = True
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert f2.enable_tracking_codes == formdef.enable_tracking_codes
|
|
assert f2.confirmation == formdef.confirmation
|
|
f2 = assert_json_import_export_works(formdef)
|
|
assert f2.enable_tracking_codes == formdef.enable_tracking_codes
|
|
assert f2.confirmation == formdef.confirmation
|
|
|
|
|
|
def test_a_field(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [fields.StringField(id=1, label='Bar', size='40')]
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
f2 = assert_json_import_export_works(formdef)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
|
|
|
|
def test_field_with_True_as_label(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.url_name = 'foo'
|
|
formdef.fields = [fields.StringField(id=1, label='True', size='40')]
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert f2.fields[0].label == 'True'
|
|
|
|
|
|
def test_more_fields(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Blah'
|
|
formdef.fields = [
|
|
fields.TextField(label='Bar', display_mode='pre'),
|
|
fields.EmailField(label='Bar'),
|
|
fields.BoolField(label='Bar'),
|
|
fields.DateField(label='Bar', minimum_date='2014-01-01'),
|
|
fields.ItemField(label='Bar', items=['foo', 'bar', 'baz']),
|
|
]
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert f2.fields[2].key == formdef.fields[2].key
|
|
assert f2.fields[3].minimum_date == formdef.fields[3].minimum_date
|
|
assert f2.fields[4].items == formdef.fields[4].items
|
|
|
|
f2 = assert_json_import_export_works(formdef)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert f2.fields[2].key == formdef.fields[2].key
|
|
assert f2.fields[3].minimum_date == formdef.fields[3].minimum_date
|
|
assert f2.fields[4].items == formdef.fields[4].items
|
|
|
|
|
|
def test_item_radio(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Blah'
|
|
formdef.fields = [
|
|
fields.ItemField(
|
|
label='Bar',
|
|
items=['foo', 'bar', 'baz'],
|
|
list_mode='radio',
|
|
id='1',
|
|
),
|
|
]
|
|
|
|
# test new mode
|
|
assert_json_import_export_works(formdef, include_id=True)
|
|
|
|
# test conversion of legacy show_as_radio attribute
|
|
formdef_xml = formdef.export_to_xml(include_id=True)
|
|
field = formdef_xml.findall('fields/field')[0]
|
|
ET.SubElement(field, 'show_as_radio').text = 'True'
|
|
field.remove(field.find('display_mode'))
|
|
fd2 = FormDef.import_from_xml_tree(formdef_xml, include_id=True)
|
|
assert fd2.fields[0].display_mode == 'radio'
|
|
|
|
# test conversion of legacy show_as_radio attribute
|
|
formdef_xml = formdef.export_to_xml(include_id=True)
|
|
field = formdef_xml.findall('fields/field')[0]
|
|
ET.SubElement(field, 'show_as_radio').text = 'False'
|
|
field.remove(field.find('display_mode'))
|
|
fd2 = FormDef.import_from_xml_tree(formdef_xml, include_id=True)
|
|
assert fd2.fields[0].display_mode == 'list'
|
|
|
|
|
|
def test_include_id(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Blah'
|
|
formdef.fields = [
|
|
fields.TextField(label='Bar', display_mode='pre'),
|
|
fields.EmailField(label='Bar'),
|
|
fields.BoolField(label='Bar'),
|
|
fields.DateField(label='Bar', minimum_date='2014-01-01'),
|
|
fields.ItemField(label='Bar', items=['foo', 'bar', 'baz']),
|
|
]
|
|
for field in formdef.fields:
|
|
field.id = formdef.get_new_field_id()
|
|
formdef.fields[4].id = '10'
|
|
f2 = assert_xml_import_export_works(formdef, include_id=True)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert f2.fields[0].id == formdef.fields[0].id
|
|
assert f2.fields[4].id == formdef.fields[4].id
|
|
|
|
f2 = assert_json_import_export_works(formdef, include_id=True)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert f2.fields[0].id == formdef.fields[0].id
|
|
assert f2.fields[4].id == formdef.fields[4].id
|
|
|
|
|
|
def test_workflow_options(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'workflow options'
|
|
formdef.workflow_options = {'foo': 'bar', 'foo2': 'baré'}
|
|
fd2 = assert_xml_import_export_works(formdef)
|
|
assert fd2.workflow_options == formdef.workflow_options
|
|
fd2 = assert_json_import_export_works(formdef)
|
|
assert fd2.workflow_options == formdef.workflow_options
|
|
|
|
|
|
def test_workflow_options_with_no_values(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.workflow_options = {'foo': None, 'foo2': None}
|
|
fd2 = assert_xml_import_export_works(formdef)
|
|
assert fd2.workflow_options == formdef.workflow_options
|
|
fd2 = assert_json_import_export_works(formdef)
|
|
assert fd2.workflow_options == formdef.workflow_options
|
|
|
|
|
|
def test_workflow_options_with_file(pub):
|
|
from quixote.http_request import Upload
|
|
|
|
from wcs.qommon.form import UploadedFile
|
|
|
|
upload = Upload('/foo/bar', content_type='application/vnd.oasis.opendocument.text')
|
|
file_content = b'''PK\x03\x04\x14\x00\x00\x08\x00\x00\'l\x8eG^\xc62\x0c\'\x00'''
|
|
upload.fp = io.BytesIO()
|
|
upload.fp.write(file_content)
|
|
upload.fp.seek(0)
|
|
model_file = UploadedFile(pub.APP_DIR, None, upload)
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.workflow_options = {'foo': model_file}
|
|
fd2 = assert_xml_import_export_works(formdef)
|
|
assert formdef.workflow_options['foo'].filename == fd2.workflow_options['foo'].filename
|
|
assert formdef.workflow_options['foo'].get_content() == fd2.workflow_options['foo'].get_content()
|
|
fd2 = assert_json_import_export_works(formdef)
|
|
assert formdef.workflow_options['foo'].filename == fd2.workflow_options['foo'].filename
|
|
assert formdef.workflow_options['foo'].get_content() == fd2.workflow_options['foo'].get_content()
|
|
|
|
|
|
def test_workflow_options_with_date(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.workflow_options = {'foo': time.strptime('2014-02-02', '%Y-%m-%d')}
|
|
fd2 = assert_xml_import_export_works(formdef)
|
|
assert formdef.workflow_options['foo'] == fd2.workflow_options['foo']
|
|
|
|
|
|
def test_workflow_options_with_boolean(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.workflow_options = {'foo': True, 'bar': False}
|
|
fd2 = assert_xml_import_export_works(formdef)
|
|
assert formdef.workflow_options['foo'] == fd2.workflow_options['foo']
|
|
|
|
|
|
def test_workflow_reference(pub):
|
|
Workflow.wipe()
|
|
FormDef.wipe()
|
|
|
|
wf = Workflow()
|
|
wf.name = 'test workflow'
|
|
wf.store()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.workflow_id = wf.id
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert f2.workflow_id == formdef.workflow_id
|
|
|
|
f2 = assert_xml_import_export_works(formdef, include_id=True)
|
|
assert f2.workflow_id == formdef.workflow_id
|
|
|
|
formdef_xml_with_id = formdef.export_to_xml(include_id=True)
|
|
|
|
# check there's no reference to a non-existing workflow
|
|
Workflow.wipe()
|
|
assert FormDef.import_from_xml_tree(formdef_xml_with_id, include_id=False).workflow_id is None
|
|
assert FormDef.import_from_xml_tree(formdef_xml_with_id, include_id=True).workflow_id is None
|
|
|
|
# check an import that is not using id fields will find the workflow by its
|
|
# name
|
|
wf = Workflow()
|
|
wf.id = '2'
|
|
wf.name = 'test workflow'
|
|
wf.store()
|
|
assert FormDef.import_from_xml_tree(formdef_xml_with_id, include_id=False).workflow_id == '2'
|
|
assert FormDef.import_from_xml_tree(formdef_xml_with_id, include_id=True).workflow_id is None
|
|
|
|
|
|
def test_category_reference(pub):
|
|
Category.wipe()
|
|
FormDef.wipe()
|
|
|
|
cat = Category()
|
|
cat.name = 'test category'
|
|
cat.store()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.category_id = cat.id
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert f2.category_id == formdef.category_id
|
|
|
|
f2 = assert_xml_import_export_works(formdef, include_id=True)
|
|
assert f2.category_id == formdef.category_id
|
|
|
|
formdef_xml_with_id = formdef.export_to_xml(include_id=True)
|
|
|
|
# check there's no reference to a non-existing category
|
|
Category.wipe()
|
|
assert FormDef.import_from_xml_tree(formdef_xml_with_id, include_id=False).category_id is None
|
|
assert FormDef.import_from_xml_tree(formdef_xml_with_id, include_id=True).category_id is None
|
|
|
|
# check an import that is not using id fields will find the category by its
|
|
# name
|
|
cat = Category()
|
|
cat.id = '2'
|
|
cat.name = 'test category'
|
|
cat.store()
|
|
assert FormDef.import_from_xml_tree(formdef_xml_with_id, include_id=False).category_id == '2'
|
|
assert FormDef.import_from_xml_tree(formdef_xml_with_id, include_id=True).category_id is None
|
|
|
|
|
|
def test_file_field(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = [
|
|
fields.FileField(
|
|
id='1',
|
|
document_type={
|
|
'id': 'justificatif-de-domicile',
|
|
'fargo': True,
|
|
'mimetypes': [
|
|
'application/pdf,application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
'image/*',
|
|
],
|
|
},
|
|
)
|
|
]
|
|
assert_xml_import_export_works(formdef, include_id=True)
|
|
assert_xml_import_export_works(formdef)
|
|
assert_json_import_export_works(formdef, include_id=True)
|
|
assert_json_import_export_works(formdef)
|
|
|
|
|
|
def test_invalid_field_type(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = [fields.StringField(id='1')]
|
|
export = ET.tostring(export_to_indented_xml(formdef)).replace(b'<type>string</type>', b'<type>xxx</type>')
|
|
with pytest.raises(FormdefImportError):
|
|
FormDef.import_from_xml(io.BytesIO(export), include_id=True)
|
|
|
|
|
|
def test_invalid_data_source(pub):
|
|
# manually edited exports
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = [fields.StringField(id='1', data_source={'type': 'xxx'})]
|
|
export = ET.tostring(formdef.export_to_xml(include_id=False))
|
|
export = export.replace(
|
|
b'<data_source><type>xxx</type></data_source>', b'<data_source><type/></data_source>'
|
|
)
|
|
formdef2 = FormDef.import_from_xml(io.BytesIO(export))
|
|
assert formdef2.fields[0].data_source == {}
|
|
|
|
export = export.replace(b'<data_source><type/></data_source>', b'<data_source> </data_source>')
|
|
formdef2 = FormDef.import_from_xml(io.BytesIO(export))
|
|
assert formdef2.fields[0].data_source == {}
|
|
|
|
|
|
def test_unknown_data_source(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = [fields.StringField(id='1', data_source={'type': 'json', 'value': 'http://example.net'})]
|
|
export = ET.tostring(export_to_indented_xml(formdef))
|
|
|
|
FormDef.import_from_xml(io.BytesIO(export))
|
|
|
|
formdef.fields = [fields.StringField(id='1', data_source={'type': 'foobar'})]
|
|
export = ET.tostring(export_to_indented_xml(formdef))
|
|
with pytest.raises(FormdefImportError) as excinfo:
|
|
FormDef.import_from_xml(io.BytesIO(export))
|
|
assert excinfo.value.msg == 'Unknown referenced objects'
|
|
assert excinfo.value.details == 'Unknown datasources: foobar'
|
|
|
|
# carddef as datasource
|
|
carddef = CardDef()
|
|
carddef.name = 'foo'
|
|
carddef.fields = [
|
|
fields.StringField(id='1', label='Test', varname='foo'),
|
|
]
|
|
carddef.store()
|
|
|
|
formdef.fields = [fields.StringField(id='1', data_source={'type': 'carddef:foo'})]
|
|
export = ET.tostring(export_to_indented_xml(formdef))
|
|
FormDef.import_from_xml(io.BytesIO(export))
|
|
|
|
formdef.fields = [fields.StringField(id='1', data_source={'type': 'carddef:unknown'})]
|
|
export = ET.tostring(export_to_indented_xml(formdef))
|
|
with pytest.raises(FormdefImportError):
|
|
FormDef.import_from_xml(io.BytesIO(export))
|
|
|
|
# cards filtered on user
|
|
formdef.fields = [fields.StringField(id='1', data_source={'type': 'carddef:foo:_with_user_filter'})]
|
|
export = ET.tostring(export_to_indented_xml(formdef))
|
|
FormDef.import_from_xml(io.BytesIO(export))
|
|
|
|
# carddef custom view as datasource
|
|
pub.custom_view_class.wipe()
|
|
custom_view = pub.custom_view_class()
|
|
custom_view.title = 'card view'
|
|
custom_view.formdef = carddef
|
|
custom_view.columns = {'list': [{'id': 'id'}]}
|
|
custom_view.filters = {}
|
|
custom_view.visibility = 'datasource'
|
|
custom_view.store()
|
|
|
|
formdef.fields = [fields.StringField(id='1', data_source={'type': 'carddef:foo:card-view'})]
|
|
export = ET.tostring(export_to_indented_xml(formdef))
|
|
FormDef.import_from_xml(io.BytesIO(export))
|
|
|
|
formdef.fields = [fields.StringField(id='1', data_source={'type': 'carddef:foo:unknown'})]
|
|
export = ET.tostring(export_to_indented_xml(formdef))
|
|
with pytest.raises(FormdefImportError):
|
|
FormDef.import_from_xml(io.BytesIO(export))
|
|
|
|
|
|
def test_formdef_with_block(pub):
|
|
BlockDef.wipe()
|
|
block = BlockDef()
|
|
block.name = 'foobar'
|
|
block.digest_template = 'X{{foobar_var_foo}}Y'
|
|
block.fields = [
|
|
fields.StringField(id='123', required=True, label='Test', varname='foo'),
|
|
]
|
|
block.store()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = [fields.BlockField(id='1', block_slug='foobar')]
|
|
|
|
BlockDef.wipe()
|
|
export = ET.tostring(export_to_indented_xml(formdef))
|
|
with pytest.raises(FormdefImportError) as excinfo:
|
|
FormDef.import_from_xml(io.BytesIO(export))
|
|
assert excinfo.value.msg == 'Unknown referenced objects'
|
|
assert excinfo.value.details == 'Unknown fields blocks: foobar'
|
|
|
|
|
|
def test_formdef_with_block_legacy(pub):
|
|
BlockDef.wipe()
|
|
block = BlockDef()
|
|
block.name = 'foobar'
|
|
block.digest_template = 'X{{foobar_var_foo}}Y'
|
|
block.fields = [
|
|
fields.StringField(id='123', required=True, label='Test', varname='foo'),
|
|
]
|
|
block.store()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = [fields.BlockField(id='1', block_slug='foobar')]
|
|
|
|
export = (
|
|
ET.tostring(export_to_indented_xml(formdef))
|
|
.replace(b'<block_slug type="str">foobar</block_slug', b'')
|
|
.replace(b'<type>block</type>', b'<type>block:foobar</type>')
|
|
)
|
|
formdef = FormDef.import_from_xml(io.BytesIO(export))
|
|
assert formdef.fields[0].key == 'block'
|
|
assert formdef.fields[0].block_slug == 'foobar'
|
|
|
|
|
|
def test_duplicated_field_ids(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = [
|
|
fields.StringField(id='2'),
|
|
fields.StringField(id='2'),
|
|
fields.StringField(id='1'),
|
|
]
|
|
export = ET.tostring(export_to_indented_xml(formdef, include_id=True))
|
|
|
|
with pytest.raises(FormdefImportError):
|
|
FormDef.import_from_xml(io.BytesIO(export))
|
|
|
|
with pytest.raises(FormdefImportError):
|
|
FormDef.import_from_xml(io.BytesIO(export), include_id=True)
|
|
|
|
formdef2 = FormDef.import_from_xml(io.BytesIO(export), fix_on_error=True)
|
|
assert formdef2.fields[0].id == '1'
|
|
assert formdef2.fields[1].id == '2'
|
|
assert formdef2.fields[2].id == '3'
|
|
|
|
|
|
def test_page_condition(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = [fields.PageField(id='1', condition={'type': 'python', 'value': 'blah'})]
|
|
fd2 = assert_xml_import_export_works(formdef)
|
|
assert fd2.fields[0].key == 'page'
|
|
assert fd2.fields[0].condition == formdef.fields[0].condition
|
|
|
|
# test legacy condition (simple string)
|
|
formdef_xml = formdef.export_to_xml(include_id=True)
|
|
condition = formdef_xml.findall('fields/field/condition')[0]
|
|
condition.clear()
|
|
condition.text = 'blah'
|
|
fd2 = FormDef.import_from_xml_tree(formdef_xml, include_id=True)
|
|
assert fd2.fields[0].condition == formdef.fields[0].condition
|
|
|
|
|
|
def test_page_post_conditions(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = [
|
|
fields.PageField(
|
|
id='1',
|
|
post_conditions=[{'condition': {'type': 'python', 'value': 'blah'}, 'error_message': 'bar'}],
|
|
),
|
|
]
|
|
fd2 = assert_xml_import_export_works(formdef)
|
|
assert fd2.fields[0].key == 'page'
|
|
assert fd2.fields[0].post_conditions == formdef.fields[0].post_conditions
|
|
|
|
# test legacy condition (simple string)
|
|
formdef_xml = formdef.export_to_xml(include_id=True)
|
|
post_condition = formdef_xml.findall('fields/field/post_conditions/post_condition/condition')[0]
|
|
post_condition.clear()
|
|
post_condition.text = 'blah'
|
|
fd2 = FormDef.import_from_xml_tree(formdef_xml, include_id=True)
|
|
assert fd2.fields[0].post_conditions[0]['condition'] == {'type': 'python', 'value': 'blah'}
|
|
assert fd2.fields[0].post_conditions[0]['error_message'] == 'bar'
|
|
|
|
# test incomplete post condition (not allowed anymore but old formdefs may
|
|
# have this)
|
|
formdef.fields = [
|
|
fields.PageField(
|
|
id='1',
|
|
post_conditions=[{'condition': {'type': 'python', 'value': 'blah'}, 'error_message': None}],
|
|
),
|
|
]
|
|
formdef_xml = formdef.export_to_xml(include_id=True)
|
|
fd2 = FormDef.import_from_xml_tree(formdef_xml, include_id=True)
|
|
assert fd2.fields[0].post_conditions[0]['condition'] == {'type': 'python', 'value': 'blah'}
|
|
assert fd2.fields[0].post_conditions[0]['error_message'] == ''
|
|
|
|
|
|
def test_geolocations(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = []
|
|
formdef.geolocations = {'base': 'Base'}
|
|
fd2 = assert_xml_import_export_works(formdef, include_id=True)
|
|
assert fd2.geolocations == formdef.geolocations
|
|
fd3 = assert_json_import_export_works(formdef)
|
|
assert fd3.geolocations == formdef.geolocations
|
|
|
|
|
|
def test_workflow_roles(pub):
|
|
pub.role_class.wipe()
|
|
role = pub.role_class(name='blah')
|
|
role.store()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = []
|
|
formdef.workflow_roles = {'_receiver': role.id}
|
|
fd2 = assert_xml_import_export_works(formdef, include_id=True)
|
|
assert fd2.workflow_roles.get('_receiver') == role.id
|
|
|
|
fd2 = assert_xml_import_export_works(formdef, include_id=False)
|
|
assert fd2.workflow_roles.get('_receiver') == role.id
|
|
|
|
xml_export = export_to_indented_xml(formdef, include_id=True)
|
|
|
|
# same id, different name
|
|
role.name = 'blah 2'
|
|
role.store()
|
|
|
|
fd2 = FormDef.import_from_xml_tree(xml_export, include_id=True)
|
|
assert fd2.workflow_roles.get('_receiver') == role.id
|
|
|
|
# found by slug
|
|
fd2 = FormDef.import_from_xml_tree(xml_export, include_id=False)
|
|
assert fd2.workflow_roles.get('_receiver') == role.id
|
|
|
|
role.slug = 'something else'
|
|
role.store()
|
|
fd2 = FormDef.import_from_xml_tree(xml_export, include_id=False)
|
|
assert fd2.workflow_roles.get('_receiver') is None
|
|
|
|
role.remove_self()
|
|
fd2 = FormDef.import_from_xml_tree(xml_export, include_id=True)
|
|
assert fd2.workflow_roles.get('_receiver') is None
|
|
|
|
|
|
def test_user_roles(pub):
|
|
pub.role_class.wipe()
|
|
|
|
role = pub.role_class(name='blah')
|
|
role.store()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = []
|
|
formdef.roles = ['logged-users', role.id]
|
|
fd2 = assert_xml_import_export_works(formdef, include_id=True)
|
|
assert fd2.roles == formdef.roles
|
|
|
|
formdef_xml = formdef.export_to_xml(include_id=True)
|
|
formdef_xml_no_id = formdef.export_to_xml(include_id=False)
|
|
role.remove_self()
|
|
fd2 = FormDef.import_from_xml_tree(formdef_xml, include_id=True)
|
|
assert fd2.roles == ['logged-users']
|
|
fd2 = FormDef.import_from_xml_tree(formdef_xml, include_id=False)
|
|
assert fd2.roles == ['logged-users']
|
|
|
|
fd2 = FormDef.import_from_xml_tree(formdef_xml_no_id, include_id=True)
|
|
assert fd2.roles == ['logged-users']
|
|
fd2 = FormDef.import_from_xml_tree(formdef_xml_no_id, include_id=False)
|
|
assert fd2.roles == ['logged-users']
|
|
|
|
|
|
def test_backoffice_submission_roles(pub):
|
|
pub.role_class.wipe()
|
|
|
|
role = pub.role_class(name='blah')
|
|
role.store()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = []
|
|
formdef.backoffice_submission_roles = [role.id]
|
|
fd2 = assert_xml_import_export_works(formdef, include_id=True)
|
|
assert fd2.backoffice_submission_roles == formdef.backoffice_submission_roles
|
|
|
|
|
|
def test_required_authentication_contexts(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = []
|
|
formdef.required_authentication_contexts = ['fedict']
|
|
fd2 = assert_xml_import_export_works(formdef, include_id=True)
|
|
assert fd2.required_authentication_contexts == formdef.required_authentication_contexts
|
|
|
|
|
|
def test_field_condition(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(id=1, label='Bar', size='40', condition={'type': 'django', 'value': '1'})
|
|
]
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert f2.fields[0].condition == {'type': 'django', 'value': '1'}
|
|
|
|
|
|
def test_field_validation(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [fields.StringField(id=1, label='Bar', size='40', validation={})]
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert not f2.fields[0].validation
|
|
|
|
formdef.fields = [fields.StringField(id=1, label='Bar', size='40', validation=None)]
|
|
formdef_xml = formdef.export_to_xml()
|
|
f2 = FormDef.import_from_xml_tree(formdef_xml)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert not f2.fields[0].validation
|
|
|
|
formdef.fields = [
|
|
fields.StringField(id=1, label='Bar', size='40', validation={'type': 'regex', 'value': r'\d'})
|
|
]
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert f2.fields[0].validation == formdef.fields[0].validation
|
|
|
|
# backward compatibility
|
|
formdef_xml = formdef.export_to_xml()
|
|
old_format = ET.tostring(formdef_xml).replace(
|
|
b'<validation><type>regex</type><value>\\d</value></validation>', b'<validation>\\d</validation>'
|
|
)
|
|
f2 = FormDef.import_from_xml(io.BytesIO(old_format))
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert f2.fields[0].validation == {'type': 'regex', 'value': '\\d'}
|
|
|
|
|
|
def test_digest_templates(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = []
|
|
formdef.digest_templates = {'default': '{{form_number}}', 'custom-view:foo-bar': 'plop'}
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert f2.digest_templates == formdef.digest_templates
|
|
|
|
|
|
def test_field_prefill(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.fields = [
|
|
fields.StringField(id=1, label='Bar', size='40', prefill={'type': 'string', 'value': 'plop'})
|
|
]
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert f2.fields[0].prefill == {'type': 'string', 'value': 'plop'}
|
|
|
|
formdef.fields = [
|
|
fields.StringField(
|
|
id=1,
|
|
label='Bar',
|
|
size='40',
|
|
prefill={'type': 'string', 'value': 'plop', 'locked': True},
|
|
)
|
|
]
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert f2.fields[0].prefill == {'type': 'string', 'value': 'plop', 'locked': True}
|
|
|
|
formdef.fields = [
|
|
fields.StringField(
|
|
id=1,
|
|
label='Bar',
|
|
size='40',
|
|
prefill={'type': 'string', 'value': 'plop', 'locked': False},
|
|
)
|
|
]
|
|
formdef_xml = formdef.export_to_xml()
|
|
f2 = FormDef.import_from_xml_tree(formdef_xml)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert f2.fields[0].prefill == {'type': 'string', 'value': 'plop'}
|
|
|
|
formdef.fields = [
|
|
fields.StringField(
|
|
id=1,
|
|
label='Bar',
|
|
size='40',
|
|
prefill={'type': 'string', 'value': 'plop', 'locked': False},
|
|
)
|
|
]
|
|
formdef_xml_str = ET.tostring(formdef.export_to_xml())
|
|
formdef_xml_str = formdef_xml_str.replace(b'<value>plop</value>', b'')
|
|
formdef_xml = ET.fromstring(formdef_xml_str)
|
|
f2 = FormDef.import_from_xml_tree(formdef_xml)
|
|
assert len(f2.fields) == len(formdef.fields)
|
|
assert f2.fields[0].prefill == {'type': 'string', 'value': None}
|
|
|
|
|
|
def test_custom_views(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = [
|
|
fields.StringField(id='1', label='Foo', varname='foo'),
|
|
fields.StringField(id='2', label='Bar', varname='bar'),
|
|
]
|
|
formdef.store()
|
|
|
|
# define also custom views
|
|
pub.custom_view_class.wipe()
|
|
|
|
custom_view = pub.custom_view_class()
|
|
custom_view.title = 'shared form view'
|
|
custom_view.formdef = formdef
|
|
custom_view.columns = {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
|
|
custom_view.filters = {'filter': 'done', 'filter-1': 'on', 'filter-status': 'on', 'filter-1-value': 'b'}
|
|
custom_view.visibility = 'any'
|
|
custom_view.order_by = 'receipt_time'
|
|
custom_view.store()
|
|
|
|
custom_view = pub.custom_view_class()
|
|
custom_view.title = 'private form view'
|
|
custom_view.formdef = formdef
|
|
custom_view.columns = {'list': [{'id': 'id'}]}
|
|
custom_view.filters = {}
|
|
custom_view.visibility = 'owner'
|
|
custom_view.usier_id = 42
|
|
custom_view.order_by = 'id'
|
|
custom_view.store()
|
|
|
|
formdef_xml = formdef.export_to_xml()
|
|
assert formdef_xml.tag == 'formdef'
|
|
formdef.data_class().wipe()
|
|
pub.custom_view_class.wipe()
|
|
|
|
formdef2 = FormDef.import_from_xml(io.BytesIO(ET.tostring(formdef_xml)))
|
|
assert formdef2.name == 'foo'
|
|
assert formdef2._custom_views
|
|
|
|
custom_views = formdef2._custom_views
|
|
assert len(custom_views) == 1
|
|
assert custom_views[0].title == 'shared form view'
|
|
assert custom_views[0].slug == 'shared-form-view'
|
|
assert custom_views[0].columns == {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
|
|
assert custom_views[0].filters == {
|
|
'filter': 'done',
|
|
'filter-1': 'on',
|
|
'filter-status': 'on',
|
|
'filter-1-value': 'b',
|
|
}
|
|
assert custom_views[0].visibility == 'any'
|
|
assert custom_views[0].order_by == 'receipt_time'
|
|
assert custom_views[0].formdef_id is None
|
|
assert custom_views[0].formdef_type is None
|
|
|
|
formdef2.store()
|
|
custom_views = pub.custom_view_class.select()
|
|
assert len(custom_views) == 1
|
|
assert custom_views[0].title == 'shared form view'
|
|
assert custom_views[0].slug == 'shared-form-view'
|
|
assert custom_views[0].columns == {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
|
|
assert custom_views[0].filters == {
|
|
'filter': 'done',
|
|
'filter-1': 'on',
|
|
'filter-status': 'on',
|
|
'filter-1-value': 'b',
|
|
}
|
|
assert custom_views[0].visibility == 'any'
|
|
assert custom_views[0].order_by == 'receipt_time'
|
|
assert custom_views[0].formdef_id == formdef2.id
|
|
assert custom_views[0].formdef_type == 'formdef'
|
|
|
|
|
|
def test_import_formdef_multiple_errors(pub):
|
|
BlockDef.wipe()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'foo'
|
|
formdef.fields = [
|
|
fields.BlockField(id='1', block_slug='foobar'),
|
|
fields.BlockField(id='2', block_slug='foobaz'),
|
|
fields.StringField(id='3', data_source={'type': 'foobar'}),
|
|
fields.StringField(id='4', data_source={'type': 'carddef:unknown'}),
|
|
fields.BoolField(id='5'),
|
|
]
|
|
|
|
export = ET.tostring(export_to_indented_xml(formdef)).replace(
|
|
b'<type>bool</type>', b'<type>foobaz</type>'
|
|
)
|
|
with pytest.raises(FormdefImportError) as excinfo:
|
|
FormDef.import_from_xml(io.BytesIO(export))
|
|
assert excinfo.value.msg == 'Unknown referenced objects'
|
|
assert excinfo.value.details == (
|
|
'Unknown datasources: carddef:unknown, foobar; '
|
|
'Unknown field types: foobaz; '
|
|
'Unknown fields blocks: foobar, foobaz'
|
|
)
|
|
|
|
|
|
def test_import_formdef_root_node_error():
|
|
export = b'<wrong_root_node><name>Name</name></wrong_root_node>'
|
|
with pytest.raises(FormdefImportError) as excinfo:
|
|
FormDef.import_from_xml(io.BytesIO(export))
|
|
assert (
|
|
excinfo.value.msg
|
|
== 'Provided XML file is invalid, it starts with a <wrong_root_node> tag instead of <formdef>'
|
|
)
|
|
|
|
with pytest.raises(FormdefImportError) as excinfo:
|
|
CardDef.import_from_xml(io.BytesIO(export))
|
|
assert (
|
|
excinfo.value.msg
|
|
== 'Provided XML file is invalid, it starts with a <wrong_root_node> tag instead of <carddef>'
|
|
)
|
|
|
|
|
|
def test_tracking_code_attributes(pub):
|
|
formdef = FormDef()
|
|
formdef.name = 'Foo'
|
|
formdef.url_name = 'foo'
|
|
formdef.confirmation = True
|
|
formdef.enable_tracking_codes = True
|
|
for verify_fields in (['1', '2'], [], None):
|
|
formdef.tracking_code_verify_fields = verify_fields
|
|
f2 = assert_xml_import_export_works(formdef)
|
|
assert f2.enable_tracking_codes == formdef.enable_tracking_codes
|
|
assert f2.tracking_code_verify_fields == formdef.tracking_code_verify_fields
|
|
assert f2.confirmation == formdef.confirmation
|
|
f2 = assert_json_import_export_works(formdef)
|
|
assert f2.enable_tracking_codes == formdef.enable_tracking_codes
|
|
assert f2.tracking_code_verify_fields == formdef.tracking_code_verify_fields
|
|
assert f2.confirmation == formdef.confirmation
|