more lxml form fixes and test cases. #111

* Do not treat "coord" attribute specially, just pass "NN,NN" as clickdata value
* Raise explicit ValueError if not clickable is found
* Fix bug looking for clickeables trough xpath when there is more than one form
* Test from_response with multiple clickdata
This commit is contained in:
Daniel Graña 2012-04-13 12:12:33 -03:00
parent 32b9f788be
commit ee1f7847a4
2 changed files with 71 additions and 10 deletions

View File

@ -118,17 +118,14 @@ def _get_clickable(clickdata, clickables, form):
# We didn't find it, so now we build an XPath expression out of the other
# arguments, because they can be used as such
xpath_pred = []
for k, v in clickdata.items():
if k == 'coord':
v = ','.join(str(c) for c in v)
xpath_pred.append('[@%s="%s"]' % (k, v))
xpath_expr = '//*%s' % ''.join(xpath_pred)
el = form.xpath(xpath_expr)
if len(el) > 1:
xpath = u'.//*' + \
u''.join(u'[@%s="%s"]' % tuple(c) for c in clickdata.iteritems())
el = form.xpath(xpath)
if len(el) == 1:
return (el[0].name, el[0].value)
elif len(el) > 1:
raise MultipleElementsFound("Multiple elements found (%r) "
"matching the criteria in clickdata: %r"
% (el, clickdata))
else:
return (el[0].name, el[0].value)
raise ValueError('No clickeable element matching clickdata')

View File

@ -306,6 +306,59 @@ class FormRequestTest(RequestTest):
self.assertEqual(urlargs['one'], ['1'])
self.assertEqual(urlargs['two'], ['2'])
def test_from_response_multiple_clickdata(self):
respbody = """
<form action="get.php" method="GET">
<input type="submit" name="clickeable" value="clicked1">
<input type="submit" name="clickeable" value="clicked2">
<input type="hidden" name="one" value="clicked1">
<input type="hidden" name="two" value="clicked2">
</form>
"""
response = HtmlResponse("http://www.example.com/this/list.html", body=respbody)
r1 = self.request_class.from_response(response, \
clickdata={'name': 'clickeable', 'value': 'clicked2'})
urlargs = cgi.parse_qs(urlparse(r1.url).query)
self.assertEqual(urlargs['clickeable'], ['clicked2'])
self.assertEqual(urlargs['one'], ['clicked1'])
self.assertEqual(urlargs['two'], ['clicked2'])
def test_from_response_unicode_clickdata(self):
body = u"""
<form action="get.php" method="GET">
<input type="submit" name="price in \u00a3" value="\u00a3 1000">
<input type="submit" name="price in \u20ac" value="\u20ac 2000">
<input type="hidden" name="poundsign" value="\u00a3">
<input type="hidden" name="eurosign" value="\u20ac">
</form>
"""
response = HtmlResponse("http://www.example.com", body=body, \
encoding='utf-8')
r1 = self.request_class.from_response(response, \
clickdata={'name': u'price in \u00a3'})
urlargs = cgi.parse_qs(urlparse(r1.url).query)
self.assertTrue(urlargs[u'price in \u00a3'.encode('utf-8')])
def test_from_response_multiple_forms_clickdata(self):
body = u"""
<form name="form1">
<input type="submit" name="clickeable" value="clicked">
<input type="hidden" name="field1" value="value1">
</form>
<form name="form2">
<input type="submit" name="clickeable" value="clicked">
<input type="hidden" name="field2" value="value2">
</form>
"""
res = HtmlResponse("http://example.com", body=body, encoding='utf-8')
req = self.request_class.from_response(res, \
formname='form2', \
clickdata={'name': 'clickeable'})
urlargs = cgi.parse_qs(urlparse(req.url).query)
self.assertEqual(urlargs['clickeable'], ['clicked'])
self.assertEqual(urlargs['field2'], ['value2'])
self.assertFalse('field1' in urlargs, urlargs)
def test_from_response_dont_click(self):
respbody = """
<form action="get.php" method="GET">
@ -336,6 +389,17 @@ class FormRequestTest(RequestTest):
response,
clickdata={'type': 'submit'})
def test_from_response_non_matching_clickdata(self):
body = """
<form>
<input type="submit" name="clickeable" value="clicked">
</form>
"""
res = HtmlResponse("http://example.com", body=body)
self.assertRaises(ValueError,
self.request_class.from_response, res,
clickdata={'nonexistent': 'notme'})
def test_from_response_errors_noform(self):
respbody = """<html></html>"""
response = HtmlResponse("http://www.example.com/lala.html", body=respbody)