Merge remote-tracking branch 'origin/pr/3333'

This commit is contained in:
Florian Bruhin 2017-12-02 14:47:24 +01:00
commit 003ec31848
8 changed files with 68 additions and 2 deletions

View File

@ -22,6 +22,7 @@
import enum
import itertools
import sip
import attr
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, QObject, QSizeF, Qt
from PyQt5.QtGui import QIcon
@ -864,3 +865,6 @@ class AbstractTab(QWidget):
except (AttributeError, RuntimeError) as exc:
url = '<{}>'.format(exc.__class__.__name__)
return utils.get_repr(self, tab_id=self.tab_id, url=url)
def is_deleted(self):
return sip.isdeleted(self._widget)

View File

@ -1644,6 +1644,8 @@ class CommandDispatcher:
"""
try:
elem.set_value(text)
except webelem.OrphanedError as e:
message.warning('Edited element vanished')
except webelem.Error as e:
raise cmdexc.CommandError(str(e))

View File

@ -60,6 +60,13 @@ class Error(Exception):
pass
class OrphanedError(Exception):
"""Raised when a webelement's parent has vanished."""
pass
class AbstractWebElement(collections.abc.MutableMapping):
"""A wrapper around QtWebKit/QtWebEngine web element.

View File

@ -100,6 +100,8 @@ class WebEngineElement(webelem.AbstractWebElement):
def _js_call(self, name, *args, callback=None):
"""Wrapper to run stuff from webelem.js."""
if self._tab.is_deleted():
raise webelem.OrphanedError("Tab containing element vanished")
js_code = javascript.assemble('webelem', name, self._id, *args)
self._tab.run_js_async(js_code, callback=callback)

View File

@ -118,6 +118,8 @@ class WebKitElement(webelem.AbstractWebElement):
def set_value(self, value):
self._check_vanished()
if self._tab.is_deleted():
raise webelem.OrphanedError("Tab containing element vanished")
if self.is_content_editable():
log.webelem.debug("Filling {!r} via set_text.".format(self))
self._elem.setPlainText(value)

View File

@ -115,6 +115,19 @@ Feature: Opening external editors
And I run :click-element id qute-button
Then the javascript message "text: foobar" should be logged
# Could not get signals working on Windows
@posix
Scenario: Spawning an editor and closing the tab
When I set up a fake editor that waits
And I open data/editor.html
And I run :click-element id qute-textarea
And I wait for "Entering mode KeyMode.insert (reason: clicking input)" in the log
And I run :open-editor
And I set tabs.last_close to blank
And I run :tab-close
And I kill the waiting editor
Then the warning "Edited element vanished" should be shown
@qtwebengine_todo: Caret mode is not implemented yet
Scenario: Spawning an editor in caret mode
When I set up a fake editor returning "foobar"

View File

@ -20,6 +20,8 @@
import sys
import json
import textwrap
import os
import signal
import pytest_bdd as bdd
bdd.scenarios('editor.feature')
@ -64,3 +66,35 @@ def set_up_editor(quteproc, server, tmpdir, text):
def set_up_editor_empty(quteproc, server, tmpdir):
"""Set up editor.command to a small python script inserting empty text."""
set_up_editor(quteproc, server, tmpdir, "")
@bdd.when(bdd.parsers.parse('I set up a fake editor that waits'))
def set_up_editor_wait(quteproc, server, tmpdir):
"""Set up editor.command to a small python script inserting a text."""
pidfile = tmpdir / 'editor_pid'
script = tmpdir / 'script.py'
script.write(textwrap.dedent("""
import os
import sys
import time
import signal
with open(r'{pidfile}', 'w') as f:
f.write(str(os.getpid()))
signal.signal(signal.SIGUSR1, lambda s, f: sys.exit(0))
time.sleep(100)
""".format(pidfile=pidfile)))
editor = json.dumps([sys.executable, str(script), '{}'])
quteproc.set_setting('editor.command', editor)
@bdd.when(bdd.parsers.parse('I kill the waiting editor'))
def kill_editor_wait(quteproc, server, tmpdir):
"""Kill the waiting editor."""
pidfile = tmpdir / 'editor_pid'
pid = int(pidfile.read())
# windows has no SIGUSR1, but we don't run this on windows anyways
# for posix, there IS a member so we need to ignore useless-suppression
# pylint: disable=no-member,useless-suppression
os.kill(pid, signal.SIGUSR1)

View File

@ -29,7 +29,7 @@ import pytest
from PyQt5.QtCore import QRect, QPoint, QUrl
QWebElement = pytest.importorskip('PyQt5.QtWebKit').QWebElement
from qutebrowser.browser import webelem
from qutebrowser.browser import webelem, browsertab
from qutebrowser.browser.webkit import webkitelem
from qutebrowser.misc import objects
from qutebrowser.utils import usertypes
@ -127,7 +127,9 @@ def get_webelem(geometry=None, frame=None, *, null=False, style=None,
return style_dict[name]
elem.styleProperty.side_effect = _style_property
wrapped = webkitelem.WebKitElement(elem, tab=None)
tab = mock.Mock(autospec=browsertab.AbstractTab)
tab.is_deleted.return_value = False
wrapped = webkitelem.WebKitElement(elem, tab=tab)
return wrapped