forms: keep block fields as parsed when prefilling (#50530)

This commit is contained in:
Frédéric Péters 2021-01-25 19:41:04 +01:00
parent 87d62e67c3
commit a9d3464319
2 changed files with 116 additions and 32 deletions

View File

@ -397,6 +397,14 @@ def test_block_string_prefill(pub, blocks_feature):
]
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 = [
@ -404,49 +412,120 @@ def test_block_string_prefill(pub, blocks_feature):
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())
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'
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['3']['data'][0]['123'] == '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 = 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 = 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'
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):

View File

@ -372,6 +372,11 @@ class FormPage(Directory, FormTemplateMixin):
if not prefilled and widget:
widget.clear_error()
widget._parsed = False
if block or field.key == 'block':
# keep block outer & inner widgets as _parsed to avoid
# later display of "required value" message that should
# only happen when pages are submitted.
widget._parsed = True
if v is not None:
# store computed value, it will be used to compare with