Permalink
Browse files

Add a :click-element command

  • Loading branch information...
The-Compiler committed Aug 18, 2016
1 parent 28a6b39 commit 0cef4ac2db5e572fd6a3b8654c5a2a2bfe4933f3
View
@@ -38,6 +38,7 @@ Added
- New `prev-category` and `next-category` arguments to `:completion-item-focus`
to focus the previous/next category in the completion (bound to `<Ctrl-Tab>`
and `<Ctrl-Shift-Tab>` by default).
- New `:click-element` command to fake a click on a element.
Changed
~~~~~~~
@@ -1528,6 +1528,47 @@ def insert_text(self, text):
this.dispatchEvent(event);
""".format(javascript.string_escape(text)))
@cmdutils.register(instance='command-dispatcher', scope='window',
hide=True)
@cmdutils.argument('filter_', choices=['id'])
def click_element(self, filter_: str, value, *,
target: usertypes.ClickTarget):
"""Click the element matching the given filter.
The given filter needs to result in exactly one element, otherwise, an
error is shown.
Args:
filter: How to filter the elements.
id: Get an element based on its ID.
value: The value to filter for.
"""
tab = self._current_widget()
def single_cb(elem):
"""Click a single element."""
if elem is None:
message.error(self._win_id, "No element found!")
return
elem.click(target)
# def multiple_cb(elems):
# """Click multiple elements (with only one expected)."""
# if not elems:
# message.error(self._win_id, "No element found!")
# return
# elif len(elems) != 1:
# message.error(self._win_id, "{} elements found!".format(
# len(elems)))
# return
# elems[0].click(target)
handlers = {
'id': (tab.elements.find_id, single_cb),
}
handler, callback = handlers[filter_]
handler(value, callback)
def _search_cb(self, found, *, tab, old_scroll_pos, options, text, prev):
"""Callback called from search/search_next/search_prev.
@@ -513,7 +513,12 @@ def find_css(self, selector, callback, *, only_visible=False):
callback(elems)
def find_id(self, elem_id, callback):
self.find_css('#' + elem_id, callback)
def find_id_cb(elems):
if not elems:
callback(None)
else:
callback(elems[0])
self.find_css('#' + elem_id, find_id_cb)
def find_focused(self, callback):
frame = self._widget.page().currentFrame()
@@ -7,5 +7,6 @@
<span onclick='console.log("click_element special chars")'>"Don't", he shouted</span>
<span>Duplicate</span>
<span>Duplicate</span>
<form><input id='qute-input'></input></form>
</body>
</html>
@@ -559,3 +559,15 @@ Feature: Various utility commands.
And I put "{url}" into the clipboard
And I run :message-info {clipboard}bar{url}
Then the message "{url}barhttp://localhost:*/hello.txt" should be shown
## :click-element
Scenario: Clicking an element with unknown ID
When I open data/click_element.html
And I run :click-element id blah
Then the error "No element found!" should be shown
Scenario: Clicking an element by ID
When I open data/click_element.html
And I run :click-element id qute-input
Then "Clicked editable element!" should be logged
@@ -548,21 +548,6 @@ def click_element_by_text(self, text):
raise ValueError('Invalid response from qutebrowser: {}'
.format(message))
def click_element_by_id(self, elem_id):
"""Click the element with the given ID."""
script = (
'var _elem = document.getElementById("{elem_id}"); '
'if (_elem === null) {{ console.log("qute:no elem"); }} '
'else {{ console.log("qute:okay"); _elem.click(); }}'
).format(elem_id=javascript.string_escape(elem_id))
self.send_cmd(':jseval ' + script, escape=False)
message = self.wait_for_js('qute:*').message
if message.endswith('qute:no elem'):
raise ValueError('No element with ID {!r} found'.format(elem_id))
elif not message.endswith('qute:okay'):
raise ValueError('Invalid response from qutebrowser: {}'
.format(message))
def compare_session(self, expected):
"""Compare the current sessions against the given template.
@@ -265,22 +265,6 @@ def test_nonexistent(self, quteproc):
assert 'No element' in str(excinfo.value)
class TestClickElementById:
@pytest.fixture(autouse=True)
def open_page(self, quteproc):
quteproc.open_path('data/click_element.html')
def test_click_element(self, quteproc):
quteproc.click_element_by_id('test')
quteproc.wait_for_js('click_element clicked')
def test_nonexistent(self, quteproc):
with pytest.raises(ValueError) as excinfo:
quteproc.click_element_by_id('blah')
assert 'No element' in str(excinfo.value)
@pytest.mark.parametrize('string, expected', [
('Test', "'Test'"),
("Don't", '"Don\'t"'),

0 comments on commit 0cef4ac

Please sign in to comment.