wcs/tests/form_pages/test_block.py

1520 lines
52 KiB
Python

# -*- coding: utf-8 -*-
import io
import json
import mock
import pytest
from utilities import clean_temporary_pub, create_temporary_pub, get_app, login
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 FormWorkflowStatusItem, WorkflowFormFieldsFormDef
from wcs.workflows import Workflow
from .test_all import create_user
def pytest_generate_tests(metafunc):
if 'pub' in metafunc.fixturenames:
metafunc.parametrize('pub', ['pickle', 'sql', 'pickle-templates', 'pickle-lazy'], 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()
if Category.count() == 0:
cat = Category(name='foobar')
cat.store()
return pub
def teardown_module(module):
clean_temporary_pub()
def test_block_simple(pub, blocks_feature):
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, blocks_feature):
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, blocks_feature):
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, blocks_feature):
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, blocks_feature):
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, blocks_feature):
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, blocks_feature):
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, blocks_feature):
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, blocks_feature):
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, blocks_feature):
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 = FormWorkflowStatusItem()
display_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'))
st1.items.append(display_form)
display_form.parent = st1
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, blocks_feature):
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, blocks_feature):
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, blocks_feature):
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, blocks_feature):
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_over_limit(pub, blocks_feature):
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_files(pub, blocks_feature):
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, blocks_feature, 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, blocks_feature, 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()
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'
def test_block_digest_item(pub, blocks_feature):
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{{foobar_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, blocks_feature):
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, blocks_feature):
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 = lambda url: data_source(url)
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, blocks_feature):
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, blocks_feature):
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, blocks_feature):
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