wcs/tests/test_testdef.py

719 lines
22 KiB
Python

import datetime
import json
import time
import pytest
from wcs import fields
from wcs.blocks import BlockDef
from wcs.formdef import FormDef
from wcs.qommon.http_request import HTTPRequest
from wcs.qommon.upload_storage import PicklableUpload
from wcs.testdef import TestDef, TestError
from wcs.wscalls import NamedWsCall
from .utilities import clean_temporary_pub, create_temporary_pub
@pytest.fixture
def pub():
pub = create_temporary_pub()
req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
pub.set_app_dir(req)
pub.write_cfg()
FormDef.wipe()
return pub
def teardown_module(module):
clean_temporary_pub()
def test_testdef_slug_generation(pub):
testdef = TestDef()
testdef.name = 'test'
testdef.object_type = 'formdef'
testdef.object_id = '1'
testdef.store()
assert testdef.slug == 'test'
testdef.slug = testdef.id = None
testdef.store()
assert testdef.slug == 'test-2'
testdef.slug = testdef.id = None
testdef.object_id = '2'
testdef.store()
assert testdef.slug == 'test'
def test_page_post_conditions(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.TitleField(id='0', label='Title', type='title'),
fields.PageField(
id='1',
label='1st page',
type='page',
post_conditions=[
{'condition': {'type': 'django', 'value': 'form_var_text == "a"'}, 'error_message': 'Error'}
],
),
fields.StringField(id='2', label='Text', varname='text'),
fields.PageField(
id='3',
label='2nd page',
type='page',
post_conditions=[
{'condition': {'type': 'django', 'value': 'form_var_text2 == "a"'}, 'error_message': 'Error'}
],
),
fields.StringField(id='4', label='Text', varname='text2'),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['2'] = 'a'
formdata.data['4'] = 'a'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdata.data['4'] = 'b'
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Page 2 post condition was not met (form_var_text2 == "a").'
formdata.data['2'] = 'b'
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Page 1 post condition was not met (form_var_text == "a").'
def test_page_post_condition_invalid(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.PageField(
id='0',
label='1st page',
type='page',
post_conditions=[{'condition': {'type': 'django', 'value': '{{}'}, 'error_message': 'Error'}],
),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Failed to evaluate page 1 post condition.'
def test_field_conditions(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.StringField(id='1', label='Text', varname='text'),
fields.StringField(
id='2',
label='Text with condition',
varname='text_cond',
required=False,
condition={'type': 'django', 'value': 'form_var_text == "a"'},
),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = 'a'
formdata.data['2'] = 'xxx'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdata.data['1'] = 'b'
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Tried to fill field "Text with condition" on page 1 but it is hidden.'
formdata.data['2'] = None
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdata.data['1'] = 'a'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
def test_multi_page_condition(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='Text', varname='text'),
fields.PageField(
id='2',
label='2nd page',
type='page',
condition={'type': 'django', 'value': 'form_var_text == "a"'},
),
fields.StringField(id='3', label='Text 2', varname='text2', required=False),
fields.PageField(
id='4', label='3rd page', type='page', condition={'type': 'django', 'value': 'form_var_text'}
),
fields.StringField(id='5', label='Text 3', varname='text3'),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = 'a'
formdata.data['3'] = 'xxx'
formdata.data['5'] = 'yyy'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdata.data['1'] = 'b'
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Tried to fill field "Text 2" on page 2 but page was not shown.'
formdata.data['3'] = None
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdata.data['1'] = 'a'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
def test_validation_string_field(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.StringField(id='1', label='String field digits', validation={'type': 'digits'}),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = '1'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdata.data['1'] = 'xxx'
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert (
str(excinfo.value) == 'Invalid value "xxx" for field "String field digits": Only digits are allowed.'
)
def test_validation_required_field(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.StringField(id='1', label='Text', required=False),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdef.fields[0].required = True
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Empty value for field "Text": required field.'
def test_validation_item_field(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [fields.ItemField(id='1', label='Test', type='item', items=['foo', 'bar', 'baz'])]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = 'foo'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdata.data['1'] = 'xxx'
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Invalid value "xxx" for field "Test": invalid value selected.'
def test_item_field_display_value(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.PageField(
id='0',
label='1st page',
type='page',
post_conditions=[
{'condition': {'type': 'django', 'value': 'form_var_item == "foo"'}, 'error_message': ''}
],
),
fields.ItemField(id='1', label='Test', type='item', items=['foo', 'bar', 'baz'], varname='item'),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = 'foo'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
def test_item_field_structured_value(pub):
data_source = {
'type': 'jsonvalue',
'value': json.dumps(
[{'id': '1', 'text': 'un', 'more': 'foo'}, {'id': '2', 'text': 'deux', 'more': 'bar'}]
),
}
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.PageField(
id='0',
label='1st page',
type='page',
post_conditions=[
{'condition': {'type': 'django', 'value': 'form_var_item_more == "bar"'}, 'error_message': ''}
],
),
fields.ItemField(id='1', label='Test', type='item', varname='item', data_source=data_source),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = '2'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
def test_validation_items_field(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [fields.ItemsField(id='1', label='Test', type='items', items=['foo', 'bar', 'baz'])]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = ['foo', 'baz']
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdata.data['1'] = ['foo', 'xxx']
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Invalid value "xxx" for field "Test": invalid value selected.'
formdata.data['1'] = []
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Empty value for field "Test": required field.'
def test_validation_email_field(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.EmailField(id='1', label='Test'),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = 'test@entrouvert.com'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdata.data['1'] = 'xxx'
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Invalid value "xxx" for field "Test": must be a valid email address.'
def test_validation_boolean_field(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.BoolField(id='1', label='Test'),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = False
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdef.fields[0].required = True
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Invalid value "False" for field "Test": required field.'
formdata.data['1'] = True
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
def test_validation_date_field(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.DateField(id='1', label='Test'),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = time.strptime('2022-07-19', '%Y-%m-%d')
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdata.data['1'] = time.strptime('1312-01-01', '%Y-%m-%d')
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Invalid value "1312-01-01" for field "Test": invalid date.'
def test_validation_map_field(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.PageField(
id='0',
label='1st page',
type='page',
post_conditions=[
{
'condition': {'type': 'django', 'value': 'form_var_map == "1.0;2.0"'},
'error_message': 'Error',
}
],
),
fields.MapField(id='1', label='Map', varname='map'),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = '1.0;2.0'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
def test_validation_file_field(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.FileField(id='1', label='File', varname='foo', max_file_size='1ko'),
fields.StringField(
id='2',
label='Text',
varname='text',
condition={'type': 'django', 'value': 'form_var_foo == "hop.pdf"'},
),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
upload = PicklableUpload('test.pdf', 'application/pdf', 'ascii')
upload.receive([b'first line', b'second line'])
formdata.data['1'] = upload
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
upload = PicklableUpload('hop.pdf', 'application/pdf', 'ascii')
upload.receive([b'first line', b'second line'])
formdata.data['1'] = upload
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Empty value for field "Text": required field.'
formdata.data['2'] = 'xxx'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
pub.site_options.set('options', 'blacklisted-file-types', 'application/pdf')
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Invalid value "hop.pdf" for field "File": forbidden file type.'
def test_validation_block_field(pub):
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='1', label='Text', varname='text'),
fields.StringField(id='2', label='Hop'),
]
block.store()
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.PageField(
id='0',
label='1st page',
type='page',
post_conditions=[
{
'condition': {'type': 'django', 'value': 'form_var_blockdata_1_text == "a"'},
'error_message': '',
}
],
),
fields.BlockField(id='1', label='Block Data', varname='blockdata', type='block:foobar', max_items=3),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = {'data': [{'1': 'a'}, {'1': 'b'}]}
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Empty value for field "Hop" (of field "Block Data"): required field.'
formdata.data['1'] = {'data': [{'1': 'a', '2': 'z'}, {'1': 'b', '2': 'z'}]}
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Page 1 post condition was not met (form_var_blockdata_1_text == "a").'
formdata.data['1'] = {'data': [{'1': 'b', '2': 'z'}, {'1': 'a', '2': 'z'}]}
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
def test_computed_field_support(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.PageField(
id='0',
label='1st page',
type='page',
post_conditions=[
{
'condition': {
'type': 'django',
'value': 'form_var_foo == "xxx" and form_var_bar == "hop"',
},
'error_message': '',
}
],
),
fields.ComputedField(
id='1',
label='Computed (frozen)',
varname='foo',
value_template='{% firstof form_var_text "xxx" %}',
freeze_on_initial_value=True,
),
fields.ComputedField(
id='2', label='Computed (live)', varname='bar', value_template='{% firstof form_var_text "xxx" %}'
),
fields.StringField(id='3', label='Text', varname='text'),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = 'zzz'
formdata.data['3'] = 'hop'
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
formdef.fields[1].value_template = '{% for %}'
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert (
str(excinfo.value)
== 'Page 1 post condition was not met (form_var_foo == "xxx" and form_var_bar == "hop").'
)
def test_computed_field_support_complex_data(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.PageField(
id='0',
label='1st page',
type='page',
post_conditions=[
{'condition': {'type': 'django', 'value': 'form_var_foo|length == 3'}, 'error_message': ''}
],
),
fields.ComputedField(
id='1',
label='Computed',
varname='foo',
value_template='{{form_objects|first|get:"form_var_items_raw"}}',
),
fields.ItemsField(id='2', label='Items', varname='items', required=False),
]
formdef.store()
submitted_formdata = formdef.data_class()()
submitted_formdata.just_created()
submitted_formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
submitted_formdata.data['2'] = ['a', 'bc']
submitted_formdata.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError) as excinfo:
testdef.run(formdef)
assert str(excinfo.value) == 'Page 1 post condition was not met (form_var_foo|length == 3).'
submitted_formdata.data['2'] = ['a', 'b', 'c']
submitted_formdata.store()
testdef.run(formdef)
def test_computed_field_support_webservice(pub, http_requests):
wscall = NamedWsCall()
wscall.name = 'Hello world'
wscall.request = {'url': 'http://remote.example.net/json'}
wscall.store()
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.PageField(
id='0',
label='1st page',
type='page',
post_conditions=[
{
'condition': {'type': 'django', 'value': 'form_var_computed_foo == "bar"'},
'error_message': '',
}
],
),
fields.ComputedField(
id='1',
label='Computed',
varname='computed',
value_template='{{ webservice.hello_world }}',
freeze_on_initial_value=True,
),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)
def test_computed_field_value_too_long(pub):
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [
fields.PageField(
id='0',
label='1st page',
type='page',
post_conditions=[
{
'condition': {'type': 'django', 'value': 'not form_var_computed'},
'error_message': '',
}
],
),
fields.ComputedField(
id='1',
label='Computed',
varname='computed',
value_template='{% token_decimal length=9999 %}',
),
]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
testdef = TestDef.create_from_formdata(formdef, formdata)
with pytest.raises(TestError):
testdef.run(formdef)
formdef.fields[1].value_template = '{% token_decimal length=100000 %}'
formdef.store()
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.run(formdef)