Projet

Général

Profil

Bug #24876

Un doute sur l'implémentation de FormDef.get_page(page_no)

Ajouté par Benjamin Dauvergne il y a presque 6 ans. Mis à jour il y a presque 6 ans.

Statut:
Rejeté
Priorité:
Normal
Assigné à:
Version cible:
-
Début:
29 juin 2018
Echéance:
% réalisé:

0%

Temps estimé:
Patch proposed:
Oui
Planning:

Description

Je regarde cette fonction:

    def get_page(self, page_no):
        return [x for x in self.fields if x.type == 'page'][page_no]

et je me rends compte que contrairement par exemple à add_fields_to_form() ça ne prend pas en compte le cas du champ initial qui est une page ou non:

    def add_fields_to_form(self, form, page_no = 0, displayed_fields = None, form_data = None):
        current_page = 0
        for field in self.fields:
            if field.type == 'page':
                if field is self.fields[0]:
                    continue
                current_page += 1
                if current_page > page_no:
                    break
                continue
            if current_page != page_no:
                continue
            if type(displayed_fields) is list:
                displayed_fields.append(field)
            value = None
            if form_data:
                value = form_data.get(field.id)
            field.add_to_form(form, value)

ici on ignore bien le premier champ PageField si il est là (la page zéro est sinon implicite).

La fonction n'est utilisé que deux fois dans tout le code (pour trouver la page suivante/précédente visible), mais j'ai l'impression que si on a pas fields0.type == 'page' on a une off-by-one error et donc il me semble qu'en l'absence d'une première page explicite, les validations de condition de page sont toutes fausses (décalés d'une pages).

Un test simple serait un formulaire avec un seul champ sur la première page implicite puis une page avec une condition qui ne passe jamais, on doit pouvoir passer à la seconde page alors qu'on ne devrait pas.

Une implémentation de get_page() qui je pense marche serait:

diff --git a/wcs/formdef.py b/wcs/formdef.py
index 0e894a9c..b32dbc15 100644
--- a/wcs/formdef.py
+++ b/wcs/formdef.py
@@ -555,7 +555,14 @@ class FormDef(StorableObject):
             field.add_to_form(form, value)

     def get_page(self, page_no):
-        return [x for x in self.fields if x.type == 'page'][page_no]
+        # if there is no first field being a PageField, PageField for page_no
+        # zero does not exist
+        if page_no == 0:
+            if self.fields and self.fields[0].type == 'page':
+                return self.fields[0]
+            raise IndexError
+        else:
+            return [x for x in self.fields[1:] if x.type == 'page'][page_no - 1]

     def create_view_form(self, dict={}, use_tokens=True, visible=True):
         form = Form(enctype='multipart/form-data', use_tokens=use_tokens)

Fichiers


Demandes liées

Duplique w.c.s. - Bug #24706: mauvais calcul de l'étape à mettre en surbrillanceFermé22 juin 2018

Actions

Historique

#1

Mis à jour par Benjamin Dauvergne il y a presque 6 ans

Et c'est confirmé avec ce test:

diff --git a/tests/test_form_pages.py b/tests/test_form_pages.py
index eeb93707..9279d34d 100644
--- a/tests/test_form_pages.py
+++ b/tests/test_form_pages.py
@@ -4825,3 +4825,21 @@ def test_condition_on_action(pub, emails):
     resp = resp.form.submit('submit')
     resp = resp.form.submit('submit')
     assert emails.get('New form2 (test condition on action)')
+
+
+def test_form_multi_page_condition_no_first_page(pub):
+    formdef = create_formdef()
+    formdef.fields = [
+            fields.StringField(id='1', label='string'),
+            fields.PageField(id='2', label='2nd page', type='page',
+                condition={'type': 'python', 'value': 'False'}),
+            fields.StringField(id='3', label='string 2')]
+    formdef.store()
+    resp = get_app(pub).get('/test/')
+    formdef.data_class().wipe()
+    resp.forms[0]['f1'] = 'foo'
+    resp = resp.forms[0].submit('submit') # should go straight to validation
+    assert 'Check values then click submit.' in resp.body
+    assert resp.forms[0]['previous']
+    resp = resp.forms[0].submit('previous')
+    assert resp.forms[0]['f1']
#2

Mis à jour par Benjamin Dauvergne il y a presque 6 ans

  • Description mis à jour (diff)
#3

Mis à jour par Frédéric Péters il y a presque 6 ans

Dans un formulaire multi-pages le premier champ doit être une page, un avertissement est affiché si ce n'est pas le cas; je suis pour conserver cette situation.

#4

Mis à jour par Benjamin Dauvergne il y a presque 6 ans

Ok, mais je propose alors commentaire dans get_page() pour clarifier la situation, c'est déjà assez dur comme ça de lire wcs.forms.root.RootDirectory (je ne cherchais pas particulièrement un bug, je réfléchissais à l'implémentation de mon idée d'autosubmit_if_filled et préfill depuis un paramètre d'URL).

#5

Mis à jour par Benjamin Dauvergne il y a presque 6 ans

  • Assigné à mis à Benjamin Dauvergne
#6

Mis à jour par Benjamin Dauvergne il y a presque 6 ans

#7

Mis à jour par Benjamin Dauvergne il y a presque 6 ans

  • Duplique Bug #24706: mauvais calcul de l'étape à mettre en surbrillance ajouté
#8

Mis à jour par Benjamin Dauvergne il y a presque 6 ans

  • Statut changé de Solution proposée à Rejeté

Rejeté en faveur du travail dans #24706.

Formats disponibles : Atom PDF