Browse files

Add a :click-element command

  • Loading branch information...
The-Compiler committed Aug 18, 2016
1 parent 28a6b39 commit 0cef4ac2db5e572fd6a3b8654c5a2a2bfe4933f3
@@ -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.
@@ -1528,6 +1528,47 @@ def insert_text(self, text):
@cmdutils.register(instance='command-dispatcher', scope='window',
@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.
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!")
# 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):
def find_id(self, elem_id, callback):
self.find_css('#' + elem_id, callback)
def find_id_cb(elems):
if not elems:
self.find_css('#' + elem_id, find_id_cb)
def find_focused(self, callback):
frame =
@@ -7,5 +7,6 @@
<span onclick='console.log("click_element special chars")'>"Don't", he shouted</span>
<form><input id='qute-input'></input></form>
@@ -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: {}'
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");; }}'
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: {}'
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:
def open_page(self, quteproc):
def test_click_element(self, quteproc):
quteproc.wait_for_js('click_element clicked')
def test_nonexistent(self, quteproc):
with pytest.raises(ValueError) as excinfo:
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.