mirror of https://github.com/scrapy/scrapy.git
Dedupe the submit button against list formdata in FormRequest.from_response
When formdata is a list of (key, value) tuples rather than a dict, from_response() failed to suppress the form's own submit button: the clickable de-dup tested `clickable[0] not in formdata`, which for a list compares the name string against tuples and is always true, so the form's default submit value was emitted in addition to the caller's override. Dedup against `formdata_keys` instead -- it already normalizes both dict and list-of-tuples and is what the regular-input de-dup on the line above uses, so both container types now behave the same.
This commit is contained in:
parent
c9446931a8
commit
6f44e92dc9
|
|
@ -245,7 +245,7 @@ def _get_inputs(
|
|||
|
||||
if not dont_click:
|
||||
clickable = _get_clickable(clickdata, form)
|
||||
if clickable and clickable[0] not in formdata and clickable[0] is not None:
|
||||
if clickable and clickable[0] not in formdata_keys and clickable[0] is not None:
|
||||
values.append(clickable)
|
||||
|
||||
formdata_items = formdata.items() if isinstance(formdata, dict) else formdata
|
||||
|
|
|
|||
|
|
@ -499,6 +499,39 @@ class TestFormRequest(TestRequest):
|
|||
fs = _qs(req)
|
||||
assert fs[b"clickme"] == [b"two"]
|
||||
|
||||
def test_from_response_override_clickable_formdata_list(self):
|
||||
# formdata as a list of (key, value) tuples (documented as equivalent to
|
||||
# a dict) must dedupe the submit button the same way; otherwise the form's
|
||||
# default submit value leaks in alongside the override.
|
||||
response = _buildresponse(
|
||||
"""<form><input type="submit" name="clickme" value="one"> </form>"""
|
||||
)
|
||||
req = self.request_class.from_response(
|
||||
response, formdata=[("clickme", "two")], clickdata={"name": "clickme"}
|
||||
)
|
||||
assert _qs(req)[b"clickme"] == [b"two"]
|
||||
|
||||
def test_from_response_override_auto_clicked_submit_formdata_list(self):
|
||||
# Same class of bug without clickdata: the auto-selected submit must be
|
||||
# overridden by a list formdata entry, not duplicated.
|
||||
response = _buildresponse(
|
||||
"""<form method="post">"""
|
||||
"""<input type="submit" name="clickme" value="one"></form>"""
|
||||
)
|
||||
req = self.request_class.from_response(response, formdata=[("clickme", "two")])
|
||||
assert _qs(req)[b"clickme"] == [b"two"]
|
||||
|
||||
def test_from_response_submit_kept_with_unrelated_formdata_list(self):
|
||||
# A list formdata that does not name the submit must not suppress it.
|
||||
response = _buildresponse(
|
||||
"""<form method="post">"""
|
||||
"""<input type="submit" name="clickme" value="one"></form>"""
|
||||
)
|
||||
req = self.request_class.from_response(response, formdata=[("extra", "x")])
|
||||
fs = _qs(req)
|
||||
assert fs[b"clickme"] == [b"one"]
|
||||
assert fs[b"extra"] == [b"x"]
|
||||
|
||||
def test_from_response_dont_click(self):
|
||||
response = _buildresponse(
|
||||
"""<form action="get.php" method="GET">
|
||||
|
|
|
|||
Loading…
Reference in New Issue