From 6e264aa7dd20558ef99da770dcb7b27acedab4d9 Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Tue, 10 Sep 2019 10:43:22 +0200
Subject: [PATCH] workflows: reevaluate form according to possible new content
 (#35903)

---
 tests/test_form_pages.py | 76 ++++++++++++++++++++++++++++++++++++++++
 wcs/forms/common.py      |  6 ++++
 2 files changed, 82 insertions(+)

diff --git a/tests/test_form_pages.py b/tests/test_form_pages.py
index 0b13ade6..a590bbd5 100644
--- a/tests/test_form_pages.py
+++ b/tests/test_form_pages.py
@@ -6303,6 +6303,82 @@ def test_field_live_select_content(pub, http_requests):
     assert formdata.data['3'] == 'a'
     assert formdata.data['3_display'] == 'b'
 
+def test_field_live_select_content_on_workflow_form(pub, http_requests):
+    create_user(pub)
+    wf = Workflow(name='wf-title')
+    st1 = wf.add_status('Status1', 'st1')
+
+    # form displayed into the workflow
+    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 = [
+        fields.StringField(type='string', id='1', label='Bar', size='40',
+            required=True, varname='bar'),
+        fields.StringField(type='string', id='2', label='Bar2', size='40',
+            required=True, varname='bar2'),
+        fields.ItemField(type='item', id='3', label='Foo',
+            required=False, varname='foo',
+            data_source={
+                'type': 'json',
+                'value': '{% if xxx_var_bar2 %}http://remote.example.net/json-list?plop={{xxx_var_bar2}}{% endif %}'
+            }),
+    ]
+    st1.items.append(display_form)
+    display_form.parent = st1
+    wf.store()
+
+    # initial empty form
+    formdef = create_formdef()
+    formdef.fields = []
+    formdef.confirmation = False
+    formdef.workflow_id = wf.id
+    formdef.store()
+    formdef.data_class().wipe()
+
+    app = get_app(pub)
+    resp = login(app, username='foo', password='foo').get('/test/')
+    assert 'Forms - test' in resp.text
+
+    resp = resp.form.submit('submit').follow()
+    assert 'The form has been recorded' in resp.text
+
+    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'
+    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
+
+    resp.form['f3'].options = []
+    for item in live_resp.json['result']['3']['items']:
+        # simulate javascript filling the <select>
+        resp.form['f3'].options.append((item['id'], False, item['text']))
+    resp.form['f3'] = 'a'
+
+    resp = resp.form.submit('submit')
+    if resp.status_code != 303:
+        assert 'invalid value selected' not in resp.content
+    resp = resp.follow()
+    formdata = formdef.data_class().select()[0]
+    assert formdata.workflow_data['xxx_var_bar'] == 'hello'
+    assert formdata.workflow_data['xxx_var_bar2'] == 'plop'
+    assert formdata.workflow_data['xxx_var_foo_raw'] == 'a'
+    assert formdata.workflow_data['xxx_var_foo'] == 'b'
+
 def test_field_live_comment_content(pub, http_requests):
     FormDef.wipe()
     formdef = FormDef()
diff --git a/wcs/forms/common.py b/wcs/forms/common.py
index c2a94a5d..5bbaacfd 100644
--- a/wcs/forms/common.py
+++ b/wcs/forms/common.py
@@ -263,6 +263,12 @@ class FormStatusPage(Directory, FormTemplateMixin):
     def get_workflow_form(self, user):
         submitted_fields = []
         form = self.filled.get_workflow_form(user, displayed_fields=submitted_fields)
+        self.filled.evaluate_live_workflow_form(user, form)
+        get_publisher().substitutions.unfeed(lambda x: x is self.filled)
+        get_publisher().substitutions.feed(self.filled)
+        # reevaluate workflow form according to possible new content
+        substitutions_fields = []
+        form = self.filled.get_workflow_form(user, displayed_fields=submitted_fields)
         if form:
             form.attrs['data-live-url'] = self.filled.get_url() + 'live'
         if form and form.is_submitted():
-- 
2.23.0

