From 8283f02eabe603419b6d7bd3709ea300b5b18070 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Mon, 12 Aug 2019 11:09:49 +0200
Subject: [PATCH 1/2] misc: use workflow form prefix when evaluating workflow
 forms (#35363)

---
 tests/test_backoffice_pages.py | 55 ++++++++++++++++++++++++++++++++++
 wcs/formdef.py                 |  1 +
 wcs/forms/common.py            |  2 +-
 3 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/tests/test_backoffice_pages.py b/tests/test_backoffice_pages.py
index dcc721751..916886033 100644
--- a/tests/test_backoffice_pages.py
+++ b/tests/test_backoffice_pages.py
@@ -3814,6 +3814,61 @@ def test_backoffice_workflow_form_with_conditions(pub):
 
     assert formdef.data_class().get(formdata.id).workflow_data == {'blah_var_str': 'xxx2', 'blah_var_str2': None}
 
+def test_backoffice_workflow_form_with_live_data_source(pub):
+    user = create_user(pub)
+    create_environment(pub)
+
+    wf = Workflow.get_default_workflow()
+    wf.id = '2'
+    wf.store()
+    wf = Workflow.get(wf.id)
+    status = wf.get_status('new')
+    status.items = []
+    display_form = FormWorkflowStatusItem()
+    display_form.id = '_display_form'
+    display_form.by = [user.roles[0]]
+    display_form.varname = 'blah'
+    display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
+    display_form.formdef.fields = [
+            fields.StringField(id='1', label='Test', varname='str', type='string', required=True),
+            fields.ItemField(id='2', label='Test2', varname='str2', type='item', required=True,
+                data_source={'type': 'json', 'value': 'https://www.example.invalid/{{ blah_var_str }}'}),
+    ]
+    status.items.append(display_form)
+    display_form.parent = status
+
+    wf.store()
+    formdef = FormDef.get_by_urlname('form-title')
+    formdef.workflow_id = wf.id
+    formdef.fields[0].varname = 'plop'
+    formdef.store()
+
+    for formdata in formdef.data_class().select():
+        if formdata.status == 'wf-new':
+            break
+
+    app = get_app(pub)
+
+    with mock.patch('qommon.misc.urlopen') as urlopen:
+        data1 = {'data': [{'id': 'A', 'text': 'hello'}, {'id': 'B', 'text': 'world'}]}
+        data2 = {'data': [{'id': 'C', 'text': 'hello'}, {'id': 'D', 'text': 'world'}]}
+        def side_effect(url, *args):
+            if 'toto' not in url:
+                return StringIO.StringIO(json.dumps(data1))
+            else:
+                return StringIO.StringIO(json.dumps(data2))
+        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')]
+
+        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'}]
+
 def test_backoffice_criticality_in_formdef_listing(pub):
     if not pub.is_using_postgresql():
         pytest.skip('this requires SQL')
diff --git a/wcs/formdef.py b/wcs/formdef.py
index e3fc84303..c67878eb1 100644
--- a/wcs/formdef.py
+++ b/wcs/formdef.py
@@ -546,6 +546,7 @@ class FormDef(StorableObject):
         current_page = 0
         on_page = (page is None)
         for field in self.fields:
+            field.formdef = self
             if field.type == 'page':
                 if on_page:
                     break
diff --git a/wcs/forms/common.py b/wcs/forms/common.py
index e1f0aafe0..079a0d9d1 100644
--- a/wcs/forms/common.py
+++ b/wcs/forms/common.py
@@ -637,7 +637,7 @@ class FormStatusPage(Directory, FormTemplateMixin):
                 if data_source.type != 'json':
                     continue
                 varnames = field.get_referenced_varnames(
-                        formdef=formdata.formdef,
+                        formdef=field.formdef,
                         value=data_source.data_source.get('value'))
                 if (modified_field_varname is None or modified_field_varname in varnames) and (
                         field.display_mode == 'autocomplete' and data_source.query_parameter):
-- 
2.23.0.rc1

