From 625bca4163a5849a3b37275184d3eb336fb9d6cd Mon Sep 17 00:00:00 2001 From: Johannes Jung <81969656+JohaJung@users.noreply.github.com> Date: Thu, 27 Mar 2025 19:55:51 +0100 Subject: [PATCH 1/4] support HTML5 form attribute By searching for input elements also outside the form tag itself, which belong to this form according to their `form` attribute. closes #8 --- webtest/forms.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/webtest/forms.py b/webtest/forms.py index 057247b..75bbbba 100644 --- a/webtest/forms.py +++ b/webtest/forms.py @@ -432,7 +432,14 @@ def _parse_fields(self): fields = OrderedDict() field_order = [] tags = ('input', 'select', 'textarea', 'button') - for pos, node in enumerate(self.html.find_all(tags)): + elements = self.html.find_all(tags) + if self.response: + elements.extend( + elt for elt in self.response.html.find_all( + tags, attrs={'form': self.id}) + if elt not in elements + ) + for pos, node in enumerate(elements): attrs = dict(node.attrs) tag = node.name name = None From 13aa794e01e627c0773c3f2593e18f047ee48143 Mon Sep 17 00:00:00 2001 From: Johannes Jung <81969656+JohaJung@users.noreply.github.com> Date: Tue, 1 Apr 2025 21:28:47 +0200 Subject: [PATCH 2/4] forms: keep order of input elements --- webtest/forms.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/webtest/forms.py b/webtest/forms.py index 75bbbba..34a7047 100644 --- a/webtest/forms.py +++ b/webtest/forms.py @@ -432,13 +432,13 @@ def _parse_fields(self): fields = OrderedDict() field_order = [] tags = ('input', 'select', 'textarea', 'button') - elements = self.html.find_all(tags) + inner_elts = self.html.find_all(tags) if self.response: - elements.extend( - elt for elt in self.response.html.find_all( - tags, attrs={'form': self.id}) - if elt not in elements - ) + def _form_elt_filter(tag): + return tag in inner_elts or tag.attrs.get('form') == self.id + elements = self.response.html.find_all(_form_elt_filter) + else: + elements = inner_elts for pos, node in enumerate(elements): attrs = dict(node.attrs) tag = node.name From dd11e56103ce883087af6a2e6cce8123a692b898 Mon Sep 17 00:00:00 2001 From: Johannes Jung <81969656+JohaJung@users.noreply.github.com> Date: Tue, 1 Apr 2025 21:32:10 +0200 Subject: [PATCH 3/4] tests: basic test for forms with input outside form tag --- tests/html/form_inputs.html | 6 ++++++ tests/test_forms.py | 3 +++ 2 files changed, 9 insertions(+) diff --git a/tests/html/form_inputs.html b/tests/html/form_inputs.html index e7ab368..0b7c53f 100644 --- a/tests/html/form_inputs.html +++ b/tests/html/form_inputs.html @@ -55,5 +55,11 @@ + +
+ +
+ + diff --git a/tests/test_forms.py b/tests/test_forms.py index 0348d0e..b6fe22a 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -134,6 +134,9 @@ def test_button_submit_by_value_and_index(self): form.submit, "action", value="activate", index=0) + def test_outer_inputs(self): + form = self.callFUT(formid='outer_inputs_form') + self.assertEqual(('foo', 'bar', 'button'), tuple(form.fields)) class TestResponseFormAttribute(unittest.TestCase): From 12c147ca3d74a6fb3933d0aed5a3b343b26fd780 Mon Sep 17 00:00:00 2001 From: Johannes Jung <81969656+JohaJung@users.noreply.github.com> Date: Fri, 25 Apr 2025 18:57:44 +0200 Subject: [PATCH 4/4] forms: simplify code and improve test make the response more likely to be a real-world response --- tests/test_forms.py | 23 +++++++++++++++-------- webtest/forms.py | 10 ++++------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/tests/test_forms.py b/tests/test_forms.py index b6fe22a..9bf0ae0 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -288,26 +288,33 @@ def test_textarea_emptyfirstline(self): class TestFormLint(unittest.TestCase): def test_form_lint(self): - form = webtest.Form(None, '''
+ def _build_response(html): + return webtest.TestResponse('{}'.format(html)) + + html = ''' -
''') + ''' + form = webtest.Form(_build_response(html), html) self.assertRaises(AttributeError, form.lint) - form = webtest.Form(None, '''
+ html = ''' -
''') + ''' + form = webtest.Form(_build_response(html), html) self.assertRaises(AttributeError, form.lint) - form = webtest.Form(None, '''
+ html = ''' -
''') + ''' + form = webtest.Form(_build_response(html), html) form.lint() - form = webtest.Form(None, '''
+ html = ''' -
''') + ''' + form = webtest.Form(_build_response(html), html) form.lint() diff --git a/webtest/forms.py b/webtest/forms.py index 34a7047..73d37f5 100644 --- a/webtest/forms.py +++ b/webtest/forms.py @@ -433,12 +433,10 @@ def _parse_fields(self): field_order = [] tags = ('input', 'select', 'textarea', 'button') inner_elts = self.html.find_all(tags) - if self.response: - def _form_elt_filter(tag): - return tag in inner_elts or tag.attrs.get('form') == self.id - elements = self.response.html.find_all(_form_elt_filter) - else: - elements = inner_elts + def _form_elt_filter(tag): + return tag in inner_elts or ( + tag.attrs.get('form') == self.id and tag.name in tags) + elements = self.response.html.find_all(_form_elt_filter) for pos, node in enumerate(elements): attrs = dict(node.attrs) tag = node.name