Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ News
3.0.6 (unreleased)
------------------

- Nothing changed yet.
- Fix a bug that inputs outside of a ``<form>`` tag were considered
belonging to that form because they had a HTML representation identical
to some input inside that ``<form>``.


3.0.5 (2025-06-04)
Expand Down
4 changes: 4 additions & 0 deletions tests/html/form_inputs.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,9 @@
</form>
<input name="button" type="submit" value="text" form="outer_inputs_form">

<!-- this input is equal (in the sense beautifulSoup checks equality)
to that in outer_inputs_form -->
<input name="bar" type="text" value="bar">

</body>
</html>
2 changes: 2 additions & 0 deletions tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ def test_button_submit_by_value_and_index(self):
def test_outer_inputs(self):
form = self.callFUT(formid='outer_inputs_form')
self.assertEqual(('foo', 'bar', 'button'), tuple(form.fields))
# check that identical input is not considered belonging to this form
self.assertTrue(all(len(itm) == 1 for itm in form.fields.values()))

class TestResponseFormAttribute(unittest.TestCase):

Expand Down
13 changes: 9 additions & 4 deletions webtest/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,15 @@ def _parse_fields(self):
field_order = []
tags = ('input', 'select', 'textarea', 'button')
inner_elts = self.html.find_all(tags)
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)
if self.id:
def _form_elt_filter(tag):
return tag.name in tags and any(
prt.name == 'form' and prt.attrs.get('id') == self.id
for prt in tag.parents
) 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
Expand Down