wcs/tests/form_pages/test_block.py

2099 lines
72 KiB
Python

import io
import json
from unittest import mock
import pytest
from webtest import Upload
from wcs import fields
from wcs.blocks import BlockDef
from wcs.categories import Category
from wcs.data_sources import NamedDataSource
from wcs.formdef import FormDef
from wcs.wf.form import WorkflowFormFieldsFormDef
from wcs.workflows import Workflow
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', ['sql', 'sql-lazy'], indirect=True)
@pytest.fixture
def pub(request, emails):
pub = create_temporary_pub(
sql_mode=bool('sql' in request.param),
lazy_mode=bool('lazy' in request.param),
)
pub.cfg['identification'] = {'methods': ['password']}
pub.cfg['language'] = {'language': 'en'}
pub.write_cfg()
if Category.count() == 0:
cat = Category(name='foobar')
cat.store()
return pub
def teardown_module(module):
clean_temporary_pub()
def test_block_simple(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.StringField(id='234', required=True, label='Test2', type='string'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar', hint='hintblock'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.text.count('>hintblock<') == 1
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'bar'
resp = resp.form.submit('submit') # -> validation page
assert resp.form['f1$element0$f123'].attrs['readonly']
assert resp.form['f1$element0$f123'].value == 'foo'
assert resp.form['f1$element0$f234'].attrs['readonly']
assert resp.form['f1$element0$f234'].value == 'bar'
resp = resp.form.submit('submit') # -> end page
resp = resp.follow()
assert '>foo<' in resp
assert '>bar<' in resp
def test_block_required(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.StringField(id='234', required=True, label='Test2', type='string'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp = resp.form.submit('submit') # -> error page
assert 'There were errors processing the form' in resp
assert resp.text.count('required field') == 1
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'bar'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp = resp.form.submit('submit') # -> error page
assert 'There were errors processing the form' in resp
assert resp.text.count('required field') == 1
resp.form['f1$element0$f234'] = 'bar'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
# only one required
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.StringField(id='234', required=False, label='Test2', type='string'),
]
block.store()
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
# none required, but globally required
block.fields = [
fields.StringField(id='123', required=False, label='Test', type='string'),
fields.StringField(id='234', required=False, label='Test2', type='string'),
]
block.store()
resp = app.get(formdef.get_url())
resp = resp.form.submit('submit') # -> error page
assert 'There were errors processing the form' in resp
assert resp.text.count('required field') == 1
resp.form['f1$element0$f234'] = 'bar'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
def test_block_required_previous_page(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.StringField(id='234', required=True, label='Test2', type='string'),
]
block.store()
for multipage in (False, True):
# single block, go to validation page, come back
formdef = FormDef()
formdef.name = 'form title'
if multipage:
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.BlockField(id='1', label='test', type='block:foobar', required=True),
fields.PageField(id='2', label='2nd page', type='page'),
]
else:
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar', required=True),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp = resp.form.submit('submit') # -> error page
assert 'There were errors processing the form' in resp
assert resp.text.count('required field') == 1
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'bar'
if multipage:
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
if multipage:
resp = resp.form.submit('previous') # -> 2nd page
resp = resp.form.submit('previous') # -> 1st page
assert resp.text.count('required field') == 0
assert resp.form['f1$element0$f123'].value == 'foo'
assert resp.form['f1$element0$f234'].value == 'bar'
if multipage:
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
resp = resp.form.submit('submit') # -> submitted
assert formdef.data_class().count() == 1
formdata = formdef.data_class().select()[0]
assert formdata.data['1']['data'] == [{'123': 'foo', '234': 'bar'}]
# add two blocks, go to validation page, come back
if multipage:
formdef.fields[1].max_items = 3
else:
formdef.fields[0].max_items = 3
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'bar'
resp = resp.form.submit('f1$add_element') # -> 1st page
resp.form['f1$element1$f123'] = 'foo2'
resp.form['f1$element1$f234'] = 'bar2'
if multipage:
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
if multipage:
resp = resp.form.submit('previous') # -> 2nd page
resp = resp.form.submit('previous') # -> 1st page
assert resp.text.count('required field') == 0
assert resp.form['f1$element0$f123'].value == 'foo'
assert resp.form['f1$element0$f234'].value == 'bar'
assert resp.form['f1$element1$f123'].value == 'foo2'
assert resp.form['f1$element1$f234'].value == 'bar2'
if multipage:
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
resp = resp.form.submit('submit') # -> submitted
assert formdef.data_class().count() == 1
formdata = formdef.data_class().select()[0]
assert formdata.data['1']['data'] == [{'123': 'foo', '234': 'bar'}, {'123': 'foo2', '234': 'bar2'}]
def test_block_date(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.DateField(id='234', required=True, label='Test2', type='date'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = '2020-06-16'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
resp = resp.form.submit('submit') # -> submit
resp = resp.follow()
assert '>2020-06-16<' in resp
def test_block_bool(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.BoolField(id='234', required=False, label='Test2', type='bool'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar'),
]
formdef.store()
for value in (True, False):
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'].checked = value
resp = resp.form.submit('submit') # -> validation page
assert resp.form['f1$element0$f234disabled'].checked is value
assert resp.form['f1$element0$f234'].value == str(value)
assert 'Check values then click submit.' in resp
resp = resp.form.submit('submit') # -> submit
resp = resp.follow()
if value:
assert '<div class="value">Yes</div>' in resp
else:
assert '<div class="value">No</div>' in resp
def test_block_autocomplete_list(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.ItemField(
id='234',
required=True,
label='Test2',
type='item',
display_mode='autocomplete',
items=['Foo', 'Bar'],
),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'Bar'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
resp = resp.form.submit('submit') # -> submit
resp = resp.follow()
assert '>Bar<' in resp
def test_block_geoloc_prefill(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(
id='123',
required=True,
label='Test',
type='string',
prefill={'type': 'geolocation', 'value': 'road'},
),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert 'qommon.geolocation.js' in resp
assert resp.html.find('div', {'data-geolocation': 'road'})
def test_block_string_prefill(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(
id='123',
required=True,
label='Test',
type='string',
prefill={'type': 'string', 'value': '{{ form_var_foo }} World'},
),
]
block.store()
block2 = BlockDef()
block2.name = 'foobar2'
block2.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
]
block2.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='string', varname='foo'),
fields.PageField(id='2', label='2nd page', type='page'),
fields.BlockField(id='3', label='test', type='block:foobar'),
fields.BlockField(id='4', label='test', type='block:foobar2'),
]
formdef.store()
for i in range(2):
if i == 1:
# second pass, add another prefilled field in second block
block2.fields.append(
fields.StringField(
id='124',
required=True,
label='Test',
type='string',
prefill={'type': 'string', 'value': '{{ form_var_foo }} World'},
)
)
block2.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1'] = 'Hello'
resp = resp.form.submit('submit') # -> 2nd page
assert not resp.pyquery('#form_error_f3') # not marked as error
assert not resp.pyquery('#form_error_f4') # ...
assert '>required field<' not in resp
assert resp.form['f3$element0$f123'].value == 'Hello World'
assert resp.form['f4$element0$f123'].value == ''
resp.form['f4$element0$f123'] = 'plop'
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> end page
resp = resp.follow()
formdata = formdef.data_class().select()[0]
assert formdata.data['3']['data'][0]['123'] == 'Hello World'
if i == 1:
assert formdata.data['4']['data'][0]['124'] == 'Hello World'
# check unmodified prefilled field
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1'] = 'Hello'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.form['f3$element0$f123'].value == 'Hello World'
resp.form['f4$element0$f123'] = 'plop'
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('previous') # -> 2nd page
resp = resp.form.submit('previous') # -> 1st page
resp.form['f1'] = 'Test'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.form['f3$element0$f123'].value == 'Test World'
# check modified prefilled field
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1'] = 'Hello'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.form['f3$element0$f123'].value == 'Hello World'
resp.form['f3$element0$f123'] = 'Foobar'
resp.form['f4$element0$f123'] = 'plop'
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('previous') # -> 2nd page
resp = resp.form.submit('previous') # -> 1st page
resp.form['f1'] = 'Test'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.form['f3$element0$f123'].value == 'Foobar'
def test_block_prefill_and_required(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(
id='123', required=True, label='Test', type='string', prefill={'type': 'string', 'value': 'World'}
),
]
block.store()
block2 = BlockDef()
block2.name = 'foobar2'
block2.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.BoolField(id='234', required=True, label='Test2', type='bool'),
]
block2.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.ItemField(id='1', required=True, label='Test2', type='item', items=['Foo', 'Bar']),
fields.BlockField(id='2', label='test', type='block:foobar'),
fields.BlockField(id='3', label='test', type='block:foobar2'),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert '>required field<' not in resp
assert resp.form['f2$element0$f123'].value == 'World'
resp.form['f3$element0$f123'] = 'Hello'
resp = resp.form.submit('submit') # -> same page, error displyed
assert resp.text.count('>required field<') == 1
resp.form['f3$element0$f234'].checked = True
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> end page
resp = resp.follow()
formdata = formdef.data_class().select()[0]
assert formdata.data['2']['data'][0]['123'] == 'World'
assert formdata.data['3']['data'][0]['123'] == 'Hello'
assert formdata.data['3']['data'][0]['234'] is True
def test_block_locked_prefill(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(
id='123',
required=True,
label='Test',
type='string',
prefill={'type': 'string', 'value': '{{ form_var_foo }} World', 'locked': True},
),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='string', varname='foo'),
fields.PageField(id='2', label='2nd page', type='page'),
fields.BlockField(id='3', label='test', type='block:foobar'),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1'] = 'Hello'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.form['f3$element0$f123'].value == 'Hello World'
assert 'readonly' in resp.form['f3$element0$f123'].attrs
resp.form['f3$element0$f123'].value = 'Hello' # try changing the value
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> end page
resp = resp.follow()
formdata = formdef.data_class().select()[0]
assert formdata.data['3']['data'][0]['123'] == 'Hello World' # value got reverted
def test_block_multi_string_prefill(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(
id='123',
required=True,
label='Test',
type='string',
prefill={'type': 'string', 'value': '{{ form_var_foo }} World'},
),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='string', varname='foo'),
fields.PageField(id='2', label='2nd page', type='page'),
fields.BlockField(id='3', label='test', type='block:foobar', max_items=5),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1'] = 'Hello'
resp = resp.form.submit('submit') # -> 2nd page
assert not resp.pyquery('#form_error_f3') # not marked as error
assert resp.form['f3$element0$f123'].value == 'Hello World'
resp = resp.form.submit('f3$add_element') # add second row
assert resp.form['f3$element1$f123'].value == 'Hello World'
resp.form['f3$element1$f123'].value = 'Something else'
resp = resp.form.submit('f3$add_element') # add third row
assert resp.form['f3$element0$f123'].value == 'Hello World'
assert resp.form['f3$element1$f123'].value == 'Something else' # unchanged
assert resp.form['f3$element2$f123'].value == 'Hello World'
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> end page
resp = resp.follow()
formdata = formdef.data_class().select()[0]
assert formdata.data['3']['data'][0]['123'] == 'Hello World'
assert formdata.data['3']['data'][1]['123'] == 'Something else'
assert formdata.data['3']['data'][2]['123'] == 'Hello World'
def test_block_multi_string_modify_prefill(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(
id='123',
required=True,
label='Test',
type='string',
prefill={'type': 'string', 'value': '{{ form_var_foo }} World'},
),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.StringField(id='1', label='string', varname='foo'),
fields.PageField(id='2', label='2nd page', type='page'),
fields.BlockField(id='3', label='test', type='block:foobar', max_items=5),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
formdef.data_class().wipe()
resp = app.get(formdef.get_url())
resp.form['f1'] = 'Hello'
resp = resp.form.submit('submit') # -> 2nd page
assert not resp.pyquery('#form_error_f3') # not marked as error
assert resp.form['f3$element0$f123'].value == 'Hello World'
resp = resp.form.submit('f3$add_element') # add second row
assert resp.form['f3$element1$f123'].value == 'Hello World'
resp.form['f3$element1$f123'].value = 'Something else'
resp = resp.form.submit('f3$add_element') # add third row
assert resp.form['f3$element0$f123'].value == 'Hello World'
assert resp.form['f3$element1$f123'].value == 'Something else' # unchanged
assert resp.form['f3$element2$f123'].value == 'Hello World'
resp = resp.form.submit('previous') # -> 1st page
resp.form['f1'] = 'Bye'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.form['f3$element0$f123'].value == 'Bye World' # updated
assert resp.form['f3$element1$f123'].value == 'Something else' # unchanged
assert resp.form['f3$element2$f123'].value == 'Bye World' # updated
def test_workflow_form_block_prefill(pub):
FormDef.wipe()
BlockDef.wipe()
create_user(pub)
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(
id='123', required=True, label='Test', type='string', prefill={'type': 'user', 'value': 'email'}
),
]
block.store()
wf = Workflow(name='status')
st1 = wf.add_status('Status1', 'st1')
display_form = st1.add_action('form', id='_x')
display_form.by = ['_submitter']
display_form.varname = 'xxx'
display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
display_form.formdef.fields.append(fields.BlockField(id='3', label='test', type='block:foobar'))
wf.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'test'
formdef.fields = []
formdef.workflow_id = wf.id
formdef.store()
formdef.data_class().wipe()
resp = login(get_app(pub), username='foo', password='foo').get('/test/')
resp = resp.form.submit('submit') # -> validation
resp = resp.form.submit('submit').follow()
assert 'The form has been recorded' in resp
assert resp.form['fxxx_3$element0$f123'].value == 'foo@localhost'
def test_block_title_and_comment(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.TitleField(id='234', label='Blah', type='title'),
fields.CommentField(id='345', label='Blah', type='comment'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
resp = resp.form.submit('submit') # -> submit
resp = resp.follow()
def test_block_label(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(
id='1', label='Block Label', type='block:foobar', hint='', required=False, label_display='normal'
),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.pyquery.find('div.title label.field--label#form_label_f1').text() == 'Block Label'
formdef.fields[0].label_display = 'subtitle'
formdef.fields[0].hint = 'foo bar !'
formdef.fields[0].required = True
formdef.store()
resp = app.get(formdef.get_url())
assert resp.pyquery.find('h4').text() == 'Block Label*'
resp.form['f1$element0$f123'] = 'something'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
assert resp.pyquery.find('h4').text() == 'Block Label'
formdef.fields[0].label_display = 'hidden'
formdef.store()
resp = app.get(formdef.get_url())
assert 'Block Label' not in resp.text
resp.form['f1$element0$f123'] = 'something'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
assert 'Block Label' not in resp.text
def test_block_multipage(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.StringField(id='234', required=True, label='Test2', type='string'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.BlockField(id='1', label='test', type='block:foobar'),
fields.PageField(id='2', label='2nd page', type='page'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'bar'
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
assert resp.form['f1$element0$f123'].attrs['readonly']
assert resp.form['f1$element0$f123'].value == 'foo'
resp = resp.form.submit('previous') # -> 2nd page
resp = resp.form.submit('previous') # -> 1st page
assert 'readonly' not in resp.form['f1$element0$f123'].attrs
assert resp.form['f1$element0$f123'].value == 'foo'
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> submit
resp = resp.follow()
assert '>foo<' in resp
assert '>bar<' in resp
def test_block_repeated(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.StringField(id='234', required=True, label='Test2', type='string'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.BlockField(id='1', label='test', type='block:foobar', max_items=3, hint='hintblock'),
fields.PageField(id='2', label='2nd page', type='page'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.text.count('>Test<') == 1
assert resp.text.count('>hintblock<') == 1
assert 'wcs-block-add-clicked' not in resp
assert 'Add another' in resp
assert resp.html.find('div', {'class': 'list-add'})
resp = resp.form.submit('f1$add_element')
assert resp.text.count('>Test<') == 2
assert resp.text.count('>hintblock<') == 1
assert 'wcs-block-add-clicked' in resp
resp = resp.form.submit('f1$add_element')
assert resp.text.count('>Test<') == 3
assert resp.text.count('>hintblock<') == 1
assert resp.pyquery('.list-add').attr['style'] == 'display: none'
# fill items (1st and 3rd row)
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'bar'
resp.form['f1$element2$f123'] = 'foo2'
resp.form['f1$element2$f234'] = 'bar2'
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
assert resp.form['f1$element0$f123'].value == 'foo'
assert resp.form['f1$element0$f234'].value == 'bar'
assert resp.form['f1$element1$f123'].value == 'foo2'
assert resp.form['f1$element1$f234'].value == 'bar2'
resp = resp.form.submit('previous') # -> 2nd page
resp = resp.form.submit('previous') # -> 1st page
assert 'wcs-block-add-clicked' not in resp
assert 'readonly' not in resp.form['f1$element0$f123'].attrs
assert resp.form['f1$element0$f123'].value == 'foo'
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> submit
resp = resp.follow()
assert '>foo<' in resp
assert '>bar<' in resp
assert '>foo2<' in resp
assert '>bar2<' in resp
def test_block_repeated_with_default(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.StringField(id='234', required=True, label='Test2', type='string'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.BlockField(
id='1', label='test', type='block:foobar', default_items_count=2, max_items=3, hint='hintblock'
),
fields.PageField(id='2', label='2nd page', type='page'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.text.count('>Test<') == 2
assert resp.text.count('>hintblock<') == 1
assert 'wcs-block-add-clicked' not in resp
assert 'Add another' in resp
assert resp.html.find('div', {'class': 'list-add'})
resp = resp.form.submit('f1$add_element')
assert resp.text.count('>Test<') == 3
assert resp.text.count('>hintblock<') == 1
assert resp.pyquery('.list-add').attr['style'] == 'display: none'
formdef.fields[1].default_items_count = 3
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.text.count('>Test<') == 3
assert resp.text.count('>hintblock<') == 1
assert resp.pyquery('.list-add').attr['style'] == 'display: none'
formdef.fields[1].default_items_count = 4
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.text.count('>Test<') == 3
def test_block_repeated_over_limit(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.StringField(id='234', required=True, label='Test2', type='string'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.BlockField(id='1', label='test', type='block:foobar', max_items=3),
fields.PageField(id='2', label='2nd page', type='page'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.text.count('>Test<') == 1
assert 'Add another' in resp
resp = resp.form.submit('f1$add_element')
assert resp.text.count('>Test<') == 2
resp = resp.form.submit('f1$add_element')
assert resp.text.count('>Test<') == 3
assert resp.pyquery('.list-add').attr['style'] == 'display: none'
# fill items
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'bar'
resp.form['f1$element1$f123'] = 'foo1'
resp.form['f1$element1$f234'] = 'bar1'
resp.form['f1$element2$f123'] = 'foo2'
resp.form['f1$element2$f234'] = 'bar2'
# (modify formdef to only allow 2)
formdef.fields[1].max_items = 2
formdef.store()
# submit form
resp = resp.form.submit('submit')
assert 'Too many elements (maximum: 2)' in resp
def test_block_repeated_under_default(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.StringField(id='234', required=True, label='Test2', type='string'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.BlockField(
id='1', label='test', type='block:foobar', default_items_count=2, max_items=2, remove_button=True
),
fields.PageField(id='2', label='2nd page', type='page'),
fields.BlockField(
id='3', label='test', type='block:foobar', default_items_count=2, max_items=2, remove_button=True
),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.text.count('>Test<') == 2
# fill items
resp.form['f1$element0$f123'] = 'foo1'
resp.form['f1$element0$f234'] = 'bar1'
resp.form['f1$element1$f123'] = 'foo2'
resp.form['f1$element1$f234'] = 'bar2'
resp = resp.form.submit('submit') # -> 2nd page
resp.form['f3$element0$f123'] = 'fooo1'
resp.form['f3$element0$f234'] = 'barr1'
resp.form['f3$element1$f123'] = 'fooo2'
resp.form['f3$element1$f234'] = 'barr2'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
assert resp.form['f1$element0$f123'].value == 'foo1'
assert resp.form['f1$element0$f234'].value == 'bar1'
assert resp.form['f1$element1$f123'].value == 'foo2'
assert resp.form['f1$element1$f234'].value == 'bar2'
assert resp.form['f3$element0$f123'].value == 'fooo1'
assert resp.form['f3$element0$f234'].value == 'barr1'
assert resp.form['f3$element1$f123'].value == 'fooo2'
assert resp.form['f3$element1$f234'].value == 'barr2'
resp = resp.form.submit('previous') # -> 2nd page
# simulate javascript removing of block elements from DOM
resp.form.field_order.remove(('f3$element0$f123', resp.form.fields['f3$element0$f123'][0]))
del resp.form.fields['f3$element0$f123']
resp.form.field_order.remove(('f3$element0$f234', resp.form.fields['f3$element0$f234'][0]))
del resp.form.fields['f3$element0$f234']
resp = resp.form.submit('previous') # -> 1st page
# simulate javascript removing of block elements from DOM
resp.form.field_order.remove(('f1$element0$f123', resp.form.fields['f1$element0$f123'][0]))
del resp.form.fields['f1$element0$f123']
resp.form.field_order.remove(('f1$element0$f234', resp.form.fields['f1$element0$f234'][0]))
del resp.form.fields['f1$element0$f234']
resp = resp.form.submit('submit') # -> 2nd page
assert resp.form['f3$element0$f123'].value == 'fooo2'
assert resp.form['f3$element0$f234'].value == 'barr2'
assert 'f3$element1$f123' in resp.form.fields
assert 'f3$element1$f234' in resp.form.fields
resp = resp.form.submit('previous') # -> 1st page
assert resp.form['f1$element0$f123'].value == 'foo2'
assert resp.form['f1$element0$f234'].value == 'bar2'
assert 'f1$element1$f123' in resp.form.fields
assert 'f1$element1$f234' in resp.form.fields
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
assert resp.form['f1$element0$f123'].value == 'foo2'
assert resp.form['f1$element0$f234'].value == 'bar2'
assert 'f1$element1$f123' not in resp.form.fields
assert 'f1$element1$f234' not in resp.form.fields
assert resp.form['f3$element0$f123'].value == 'fooo2'
assert resp.form['f3$element0$f234'].value == 'barr2'
assert 'f3$element1$f123' not in resp.form.fields
assert 'f3$element1$f234' not in resp.form.fields
resp = resp.form.submit('submit') # -> submit
assert len(formdef.data_class().select()[0].data['1']['data']) == 1
assert len(formdef.data_class().select()[0].data['3']['data']) == 1
def test_block_repeated_files(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.FileField(id='234', required=True, label='Test2', type='file'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.BlockField(id='1', label='test', type='block:foobar', max_items=3),
fields.PageField(id='2', label='2nd page', type='page'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.text.count('>Test<') == 1
assert 'Add another' in resp
resp = resp.form.submit('f1$add_element')
assert resp.text.count('>Test<') == 2
resp = resp.form.submit('f1$add_element')
assert resp.text.count('>Test<') == 3
assert resp.pyquery('.list-add').attr['style'] == 'display: none'
# fill items (1st and 3rd row)
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234$file'] = Upload('test1.txt', b'foobar1', 'text/plain')
resp.form['f1$element2$f123'] = 'foo2'
resp.form['f1$element2$f234$file'] = Upload('test2.txt', b'foobar2', 'text/plain')
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
assert resp.form['f1$element0$f123'].value == 'foo'
assert 'test1.txt' in resp
assert resp.form['f1$element1$f123'].value == 'foo2'
assert 'test2.txt' in resp
resp = resp.form.submit('previous') # -> 2nd page
resp = resp.form.submit('previous') # -> 1st page
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> submit
resp = resp.follow()
assert '>foo<' in resp
assert 'test1.txt' in resp
assert '>foo2<' in resp
assert 'test2.txt' in resp
@pytest.mark.parametrize('removed_line', [0, 1, 2])
def test_block_repeated_remove_line(pub, removed_line):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.StringField(id='234', required=True, label='Test2', type='string'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.BlockField(
id='1', label='test', type='block:foobar', max_items=5, hint='hintblock', remove_button=True
),
fields.PageField(id='2', label='2nd page', type='page'),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.text.count('>Test<') == 1
resp = resp.form.submit('f1$add_element')
assert resp.text.count('>Test<') == 2
resp = resp.form.submit('f1$add_element')
assert resp.text.count('>Test<') == 3
# fill items on three rows
resp.form['f1$element0$f123'] = 'foo1'
resp.form['f1$element0$f234'] = 'bar1'
resp.form['f1$element1$f123'] = 'foo2'
resp.form['f1$element1$f234'] = 'bar2'
resp.form['f1$element2$f123'] = 'foo3'
resp.form['f1$element2$f234'] = 'bar3'
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
assert resp.form['f1$element0$f123'].value == 'foo1'
assert resp.form['f1$element0$f234'].value == 'bar1'
assert resp.form['f1$element1$f123'].value == 'foo2'
assert resp.form['f1$element1$f234'].value == 'bar2'
assert resp.form['f1$element2$f123'].value == 'foo3'
assert resp.form['f1$element2$f234'].value == 'bar3'
resp = resp.form.submit('previous') # -> 2nd page
resp = resp.form.submit('previous') # -> 1st page
# simulate javascript removing of block elements from DOM
resp.form.field_order.remove(
('f1$element%s$f123' % removed_line, resp.form.fields['f1$element%s$f123' % removed_line][0])
)
del resp.form.fields['f1$element%s$f123' % removed_line]
resp.form.field_order.remove(
('f1$element%s$f234' % removed_line, resp.form.fields['f1$element%s$f234' % removed_line][0])
)
del resp.form.fields['f1$element%s$f234' % removed_line]
resp = resp.form.submit('submit') # -> 2nd page
resp = resp.form.submit('submit') # -> validation page
values = ['1', '2', '3']
del values[removed_line]
assert resp.form['f1$element0$f123'].value == 'foo%s' % values[0]
assert resp.form['f1$element0$f234'].value == 'bar%s' % values[0]
assert resp.form['f1$element1$f123'].value == 'foo%s' % values[1]
assert resp.form['f1$element1$f234'].value == 'bar%s' % values[1]
assert 'f1$element2$f123' not in resp.form.fields
assert 'f1$element2$f234' not in resp.form.fields
resp = resp.form.submit('submit') # -> submit
assert len(formdef.data_class().select()[0].data['1']['data']) == 2
@pytest.mark.parametrize('block_name', ['foobar', 'Foo bar'])
def test_block_digest(pub, block_name):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = block_name
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string', varname='foo'),
fields.StringField(id='234', required=True, label='Test2', type='string', varname='bar'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:%s' % block.slug, max_items=3),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'bar'
resp = resp.form.submit('f1$add_element')
resp.form['f1$element1$f123'] = 'foo2'
resp.form['f1$element1$f234'] = 'bar2'
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> submit
assert formdef.data_class().select()[0].data['1']['data'] == [
{'123': 'foo', '234': 'bar'},
{'123': 'foo2', '234': 'bar2'},
]
# by default it gets the type of object
assert formdef.data_class().select()[0].data['1_display'] == '%s, %s' % (block.name, block.name)
# set a digest template
formdef.data_class().wipe()
# legacy, <slug>_var_
block.digest_template = 'X{{%s_var_foo}}Y' % block.slug.replace('-', '_')
block.store()
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'bar'
resp = resp.form.submit('f1$add_element')
resp.form['f1$element1$f123'] = 'foo2'
resp.form['f1$element1$f234'] = 'bar2'
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> submit
assert formdef.data_class().select()[0].data['1']['data'] == [
{'123': 'foo', '234': 'bar'},
{'123': 'foo2', '234': 'bar2'},
]
assert formdef.data_class().select()[0].data['1_display'] == 'XfooY, Xfoo2Y'
# non-legacy, block_var_
formdef.data_class().wipe()
block.digest_template = 'X{{block_var_foo}}Y'
block.store()
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'bar'
resp = resp.form.submit('f1$add_element')
resp.form['f1$element1$f123'] = 'foo2'
resp.form['f1$element1$f234'] = 'bar2'
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> submit
assert formdef.data_class().select()[0].data['1']['data'] == [
{'123': 'foo', '234': 'bar'},
{'123': 'foo2', '234': 'bar2'},
]
assert formdef.data_class().select()[0].data['1_display'] == 'XfooY, Xfoo2Y'
def test_block_digest_item(pub):
FormDef.wipe()
BlockDef.wipe()
NamedDataSource.wipe()
# add a named data source
data_source = NamedDataSource(name='foobar')
data_source.data_source = {
'type': 'formula',
'value': repr([{'id': '1', 'text': 'un'}, {'id': '2', 'text': 'deux'}]),
}
data_source.store()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string', varname='foo'),
fields.ItemField(
id='234', required=True, label='Test2', type='item', varname='bar', data_source={'type': 'foobar'}
),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar', max_items=3),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = '1'
resp = resp.form.submit('f1$add_element')
resp.form['f1$element1$f123'] = 'foo2'
resp.form['f1$element1$f234'] = '2'
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> submit
assert formdef.data_class().select()[0].data['1']['data'] == [
{'123': 'foo', '234': '1', '234_display': 'un'},
{'123': 'foo2', '234': '2', '234_display': 'deux'},
]
# by default it gets the type of object
assert formdef.data_class().select()[0].data['1_display'] == 'foobar, foobar'
# set a digest template
formdef.data_class().wipe()
block.digest_template = 'X{{block_var_bar}}Y'
block.store()
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = '1'
resp = resp.form.submit('f1$add_element')
resp.form['f1$element1$f123'] = 'foo2'
resp.form['f1$element1$f234'] = '2'
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> submit
assert formdef.data_class().select()[0].data['1']['data'] == [
{'123': 'foo', '234': '1', '234_display': 'un'},
{'123': 'foo2', '234': '2', '234_display': 'deux'},
]
assert formdef.data_class().select()[0].data['1_display'] == 'XunY, XdeuxY'
def test_block_post_condition_on_2nd_page(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string', varname='foo'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.PageField(
id='1',
label='2nd page',
type='page',
post_conditions=[
{
'condition': {'type': 'django', 'value': 'form_var_blockfoo|getlist:"foo"|sum == 5'},
'error_message': 'You shall not pass.',
}
],
),
fields.BlockField(id='2', label='test', type='block:foobar', max_items=3, varname='blockfoo'),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp = resp.form.submit('submit') # -> second page
resp.form['f2$element0$f123'] = 2
resp = resp.form.submit('f2$add_element')
resp.form['f2$element1$f123'] = 3
resp = resp.form.submit('submit') # -> validation page
assert 'You shall not pass.' not in resp.text
resp = resp.form.submit('submit') # -> submit
resp = resp.follow()
@mock.patch('wcs.qommon.misc.urlopen')
def test_block_with_dynamic_item_field(mock_urlopen, pub):
def data_source(url):
url, query = url.split('?q=')
payload = []
if query == 'foo':
payload = [{'id': '1', 'text': 'foo'}]
elif query == 'bar':
payload = [{'id': '2', 'text': 'bar'}]
return io.StringIO(json.dumps({'data': payload}))
mock_urlopen.side_effect = data_source
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string', varname='foo'),
]
block.store()
formdef = FormDef()
formdef.name = 'foo'
formdef.fields = [
fields.StringField(id='1', label='field 1', type='string', varname='foo'),
fields.ItemField(
id='2',
label='field 2',
varname='bar',
data_source={
'type': 'json',
'value': 'http://whatever/data-source?q={{form_var_foo|default:""}}',
},
),
fields.BlockField(id='3', label='block', type='block:foobar', max_items=3),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
# select first field
resp.form['f1'] = 'foo'
live_resp = app.post('/foo/live?modified_field_id=1', params=resp.form.submit_fields())
assert live_resp.json['result']['2']['items'] == [{'id': '1', 'text': 'foo'}]
resp.form['f2'].options = []
for item in live_resp.json['result']['2']['items']:
# simulate javascript filling the <select>
resp.form['f2'].options.append((item['id'], False, item['text']))
# select second field
resp.form['f2'] = '1'
# add block
resp = resp.form.submit('f3$add_element')
# second field value is kept
assert resp.form['f2'].value == '1'
resp = app.get(formdef.get_url())
# select first field
resp.form['f1'] = 'foo'
live_resp = app.post('/foo/live?modified_field_id=1', params=resp.form.submit_fields())
assert live_resp.json['result']['2']['items'] == [{'id': '1', 'text': 'foo'}]
resp.form['f2'].options = []
for item in live_resp.json['result']['2']['items']:
# simulate javascript filling the <select>
resp.form['f2'].options.append((item['id'], False, item['text']))
# select second field
resp.form['f2'] = '1'
# submit form with empty value in block
resp = resp.form.submit()
# second field value is kept
assert resp.form['f2'].value == '1'
def test_block_used_in_later_prefill(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Amount', type='string', varname='amount'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.PageField(id='0', label='1st page', type='page'),
fields.BlockField(
id='1', label='test', type='block:foobar', varname='data', max_items=3, hint='hintblock'
),
fields.PageField(id='2', label='2nd page', type='page'),
fields.StringField(
id='3', label='sum', prefill={'type': 'string', 'value': '{{form_var_data|getlist:"amount"|sum}}'}
),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = '5'
resp = resp.form.submit('f1$add_element')
resp.form['f1$element1$f123'] = '3'
resp = resp.form.submit('f1$add_element')
resp.form['f1$element2$f123'] = '2'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.form['f3'].value == '10'
resp = resp.form.submit('previous') # -> 1st page
resp.form['f1$element2$f123'] = '1'
resp = resp.form.submit('submit') # -> 2nd page
assert resp.form['f3'].value == '9'
def test_block_add_and_locked_field(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Amount', type='string', varname='amount'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar', varname='data', max_items=3),
fields.StringField(id='2', label='foo', prefill={'type': 'string', 'value': 'Foo', 'locked': True}),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.form['f2'].value == 'Foo'
assert 'readonly' in resp.form['f2'].attrs
resp.form['f1$element0$f123'] = 'a'
resp = resp.form.submit('f1$add_element')
assert resp.form['f2'].value == 'Foo'
assert 'readonly' in resp.form['f2'].attrs
resp.form['f1$element1$f123'] = 'b'
resp = resp.form.submit('f1$add_element')
resp.form['f1$element2$f123'] = 'c'
resp = resp.form.submit('submit') # -> validation page
resp = resp.form.submit('submit') # -> submit
def test_block_subfields_display_locations(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.TitleField(id='234', label='Blah Title', type='title'),
fields.SubtitleField(id='345', label='Blah Subtitle', type='subtitle'),
fields.CommentField(id='456', label='Blah Comment', type='comment'),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar'),
]
formdef.store()
# default mode
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'Blah Field'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
assert not resp.pyquery('[style="display: none"] [data-field-id="123"]')
assert resp.pyquery('[data-field-id="234"]')
assert not resp.pyquery('[style="display: none"] [data-field-id="234"]')
assert resp.pyquery('[data-field-id="345"]')
assert not resp.pyquery('[style="display: none"] [data-field-id="345"]')
resp = resp.form.submit('submit').follow() # -> submitted
assert 'Blah Field' in resp.text
assert 'Blah Title' in resp.text
assert 'Blah Subtitle' in resp.text
assert 'Blah Comment' not in resp.text
# all on validation page
for field in block.fields:
field.display_locations = ['validation']
block.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'Blah Field'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
assert not resp.pyquery('[style="display: none"] [data-field-id="123"]')
assert resp.pyquery('[data-field-id="234"]')
assert not resp.pyquery('[style="display: none"] [data-field-id="234"]')
assert resp.pyquery('[data-field-id="345"]')
assert not resp.pyquery('[style="display: none"] [data-field-id="345"]')
assert resp.pyquery('[data-field-id="456"]')
assert not resp.pyquery('[style="display: none"] [data-field-id="456"]')
# none on validation page
for field in block.fields:
field.display_locations = []
block.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'Blah Field'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
assert resp.pyquery('[style="display: none"] [data-field-id="123"]')
assert resp.pyquery('[style="display: none"] [data-field-id="234"]')
assert resp.pyquery('[style="display: none"] [data-field-id="345"]')
assert not resp.pyquery('[data-field-id="456"]')
# all on summary page
for field in block.fields:
field.display_locations = ['summary']
block.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'Blah Field'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
resp = resp.form.submit('submit').follow() # -> submitted
assert 'Blah Field' in resp.text
assert 'Blah Title' in resp.text
assert 'Blah Subtitle' in resp.text
assert 'Blah Comment' in resp.text
# none on summary page
for field in block.fields:
field.display_locations = []
block.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'Blah Field'
resp = resp.form.submit('submit') # -> validation page
assert 'Check values then click submit.' in resp.text
resp = resp.form.submit('submit').follow() # -> submitted
assert 'Blah Field' not in resp.text
assert 'Blah Title' not in resp.text
assert 'Blah Subtitle' not in resp.text
assert 'Blah Comment' not in resp.text
def test_block_block_counter(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
fields.TitleField(
id='234', label='Blah Title #{{ block_counter.index }} #{{ block_counter.index0 }}', type='title'
),
fields.SubtitleField(
id='345',
label='Blah Subtitle #{{ block_counter_index }} #{{ block_counter_index0 }}',
type='subtitle',
),
fields.CommentField(
id='456',
label='Blah Comment #{{ block_counter.index }} #{{ block_counter.index0 }}',
type='comment',
),
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar', max_items=3),
]
formdef.store()
app = get_app(pub)
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'Blah Field 1'
assert 'Blah Title #1 #0' in resp.text
assert 'Blah Subtitle #1 #0' in resp.text
assert 'Blah Comment #1 #0' in resp.text
resp = resp.form.submit('f1$add_element')
assert 'Blah Title #1 #0' in resp.text
assert 'Blah Subtitle #1 #0' in resp.text
assert 'Blah Comment #1 #0' in resp.text
resp.form['f1$element1$f123'] = 'Blah Field 2'
assert 'Blah Title #2 #1' in resp.text
assert 'Blah Subtitle #2 #1' in resp.text
assert 'Blah Comment #2 #1' in resp.text
resp = resp.form.submit('submit') # -> validation page
assert 'Blah Field 1' in resp.text
assert 'Blah Title #1 #0' in resp.text
assert 'Blah Subtitle #1 #0' in resp.text
assert 'Blah Field 2' in resp.text
assert 'Blah Title #2 #1' in resp.text
assert 'Blah Subtitle #2 #1' in resp.text
resp = resp.form.submit('submit').follow() # -> submitted
assert 'Blah Field 1' in resp.text
assert 'Blah Title #1 #0' in resp.text
assert 'Blah Subtitle #1 #0' in resp.text
assert 'Blah Field 2' in resp.text
assert 'Blah Title #2 #1' in resp.text
assert 'Blah Subtitle #2 #1' in resp.text
def test_workflow_display_form_with_block_add(pub):
user = create_user(pub)
block = BlockDef()
block.name = 'foobar2'
block.fields = [
fields.StringField(id='123', required=True, label='Test', type='string'),
]
block.store()
wf = Workflow.get_default_workflow()
wf.id = '2'
wf.store()
wf = Workflow.get(wf.id)
status = wf.get_status('new')
display_form = status.add_action('form', id='_display_form')
display_form.by = ['_submitter']
display_form.varname = 'blah'
display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
display_form.formdef.fields = [
fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
fields.BlockField(id='2', label='Blocks', type='block:foobar2', varname='data', max_items=3),
]
jump = status.add_action('jumponsubmit', id='_jump')
jump.status = 'accepted'
wf.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = []
formdef.workflow_id = wf.id
formdef.store()
formdef.data_class().wipe()
formdata = formdef.data_class()()
formdata.user_id = user.id
formdata.just_created()
formdata.status = 'wf-new'
formdata.store()
resp = login(get_app(pub), username='foo', password='foo').get(formdata.get_url())
resp.form['fblah_1'] = 'blah'
resp.form['fblah_2$element0$f123'] = 'foo'
resp = resp.form.submit('fblah_2$add_element')
resp.form['fblah_2$element1$f123'] = 'bar'
resp = resp.form.submit('submit')
assert formdef.data_class().get(formdata.id).workflow_data == {
'blah_var_data': 'foobar2, foobar2',
'blah_var_data_raw': {'data': [{'123': 'foo'}, {'123': 'bar'}], 'schema': {'123': 'string'}},
'blah_var_str': 'blah',
}
def test_removed_block_in_form_page(pub):
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='0', label='test', type='block:removed'),
]
formdef.store()
resp = get_app(pub).get(formdef.get_url(), status=500)
assert 'A fatal error happened.' in resp.text
assert pub.loggederror_class.count() == 1
logged_error = pub.loggederror_class.select()[0]
assert '(id:%s)' % logged_error.id in resp.text
resp = get_app(pub).get(formdef.get_url(), status=500)
assert '(id:%s)' % logged_error.id in resp.text
logged_error = pub.loggederror_class.select()[0]
assert logged_error.occurences_count == 2
def test_block_with_static_condition(pub):
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='One', type='string', varname='one'),
fields.StringField(
id='234',
required=True,
label='Two',
type='string',
condition={'type': 'django', 'value': 'False'},
),
fields.StringField(
id='345',
required=True,
label='Three',
type='string',
condition={'type': 'django', 'value': 'True'},
),
]
block.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar'),
]
formdef.store()
formdef.data_class().wipe()
resp = get_app(pub).get(formdef.get_url())
assert 'f1$element0$f123' in resp.form.fields
assert 'f1$element0$f234' in resp.form.fields
assert resp.pyquery('[data-widget-name="f1$element0$f234"]').attr.style == 'display: none'
assert 'f1$element0$f345' in resp.form.fields
assert resp.pyquery('[data-widget-name="f1$element0$f345"]').attr.style is None
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f345'] = 'bar'
resp = resp.form.submit('submit') # -> validation page
assert resp.form['f1$element0$f123'].attrs['readonly']
assert resp.form['f1$element0$f123'].value == 'foo'
assert resp.form['f1$element0$f234'].value == ''
assert resp.pyquery('[data-widget-name="f1$element0$f234"]').attr.style == 'display: none'
assert resp.form['f1$element0$f345'].value == 'bar'
resp = resp.form.submit('submit') # -> end page
formdata = formdef.data_class().select()[0]
assert formdata.data == {
'1': {
'data': [{'123': 'foo', '345': 'bar'}],
'schema': {'123': 'string', '234': 'string', '345': 'string'},
},
'1_display': 'foobar',
}
def test_block_with_block_field_condition(pub):
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='One', type='string', varname='one'),
fields.StringField(
id='234',
required=True,
label='Two',
type='string',
condition={'type': 'django', 'value': 'block_var_one == "test"'},
),
]
block.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar'),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.pyquery('[data-widget-name="f1$element0$f123"]').attr['data-live-source'] == 'true'
assert resp.pyquery('[data-widget-name="f1$element0$f234"]').attr.style == 'display: none'
resp.form['f1$element0$f123'] = 'foo'
live_resp = app.post(
formdef.get_url() + 'live?modified_field_id=123&modified_block_id=1&modified_block_row=0',
params=resp.form.submit_fields(),
)
assert live_resp.json['result']['1-123-0']['visible'] is True
assert live_resp.json['result']['1-234-0']['visible'] is False
resp.form['f1$element0$f123'] = 'test'
live_resp = app.post(
formdef.get_url() + 'live?modified_field_id=123&modified_block_id=1&modified_block_row=0',
params=resp.form.submit_fields(),
)
assert live_resp.json['result']['1-123-0']['visible'] is True
assert live_resp.json['result']['1-234-0']['visible'] is True
resp = resp.form.submit('submit') # -> error as 1-234-0 is required
assert 'There were errors processing the form' in resp
resp.form['f1$element0$f234'] = 'test'
resp = resp.form.submit('submit') # validation
assert 'There were errors processing the form' not in resp
resp = resp.form.submit('previous') # -> 1st page
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = ''
resp = resp.form.submit('submit') # validation
assert 'There were errors processing the form' not in resp
resp = resp.form.submit('submit') # -> end page
formdata = formdef.data_class().select()[0]
assert formdata.data == {
'1': {
'data': [{'123': 'foo'}],
'schema': {'123': 'string', '234': 'string'},
},
'1_display': 'foobar',
}
formdef.data_class().wipe()
# check with repetition
formdef.fields[0].max_items = 3
formdef.store()
resp = app.get(formdef.get_url())
resp = resp.form.submit('f1$add_element')
assert 'There were errors processing the form' not in resp
assert resp.pyquery('[data-widget-name="f1$element0$f234"]').attr.style == 'display: none'
assert resp.pyquery('[data-widget-name="f1$element1$f234"]').attr.style == 'display: none'
resp.form['f1$element0$f123'] = 'test'
live_resp = app.post(
formdef.get_url() + 'live?modified_field_id=123&modified_block_id=1&modified_block_row=0',
params=resp.form.submit_fields(),
)
assert live_resp.json['result']['1-123-0']['visible'] is True
assert live_resp.json['result']['1-234-0']['visible'] is True
assert live_resp.json['result']['1-123-1']['visible'] is True
assert live_resp.json['result']['1-234-1']['visible'] is False
resp.form['f1$element0$f234'] = 'foo'
resp.form['f1$element1$f123'] = 'xxx'
resp = resp.form.submit('submit') # validation
resp = resp.form.submit('submit') # -> end page
formdata = formdef.data_class().select()[0]
assert formdata.data == {
'1': {
'data': [{'123': 'test', '234': 'foo'}, {'123': 'xxx'}],
'schema': {'123': 'string', '234': 'string'},
},
'1_display': 'foobar, foobar',
}
def test_block_with_block_counter_condition(pub):
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', required=True, label='One', type='string', varname='one'),
fields.StringField(
id='234',
required=True,
label='Two',
type='string',
condition={'type': 'django', 'value': 'block_counter.index == 1'},
),
]
block.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar', max_items=3),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.pyquery('[data-widget-name="f1$element0$f234"]').attr.style is None
resp = resp.form.submit('f1$add_element')
assert resp.pyquery('[data-widget-name="f1$element1$f234"]').attr.style == 'display: none'
resp = resp.form.submit('f1$add_element')
assert resp.pyquery('[data-widget-name="f1$element2$f234"]').attr.style == 'display: none'
resp.form['f1$element0$f123'] = 'foo'
resp.form['f1$element0$f234'] = 'foo'
resp.form['f1$element1$f123'] = 'bar'
live_resp = app.post(
formdef.get_url() + 'live',
params=resp.form.submit_fields(),
)
assert live_resp.json['result']['1-123-0']['visible'] is True
assert live_resp.json['result']['1-234-0']['visible'] is True
assert live_resp.json['result']['1-123-1']['visible'] is True
assert live_resp.json['result']['1-234-1']['visible'] is False
assert live_resp.json['result']['1-123-2']['visible'] is True
assert live_resp.json['result']['1-234-2']['visible'] is False
resp = resp.form.submit('submit') # validation
resp = resp.form.submit('submit') # -> end page
formdata = formdef.data_class().select()[0]
assert formdata.data == {
'1': {
'data': [{'123': 'foo', '234': 'foo'}, {'123': 'bar'}],
'schema': {'123': 'string', '234': 'string'},
},
'1_display': 'foobar, foobar',
}
formdef.data_class().wipe()
def test_block_with_block_item_field_condition_and_prefill(pub):
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(
id='123',
required=True,
label='One',
type='string',
prefill={'type': 'string', 'value': '{{ "plop" }}'},
),
fields.ItemField(
id='234',
required=True,
label='Test2',
type='item',
varname='item',
items=['Foo', 'Bar'],
prefill={'type': 'none'}, # not a real prefill
),
fields.StringField(
id='345',
required=True,
label='Two',
type='string',
condition={'type': 'django', 'value': 'block_var_item == "Foo"'},
),
]
block.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', type='block:foobar'),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
resp = app.get(formdef.get_url())
assert resp.form['f1$element0$f123'].value == 'plop'
assert resp.form['f1$element0$f234'].value == 'Foo'
assert resp.pyquery('[data-widget-name="f1$element0$f234"]').attr['data-live-source'] == 'true'
assert resp.pyquery('[data-widget-name="f1$element0$f345"]').attr.style == 'display: none'
live_resp = app.post(
formdef.get_url() + 'live?modified_field_id=123&modified_block_id=1&modified_block_row=0',
params=resp.form.submit_fields(),
)
assert live_resp.json['result']['1-123-0']['visible'] is True
assert live_resp.json['result']['1-234-0']['visible'] is True
assert live_resp.json['result']['1-345-0']['visible'] is True
resp.form['f1$element0$f345'] = 'test'
resp = resp.form.submit('submit') # validation
# check with real prefill
block.fields[1].prefill = {'type': 'string', 'value': '{{ "Bar" }}'}
block.store()
resp = app.get(formdef.get_url())
assert resp.form['f1$element0$f123'].value == 'plop'
assert resp.form['f1$element0$f234'].value == 'Bar'