workflow: prefix fields in FormWorkflowStatusItem (#13846)

This commit is contained in:
Lauréline Guérin 2020-11-13 09:44:24 +01:00
parent 40f6ae2551
commit 081ff59114
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
7 changed files with 179 additions and 99 deletions

View File

@ -3804,13 +3804,13 @@ def test_backoffice_workflow_display_form(pub):
break
app = login(get_app(pub))
resp = app.get(formdata.get_url(backoffice=True))
assert 'f1' in resp.form.fields
resp.form['f1'] = 'blah'
assert 'fblah_1' in resp.form.fields
resp.form['fblah_1'] = 'blah'
# don't fill required radio button
resp = resp.form.submit('submit')
assert formdef.data_class().get(formdata.id).status == 'wf-new'
assert 'There were errors processing your form.' in resp.text
resp.form['f2'] = 'c'
resp.form['fblah_2'] = 'c'
resp = resp.form.submit('submit')
assert formdef.data_class().get(formdata.id).status == 'wf-accepted'
assert formdef.data_class().get(formdata.id).workflow_data == {
@ -3854,8 +3854,8 @@ def test_backoffice_workflow_form_with_conditions(pub):
break
app = login(get_app(pub))
resp = app.get(formdata.get_url(backoffice=True))
assert 'f1' in resp.form.fields
assert 'f2' in resp.form.fields
assert 'fblah_1' in resp.form.fields
assert 'fblah_2' in resp.form.fields
# check with static condition
display_form.formdef.fields = [
@ -3867,8 +3867,8 @@ def test_backoffice_workflow_form_with_conditions(pub):
wf.store()
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
assert 'f1' in resp.form.fields
assert 'f2' not in resp.form.fields
assert 'fblah_1' in resp.form.fields
assert 'fblah_2' not in resp.form.fields
# check condition based on formdata
display_form.formdef.fields = [
@ -3880,8 +3880,8 @@ def test_backoffice_workflow_form_with_conditions(pub):
wf.store()
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
assert 'f1' in resp.form.fields
assert 'f2' in resp.form.fields
assert 'fblah_1' in resp.form.fields
assert 'fblah_2' in resp.form.fields
display_form.formdef.fields = [
fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
@ -3892,8 +3892,8 @@ def test_backoffice_workflow_form_with_conditions(pub):
wf.store()
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
assert 'f1' in resp.form.fields
assert 'f2' in resp.form.fields
assert 'fblah_1' in resp.form.fields
assert 'fblah_2' in resp.form.fields
# check with live conditions
display_form.formdef.fields = [
@ -3905,30 +3905,30 @@ def test_backoffice_workflow_form_with_conditions(pub):
wf.store()
resp = login(get_app(pub)).get(formdata.get_url(backoffice=True))
assert 'f1' in resp.form.fields
assert 'f2' in resp.form.fields
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
assert 'fblah_1' in resp.form.fields
assert 'fblah_2' in resp.form.fields
assert resp.html.find('div', {'data-field-id': 'blah_1'}).attrs['data-live-source'] == 'true'
assert resp.html.find('div', {'data-field-id': 'blah_2'}).attrs.get('style') == 'display: none'
live_url = resp.html.find('form').attrs['data-live-url']
assert '/backoffice/' in live_url
resp.form['f1'] = ''
resp.form['fblah_1'] = ''
live_resp = app.post(live_url, params=resp.form.submit_fields())
assert live_resp.json['result']['1']['visible']
assert not live_resp.json['result']['2']['visible']
assert live_resp.json['result']['blah_1']['visible']
assert not live_resp.json['result']['blah_2']['visible']
resp.form['f1'] = 'xxx'
resp.form['fblah_1'] = 'xxx'
live_resp = app.post(live_url, params=resp.form.submit_fields())
assert live_resp.json['result']['1']['visible']
assert live_resp.json['result']['2']['visible']
assert live_resp.json['result']['blah_1']['visible']
assert live_resp.json['result']['blah_2']['visible']
# check submit doesn't work
resp = resp.form.submit('submit')
assert 'There were errors processing your form.' in resp.text
resp.form['f1'] = 'xxx2'
resp.form['fblah_1'] = 'xxx2'
live_resp = app.post(live_url, params=resp.form.submit_fields())
assert live_resp.json['result']['1']['visible']
assert not live_resp.json['result']['2']['visible']
assert live_resp.json['result']['blah_1']['visible']
assert not live_resp.json['result']['blah_2']['visible']
# check submit does work when second field is hidden
resp = resp.form.submit('submit').follow()
@ -3982,14 +3982,14 @@ def test_backoffice_workflow_form_with_live_data_source(pub):
urlopen.side_effect = side_effect
resp = login(app).get(formdata.get_url(backoffice=True))
assert 'f1' in resp.form.fields
assert 'f2' in resp.form.fields
assert resp.form.fields['f2'][0].options == [(u'A', False, u'hello'), (u'B', False, u'world')]
assert 'fblah_1' in resp.form.fields
assert 'fblah_2' in resp.form.fields
assert resp.form.fields['fblah_2'][0].options == [(u'A', False, u'hello'), (u'B', False, u'world')]
live_url = resp.html.find('form').attrs['data-live-url']
resp.form['f1'] = 'toto'
live_resp = app.post(live_url + '?modified_field_id=1', params=resp.form.submit_fields())
assert live_resp.json['result']['2']['items'] == [{u'text': u'hello', u'id': u'C'}, {u'text': u'world', u'id': u'D'}]
resp.form['fblah_1'] = 'toto'
live_resp = app.post(live_url + '?modified_field_id=blah_1', params=resp.form.submit_fields())
assert live_resp.json['result']['blah_2']['items'] == [{u'text': u'hello', u'id': u'C'}, {u'text': u'world', u'id': u'D'}]
def test_backoffice_criticality_in_formdef_listing(pub):
@ -5389,8 +5389,8 @@ def test_lazy_eval_with_conditional_workflow_form(pub):
formdata.store()
resp = app.get(formdata.get_url(backoffice=True))
resp.forms[0]['f1'] = 'a'
resp.forms[0]['f2'] = 'b'
resp.forms[0]['flocal_1'] = 'a'
resp.forms[0]['flocal_2'] = 'b'
resp = resp.forms[0].submit()
assert formdata.select()[0].status == 'wf-done'

View File

@ -6149,7 +6149,7 @@ def test_user_global_action_along_form(pub):
formdata = formdef.data_class().select()[0]
resp = app.get(formdata.get_url())
assert resp.form['f1'].attrs['aria-required'] == 'true'
assert resp.form['fxxx_1'].attrs['aria-required'] == 'true'
assert 'button-action-1' in resp.form.fields
resp = resp.form.submit('button-action-1')
@ -6753,35 +6753,35 @@ def test_field_live_select_content_on_workflow_form(pub, http_requests):
assert 'The form has been recorded' in resp.text
assert 'data-live-url' in resp.html.find('form').attrs
assert 'f1' in resp.form.fields
assert 'f2' in resp.form.fields
assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
assert resp.html.find('div', {'data-field-id': '3'}).find('select')
assert 'fxxx_1' in resp.form.fields
assert 'fxxx_2' in resp.form.fields
assert resp.html.find('div', {'data-field-id': 'xxx_2'}).attrs['data-live-source'] == 'true'
assert resp.html.find('div', {'data-field-id': 'xxx_3'}).find('select')
resp = resp.form.submit('submit') # submit with error, to check <form> attributes
assert 'data-live-url' in resp.html.find('form').attrs
assert 'f1' in resp.form.fields
assert 'f2' in resp.form.fields
assert resp.html.find('div', {'data-field-id': '2'}).attrs['data-live-source'] == 'true'
assert resp.html.find('div', {'data-field-id': '3'}).find('select')
resp.form['f1'] = 'hello'
assert 'fxxx_1' in resp.form.fields
assert 'fxxx_2' in resp.form.fields
assert resp.html.find('div', {'data-field-id': 'xxx_2'}).attrs['data-live-source'] == 'true'
assert resp.html.find('div', {'data-field-id': 'xxx_3'}).find('select')
resp.form['fxxx_1'] = 'hello'
live_resp = app.post('/test/1/live', params=resp.form.submit_fields())
assert live_resp.json['result']['1']['visible']
assert live_resp.json['result']['2']['visible']
assert live_resp.json['result']['3']['visible']
assert not 'items' in live_resp.json['result']['3']
resp.form['f2'] = 'plop'
live_resp = app.post('/test/1/live?modified_field_id=2', params=resp.form.submit_fields())
assert live_resp.json['result']['1']['visible']
assert live_resp.json['result']['2']['visible']
assert live_resp.json['result']['3']['visible']
assert 'items' in live_resp.json['result']['3']
assert len(live_resp.json['result']['3']['items']) > 0
assert live_resp.json['result']['xxx_1']['visible']
assert live_resp.json['result']['xxx_2']['visible']
assert live_resp.json['result']['xxx_3']['visible']
assert not 'items' in live_resp.json['result']['xxx_3']
resp.form['fxxx_2'] = 'plop'
live_resp = app.post('/test/1/live?modified_field_id=xxx_2', params=resp.form.submit_fields())
assert live_resp.json['result']['xxx_1']['visible']
assert live_resp.json['result']['xxx_2']['visible']
assert live_resp.json['result']['xxx_3']['visible']
assert 'items' in live_resp.json['result']['xxx_3']
assert len(live_resp.json['result']['xxx_3']['items']) > 0
resp.form['f3'].options = []
for item in live_resp.json['result']['3']['items']:
resp.form['fxxx_3'].options = []
for item in live_resp.json['result']['xxx_3']['items']:
# simulate javascript filling the <select>
resp.form['f3'].options.append((item['id'], False, item['text']))
resp.form['f3'] = 'a'
resp.form['fxxx_3'].options.append((item['id'], False, item['text']))
resp.form['fxxx_3'] = 'a'
resp = resp.form.submit('submit')
assert 'invalid value selected' not in resp
@ -7371,8 +7371,8 @@ def test_frontoffice_workflow_form_with_conditions(pub):
app = login(get_app(pub), username='foo', password='foo')
resp = app.get(formdata.get_url(backoffice=False))
assert 'f1' in resp.form.fields
assert 'f2' in resp.form.fields
assert 'fblah_1' in resp.form.fields
assert 'fblah_2' in resp.form.fields
# check with static condition
display_form.formdef.fields = [
@ -7384,8 +7384,8 @@ def test_frontoffice_workflow_form_with_conditions(pub):
wf.store()
resp = login(get_app(pub), username='foo', password='foo').get(formdata.get_url(backoffice=False))
assert 'f1' in resp.form.fields
assert 'f2' not in resp.form.fields
assert 'fblah_1' in resp.form.fields
assert 'fblah_2' not in resp.form.fields
# check condition based on formdata
display_form.formdef.fields = [
@ -7397,8 +7397,8 @@ def test_frontoffice_workflow_form_with_conditions(pub):
wf.store()
resp = login(get_app(pub), username='foo', password='foo').get(formdata.get_url(backoffice=False))
assert 'f1' in resp.form.fields
assert 'f2' in resp.form.fields
assert 'fblah_1' in resp.form.fields
assert 'fblah_2' in resp.form.fields
display_form.formdef.fields = [
fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
@ -7409,8 +7409,8 @@ def test_frontoffice_workflow_form_with_conditions(pub):
wf.store()
resp = login(get_app(pub), username='foo', password='foo').get(formdata.get_url(backoffice=False))
assert 'f1' in resp.form.fields
assert 'f2' in resp.form.fields
assert 'fblah_1' in resp.form.fields
assert 'fblah_2' in resp.form.fields
# check with live conditions
display_form.formdef.fields = [
@ -7422,29 +7422,29 @@ def test_frontoffice_workflow_form_with_conditions(pub):
wf.store()
resp = login(get_app(pub), username='foo', password='foo').get(formdata.get_url(backoffice=False))
assert 'f1' in resp.form.fields
assert 'f2' in resp.form.fields
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
assert 'fblah_1' in resp.form.fields
assert 'fblah_2' in resp.form.fields
assert resp.html.find('div', {'data-field-id': 'blah_1'}).attrs['data-live-source'] == 'true'
assert resp.html.find('div', {'data-field-id': 'blah_2'}).attrs.get('style') == 'display: none'
live_url = resp.html.find('form').attrs['data-live-url']
resp.form['f1'] = ''
resp.form['fblah_1'] = ''
live_resp = app.post(live_url, params=resp.form.submit_fields())
assert live_resp.json['result']['1']['visible']
assert not live_resp.json['result']['2']['visible']
assert live_resp.json['result']['blah_1']['visible']
assert not live_resp.json['result']['blah_2']['visible']
resp.form['f1'] = 'xxx'
resp.form['fblah_1'] = 'xxx'
live_resp = app.post(live_url, params=resp.form.submit_fields())
assert live_resp.json['result']['1']['visible']
assert live_resp.json['result']['2']['visible']
assert live_resp.json['result']['blah_1']['visible']
assert live_resp.json['result']['blah_2']['visible']
# check submit doesn't work
resp = resp.form.submit('submit')
assert 'There were errors processing your form.' in resp.text
resp.form['f1'] = 'xxx2'
resp.form['fblah_1'] = 'xxx2'
live_resp = app.post(live_url, params=resp.form.submit_fields())
assert live_resp.json['result']['1']['visible']
assert not live_resp.json['result']['2']['visible']
assert live_resp.json['result']['blah_1']['visible']
assert not live_resp.json['result']['blah_2']['visible']
# check submit does work when second field is hidden
resp = resp.form.submit('submit').follow()
@ -7488,13 +7488,13 @@ def test_frontoffice_workflow_form_with_dynamic_comment(pub):
app = login(get_app(pub), username='foo', password='foo')
resp = app.get(formdata.get_url(backoffice=False))
assert 'f1' in resp.form.fields
assert 'fblah_1' in resp.form.fields
live_url = resp.html.find('form').attrs['data-live-url']
resp.form['f1'] = 'test'
resp.form['fblah_1'] = 'test'
live_resp = app.post(live_url, params=resp.form.submit_fields())
assert live_resp.json['result']['2']['visible']
assert live_resp.json['result']['2']['content'] == '<p>value is test</p>'
assert live_resp.json['result']['blah_2']['visible']
assert live_resp.json['result']['blah_2']['content'] == '<p>value is test</p>'
def test_frontoffice_workflow_form_with_impossible_condition(pub):
@ -7534,8 +7534,8 @@ def test_frontoffice_workflow_form_with_impossible_condition(pub):
app = login(get_app(pub), username='foo', password='foo')
resp = app.get(formdata.get_url(backoffice=False))
assert 'f1' not in resp.form.fields
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
assert 'fblah_1' not in resp.form.fields
assert resp.html.find('div', {'data-field-id': 'blah_2'}).attrs.get('style') == 'display: none'
def test_choice_button_ignore_form_errors(pub):

View File

@ -594,7 +594,7 @@ def test_workflow_form_block_prefill(pub):
resp = resp.form.submit('submit') # -> validation
resp = resp.form.submit('submit').follow()
assert 'The form has been recorded' in resp
assert resp.form['f3$element0$f123'].value == 'foo@localhost'
assert resp.form['fxxx_3$element0$f123'].value == 'foo@localhost'
def test_block_title_and_comment(pub, blocks_feature):

View File

@ -1080,7 +1080,7 @@ def test_formdata_form_file_download(pub):
assert 'The form has been recorded' in resp.text
assert 'qommon.fileupload.js' in resp.text
resp.forms[0]['f1$file'] = Upload('test.txt', b'foobar', 'text/plain')
resp.forms[0]['fxxx_1$file'] = Upload('test.txt', b'foobar', 'text/plain')
resp = resp.forms[0].submit('submit')
assert formdef.data_class().count() == 1
@ -1129,7 +1129,7 @@ def test_formdata_workflow_form_prefill(pub):
assert resp.status_int == 302
resp = resp.follow()
assert 'The form has been recorded' in resp.text
assert resp.forms[0]['f1'].value == 'foo@localhost'
assert resp.forms[0]['fxxx_1'].value == 'foo@localhost'
def test_formdata_workflow_form_prefill_conditional_field(pub):
@ -1170,7 +1170,7 @@ def test_formdata_workflow_form_prefill_conditional_field(pub):
assert resp.status_int == 302
resp = resp.follow()
assert 'The form has been recorded' in resp.text
assert resp.forms[0]['f2'].value == 'foo@localhost'
assert resp.forms[0]['fxxx_2'].value == 'foo@localhost'
def test_formdata_workflow_form_prefill_checkbox(pub):
@ -1207,9 +1207,9 @@ def test_formdata_workflow_form_prefill_checkbox(pub):
assert 'Check values then click submit.' in resp
resp = resp.form.submit('submit').follow()
assert 'The form has been recorded' in resp
assert resp.form['f1'].checked is True
assert resp.form['f2'].checked is True
resp.form['f1'].checked = False
assert resp.form['fxxx_1'].checked is True
assert resp.form['fxxx_2'].checked is True
resp.form['fxxx_1'].checked = False
resp = resp.form.submit('submit')
formdata = formdef.data_class().select()[0]
@ -1285,13 +1285,83 @@ def test_formdata_workflow_form_prefill_autocomplete(pub):
assert 'The form has been recorded' in resp
# check display value is in form action widget
assert resp.form['f4'].attrs['data-value'] == '1'
assert resp.form['f4'].attrs['data-initial-display-value'] == 'hello'
assert resp.form['fxxx_4'].attrs['data-value'] == '1'
assert resp.form['fxxx_4'].attrs['data-initial-display-value'] == 'hello'
# check it is also displayed in a fresh session
resp = login(get_app(pub), username='foo', password='foo').get(resp.request.url)
assert resp.form['f4'].attrs['data-value'] == '1'
assert resp.form['f4'].attrs['data-initial-display-value'] == 'hello'
assert resp.form['fxxx_4'].attrs['data-value'] == '1'
assert resp.form['fxxx_4'].attrs['data-initial-display-value'] == 'hello'
def test_formdata_workflow_many_forms(pub):
create_user(pub)
wf = Workflow(name='status')
st1 = wf.add_status('Status1', 'st1')
# first form
display_form1 = FormWorkflowStatusItem()
display_form1.id = '_x'
display_form1.by = ['_submitter']
display_form1.varname = 'xxx'
display_form1.formdef = WorkflowFormFieldsFormDef(item=display_form1)
display_form1.formdef.fields = [fields.StringField(id='1', label='blah1')]
st1.items.append(display_form1)
display_form1.parent = st1
# second form with live condition
display_form2 = FormWorkflowStatusItem()
display_form2.id = '_y'
display_form2.by = ['_submitter']
display_form2.varname = 'yyy'
display_form2.formdef = WorkflowFormFieldsFormDef(item=display_form2)
display_form2.formdef.fields = [
fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
fields.StringField(
id='2', label='Test2', varname='str2',
type='string', required=True,
condition={'type': 'django', 'value': 'yyy_var_str == "xxx"'}),
]
st1.items.append(display_form2)
display_form2.parent = st1
wf.store()
FormDef.wipe()
formdef = FormDef()
formdef.name = 'test'
formdef.workflow_id = wf.id
formdef.fields = [fields.StringField(id='1', label='blah')]
formdef.store()
formdef.data_class().wipe()
app = login(get_app(pub), username='foo', password='foo')
resp = app.get('/test/')
resp.form['f1'] = 'foobar'
resp = resp.forms[0].submit('submit')
assert 'Check values then click submit.' in resp.text
resp = resp.forms[0].submit('submit')
assert resp.status_int == 302
resp = resp.follow()
assert 'The form has been recorded' in resp.text
assert 'fxxx_1' in resp.form.fields
assert 'fyyy_1' in resp.form.fields
assert 'fyyy_2' in resp.form.fields
assert 'submit' in resp.form.fields # only one submit button
assert resp.html.find('div', {'data-field-id': 'yyy_1'}).attrs['data-live-source'] == 'true'
assert resp.html.find('div', {'data-field-id': 'yyy_2'}).attrs.get('style') == 'display: none'
live_url = resp.html.find('form').attrs['data-live-url']
resp.form['fyyy_1'] = ''
live_resp = app.post(live_url, params=resp.form.submit_fields())
assert live_resp.json['result']['xxx_1']['visible']
assert live_resp.json['result']['yyy_1']['visible']
assert not live_resp.json['result']['yyy_2']['visible']
resp.form['fyyy_1'] = 'xxx'
live_resp = app.post(live_url, params=resp.form.submit_fields())
assert live_resp.json['result']['xxx_1']['visible']
assert live_resp.json['result']['yyy_1']['visible']
assert live_resp.json['result']['yyy_2']['visible']
def test_formdata_named_wscall(http_requests, pub):

View File

@ -2610,7 +2610,7 @@ def test_display_form(two_pubs):
assert form.widgets[1].title == 'Date'
two_pubs.get_request().environ['REQUEST_METHOD'] = 'POST'
two_pubs.get_request().form = {'f1': 'Foobar', 'f2': '2015-05-12', 'submit': 'submit'}
two_pubs.get_request().form = {'fxxx_1': 'Foobar', 'fxxx_2': '2015-05-12', 'submit': 'submit'}
display_form.submit_form(form, formdata, None, None)
assert formdata.get_substitution_variables()['xxx_var_date'] == '2015-05-12'
@ -2623,7 +2623,7 @@ def test_display_form(two_pubs):
form = Form(action='#', use_tokens=False)
display_form.fill_form(form, formdata, None)
two_pubs.get_request().environ['REQUEST_METHOD'] = 'POST'
two_pubs.get_request().form = {'f1': 'Foobar', 'f2': '12/05/2015', 'submit': 'submit'}
two_pubs.get_request().form = {'fxxx_1': 'Foobar', 'fxxx_2': '12/05/2015', 'submit': 'submit'}
display_form.submit_form(form, formdata, None, None)
assert formdata.get_substitution_variables()['xxx_var_date'] == '12/05/2015'

View File

@ -553,7 +553,6 @@ class WidgetField(Field):
def perform_more_widget_changes(self, form, kwargs, edit = True):
pass
def add_to_view_form(self, form, value = None):
kwargs = {'render_br': False}

View File

@ -177,12 +177,22 @@ class FormWorkflowStatusItem(WorkflowStatusItem):
return fields_directory
return None
def prefix_form_fields(self):
for field in self.formdef.fields:
try:
field.id = '%s_%s' % (self.varname, int(field.id))
except ValueError:
# already prefixed
pass
def fill_form(self, form, formdata, user, displayed_fields=None, **kwargs):
if not self.formdef:
return
self.prefix_form_fields()
self.formdef.var_prefix = self.varname
self.formdef.add_fields_to_form(form, displayed_fields=displayed_fields)
form.add_submit('submit', _('Submit'))
if 'submit' not in form._names:
form.add_submit('submit', _('Submit'))
# put varname in a form attribute so it can be used in templates to
# identify the form.
@ -206,6 +216,7 @@ class FormWorkflowStatusItem(WorkflowStatusItem):
if not self.formdef:
return
workflow_data = {}
self.prefix_form_fields()
for k, v in get_dict_with_varnames(
self.formdef.fields, self.formdef.get_data(form),
varnames_only=True).items():