413 lines
13 KiB
Python
413 lines
13 KiB
Python
import datetime
|
|
import decimal
|
|
|
|
import pytest
|
|
from django.utils.timezone import make_aware
|
|
|
|
from wcs import fields
|
|
from wcs.formdef import FormDef
|
|
from wcs.qommon.substitution import CompatibilityNamesDict
|
|
from wcs.wscalls import NamedWsCall
|
|
|
|
from ..utilities import clean_temporary_pub, create_temporary_pub, get_app, login
|
|
from .test_all import create_user
|
|
|
|
|
|
def pytest_generate_tests(metafunc):
|
|
if 'pub' in metafunc.fixturenames:
|
|
metafunc.parametrize('pub', ['pickle', 'sql'], indirect=True)
|
|
|
|
|
|
@pytest.fixture
|
|
def pub(request, emails):
|
|
pub = create_temporary_pub(
|
|
sql_mode=bool('sql' in request.param),
|
|
templates_mode=bool('templates' in request.param),
|
|
lazy_mode=bool('lazy' in request.param),
|
|
)
|
|
pub.cfg['identification'] = {'methods': ['password']}
|
|
pub.cfg['language'] = {'language': 'en'}
|
|
pub.write_cfg()
|
|
|
|
return pub
|
|
|
|
|
|
def teardown_module(module):
|
|
clean_temporary_pub()
|
|
|
|
|
|
def test_computed_field_simple(pub):
|
|
create_user(pub)
|
|
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.ComputedField(id='1', label='computed', varname='computed', value_template='{{ "xxx" }}'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
resp = resp.forms[0].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data == {'1': 'xxx'}
|
|
|
|
|
|
def test_computed_field_used_in_prefill(pub):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.ComputedField(id='1', label='computed', varname='computed', value_template='xxx'),
|
|
fields.StringField(
|
|
id='2', label='string', prefill={'type': 'string', 'value': '{{ form_var_computed }}'}
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert resp.forms[0]['f2'].value == 'xxx'
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
resp = resp.forms[0].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data == {'1': 'xxx', '2': 'xxx'}
|
|
|
|
|
|
def test_computed_field_used_in_comment(pub):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.ComputedField(id='1', label='computed', varname='computed', value_template='xxx'),
|
|
fields.CommentField(id='2', label='X{{ form_var_computed }}Y', type='comment'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert 'XxxxY' in resp.text
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
resp = resp.forms[0].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data == {'1': 'xxx'}
|
|
|
|
|
|
def test_computed_field_freeze(pub, freezer):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.ComputedField(
|
|
id='1',
|
|
label='computed',
|
|
varname='computed',
|
|
value_template='{% now "H:i" %}',
|
|
freeze_on_initial_value=False,
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
freezer.move_to(make_aware(datetime.datetime(2021, 4, 6, 10, 0)))
|
|
resp = get_app(pub).get('/test/')
|
|
freezer.move_to(make_aware(datetime.datetime(2021, 4, 6, 10, 5)))
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
resp = resp.forms[0].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data == {'1': '10:05'}
|
|
|
|
formdef.data_class().wipe()
|
|
formdef.fields[0].freeze_on_initial_value = True
|
|
formdef.store()
|
|
|
|
freezer.move_to(make_aware(datetime.datetime(2021, 4, 6, 10, 0)))
|
|
resp = get_app(pub).get('/test/')
|
|
freezer.move_to(make_aware(datetime.datetime(2021, 4, 6, 10, 5)))
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
resp = resp.forms[0].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data == {'1': '10:00'}
|
|
|
|
|
|
def test_computed_field_from_request_get(pub):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.ComputedField(
|
|
id='1',
|
|
label='computed',
|
|
varname='computed',
|
|
value_template='{{ request.GET.param }}',
|
|
freeze_on_initial_value=True,
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = get_app(pub).get('/test/?param=value')
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
resp = resp.forms[0].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data == {'1': 'value'}
|
|
|
|
|
|
def test_computed_field_usage_in_post_condition(pub):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.PageField(
|
|
id='0',
|
|
label='1st page',
|
|
type='page',
|
|
post_conditions=[
|
|
{
|
|
'condition': {
|
|
'type': 'django',
|
|
'value': 'form_var_computed == "xxx"',
|
|
},
|
|
'error_message': 'You shall not pass.',
|
|
}
|
|
],
|
|
),
|
|
fields.ComputedField(
|
|
id='1',
|
|
label='computed',
|
|
varname='computed',
|
|
value_template='{{ request.GET.param }}',
|
|
freeze_on_initial_value=True,
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = get_app(pub).get('/test/?param=test')
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
assert 'You shall not pass.' in resp.text
|
|
resp = get_app(pub).get('/test/?param=xxx')
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
resp = resp.forms[0].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
|
|
|
|
def test_computed_field_usage_updated_in_post_condition(pub):
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.PageField(
|
|
id='0',
|
|
label='1st page',
|
|
type='page',
|
|
post_conditions=[
|
|
{
|
|
'condition': {
|
|
'type': 'django',
|
|
'value': 'form_var_computed == "xxx"',
|
|
},
|
|
'error_message': 'You shall not pass.',
|
|
}
|
|
],
|
|
),
|
|
fields.ComputedField(
|
|
id='1',
|
|
label='computed',
|
|
varname='computed',
|
|
value_template='{{ form_var_field }}',
|
|
),
|
|
fields.StringField(id='2', label='string', varname='field'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
resp.forms[0]['f2'].value = 'test'
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
assert 'You shall not pass.' in resp.text
|
|
resp.forms[0]['f2'].value = 'xxx'
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
resp = resp.forms[0].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
|
|
|
|
def test_computed_field_recall_draft(pub):
|
|
create_user(pub)
|
|
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.ComputedField(
|
|
id='1',
|
|
label='computed',
|
|
varname='computed',
|
|
value_template='{{ request.GET.param }}',
|
|
freeze_on_initial_value=True,
|
|
),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/?param=value')
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.is_draft()
|
|
|
|
# recall draft
|
|
resp = login(get_app(pub), username='foo', password='foo').get(formdata.get_url()).follow()
|
|
assert 'form-validation' in resp.text
|
|
resp = resp.forms[1].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data == {'1': 'value'}
|
|
|
|
# retry, moving back to first page
|
|
formdef.data_class().wipe()
|
|
resp = login(get_app(pub), username='foo', password='foo').get('/test/?param=value')
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.is_draft()
|
|
|
|
resp = login(get_app(pub), username='foo', password='foo').get(formdata.get_url()).follow()
|
|
assert 'form-validation' in resp.text
|
|
resp = resp.forms[1].submit('previous') # -> first page
|
|
resp = resp.forms[1].submit('submit') # -> validation
|
|
resp = resp.forms[1].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data == {'1': 'value'}
|
|
|
|
|
|
def test_computed_field_complex_data(pub, http_requests):
|
|
FormDef.wipe()
|
|
|
|
wscall = NamedWsCall()
|
|
wscall.name = 'Hello world'
|
|
wscall.request = {'url': 'http://remote.example.net/json'}
|
|
wscall.store()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.ComputedField(
|
|
id='1',
|
|
label='computed',
|
|
varname='computed',
|
|
value_template='{{ webservice.hello_world }}',
|
|
freeze_on_initial_value=True,
|
|
),
|
|
fields.CommentField(id='2', label='X{{form_var_computed_foo}}Y', type='comment'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert 'XbarY' in resp.text
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
resp = resp.forms[0].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
assert formdata.data['1'] == {'foo': 'bar'}
|
|
|
|
|
|
def test_computed_field_decimal_data(pub, http_requests):
|
|
FormDef.wipe()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.ComputedField(
|
|
id='1',
|
|
label='computed',
|
|
varname='computed',
|
|
value_template='{{ "123.45"|decimal }}',
|
|
freeze_on_initial_value=True,
|
|
),
|
|
fields.CommentField(id='2', label='X{{form_var_computed}}Y', type='comment'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
resp = get_app(pub).get('/test/')
|
|
assert 'X123.45Y' in resp.text
|
|
resp = resp.forms[0].submit('submit') # -> validation
|
|
resp = resp.forms[0].submit('submit').follow() # -> submit
|
|
assert 'The form has been recorded' in resp.text
|
|
assert formdef.data_class().count() == 1
|
|
formdata = formdef.data_class().select()[0]
|
|
# pickle storage keeps the typed data but postgresql storage has to convert
|
|
# it to stringfor json storage, hence the casting here:
|
|
assert decimal.Decimal(formdata.data['1']) == decimal.Decimal('123.45')
|
|
|
|
|
|
def test_computed_field_usage_in_live_data(pub, http_requests):
|
|
FormDef.wipe()
|
|
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.ComputedField(
|
|
id='1',
|
|
label='computed',
|
|
varname='computed',
|
|
value_template='{{ "xxx" }}',
|
|
),
|
|
fields.StringField(id='0', label='string', varname='string'),
|
|
fields.CommentField(id='2', label='X{{form_var_computed}}Y{{form_var_string}}Z', type='comment'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
app = get_app(pub)
|
|
resp = app.get('/test/')
|
|
assert 'XxxxYNoneZ' in resp.text
|
|
resp.form['f0'] = 'hello'
|
|
live_resp = app.post('/test/live', params=resp.form.submit_fields())
|
|
assert live_resp.json['result']['2']['content'] == '<p>XxxxYhelloZ</p>'
|
|
|
|
|
|
def test_computed_field_inspect_keys(pub):
|
|
create_user(pub)
|
|
|
|
FormDef.wipe()
|
|
formdef = FormDef()
|
|
formdef.name = 'test'
|
|
formdef.fields = [
|
|
fields.ComputedField(id='1', label='computed', varname='computed', value_template='{{ "xxx" }}'),
|
|
]
|
|
formdef.store()
|
|
formdef.data_class().wipe()
|
|
|
|
formdata = formdef.data_class()()
|
|
formdata.data = {'1': 'xxx'}
|
|
|
|
substvars = CompatibilityNamesDict()
|
|
substvars.update(formdata.get_substitution_variables())
|
|
assert 'form_var_computed' in substvars.get_flat_keys()
|
|
assert substvars['form_var_computed'] == 'xxx'
|
|
|
|
formdata.data = {'1': {'foo': 'bar'}}
|
|
assert 'form_var_computed_foo' in substvars.get_flat_keys()
|
|
assert substvars['form_var_computed_foo'] == 'bar'
|