From b3ff459068b520122b74259e0e462ad8f72031ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Sun, 20 Dec 2020 11:14:52 +0100
Subject: [PATCH] forms: don't display "required field" on blocks when going
 back (#48798)

---
 tests/form_pages/test_block.py | 98 ++++++++++++++++++++++++++++++++++
 wcs/blocks.py                  |  1 +
 2 files changed, 99 insertions(+)

diff --git a/tests/form_pages/test_block.py b/tests/form_pages/test_block.py
index d770f30d0..557c43031 100644
--- a/tests/form_pages/test_block.py
+++ b/tests/form_pages/test_block.py
@@ -162,6 +162,104 @@ def test_block_required(pub, blocks_feature):
     assert 'Check values then click submit.' in resp.text
 
 
+def test_block_required_previous_page(pub, blocks_feature):
+    FormDef.wipe()
+    BlockDef.wipe()
+
+    block = BlockDef()
+    block.name = 'foobar'
+    block.fields = [
+        fields.StringField(id='123', required=True, label='Test', type='string'),
+        fields.StringField(id='234', required=True, label='Test2', type='string'),
+    ]
+    block.store()
+
+    for multipage in (False, True):
+        # single block, go to validation page, come back
+        formdef = FormDef()
+        formdef.name = 'form title'
+        if multipage:
+            formdef.fields = [
+                fields.PageField(id='0', label='1st page', type='page'),
+                fields.BlockField(id='1', label='test', type='block:foobar', required=True),
+                fields.PageField(id='2', label='2nd page', type='page'),
+            ]
+        else:
+            formdef.fields = [
+                fields.BlockField(id='1', label='test', type='block:foobar', required=True),
+            ]
+        formdef.store()
+        formdef.data_class().wipe()
+
+        app = get_app(pub)
+        resp = app.get(formdef.get_url())
+        resp = resp.form.submit('submit')  # -> error page
+        assert 'There were errors processing the form' in resp
+        assert resp.text.count('required field') == 1
+        resp.form['f1$element0$f123'] = 'foo'
+        resp.form['f1$element0$f234'] = 'bar'
+        if multipage:
+            resp = resp.form.submit('submit')  # -> 2nd page
+        resp = resp.form.submit('submit')  # -> validation page
+        assert 'Check values then click submit.' in resp.text
+
+        if multipage:
+            resp = resp.form.submit('previous')  # -> 2nd page
+        resp = resp.form.submit('previous')  # -> 1st page
+        assert resp.text.count('required field') == 0
+        assert resp.form['f1$element0$f123'].value == 'foo'
+        assert resp.form['f1$element0$f234'].value == 'bar'
+
+        if multipage:
+            resp = resp.form.submit('submit')  # -> 2nd page
+        resp = resp.form.submit('submit')  # -> validation page
+        assert 'Check values then click submit.' in resp.text
+        resp = resp.form.submit('submit')  # -> submitted
+
+        assert formdef.data_class().count() == 1
+        formdata = formdef.data_class().select()[0]
+        assert formdata.data['1']['data'] == [{'123': 'foo', '234': 'bar'}]
+
+        # add two blocks, go to validation page, come back
+        if multipage:
+            formdef.fields[1].max_items = 3
+        else:
+            formdef.fields[0].max_items = 3
+        formdef.store()
+        formdef.data_class().wipe()
+
+        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('f1$add_element')  # -> 1st page
+        resp.form['f1$element1$f123'] = 'foo2'
+        resp.form['f1$element1$f234'] = 'bar2'
+        if multipage:
+            resp = resp.form.submit('submit')  # -> 2nd page
+        resp = resp.form.submit('submit')  # -> validation page
+        assert 'Check values then click submit.' in resp.text
+
+        if multipage:
+            resp = resp.form.submit('previous')  # -> 2nd page
+        resp = resp.form.submit('previous')  # -> 1st page
+        assert resp.text.count('required field') == 0
+        assert resp.form['f1$element0$f123'].value == 'foo'
+        assert resp.form['f1$element0$f234'].value == 'bar'
+        assert resp.form['f1$element1$f123'].value == 'foo2'
+        assert resp.form['f1$element1$f234'].value == 'bar2'
+
+        if multipage:
+            resp = resp.form.submit('submit')  # -> 2nd page
+        resp = resp.form.submit('submit')  # -> validation page
+        assert 'Check values then click submit.' in resp.text
+        resp = resp.form.submit('submit')  # -> submitted
+
+        assert formdef.data_class().count() == 1
+        formdata = formdef.data_class().select()[0]
+        assert formdata.data['1']['data'] == [{'123': 'foo', '234': 'bar'}, {'123': 'foo2', '234': 'bar2'}]
+
+
 def test_block_date(pub, blocks_feature):
     FormDef.wipe()
     BlockDef.wipe()
diff --git a/wcs/blocks.py b/wcs/blocks.py
index e8623076f..5ffdb340e 100644
--- a/wcs/blocks.py
+++ b/wcs/blocks.py
@@ -209,6 +209,7 @@ class BlockSubWidget(CompositeWidget):
             self.set_value(value)
 
     def set_value(self, value):
+        self.value = value
         for widget in self.get_widgets():
             if hasattr(widget, 'set_value') and not getattr(widget, 'secondary', False):
                 widget.set_value(value.get(widget.field.id))
-- 
2.29.2

