Compare commits

..

2 Commits

Author SHA1 Message Date
Frédéric Péters 24195b7bd6 blocks: add support for post conditions (#71778)
gitea/wcs/pipeline/head This commit looks good Details
2024-03-12 13:42:36 +01:00
Frédéric Péters 1ad4bbee35 blocks: add/manage post conditions attribute (#71778) 2024-03-12 13:42:36 +01:00
2 changed files with 112 additions and 4 deletions

View File

@ -2790,3 +2790,108 @@ def test_block_titles_and_empty_block_on_summary_page(pub, emails):
assert 'Form Title' not in resp.text
assert 'Form Page' not in emails.get('New form (form title)')['msg'].get_payload()[0].get_payload()
assert 'Form Title' not in emails.get('New form (form title)')['msg'].get_payload()[0].get_payload()
def test_block_field_post_condition(pub):
FormDef.wipe()
BlockDef.wipe()
block = BlockDef()
block.name = 'foobar'
block.fields = [
fields.StringField(id='123', label='Foo', varname='foo'),
fields.StringField(id='234', label='Bar', varname='bar'),
]
block.post_conditions = [
{
'condition': {'type': 'django', 'value': 'block_var_foo|startswith:"b"'},
'error_message': 'foo must start with a b.',
},
{
'condition': {'type': 'django', 'value': 'block_var_foo == block_var_bar'},
'error_message': 'foo and bar must be identical.',
},
]
block.store()
formdef = FormDef()
formdef.name = 'form title'
formdef.fields = [
fields.BlockField(id='1', label='test', block_slug='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') # -> error
assert (
resp.pyquery('.widget-with-error .error').text()
== 'foo must start with a b. foo and bar must be identical.'
)
resp.form['f1$element0$f123'] = 'baz'
resp.form['f1$element0$f234'] = 'bar'
resp = resp.form.submit('submit') # -> error
assert resp.pyquery('.widget-with-error .error').text() == 'foo and bar must be identical.'
resp.form['f1$element0$f123'] = 'baz'
resp.form['f1$element0$f234'] = 'baz'
resp = resp.form.submit('submit') # -> validation page
assert resp.form['f1$element0$f123'].attrs['readonly']
resp = resp.form.submit('submit') # -> end page
formdata = formdef.data_class().select()[0]
assert formdata.status == 'wf-new'
assert formdata.data == {
'1': {'data': [{'123': 'baz', '234': 'baz'}], 'schema': {'123': 'string', '234': 'string'}},
'1_display': 'foobar',
}
# multiple rows
formdef.fields[0].max_items = 3
formdef.store()
formdef.data_class().wipe()
resp = app.get(formdef.get_url())
resp.form['f1$element0$f123'] = 'baz'
resp.form['f1$element0$f234'] = 'bar'
resp = resp.form.submit('f1$add_element')
assert not resp.pyquery('.widget-with-error')
resp.form['f1$element1$f123'] = 'bar'
resp.form['f1$element1$f234'] = 'bar'
resp = resp.form.submit('submit') # -> error
assert (
resp.pyquery('.widget-with-error[data-block-row="element0"] .error').text()
== 'foo and bar must be identical.'
)
assert resp.pyquery('.widget-with-error[data-block-row="element1"] .error').text() == ''
resp.form['f1$element1$f234'] = 'baz'
resp = resp.form.submit('submit') # -> error
assert (
resp.pyquery('.widget-with-error[data-block-row="element0"] .error').text()
== 'foo and bar must be identical.'
)
assert (
resp.pyquery('.widget-with-error[data-block-row="element1"] .error').text()
== 'foo and bar must be identical.'
)
resp.form['f1$element0$f123'] = 'bar'
resp.form['f1$element1$f234'] = 'bar'
resp = resp.form.submit('submit') # -> validation page
assert resp.form['f1$element0$f123'].attrs['readonly']
resp = resp.form.submit('submit') # -> end page
formdata = formdef.data_class().select()[0]
assert formdata.status == 'wf-new'
assert formdata.data == {
'1': {
'data': [{'123': 'bar', '234': 'bar'}, {'123': 'bar', '234': 'bar'}],
'schema': {'123': 'string', '234': 'string'},
},
'1_display': 'foobar, foobar',
}

View File

@ -322,6 +322,8 @@ class BlockDef(StorableObject, PostConditionsXmlMixin):
location = 'forms/blocks/%s/' % self.id
for field in self.fields or []:
yield from field.i18n_scan(base_location=location)
for post_condition in self.post_conditions or []:
yield location, None, post_condition.get('error_message')
def get_all_fields(self):
return self.fields
@ -441,12 +443,13 @@ class BlockSubWidget(CompositeWidget):
with self.block.visibility_context(value, self.index):
for i, post_condition in enumerate(self.block.post_conditions):
condition = post_condition.get('condition')
error_message = post_condition.get('error_message')
try:
if not conditions.Condition(condition, record_errors=False).evaluate():
error_messages.append(error_message)
if conditions.Condition(condition, record_errors=False).evaluate():
continue
except RuntimeError:
error_messages.append(error_message)
pass
error_message = post_condition.get('error_message')
error_messages.append(get_publisher().translate(error_message))
if error_messages:
self.set_error(' '.join(error_messages))