quteprocess: properly escape xpath expression
Since XPath doesn't have a way to escape quotes (or any other character), we have to use a workaround by using concat() and switching between quoting styles.
This commit is contained in:
parent
b6c5ff25fd
commit
f82d0f0c94
@ -432,13 +432,13 @@ class QuteProc(testprocess.Process):
|
|||||||
# Use Javascript and XPath to find the right element, use console.log to
|
# Use Javascript and XPath to find the right element, use console.log to
|
||||||
# return an error (no element found, ambiguous element)
|
# return an error (no element found, ambiguous element)
|
||||||
script = (
|
script = (
|
||||||
'var _es = document.evaluate(\'//*[text()="{text}"]\', document, '
|
'var _es = document.evaluate(\'//*[text()={text}]\', document, '
|
||||||
'null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);'
|
'null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);'
|
||||||
'if (_es.snapshotLength == 0) {{ console.log("qute:no elems"); }} '
|
'if (_es.snapshotLength == 0) {{ console.log("qute:no elems"); }} '
|
||||||
'else if (_es.snapshotLength > 1) {{ console.log("qute:ambiguous '
|
'else if (_es.snapshotLength > 1) {{ console.log("qute:ambiguous '
|
||||||
'elems") }} '
|
'elems") }} '
|
||||||
'else {{ console.log("qute:okay"); _es.snapshotItem(0).click() }}'
|
'else {{ console.log("qute:okay"); _es.snapshotItem(0).click() }}'
|
||||||
).format(text=webelem.javascript_escape(text))
|
).format(text=webelem.javascript_escape(_xpath_escape(text)))
|
||||||
self.send_cmd(':jseval ' + script)
|
self.send_cmd(':jseval ' + script)
|
||||||
message = self.wait_for_js('qute:*').message
|
message = self.wait_for_js('qute:*').message
|
||||||
if message.endswith('qute:no elems'):
|
if message.endswith('qute:no elems'):
|
||||||
@ -450,6 +450,35 @@ class QuteProc(testprocess.Process):
|
|||||||
.format(message))
|
.format(message))
|
||||||
|
|
||||||
|
|
||||||
|
def _xpath_escape(text):
|
||||||
|
"""Escape a string to be used in an XPath expression.
|
||||||
|
|
||||||
|
The resulting string should still be escaped with javascript_escape, to
|
||||||
|
prevent javascript from interpreting the quotes.
|
||||||
|
|
||||||
|
This function is needed because XPath does not provide any character
|
||||||
|
escaping mechanisms, so to get the string
|
||||||
|
"I'm back", he said
|
||||||
|
you have to use concat like
|
||||||
|
concat('"I', "'m back", '", he said')
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text: Text to escape
|
||||||
|
|
||||||
|
Return:
|
||||||
|
The string "escaped" as a concat() call.
|
||||||
|
"""
|
||||||
|
# Shortcut if at most a single quoting style is used
|
||||||
|
if not "'" in text or not '"' in text:
|
||||||
|
return repr(text)
|
||||||
|
parts = re.split('([\'"])', text)
|
||||||
|
# Python's repr() of strings will automatically choose the right quote type.
|
||||||
|
# Since each part only contains one "type" of quote, no escaping should be
|
||||||
|
# necessary.
|
||||||
|
parts = [repr(part) for part in parts if part]
|
||||||
|
return 'concat({})'.format(', '.join(parts))
|
||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(scope='module')
|
@pytest.yield_fixture(scope='module')
|
||||||
def quteproc_process(qapp, httpbin, request):
|
def quteproc_process(qapp, httpbin, request):
|
||||||
"""Fixture for qutebrowser process which is started once per file."""
|
"""Fixture for qutebrowser process which is started once per file."""
|
||||||
|
Loading…
Reference in New Issue
Block a user