wcs/tests/form_pages/test_computed_field.py

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'