From a4cd0291a687070e05736fbb8c312e59377cc2d3 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 2 Sep 2016 07:41:48 +0200 Subject: [PATCH 01/34] Implement QWebEngineView.createWindow --- qutebrowser/browser/webengine/webenginetab.py | 2 +- qutebrowser/browser/webengine/webview.py | 56 ++++++++++++++++--- .../end2end/data/javascript/window_open.html | 22 ++++++++ tests/end2end/features/hints.feature | 5 -- tests/end2end/features/javascript.feature | 1 - tests/end2end/features/misc.feature | 1 - 6 files changed, 72 insertions(+), 15 deletions(-) create mode 100644 tests/end2end/data/javascript/window_open.html diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index 41ddc6c80..bc9c5cc18 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -381,7 +381,7 @@ class WebEngineTab(browsertab.AbstractTab): def __init__(self, win_id, mode_manager, parent=None): super().__init__(win_id) - widget = webview.WebEngineView(tabdata=self.data) + widget = webview.WebEngineView(tabdata=self.data, win_id=win_id) self.history = WebEngineHistory(self) self.scroller = WebEngineScroller(self, parent=self) self.caret = WebEngineCaret(win_id=win_id, mode_manager=mode_manager, diff --git a/qutebrowser/browser/webengine/webview.py b/qutebrowser/browser/webengine/webview.py index 451a493a0..5c8d863e4 100644 --- a/qutebrowser/browser/webengine/webview.py +++ b/qutebrowser/browser/webengine/webview.py @@ -26,17 +26,64 @@ from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage # pylint: enable=no-name-in-module,import-error,useless-suppression from qutebrowser.config import config -from qutebrowser.utils import log, debug, usertypes +from qutebrowser.utils import log, debug, usertypes, objreg class WebEngineView(QWebEngineView): """Custom QWebEngineView subclass with qutebrowser-specific features.""" - def __init__(self, tabdata, parent=None): + def __init__(self, tabdata, win_id, parent=None): super().__init__(parent) + self._win_id = win_id self.setPage(WebEnginePage(tabdata, parent=self)) + def createWindow(self, wintype): + """Called by Qt when a page wants to create a new window. + + This function is called from the createWindow() method of the + associated QWebEnginePage, each time the page wants to create a new + window of the given type. This might be the result, for example, of a + JavaScript request to open a document in a new window. + + Args: + wintype: This enum describes the types of window that can be + created by the createWindow() function. + + QWebEnginePage::WebBrowserWindow: + A complete web browser window. + QWebEnginePage::WebBrowserTab: + A web browser tab. + QWebEnginePage::WebDialog: + A window without decoration. + QWebEnginePage::WebBrowserBackgroundTab: + A web browser tab without hiding the current visible + WebEngineView. (Added in Qt 5.7) + + Return: + The new QWebEngineView object. + """ + background = False + if wintype == QWebEnginePage.WebBrowserWindow: + log.webview.warning("WebBrowserWindow requested, but we don't " + "support that!") + elif wintype == QWebEnginePage.WebBrowserTab: + pass + elif wintype == QWebEnginePage.WebDialog: + log.webview.warning("WebDialog requested, but we don't support " + "that!") + elif (hasattr(QWebEnginePage, 'WebBrowserBackgroundTab') and + wintype == QWebEnginePage.WebBrowserBackgroundTab): + background = True + else: + raise ValueError("Invalid wintype {}".format(debug.qenum_key( + QWebEnginePage, wintype))) + + tabbed_browser = objreg.get('tabbed-browser', scope='window', + window=self._win_id) + # pylint: disable=protected-access + return tabbed_browser.tabopen(background=background)._widget + class WebEnginePage(QWebEnginePage): @@ -74,11 +121,6 @@ class WebEnginePage(QWebEnginePage): logger = level_to_logger[level] logger(logstring) - def createWindow(self, _typ): - """Handle new windows via JS.""" - log.stub() - return None - def acceptNavigationRequest(self, url: QUrl, typ: QWebEnginePage.NavigationType, diff --git a/tests/end2end/data/javascript/window_open.html b/tests/end2end/data/javascript/window_open.html new file mode 100644 index 000000000..974f821f0 --- /dev/null +++ b/tests/end2end/data/javascript/window_open.html @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/tests/end2end/features/hints.feature b/tests/end2end/features/hints.feature index 683defd8c..420ec12d1 100644 --- a/tests/end2end/features/hints.feature +++ b/tests/end2end/features/hints.feature @@ -19,7 +19,6 @@ Feature: Using hints ### Opening in current or new tab - @qtwebengine_todo: createWindow is not implemented yet Scenario: Following a hint and force to open in current tab. When I open data/hints/link_blank.html And I hint with args "links current" and follow a @@ -27,7 +26,6 @@ Feature: Using hints Then the following tabs should be open: - data/hello.txt (active) - @qtwebengine_todo: createWindow is not implemented yet Scenario: Following a hint and allow to open in new tab. When I open data/hints/link_blank.html And I hint with args "links normal" and follow a @@ -36,7 +34,6 @@ Feature: Using hints - data/hints/link_blank.html - data/hello.txt (active) - @qtwebengine_todo: createWindow is not implemented yet Scenario: Following a hint to link with sub-element and force to open in current tab. When I open data/hints/link_span.html And I run :tab-close @@ -154,13 +151,11 @@ Feature: Using hints And I hint wht args "links normal" and follow a Then "navigation request: url http://localhost:*/data/hello2.txt, type NavigationTypeLinkClicked, *" should be logged - @qtwebengine_todo: createWindow is not implemented yet Scenario: Opening a link inside a specific iframe When I open data/hints/iframe_target.html And I hint with args "links normal" and follow a Then "navigation request: url http://localhost:*/data/hello.txt, type NavigationTypeLinkClicked, *" should be logged - @qtwebengine_todo: createWindow is not implemented yet Scenario: Opening a link with specific target frame in a new tab When I open data/hints/iframe_target.html And I hint with args "links tab" and follow a diff --git a/tests/end2end/features/javascript.feature b/tests/end2end/features/javascript.feature index b95e4e7d7..bb34db70b 100644 --- a/tests/end2end/features/javascript.feature +++ b/tests/end2end/features/javascript.feature @@ -9,7 +9,6 @@ Feature: Javascript stuff # https://github.com/The-Compiler/qutebrowser/issues/906 - @qtwebengine_todo: createWindow is not implemented yet Scenario: Closing a JS window twice (issue 906) When I open about:blank And I open data/javascript/issue906.html in a new tab diff --git a/tests/end2end/features/misc.feature b/tests/end2end/features/misc.feature index 493e6e8af..9ae612f87 100644 --- a/tests/end2end/features/misc.feature +++ b/tests/end2end/features/misc.feature @@ -551,7 +551,6 @@ Feature: Various utility commands. Then the page should not be scrolled And the error "prompt-accept: This command is only allowed in prompt/yesno mode." should be shown - @qtwebengine_todo: createWindow is not implemented yet Scenario: :repeat-command with mode-switching command Given I open data/hints/link_blank.html And I run :tab-only From 2687b59373ba285e378001e35adf80b609d107f3 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 2 Sep 2016 16:26:36 +0200 Subject: [PATCH 02/34] Code cleanup --- qutebrowser/browser/webengine/webenginetab.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index bc9c5cc18..d29ee8ed3 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -406,9 +406,9 @@ class WebEngineTab(browsertab.AbstractTab): ]) script = QWebEngineScript() script.setInjectionPoint(QWebEngineScript.DocumentCreation) - page = self._widget.page() script.setSourceCode(js_code) + page = self._widget.page() try: page.runJavaScript("", QWebEngineScript.ApplicationWorld) except TypeError: From 8b7d21876f07db33bf8eefe0fa4539409176ef04 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 2 Sep 2016 16:27:28 +0200 Subject: [PATCH 03/34] Add debug logging to createWindow --- qutebrowser/browser/webengine/webview.py | 15 +++++++-------- qutebrowser/browser/webkit/webview.py | 4 +++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/qutebrowser/browser/webengine/webview.py b/qutebrowser/browser/webengine/webview.py index 5c8d863e4..73a44c9ae 100644 --- a/qutebrowser/browser/webengine/webview.py +++ b/qutebrowser/browser/webengine/webview.py @@ -63,21 +63,20 @@ class WebEngineView(QWebEngineView): Return: The new QWebEngineView object. """ + debug_type = debug.qenum_key(QWebEnginePage, wintype) + log.webview.debug("createWindow with type {}".format(debug_type)) background = False - if wintype == QWebEnginePage.WebBrowserWindow: - log.webview.warning("WebBrowserWindow requested, but we don't " - "support that!") + if wintype in [QWebEnginePage.WebBrowserWindow, + QWebEnginePage.WebDialog]: + log.webview.warning("{} requested, but we don't support that!".format( + debug_type)) elif wintype == QWebEnginePage.WebBrowserTab: pass - elif wintype == QWebEnginePage.WebDialog: - log.webview.warning("WebDialog requested, but we don't support " - "that!") elif (hasattr(QWebEnginePage, 'WebBrowserBackgroundTab') and wintype == QWebEnginePage.WebBrowserBackgroundTab): background = True else: - raise ValueError("Invalid wintype {}".format(debug.qenum_key( - QWebEnginePage, wintype))) + raise ValueError("Invalid wintype {}".format(debug_type)) tabbed_browser = objreg.get('tabbed-browser', scope='window', window=self._win_id) diff --git a/qutebrowser/browser/webkit/webview.py b/qutebrowser/browser/webkit/webview.py index 52e75ad14..f9d22c9d6 100644 --- a/qutebrowser/browser/webkit/webview.py +++ b/qutebrowser/browser/webkit/webview.py @@ -29,7 +29,7 @@ from PyQt5.QtWebKitWidgets import QWebView, QWebPage, QWebFrame from qutebrowser.config import config from qutebrowser.keyinput import modeman -from qutebrowser.utils import log, usertypes, utils, qtutils, objreg +from qutebrowser.utils import log, usertypes, utils, qtutils, objreg, debug from qutebrowser.browser.webkit import webpage, webkitelem @@ -218,6 +218,8 @@ class WebView(QWebView): Return: The new QWebView object. """ + debug_type = debug.qenum_key(QWebPage, wintype) + log.webview.debug("createWindow with type {}".format(debug_type)) if wintype == QWebPage.WebModalDialog: log.webview.warning("WebModalDialog requested, but we don't " "support that!") From 30c07e9b5cd0d7c58e42e90ca06317611e1bee3c Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 2 Sep 2016 16:28:15 +0200 Subject: [PATCH 04/34] tests: Add url to window_open.html --- tests/end2end/data/javascript/window_open.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/end2end/data/javascript/window_open.html b/tests/end2end/data/javascript/window_open.html index 974f821f0..9e217f57d 100644 --- a/tests/end2end/data/javascript/window_open.html +++ b/tests/end2end/data/javascript/window_open.html @@ -7,7 +7,7 @@ if (window.showModalDialog) { window.showModalDialog(); } else { - window.open('', 'window', 'modal'); + window.open('hello.txt', 'window', 'modal'); } } @@ -15,7 +15,7 @@ - + From 6c6e98aac44f0225751571739650265e61f5171e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 10:44:07 +0200 Subject: [PATCH 05/34] Add a @qtwebkit_skip marker --- pytest.ini | 1 + tests/conftest.py | 7 ++++--- tests/end2end/features/conftest.py | 11 +++++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/pytest.ini b/pytest.ini index 812063e54..eda54aa56 100644 --- a/pytest.ini +++ b/pytest.ini @@ -17,6 +17,7 @@ markers = flaky_once: Try to rerun this test once if it fails qtwebengine_todo: Features still missing with QtWebEngine qtwebengine_skip: Tests not applicable with QtWebEngine + qtwebkit_skip: Tests not applicable with QtWebKit qt_log_level_fail = WARNING qt_log_ignore = ^SpellCheck: .* diff --git a/tests/conftest.py b/tests/conftest.py index b04698dbe..c0493bbf5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -226,11 +226,12 @@ if not getattr(sys, 'frozen', False): else: raise ValueError("Invalid package {!r}".format(package)) - def _get_qtwebengine_tag(tag): - """Handle a @qtwebengine_* tag.""" + def _get_backend_tag(tag): + """Handle a @qtwebengine_*/@qtwebkit_skip tag.""" pytest_marks = { 'qtwebengine_todo': pytest.mark.qtwebengine_todo, 'qtwebengine_skip': pytest.mark.qtwebengine_skip, + 'qtwebkit_skip': pytest.mark.qtwebkit_skip } if not any(tag.startswith(t + ':') for t in pytest_marks): return None @@ -243,7 +244,7 @@ if not getattr(sys, 'frozen', False): This tries various functions, and if none knows how to handle this tag, it returns None so it falls back to pytest-bdd's implementation. """ - funcs = [_get_version_tag, _get_qtwebengine_tag] + funcs = [_get_version_tag, _get_backend_tag] for func in funcs: mark = func(tag) if mark is not None: diff --git a/tests/end2end/features/conftest.py b/tests/end2end/features/conftest.py index 5738531fa..75e463689 100644 --- a/tests/end2end/features/conftest.py +++ b/tests/end2end/features/conftest.py @@ -39,19 +39,22 @@ def pytest_collection_modifyitems(config, items): webengine = config.getoption('--qute-bdd-webengine') markers = { - 'qtwebengine_todo': ('QtWebEngine TODO', pytest.mark.xfail), - 'qtwebengine_skip': ('Skipped with QtWebEngine', pytest.mark.skipif), + 'qtwebengine_todo': ('QtWebEngine TODO', pytest.mark.xfail, webengine), + 'qtwebengine_skip': ('Skipped with QtWebEngine', pytest.mark.skipif, + webengine), + 'qtwebkit_skip': ('Skipped with QtWebKit', pytest.mark.skipif, + not webengine), } for item in items: - for name, (prefix, pytest_mark) in markers.items(): + for name, (prefix, pytest_mark, condition) in markers.items(): marker = item.get_marker(name) if marker: if marker.args: text = '{}: {}'.format(prefix, marker.args[0]) else: text = prefix - item.add_marker(pytest_mark(webengine, reason=text, + item.add_marker(pytest_mark(condition, reason=text, **marker.kwargs)) From 30327b2acf62268b995db70dfe4c6e8a6acf3566 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 10:54:09 +0200 Subject: [PATCH 06/34] Move end2end tag handling to end2end/conftest.py --- tests/conftest.py | 75 ---------------------- tests/end2end/conftest.py | 100 +++++++++++++++++++++++++++++ tests/end2end/features/conftest.py | 24 ------- 3 files changed, 100 insertions(+), 99 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index c0493bbf5..4e5e19738 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -21,11 +21,9 @@ """The qutebrowser test suite conftest file.""" -import re import os import sys import warnings -import operator import pytest import hypothesis @@ -37,10 +35,6 @@ from helpers.logfail import fail_on_logging from helpers.messagemock import message_mock from helpers.fixtures import * # pylint: disable=wildcard-import -from PyQt5.QtCore import PYQT_VERSION - -from qutebrowser.utils import qtutils - # Set hypothesis settings hypothesis.settings.register_profile('default', @@ -182,72 +176,3 @@ def pytest_sessionfinish(exitstatus): status_file = os.path.join(cache_dir, 'pytest_status') with open(status_file, 'w', encoding='ascii') as f: f.write(str(exitstatus)) - - -if not getattr(sys, 'frozen', False): - def _get_version_tag(tag): - """Handle tags like pyqt>=5.3.1 for BDD tests. - - This transforms e.g. pyqt>=5.3.1 into an appropriate @pytest.mark.skip - marker, and falls back to pytest-bdd's implementation for all other - casesinto an appropriate @pytest.mark.skip marker, and falls back to - """ - version_re = re.compile(r""" - (?Pqt|pyqt) - (?P==|>|>=|<|<=|!=) - (?P\d+\.\d+\.\d+) - """, re.VERBOSE) - - match = version_re.match(tag) - if not match: - return None - - operators = { - '==': operator.eq, - '>': operator.gt, - '<': operator.lt, - '>=': operator.ge, - '<=': operator.le, - '!=': operator.ne, - } - - package = match.group('package') - op = operators[match.group('operator')] - version = match.group('version') - - if package == 'qt': - return pytest.mark.skipif(qtutils.version_check(version, op), - reason='Needs ' + tag) - elif package == 'pyqt': - major, minor, patch = [int(e) for e in version.split('.')] - hex_version = (major << 16) | (minor << 8) | patch - return pytest.mark.skipif(not op(PYQT_VERSION, hex_version), - reason='Needs ' + tag) - else: - raise ValueError("Invalid package {!r}".format(package)) - - def _get_backend_tag(tag): - """Handle a @qtwebengine_*/@qtwebkit_skip tag.""" - pytest_marks = { - 'qtwebengine_todo': pytest.mark.qtwebengine_todo, - 'qtwebengine_skip': pytest.mark.qtwebengine_skip, - 'qtwebkit_skip': pytest.mark.qtwebkit_skip - } - if not any(tag.startswith(t + ':') for t in pytest_marks): - return None - name, desc = tag.split(':', maxsplit=1) - return pytest_marks[name](desc) - - def pytest_bdd_apply_tag(tag, function): - """Handle custom tags for BDD tests. - - This tries various functions, and if none knows how to handle this tag, - it returns None so it falls back to pytest-bdd's implementation. - """ - funcs = [_get_version_tag, _get_backend_tag] - for func in funcs: - mark = func(tag) - if mark is not None: - mark(function) - return True - return None diff --git a/tests/end2end/conftest.py b/tests/end2end/conftest.py index 73d4a87ab..c18f92a11 100644 --- a/tests/end2end/conftest.py +++ b/tests/end2end/conftest.py @@ -21,11 +21,16 @@ """Things needed for end2end testing.""" +import re import os +import sys import shutil import pstats import os.path +import operator + import pytest +from PyQt5.QtCore import PYQT_VERSION pytest.register_assert_rewrite('end2end.fixtures') @@ -33,6 +38,7 @@ from end2end.fixtures.webserver import httpbin, httpbin_after_test, ssl_server from end2end.fixtures.quteprocess import (quteproc_process, quteproc, quteproc_new) from end2end.fixtures.testprocess import pytest_runtest_makereport +from qutebrowser.utils import qtutils def pytest_configure(config): @@ -51,3 +57,97 @@ def pytest_unconfigure(config): for fn in os.listdir('prof'): stats.add(os.path.join('prof', fn)) stats.dump_stats(os.path.join('prof', 'combined.pstats')) + + +def _get_version_tag(tag): + """Handle tags like pyqt>=5.3.1 for BDD tests. + + This transforms e.g. pyqt>=5.3.1 into an appropriate @pytest.mark.skip + marker, and falls back to pytest-bdd's implementation for all other + casesinto an appropriate @pytest.mark.skip marker, and falls back to + """ + version_re = re.compile(r""" + (?Pqt|pyqt) + (?P==|>|>=|<|<=|!=) + (?P\d+\.\d+\.\d+) + """, re.VERBOSE) + + match = version_re.match(tag) + if not match: + return None + + operators = { + '==': operator.eq, + '>': operator.gt, + '<': operator.lt, + '>=': operator.ge, + '<=': operator.le, + '!=': operator.ne, + } + + package = match.group('package') + op = operators[match.group('operator')] + version = match.group('version') + + if package == 'qt': + return pytest.mark.skipif(qtutils.version_check(version, op), + reason='Needs ' + tag) + elif package == 'pyqt': + major, minor, patch = [int(e) for e in version.split('.')] + hex_version = (major << 16) | (minor << 8) | patch + return pytest.mark.skipif(not op(PYQT_VERSION, hex_version), + reason='Needs ' + tag) + else: + raise ValueError("Invalid package {!r}".format(package)) + +def _get_backend_tag(tag): + """Handle a @qtwebengine_*/@qtwebkit_skip tag.""" + pytest_marks = { + 'qtwebengine_todo': pytest.mark.qtwebengine_todo, + 'qtwebengine_skip': pytest.mark.qtwebengine_skip, + 'qtwebkit_skip': pytest.mark.qtwebkit_skip + } + if not any(tag.startswith(t + ':') for t in pytest_marks): + return None + name, desc = tag.split(':', maxsplit=1) + return pytest_marks[name](desc) + + +if not getattr(sys, 'frozen', False): + def pytest_bdd_apply_tag(tag, function): + """Handle custom tags for BDD tests. + + This tries various functions, and if none knows how to handle this tag, + it returns None so it falls back to pytest-bdd's implementation. + """ + funcs = [_get_version_tag, _get_backend_tag] + for func in funcs: + mark = func(tag) + if mark is not None: + mark(function) + return True + return None + + +def pytest_collection_modifyitems(config, items): + """Apply @qtwebengine_* markers.""" + webengine = config.getoption('--qute-bdd-webengine') + + markers = { + 'qtwebengine_todo': ('QtWebEngine TODO', pytest.mark.xfail, webengine), + 'qtwebengine_skip': ('Skipped with QtWebEngine', pytest.mark.skipif, + webengine), + 'qtwebkit_skip': ('Skipped with QtWebKit', pytest.mark.skipif, + not webengine), + } + + for item in items: + for name, (prefix, pytest_mark, condition) in markers.items(): + marker = item.get_marker(name) + if marker: + if marker.args: + text = '{}: {}'.format(prefix, marker.args[0]) + else: + text = prefix + item.add_marker(pytest_mark(condition, reason=text, + **marker.kwargs)) diff --git a/tests/end2end/features/conftest.py b/tests/end2end/features/conftest.py index 75e463689..c350753b5 100644 --- a/tests/end2end/features/conftest.py +++ b/tests/end2end/features/conftest.py @@ -34,30 +34,6 @@ from qutebrowser.utils import log from helpers import utils -def pytest_collection_modifyitems(config, items): - """Apply @qtwebengine_* markers.""" - webengine = config.getoption('--qute-bdd-webengine') - - markers = { - 'qtwebengine_todo': ('QtWebEngine TODO', pytest.mark.xfail, webengine), - 'qtwebengine_skip': ('Skipped with QtWebEngine', pytest.mark.skipif, - webengine), - 'qtwebkit_skip': ('Skipped with QtWebKit', pytest.mark.skipif, - not webengine), - } - - for item in items: - for name, (prefix, pytest_mark, condition) in markers.items(): - marker = item.get_marker(name) - if marker: - if marker.args: - text = '{}: {}'.format(prefix, marker.args[0]) - else: - text = prefix - item.add_marker(pytest_mark(condition, reason=text, - **marker.kwargs)) - - @pytest.hookimpl(hookwrapper=True) def pytest_runtest_makereport(item, call): """Add a BDD section to the test output.""" From 2c2375ff1865379dc385739023d6f0d4b54554bc Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 10:54:28 +0200 Subject: [PATCH 07/34] Add a separate QtWebEngine test for #906 --- tests/end2end/features/javascript.feature | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/end2end/features/javascript.feature b/tests/end2end/features/javascript.feature index bb34db70b..a29c33373 100644 --- a/tests/end2end/features/javascript.feature +++ b/tests/end2end/features/javascript.feature @@ -9,7 +9,8 @@ Feature: Javascript stuff # https://github.com/The-Compiler/qutebrowser/issues/906 - Scenario: Closing a JS window twice (issue 906) + @qtwebengine_skip + Scenario: Closing a JS window twice (issue 906) - qtwebkit When I open about:blank And I open data/javascript/issue906.html in a new tab And I run :click-element id open-button @@ -17,3 +18,15 @@ Feature: Javascript stuff And I run :tab-focus 2 And I run :click-element id close-button Then "Requested to close * which does not exist!" should be logged + + @qtwebkit_skip + Scenario: Closing a JS window twice (issue 906) - qtwebengine + When I open about:blank + And I open data/javascript/issue906.html in a new tab + And I run :click-element id open-button + And I wait for "WebDialog requested, but we don't support that!" in the log + And I wait for "Changing title for idx 2 to 'about:blank'" in the log + And I run :tab-focus 2 + And I run :click-element id close-button + And I wait for "Focus object changed: *" in the log + Then no crash should happen From 6a26907dede1cde2946736fd91933d1087705c23 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 10:56:49 +0200 Subject: [PATCH 08/34] Fix lint --- qutebrowser/browser/webengine/webview.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qutebrowser/browser/webengine/webview.py b/qutebrowser/browser/webengine/webview.py index 73a44c9ae..9ba128c15 100644 --- a/qutebrowser/browser/webengine/webview.py +++ b/qutebrowser/browser/webengine/webview.py @@ -68,8 +68,8 @@ class WebEngineView(QWebEngineView): background = False if wintype in [QWebEnginePage.WebBrowserWindow, QWebEnginePage.WebDialog]: - log.webview.warning("{} requested, but we don't support that!".format( - debug_type)) + log.webview.warning("{} requested, but we don't support " + "that!".format(debug_type)) elif wintype == QWebEnginePage.WebBrowserTab: pass elif (hasattr(QWebEnginePage, 'WebBrowserBackgroundTab') and From cf070d48f2de931bb4c00f37a1b8077ba69956a4 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 12:16:58 +0200 Subject: [PATCH 09/34] WebEngine: Disable createWindow for Qt < 5.7.1 Fixes #1911. The bugfix is backported in my qt5-webengine-debug package, and QUTE_QTBUG54419_PATCHED can be set to force qutebrowser to use createWindow. --- pytest.ini | 1 + qutebrowser/browser/webengine/webview.py | 13 ++++++++++++- qutebrowser/misc/crashdialog.py | 2 +- tests/end2end/conftest.py | 6 ++++++ tests/end2end/features/hints.feature | 5 +++++ tests/end2end/features/javascript.feature | 1 + tests/end2end/features/misc.feature | 1 + tests/unit/misc/test_crashdialog.py | 1 + tox.ini | 2 +- 9 files changed, 29 insertions(+), 3 deletions(-) diff --git a/pytest.ini b/pytest.ini index eda54aa56..b8232c733 100644 --- a/pytest.ini +++ b/pytest.ini @@ -18,6 +18,7 @@ markers = qtwebengine_todo: Features still missing with QtWebEngine qtwebengine_skip: Tests not applicable with QtWebEngine qtwebkit_skip: Tests not applicable with QtWebKit + qtwebengine_createWindow: Tests using createWindow with QtWebEngine (QTBUG-54419) qt_log_level_fail = WARNING qt_log_ignore = ^SpellCheck: .* diff --git a/qutebrowser/browser/webengine/webview.py b/qutebrowser/browser/webengine/webview.py index 9ba128c15..af1b5c0c3 100644 --- a/qutebrowser/browser/webengine/webview.py +++ b/qutebrowser/browser/webengine/webview.py @@ -19,6 +19,7 @@ """The main browser widget for QtWebEngine.""" +import os from PyQt5.QtCore import pyqtSignal, QUrl # pylint: disable=no-name-in-module,import-error,useless-suppression @@ -26,7 +27,7 @@ from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage # pylint: enable=no-name-in-module,import-error,useless-suppression from qutebrowser.config import config -from qutebrowser.utils import log, debug, usertypes, objreg +from qutebrowser.utils import log, debug, usertypes, objreg, qtutils, message class WebEngineView(QWebEngineView): @@ -63,6 +64,16 @@ class WebEngineView(QWebEngineView): Return: The new QWebEngineView object. """ + # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-54419 + vercheck = qtutils.version_check + qtbug_54419_fixed = ((vercheck('5.6.2') and not vercheck('5.7.0')) or + qtutils.version_check('5.7.1') or + os.environ.get('QUTE_QTBUG54419_PATCHED', '')) + if not qtbug_54419_fixed: + message.error(self._win_id, "Qt 5.6.2/5.7.1 or newer is required " + "to open new tabs via JS!") + return None + debug_type = debug.qenum_key(QWebEnginePage, wintype) log.webview.debug("createWindow with type {}".format(debug_type)) background = False diff --git a/qutebrowser/misc/crashdialog.py b/qutebrowser/misc/crashdialog.py index d22415b7b..8d44da041 100644 --- a/qutebrowser/misc/crashdialog.py +++ b/qutebrowser/misc/crashdialog.py @@ -99,7 +99,7 @@ def get_fatal_crash_dialog(debug, data): def _get_environment_vars(): """Gather environment variables for the crash info.""" masks = ('DESKTOP_SESSION', 'DE', 'QT_*', 'PYTHON*', 'LC_*', 'LANG', - 'XDG_*') + 'XDG_*', 'QUTE_*') info = [] for key, value in os.environ.items(): for m in masks: diff --git a/tests/end2end/conftest.py b/tests/end2end/conftest.py index c18f92a11..a8a40d824 100644 --- a/tests/end2end/conftest.py +++ b/tests/end2end/conftest.py @@ -132,6 +132,10 @@ if not getattr(sys, 'frozen', False): def pytest_collection_modifyitems(config, items): """Apply @qtwebengine_* markers.""" webengine = config.getoption('--qute-bdd-webengine') + vercheck = qtutils.version_check + qtbug_54419_fixed = ((vercheck('5.6.2') and not vercheck('5.7.0')) or + qtutils.version_check('5.7.1') or + os.environ.get('QUTE_QTBUG54419_PATCHED', '')) markers = { 'qtwebengine_todo': ('QtWebEngine TODO', pytest.mark.xfail, webengine), @@ -139,6 +143,8 @@ def pytest_collection_modifyitems(config, items): webengine), 'qtwebkit_skip': ('Skipped with QtWebKit', pytest.mark.skipif, not webengine), + 'qtwebengine_createWindow': ('Skipped because of QTBUG-54419', + pytest.mark.skipif, not qtbug_54419_fixed) } for item in items: diff --git a/tests/end2end/features/hints.feature b/tests/end2end/features/hints.feature index 420ec12d1..f100b5c10 100644 --- a/tests/end2end/features/hints.feature +++ b/tests/end2end/features/hints.feature @@ -19,6 +19,7 @@ Feature: Using hints ### Opening in current or new tab + @qtwebengine_createWindow Scenario: Following a hint and force to open in current tab. When I open data/hints/link_blank.html And I hint with args "links current" and follow a @@ -26,6 +27,7 @@ Feature: Using hints Then the following tabs should be open: - data/hello.txt (active) + @qtwebengine_createWindow Scenario: Following a hint and allow to open in new tab. When I open data/hints/link_blank.html And I hint with args "links normal" and follow a @@ -34,6 +36,7 @@ Feature: Using hints - data/hints/link_blank.html - data/hello.txt (active) + @qtwebengine_createWindow Scenario: Following a hint to link with sub-element and force to open in current tab. When I open data/hints/link_span.html And I run :tab-close @@ -151,11 +154,13 @@ Feature: Using hints And I hint wht args "links normal" and follow a Then "navigation request: url http://localhost:*/data/hello2.txt, type NavigationTypeLinkClicked, *" should be logged + @qtwebengine_createWindow Scenario: Opening a link inside a specific iframe When I open data/hints/iframe_target.html And I hint with args "links normal" and follow a Then "navigation request: url http://localhost:*/data/hello.txt, type NavigationTypeLinkClicked, *" should be logged + @qtwebengine_createWindow Scenario: Opening a link with specific target frame in a new tab When I open data/hints/iframe_target.html And I hint with args "links tab" and follow a diff --git a/tests/end2end/features/javascript.feature b/tests/end2end/features/javascript.feature index a29c33373..b2273cb1d 100644 --- a/tests/end2end/features/javascript.feature +++ b/tests/end2end/features/javascript.feature @@ -20,6 +20,7 @@ Feature: Javascript stuff Then "Requested to close * which does not exist!" should be logged @qtwebkit_skip + @qtwebengine_createWindow Scenario: Closing a JS window twice (issue 906) - qtwebengine When I open about:blank And I open data/javascript/issue906.html in a new tab diff --git a/tests/end2end/features/misc.feature b/tests/end2end/features/misc.feature index 9ae612f87..a7fc0bf80 100644 --- a/tests/end2end/features/misc.feature +++ b/tests/end2end/features/misc.feature @@ -551,6 +551,7 @@ Feature: Various utility commands. Then the page should not be scrolled And the error "prompt-accept: This command is only allowed in prompt/yesno mode." should be shown + @qtwebengine_createWindow Scenario: :repeat-command with mode-switching command Given I open data/hints/link_blank.html And I run :tab-only diff --git a/tests/unit/misc/test_crashdialog.py b/tests/unit/misc/test_crashdialog.py index 6f38cd50c..dd2ebd35e 100644 --- a/tests/unit/misc/test_crashdialog.py +++ b/tests/unit/misc/test_crashdialog.py @@ -76,6 +76,7 @@ def test_parse_fatal_stacktrace(text, typ, func): "QT_IM_MODULE = fcitx" ), ({'LANGUAGE': 'foo', 'LANG': 'en_US.UTF-8'}, "LANG = en_US.UTF-8"), + ({'FOO': 'bar', 'QUTE_BLAH': '1'}, "QUTE_BLAH = 1"), ], ids=lambda e: e[1]) def test_get_environment_vars(monkeypatch, env, expected): """Test for crashdialog._get_environment_vars.""" diff --git a/tox.ini b/tox.ini index f6a6b88cd..5c49ecce4 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,7 @@ skipsdist = true setenv = QT_QPA_PLATFORM_PLUGIN_PATH={envdir}/Lib/site-packages/PyQt5/plugins/platforms PYTEST_QT_API=pyqt5 -passenv = PYTHON DISPLAY XAUTHORITY HOME USERNAME USER CI TRAVIS XDG_* +passenv = PYTHON DISPLAY XAUTHORITY HOME USERNAME USER CI TRAVIS XDG_* QUTE_* deps = -r{toxinidir}/misc/requirements/requirements-pip.txt -r{toxinidir}/requirements.txt From 19ac4889977edda6b2b2e87d2940b355ed39176e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 12:31:29 +0200 Subject: [PATCH 10/34] tests: Add QUTE_BDD_WEBENGINE environment variable --- tests/conftest.py | 6 ++++++ tests/end2end/conftest.py | 8 ++++---- tests/end2end/features/conftest.py | 8 ++++---- tests/end2end/features/test_marks_bdd.py | 2 +- tests/end2end/fixtures/quteprocess.py | 5 ++--- tests/end2end/test_hints_html.py | 11 +++++------ tests/end2end/test_insert_mode.py | 2 +- 7 files changed, 23 insertions(+), 19 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 4e5e19738..aac0e2014 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -138,6 +138,12 @@ def pytest_addoption(parser): help='Use QtWebEngine for BDD tests') +def pytest_configure(config): + webengine_arg = config.getoption('--qute-bdd-webengine') + webengine_env = os.environ.get('QUTE_BDD_WEBENGINE', '') + config.webengine = bool(webengine_arg or webengine_env) + + @pytest.fixture(scope='session', autouse=True) def check_display(request): if (not request.config.getoption('--no-xvfb') and diff --git a/tests/end2end/conftest.py b/tests/end2end/conftest.py index a8a40d824..79bcb5e0b 100644 --- a/tests/end2end/conftest.py +++ b/tests/end2end/conftest.py @@ -131,18 +131,18 @@ if not getattr(sys, 'frozen', False): def pytest_collection_modifyitems(config, items): """Apply @qtwebengine_* markers.""" - webengine = config.getoption('--qute-bdd-webengine') vercheck = qtutils.version_check qtbug_54419_fixed = ((vercheck('5.6.2') and not vercheck('5.7.0')) or qtutils.version_check('5.7.1') or os.environ.get('QUTE_QTBUG54419_PATCHED', '')) markers = { - 'qtwebengine_todo': ('QtWebEngine TODO', pytest.mark.xfail, webengine), + 'qtwebengine_todo': ('QtWebEngine TODO', pytest.mark.xfail, + config.webengine), 'qtwebengine_skip': ('Skipped with QtWebEngine', pytest.mark.skipif, - webengine), + config.webengine), 'qtwebkit_skip': ('Skipped with QtWebKit', pytest.mark.skipif, - not webengine), + not config.webengine), 'qtwebengine_createWindow': ('Skipped because of QTBUG-54419', pytest.mark.skipif, not qtbug_54419_fixed) } diff --git a/tests/end2end/features/conftest.py b/tests/end2end/features/conftest.py index c350753b5..e911b14a5 100644 --- a/tests/end2end/features/conftest.py +++ b/tests/end2end/features/conftest.py @@ -408,7 +408,7 @@ def compare_session(request, quteproc, expected): partial_compare is used, which means only the keys/values listed will be compared. """ - if request.config.getoption('--qute-bdd-webengine'): + if request.config.webengine: pytest.xfail(reason="QtWebEngine TODO: Sessions are not implemented") quteproc.compare_session(expected) @@ -473,7 +473,7 @@ def check_open_tabs(quteproc, request, tabs): It expects a list of URLs, with an optional "(active)" suffix. """ - if request.config.getoption('--qute-bdd-webengine'): + if request.config.webengine: pytest.xfail(reason="QtWebEngine TODO: Sessions are not implemented") session = quteproc.get_session() active_suffix = ' (active)' @@ -530,7 +530,7 @@ def _get_scroll_values(quteproc): @bdd.then(bdd.parsers.re(r"the page should be scrolled " r"(?Phorizontally|vertically)")) def check_scrolled(request, quteproc, direction): - if request.config.getoption('--qute-bdd-webengine'): + if request.config.webengine: pytest.xfail(reason="QtWebEngine TODO: Sessions are not implemented") x, y = _get_scroll_values(quteproc) if direction == 'horizontally': @@ -543,7 +543,7 @@ def check_scrolled(request, quteproc, direction): @bdd.then("the page should not be scrolled") def check_not_scrolled(request, quteproc): - if request.config.getoption('--qute-bdd-webengine'): + if request.config.webengine: pytest.xfail(reason="QtWebEngine TODO: Sessions are not implemented") x, y = _get_scroll_values(quteproc) assert x == 0 diff --git a/tests/end2end/features/test_marks_bdd.py b/tests/end2end/features/test_marks_bdd.py index 858456996..58aec5a00 100644 --- a/tests/end2end/features/test_marks_bdd.py +++ b/tests/end2end/features/test_marks_bdd.py @@ -24,7 +24,7 @@ bdd.scenarios('marks.feature') @bdd.then(bdd.parsers.parse("the page should be scrolled to {x} {y}")) def check_y(request, quteproc, x, y): - if request.config.getoption('--qute-bdd-webengine'): + if request.config.webengine: pytest.xfail(reason="QtWebEngine TODO: Sessions are not implemented") data = quteproc.get_session() pos = data['windows'][0]['tabs'][0]['history'][-1]['scroll-pos'] diff --git a/tests/end2end/fixtures/quteprocess.py b/tests/end2end/fixtures/quteprocess.py index 5b621af47..778ae732f 100644 --- a/tests/end2end/fixtures/quteprocess.py +++ b/tests/end2end/fixtures/quteprocess.py @@ -157,7 +157,6 @@ class QuteProc(testprocess.Process): def __init__(self, request, *, parent=None): super().__init__(parent) - self._webengine = request.config.getoption('--qute-bdd-webengine') self._ipc_socket = None self.basedir = None self._focus_ready = False @@ -261,7 +260,7 @@ class QuteProc(testprocess.Process): return executable, args def _default_args(self): - backend = 'webengine' if self._webengine else 'webkit' + backend = 'webengine' if self.request.config.webengine else 'webkit' return ['--debug', '--no-err-windows', '--temp-basedir', '--json-logging', '--backend', backend, 'about:blank'] @@ -338,7 +337,7 @@ class QuteProc(testprocess.Process): ('general', 'auto-save-interval', '0'), ('general', 'new-instance-open-target.window', 'last-opened') ] - if not self._webengine: + if not self.request.config.webengine: settings.append(('network', 'ssl-strict', 'false')) for sect, opt, value in settings: diff --git a/tests/end2end/test_hints_html.py b/tests/end2end/test_hints_html.py index 406e1bd46..c2d5143bc 100644 --- a/tests/end2end/test_hints_html.py +++ b/tests/end2end/test_hints_html.py @@ -85,21 +85,20 @@ def _parse_file(test_name): @pytest.mark.parametrize('find_implementation', ['javascript', 'python']) def test_hints(test_name, zoom_text_only, zoom_level, find_implementation, quteproc, request): - webengine = bool(request.config.getoption('--qute-bdd-webengine')) - if zoom_text_only and webengine: + if zoom_text_only and request.config.webengine: pytest.skip("QtWebEngine doesn't have zoom-text-only") - if find_implementation == 'python' and webengine: + if find_implementation == 'python' and request.config.webengine: pytest.skip("QtWebEngine doesn't have a python find implementation") parsed = _parse_file(test_name) - if parsed.qtwebengine_todo is not None and webengine: + if parsed.qtwebengine_todo is not None and request.config.webengine: pytest.xfail("QtWebEngine TODO: {}".format(parsed.qtwebengine_todo)) url_path = 'data/hints/html/{}'.format(test_name) quteproc.open_path(url_path) # setup - if not webengine: + if not request.config.webengine: quteproc.set_setting('ui', 'zoom-text-only', str(zoom_text_only)) quteproc.set_setting('hints', 'find-implementation', find_implementation) @@ -111,7 +110,7 @@ def test_hints(test_name, zoom_text_only, zoom_level, find_implementation, quteproc.wait_for_load_finished('data/' + parsed.target) # reset quteproc.send_cmd(':zoom 100') - if not webengine: + if not request.config.webengine: quteproc.set_setting('ui', 'zoom-text-only', 'false') quteproc.set_setting('hints', 'find-implementation', 'javascript') diff --git a/tests/end2end/test_insert_mode.py b/tests/end2end/test_insert_mode.py index f8dc7a547..a3edd651e 100644 --- a/tests/end2end/test_insert_mode.py +++ b/tests/end2end/test_insert_mode.py @@ -48,7 +48,7 @@ def test_insert_mode(file_name, elem_id, source, input_text, auto_insert, if source == 'keypress': quteproc.press_keys(input_text) elif source == 'clipboard': - if request.config.getoption('--qute-bdd-webengine'): + if request.config.webengine: pytest.xfail(reason="QtWebEngine TODO: :insert-text is not " "implemented") quteproc.send_cmd(':debug-set-fake-clipboard "{}"'.format(input_text)) From aec0e4ca40fe5e70e4f1142870c8ba36db27ec79 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 13:16:48 +0200 Subject: [PATCH 11/34] tests: Fix applying of end2end marker --- tests/conftest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index aac0e2014..a53223dff 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -104,7 +104,9 @@ def pytest_collection_modifyitems(items): item.module.__file__, os.path.commonprefix([__file__, item.module.__file__])) - module_root_dir = os.path.split(module_path)[0] + module_root_dir = module_path.split(os.sep)[0] + assert module_root_dir in ['end2end', 'unit', 'helpers', + 'test_conftest.py'] if module_root_dir == 'end2end': item.add_marker(pytest.mark.end2end) From ebf093bb6e211a7cbd9b60217a87ffbb6216d6d8 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 13:19:56 +0200 Subject: [PATCH 12/34] tests: Skip unittests with QUTE_BDD_WEBENGINE --- tests/end2end/conftest.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/end2end/conftest.py b/tests/end2end/conftest.py index 79bcb5e0b..4be09f974 100644 --- a/tests/end2end/conftest.py +++ b/tests/end2end/conftest.py @@ -129,8 +129,9 @@ if not getattr(sys, 'frozen', False): return None +@pytest.hookimpl(trylast=True) def pytest_collection_modifyitems(config, items): - """Apply @qtwebengine_* markers.""" + """Apply @qtwebengine_* markers; skip unittests with QUTE_BDD_WEBENGINE.""" vercheck = qtutils.version_check qtbug_54419_fixed = ((vercheck('5.6.2') and not vercheck('5.7.0')) or qtutils.version_check('5.7.1') or @@ -157,3 +158,14 @@ def pytest_collection_modifyitems(config, items): text = prefix item.add_marker(pytest_mark(condition, reason=text, **marker.kwargs)) + + if os.environ.get('QUTE_BDD_WEBENGINE', ''): + remaining = [] + deselected = [] + for item in items: + if not item.get_marker('end2end'): + deselected.append(item) + else: + remaining.append(item) + config.hook.pytest_deselected(items=deselected) + items[:] = remaining From 1c1d75e793eef825d93e6f23f093814a990aa4e7 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 13:20:16 +0200 Subject: [PATCH 13/34] travis: Add a build job for QtWebEngine --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 449230232..3812ca614 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,9 @@ matrix: - os: linux env: DOCKER=archlinux services: docker + - os: linux + env: DOCKER=archlinux QUTE_BDD_WEBENGINE=true + services: docker - os: linux env: DOCKER=ubuntu-xenial services: docker From 141b7c589346fde441fc742716663647c34f6a0a Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 13:26:54 +0200 Subject: [PATCH 14/34] Increase timeout in auto-follow-timeout test --- tests/end2end/features/hints.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/end2end/features/hints.feature b/tests/end2end/features/hints.feature index f100b5c10..5d0d0c88e 100644 --- a/tests/end2end/features/hints.feature +++ b/tests/end2end/features/hints.feature @@ -172,7 +172,7 @@ Feature: Using hints ### hints -> auto-follow-timeout Scenario: Ignoring key presses after auto-following hints - When I set hints -> auto-follow-timeout to 200 + When I set hints -> auto-follow-timeout to 500 And I set hints -> mode to number And I run :bind --force , message-error "This should not happen" And I open data/hints/html/simple.html From cf89204ac3ccee025337d762515db8e3e3ca5c27 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 14:12:15 +0200 Subject: [PATCH 15/34] Only skip because of QTBUG-54419 with WebEngine --- tests/end2end/conftest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/end2end/conftest.py b/tests/end2end/conftest.py index 4be09f974..c9f18e8c3 100644 --- a/tests/end2end/conftest.py +++ b/tests/end2end/conftest.py @@ -145,7 +145,9 @@ def pytest_collection_modifyitems(config, items): 'qtwebkit_skip': ('Skipped with QtWebKit', pytest.mark.skipif, not config.webengine), 'qtwebengine_createWindow': ('Skipped because of QTBUG-54419', - pytest.mark.skipif, not qtbug_54419_fixed) + pytest.mark.skipif, + not qtbug_54419_fixed and + config.webengine) } for item in items: From ce98d893520c493b189c82db15735d997aa81433 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 14:34:52 +0200 Subject: [PATCH 16/34] Add some (crashing...) window.open/.close tests --- tests/end2end/data/javascript/issue906.html | 2 +- .../end2end/data/javascript/window_open.html | 16 ++++++++-- tests/end2end/features/javascript.feature | 30 +++++++++++++++++-- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/tests/end2end/data/javascript/issue906.html b/tests/end2end/data/javascript/issue906.html index dbbf54ee9..ec2e0041b 100644 --- a/tests/end2end/data/javascript/issue906.html +++ b/tests/end2end/data/javascript/issue906.html @@ -9,7 +9,7 @@ var myWindow; function openWin() { - myWindow = window.open("", "myWindow", "width=200, height=100"); + myWindow = window.open("about:blank", "myWindow", "width=200, height=100"); } function closeWin() { diff --git a/tests/end2end/data/javascript/window_open.html b/tests/end2end/data/javascript/window_open.html index 9e217f57d..9e0f2ca8a 100644 --- a/tests/end2end/data/javascript/window_open.html +++ b/tests/end2end/data/javascript/window_open.html @@ -3,20 +3,32 @@ - + + + diff --git a/tests/end2end/features/javascript.feature b/tests/end2end/features/javascript.feature index b2273cb1d..d7b3b4d89 100644 --- a/tests/end2end/features/javascript.feature +++ b/tests/end2end/features/javascript.feature @@ -7,22 +7,46 @@ Feature: Javascript stuff And I open data/javascript/consolelog.html Then the javascript message "console.log works!" should be logged + # Causes segfaults... + @qtwebengine_createWindow @xfail_norun + Scenario: Opening/Closing a window via JS + When I open data/javascript/window_open.html + And I run :tab-only + And I run :click-element id open-normal + And I wait for "Changing title for idx 1 to 'about:blank'" in the log + And I run :tab-focus 1 + And I run :click-element id close-normal + Then "Focus object changed: *" should be logged + + # Causes segfaults... + @qtwebengine_createWindow @xfail_norun + Scenario: Opening/closing a modal window via JS + When I open data/javascript/window_open.html + And I run :tab-only + And I run :click-element id open-modal + And I wait for "Changing title for idx 1 to 'about:blank'" in the log + And I run :tab-focus 1 + And I run :click-element id close-normal + Then "Focus object changed: *" should be logged + And "WebModalDialog requested, but we don't support that!" should be logged + # https://github.com/The-Compiler/qutebrowser/issues/906 @qtwebengine_skip Scenario: Closing a JS window twice (issue 906) - qtwebkit When I open about:blank - And I open data/javascript/issue906.html in a new tab + And I run :tab-only + When I open data/javascript/issue906.html in a new tab And I run :click-element id open-button And I wait for "Changing title for idx 2 to 'about:blank'" in the log And I run :tab-focus 2 And I run :click-element id close-button Then "Requested to close * which does not exist!" should be logged - @qtwebkit_skip - @qtwebengine_createWindow + @qtwebengine_createWindow @qtwebkit_skip Scenario: Closing a JS window twice (issue 906) - qtwebengine When I open about:blank + And I run :tab-only And I open data/javascript/issue906.html in a new tab And I run :click-element id open-button And I wait for "WebDialog requested, but we don't support that!" in the log From a52c8d6576cfb06f60fc38948da68581ec9244e6 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 14:41:05 +0200 Subject: [PATCH 17/34] Clean up javascript double-close test The test for QtWebEngine was removed because something weird happened with the two pytest-bdd tags, and I'm too annoyed with everything being broken to investigate now... Future me, I'm sorry. --- tests/end2end/data/javascript/issue906.html | 22 ------------------- .../end2end/data/javascript/window_open.html | 5 +++++ tests/end2end/features/javascript.feature | 19 +++------------- 3 files changed, 8 insertions(+), 38 deletions(-) delete mode 100644 tests/end2end/data/javascript/issue906.html diff --git a/tests/end2end/data/javascript/issue906.html b/tests/end2end/data/javascript/issue906.html deleted file mode 100644 index ec2e0041b..000000000 --- a/tests/end2end/data/javascript/issue906.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - diff --git a/tests/end2end/data/javascript/window_open.html b/tests/end2end/data/javascript/window_open.html index 9e0f2ca8a..af09755e0 100644 --- a/tests/end2end/data/javascript/window_open.html +++ b/tests/end2end/data/javascript/window_open.html @@ -20,6 +20,11 @@ function close() { my_window.close(); } + + function close_twice() { + my_window.close(); + my_window.close(); + } diff --git a/tests/end2end/features/javascript.feature b/tests/end2end/features/javascript.feature index d7b3b4d89..aad1eee4d 100644 --- a/tests/end2end/features/javascript.feature +++ b/tests/end2end/features/javascript.feature @@ -36,22 +36,9 @@ Feature: Javascript stuff Scenario: Closing a JS window twice (issue 906) - qtwebkit When I open about:blank And I run :tab-only - When I open data/javascript/issue906.html in a new tab - And I run :click-element id open-button + When I open data/javascript/window_open.html in a new tab + And I run :click-element id open-normal And I wait for "Changing title for idx 2 to 'about:blank'" in the log And I run :tab-focus 2 - And I run :click-element id close-button + And I run :click-element id close-twice Then "Requested to close * which does not exist!" should be logged - - @qtwebengine_createWindow @qtwebkit_skip - Scenario: Closing a JS window twice (issue 906) - qtwebengine - When I open about:blank - And I run :tab-only - And I open data/javascript/issue906.html in a new tab - And I run :click-element id open-button - And I wait for "WebDialog requested, but we don't support that!" in the log - And I wait for "Changing title for idx 2 to 'about:blank'" in the log - And I run :tab-focus 2 - And I run :click-element id close-button - And I wait for "Focus object changed: *" in the log - Then no crash should happen From 8115fa2af847d595f44ad411736a92ccdc443953 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 14:45:34 +0200 Subject: [PATCH 18/34] Re-enable some createWindow tests --- tests/end2end/features/javascript.feature | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/end2end/features/javascript.feature b/tests/end2end/features/javascript.feature index aad1eee4d..3942e00e1 100644 --- a/tests/end2end/features/javascript.feature +++ b/tests/end2end/features/javascript.feature @@ -8,7 +8,7 @@ Feature: Javascript stuff Then the javascript message "console.log works!" should be logged # Causes segfaults... - @qtwebengine_createWindow @xfail_norun + @qtwebengine_createWindow Scenario: Opening/Closing a window via JS When I open data/javascript/window_open.html And I run :tab-only @@ -19,7 +19,7 @@ Feature: Javascript stuff Then "Focus object changed: *" should be logged # Causes segfaults... - @qtwebengine_createWindow @xfail_norun + @qtwebengine_createWindow Scenario: Opening/closing a modal window via JS When I open data/javascript/window_open.html And I run :tab-only @@ -28,7 +28,8 @@ Feature: Javascript stuff And I run :tab-focus 1 And I run :click-element id close-normal Then "Focus object changed: *" should be logged - And "WebModalDialog requested, but we don't support that!" should be logged + # WebModalDialog with QtWebKit, WebDialog with QtWebEngine + And "Web*Dialog requested, but we don't support that!" should be logged # https://github.com/The-Compiler/qutebrowser/issues/906 From f2c4cedf619f89045172ce2be57ea1c8416ecead Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 14:56:02 +0200 Subject: [PATCH 19/34] QtWebEngine: Don't add invalid URLs to history --- qutebrowser/browser/webengine/webenginetab.py | 5 +++++ tests/end2end/data/javascript/window_open.html | 5 +++++ tests/end2end/features/backforward.feature | 2 -- tests/end2end/features/history.feature | 5 +++++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index d29ee8ed3..97f810e67 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -504,6 +504,11 @@ class WebEngineTab(browsertab.AbstractTab): if title == title_url.toDisplayString(QUrl.RemoveScheme).strip('/'): title = "" + # Don't add history entry if the URL is invalid anyways + if not url.isValid(): + log.misc.debug("Ignoring invalid URL being added to history") + return + self.add_history_item.emit(url, requested_url, title) def _connect_signals(self): diff --git a/tests/end2end/data/javascript/window_open.html b/tests/end2end/data/javascript/window_open.html index af09755e0..b8e178db3 100644 --- a/tests/end2end/data/javascript/window_open.html +++ b/tests/end2end/data/javascript/window_open.html @@ -17,6 +17,10 @@ my_window = window.open('about:blank', 'my_window'); } + function open_invalid() { + window.open('', 'my_window'); + } + function close() { my_window.close(); } @@ -32,6 +36,7 @@ + diff --git a/tests/end2end/features/backforward.feature b/tests/end2end/features/backforward.feature index 1b43cac4d..835ad9351 100644 --- a/tests/end2end/features/backforward.feature +++ b/tests/end2end/features/backforward.feature @@ -88,7 +88,6 @@ Feature: Going back and forward. - url: http://localhost:*/data/backforward/2.txt - url: http://localhost:*/data/backforward/3.txt - @qtwebengine_skip: Causes 'Ignoring invalid URL being added to history' sometimes? Scenario: Going back too much with count. Given I open data/backforward/1.txt When I open data/backforward/2.txt @@ -138,7 +137,6 @@ Feature: Going back and forward. When I run :forward Then the error "At end of history." should be shown - @qtwebengine_skip: Causes 'Ignoring invalid URL being added to history' sometimes? Scenario: Going forward too much with count. Given I open data/backforward/1.txt When I open data/backforward/2.txt diff --git a/tests/end2end/features/history.feature b/tests/end2end/features/history.feature index badb26aac..f6ea4c79f 100644 --- a/tests/end2end/features/history.feature +++ b/tests/end2end/features/history.feature @@ -48,6 +48,11 @@ Feature: Page history Then the history file should contain: http://localhost:(port)/status/404 Error loading page: http://localhost:(port)/status/404 + Scenario: History with invalid URL + When I open data/javascript/window_open.html + And I run :click-element id open-invalid + Then "Changing title for idx 1 to 'about:blank'" should be logged + Scenario: Clearing history When I open data/title.html And I run :history-clear From 21fe8f43f966d2bd02b41030dc3b7bf866b98909 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 15:32:12 +0200 Subject: [PATCH 20/34] tests: Fix handling of QUTE_BDD_WEBENGINE The tryfirst decorator somehow messed up handling of other pytest marks... Also we need to do this in the root conftest for it to work properly. --- tests/conftest.py | 17 ++++++++++++++++- tests/end2end/conftest.py | 12 ------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index a53223dff..e1ac19549 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -72,7 +72,7 @@ def _apply_platform_markers(item): item.add_marker(skipif_marker) -def pytest_collection_modifyitems(items): +def pytest_collection_modifyitems(config, items): """Handle custom markers. pytest hook called after collection has been performed. @@ -95,7 +95,12 @@ def pytest_collection_modifyitems(items): Reference: http://pytest.org/latest/plugins.html """ + remaining_items = [] + deselected_items = [] + for item in items: + deselected = False + if 'qapp' in getattr(item, 'fixturenames', ()): item.add_marker('gui') @@ -109,6 +114,8 @@ def pytest_collection_modifyitems(items): 'test_conftest.py'] if module_root_dir == 'end2end': item.add_marker(pytest.mark.end2end) + elif os.environ.get('QUTE_BDD_WEBENGINE', ''): + deselected = True _apply_platform_markers(item) if item.get_marker('xfail_norun'): @@ -116,6 +123,14 @@ def pytest_collection_modifyitems(items): if item.get_marker('flaky_once'): item.add_marker(pytest.mark.flaky(reruns=1)) + if deselected: + deselected_items.append(item) + else: + remaining_items.append(item) + + config.hook.pytest_deselected(items=deselected_items) + items[:] = remaining_items + def pytest_ignore_collect(path): """Ignore BDD tests if we're unable to run them.""" diff --git a/tests/end2end/conftest.py b/tests/end2end/conftest.py index c9f18e8c3..a3c8d903c 100644 --- a/tests/end2end/conftest.py +++ b/tests/end2end/conftest.py @@ -129,7 +129,6 @@ if not getattr(sys, 'frozen', False): return None -@pytest.hookimpl(trylast=True) def pytest_collection_modifyitems(config, items): """Apply @qtwebengine_* markers; skip unittests with QUTE_BDD_WEBENGINE.""" vercheck = qtutils.version_check @@ -160,14 +159,3 @@ def pytest_collection_modifyitems(config, items): text = prefix item.add_marker(pytest_mark(condition, reason=text, **marker.kwargs)) - - if os.environ.get('QUTE_BDD_WEBENGINE', ''): - remaining = [] - deselected = [] - for item in items: - if not item.get_marker('end2end'): - deselected.append(item) - else: - remaining.append(item) - config.hook.pytest_deselected(items=deselected) - items[:] = remaining From 6151a5faa7e929c6fd8bee7efe1a844fd8654d4e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 15:53:19 +0200 Subject: [PATCH 21/34] bdd: Fix handling of @qtweb{kit_engine}_* tags --- tests/end2end/conftest.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/tests/end2end/conftest.py b/tests/end2end/conftest.py index a3c8d903c..3f0eb702a 100644 --- a/tests/end2end/conftest.py +++ b/tests/end2end/conftest.py @@ -136,21 +136,23 @@ def pytest_collection_modifyitems(config, items): qtutils.version_check('5.7.1') or os.environ.get('QUTE_QTBUG54419_PATCHED', '')) - markers = { - 'qtwebengine_todo': ('QtWebEngine TODO', pytest.mark.xfail, - config.webengine), - 'qtwebengine_skip': ('Skipped with QtWebEngine', pytest.mark.skipif, - config.webengine), - 'qtwebkit_skip': ('Skipped with QtWebKit', pytest.mark.skipif, - not config.webengine), - 'qtwebengine_createWindow': ('Skipped because of QTBUG-54419', - pytest.mark.skipif, - not qtbug_54419_fixed and - config.webengine) - } + # Note the order here is important! Markers we add later override earlier + # markers, so we should apply the most general markers last. + markers = [ + ('qtwebengine_createWindow', 'Skipped because of QTBUG-54419', + pytest.mark.skipif, + not qtbug_54419_fixed and + config.webengine), + ('qtwebengine_todo', 'QtWebEngine TODO', pytest.mark.xfail, + config.webengine), + ('qtwebengine_skip', 'Skipped with QtWebEngine', pytest.mark.skipif, + config.webengine), + ('qtwebkit_skip', 'Skipped with QtWebKit', pytest.mark.skipif, + not config.webengine), + ] for item in items: - for name, (prefix, pytest_mark, condition) in markers.items(): + for name, prefix, pytest_mark, condition in markers: marker = item.get_marker(name) if marker: if marker.args: From c6142df3ec6366c5deac8a7bd4db9aaba91d554e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 15:53:31 +0200 Subject: [PATCH 22/34] bdd: Re-add test for #906 for QtWebEngine --- tests/end2end/features/javascript.feature | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/end2end/features/javascript.feature b/tests/end2end/features/javascript.feature index 3942e00e1..11288c13b 100644 --- a/tests/end2end/features/javascript.feature +++ b/tests/end2end/features/javascript.feature @@ -43,3 +43,16 @@ Feature: Javascript stuff And I run :tab-focus 2 And I run :click-element id close-twice Then "Requested to close * which does not exist!" should be logged + + @qtwebengine_createWindow @qtwebkit_skip + Scenario: Closing a JS window twice (issue 906) - qtwebengine + When I open about:blank + And I run :tab-only + And I open data/javascript/window_open.html in a new tab + And I run :click-element id open-normal + And I wait for "WebDialog requested, but we don't support that!" in the log + And I wait for "Changing title for idx 2 to 'about:blank'" in the log + And I run :tab-focus 2 + And I run :click-element id close-twice + And I wait for "Focus object changed: *" in the log + Then no crash should happen From baf6bb5514e83471b8b0073d47076cbca4a2ca71 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 16:00:23 +0200 Subject: [PATCH 23/34] Pass $QUTE_BDD_WEBENGINE to Docker correctly --- scripts/dev/ci/travis_run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/dev/ci/travis_run.sh b/scripts/dev/ci/travis_run.sh index 1cb8d2981..5b42d6057 100644 --- a/scripts/dev/ci/travis_run.sh +++ b/scripts/dev/ci/travis_run.sh @@ -1,7 +1,7 @@ #!/bin/bash if [[ $DOCKER ]]; then - docker run --privileged -v $PWD:/outside qutebrowser/travis:$DOCKER + docker run --privileged -v $PWD:/outside -e QUTE_BDD_WEBENGINE=$QUTE_BDD_WEBENGINE qutebrowser/travis:$DOCKER else args=() [[ $TESTENV == docs ]] && args=('--no-authors') From ba718a2b9d82cd03776db00ae4252fbe258d0cab Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 16:19:22 +0200 Subject: [PATCH 24/34] end2end: Improve output when subprocess exits We don't really have the "infrastructure" set up yet to have proper log output at that point, but we can always just show the log output as part of the exception. --- tests/end2end/fixtures/testprocess.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/end2end/fixtures/testprocess.py b/tests/end2end/fixtures/testprocess.py index 86a883aea..c8868e2a5 100644 --- a/tests/end2end/fixtures/testprocess.py +++ b/tests/end2end/fixtures/testprocess.py @@ -234,7 +234,7 @@ class Process(QObject): if not self.is_running(): # _start ensures it actually started, but it might quit shortly # afterwards - raise ProcessExited() + raise ProcessExited('\n' + _render_log(self.captured_log)) if blocker.signal_triggered: self._after_start() From 61270b8f92b68d0db3b3f1343240632d0e437376 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 16:21:30 +0200 Subject: [PATCH 25/34] Fix lint --- qutebrowser/browser/webengine/webview.py | 4 ++-- tests/end2end/conftest.py | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/qutebrowser/browser/webengine/webview.py b/qutebrowser/browser/webengine/webview.py index af1b5c0c3..daa90f85a 100644 --- a/qutebrowser/browser/webengine/webview.py +++ b/qutebrowser/browser/webengine/webview.py @@ -67,8 +67,8 @@ class WebEngineView(QWebEngineView): # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-54419 vercheck = qtutils.version_check qtbug_54419_fixed = ((vercheck('5.6.2') and not vercheck('5.7.0')) or - qtutils.version_check('5.7.1') or - os.environ.get('QUTE_QTBUG54419_PATCHED', '')) + qtutils.version_check('5.7.1') or + os.environ.get('QUTE_QTBUG54419_PATCHED', '')) if not qtbug_54419_fixed: message.error(self._win_id, "Qt 5.6.2/5.7.1 or newer is required " "to open new tabs via JS!") diff --git a/tests/end2end/conftest.py b/tests/end2end/conftest.py index 3f0eb702a..336d22679 100644 --- a/tests/end2end/conftest.py +++ b/tests/end2end/conftest.py @@ -100,6 +100,7 @@ def _get_version_tag(tag): else: raise ValueError("Invalid package {!r}".format(package)) + def _get_backend_tag(tag): """Handle a @qtwebengine_*/@qtwebkit_skip tag.""" pytest_marks = { @@ -140,15 +141,13 @@ def pytest_collection_modifyitems(config, items): # markers, so we should apply the most general markers last. markers = [ ('qtwebengine_createWindow', 'Skipped because of QTBUG-54419', - pytest.mark.skipif, - not qtbug_54419_fixed and - config.webengine), + pytest.mark.skipif, not qtbug_54419_fixed and config.webengine), ('qtwebengine_todo', 'QtWebEngine TODO', pytest.mark.xfail, - config.webengine), + config.webengine), ('qtwebengine_skip', 'Skipped with QtWebEngine', pytest.mark.skipif, - config.webengine), + config.webengine), ('qtwebkit_skip', 'Skipped with QtWebKit', pytest.mark.skipif, - not config.webengine), + not config.webengine), ] for item in items: From a94cf9084275458b96eee9921a164352a04c2a28 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 16:30:23 +0200 Subject: [PATCH 26/34] Fail early when running WebEngine tests without it --- tests/conftest.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index e1ac19549..ddfef250e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -159,6 +159,9 @@ def pytest_configure(config): webengine_arg = config.getoption('--qute-bdd-webengine') webengine_env = os.environ.get('QUTE_BDD_WEBENGINE', '') config.webengine = bool(webengine_arg or webengine_env) + # Fail early if QtWebEngine is not available + if config.webengine: + import PyQt5.QtWebEngineWidgets @pytest.fixture(scope='session', autouse=True) From bdc1885f6dae934753cf2e61165ead92fb900ae6 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 16:48:21 +0200 Subject: [PATCH 27/34] Add missing @qtwebengine_createWindow marker --- tests/end2end/features/history.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/end2end/features/history.feature b/tests/end2end/features/history.feature index f6ea4c79f..165bdd792 100644 --- a/tests/end2end/features/history.feature +++ b/tests/end2end/features/history.feature @@ -48,6 +48,7 @@ Feature: Page history Then the history file should contain: http://localhost:(port)/status/404 Error loading page: http://localhost:(port)/status/404 + @qtwebengine_createWindow Scenario: History with invalid URL When I open data/javascript/window_open.html And I run :click-element id open-invalid From f26ce3a8ffaf2f1acad4f58aa592fab587f336a6 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 16:48:38 +0200 Subject: [PATCH 28/34] Only add BDD markers if condition matches This should make multiple markers on the same test work correctly. --- tests/end2end/conftest.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/end2end/conftest.py b/tests/end2end/conftest.py index 336d22679..09ca18f28 100644 --- a/tests/end2end/conftest.py +++ b/tests/end2end/conftest.py @@ -137,8 +137,6 @@ def pytest_collection_modifyitems(config, items): qtutils.version_check('5.7.1') or os.environ.get('QUTE_QTBUG54419_PATCHED', '')) - # Note the order here is important! Markers we add later override earlier - # markers, so we should apply the most general markers last. markers = [ ('qtwebengine_createWindow', 'Skipped because of QTBUG-54419', pytest.mark.skipif, not qtbug_54419_fixed and config.webengine), @@ -153,7 +151,7 @@ def pytest_collection_modifyitems(config, items): for item in items: for name, prefix, pytest_mark, condition in markers: marker = item.get_marker(name) - if marker: + if marker and condition: if marker.args: text = '{}: {}'.format(prefix, marker.args[0]) else: From 22be46e7d36ae6fc0b2e0d5dd820dddba218bd7e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 16:53:27 +0200 Subject: [PATCH 29/34] Skip flaky QtWebEngine test --- tests/end2end/features/misc.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/end2end/features/misc.feature b/tests/end2end/features/misc.feature index a7fc0bf80..1c5a25bf4 100644 --- a/tests/end2end/features/misc.feature +++ b/tests/end2end/features/misc.feature @@ -620,6 +620,7 @@ Feature: Various utility commands. - data/click_element.html - data/hello.txt (active) + @qtwebengine_skip: Flaky because scrolling happens async Scenario: Clicking an element which is out of view When I open data/scroll/simple.html And I run :scroll-page 0 1 From d2a3541d6ee140f8c4990a94a4d236cdfc4a964d Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 16:54:31 +0200 Subject: [PATCH 30/34] Make pylint shut up --- tests/conftest.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index ddfef250e..71018fd1d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -160,8 +160,10 @@ def pytest_configure(config): webengine_env = os.environ.get('QUTE_BDD_WEBENGINE', '') config.webengine = bool(webengine_arg or webengine_env) # Fail early if QtWebEngine is not available + # pylint: disable=no-name-in-module,unused-variable,useless-suppression if config.webengine: import PyQt5.QtWebEngineWidgets + # pylint: enable=no-name-in-module,unused-variable,useless-suppression @pytest.fixture(scope='session', autouse=True) From 308f38ab34f87108d326a3c3a0d229419dd29a5a Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 17:09:14 +0200 Subject: [PATCH 31/34] Rename javascript-can-open-windows setting Fixes #1896. --- CHANGELOG.asciidoc | 2 ++ doc/help/settings.asciidoc | 8 ++++---- qutebrowser/browser/webengine/webenginesettings.py | 2 +- qutebrowser/browser/webkit/webkitsettings.py | 2 +- qutebrowser/config/config.py | 2 ++ qutebrowser/config/configdata.py | 5 +++-- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 07a23092e..5dfaa0086 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -107,6 +107,8 @@ Changed - Lots of improvements to and bugfixes for the QtWebEngine backend, such as working hints. However, using qutebrowser directly from git is still advised when using `--backend webengine`. +- `content -> javascript-can-open-windows` got renamed to + `javascript-can-open-windows-automatically`. Deprecated ~~~~~~~~~~ diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index f3a6e29f5..6f4d58868 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -157,7 +157,7 @@ |<>|Enable or disable hyperlink auditing (). |<>|Allow websites to request geolocations. |<>|Allow websites to show notifications. -|<>|Whether JavaScript programs can open new windows. +|<>|Whether JavaScript programs can open new windows without user interaction. |<>|Whether JavaScript programs can close windows. |<>|Whether JavaScript programs can read or write to the clipboard. |<>|Whether all javascript prompts should be ignored. @@ -1427,9 +1427,9 @@ Valid values: Default: +pass:[ask]+ -[[content-javascript-can-open-windows]] -=== javascript-can-open-windows -Whether JavaScript programs can open new windows. +[[content-javascript-can-open-windows-automatically]] +=== javascript-can-open-windows-automatically +Whether JavaScript programs can open new windows without user interaction. Valid values: diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py index 5c93bae49..a8ca17149 100644 --- a/qutebrowser/browser/webengine/webenginesettings.py +++ b/qutebrowser/browser/webengine/webenginesettings.py @@ -112,7 +112,7 @@ MAPPINGS = { Attribute(QWebEngineSettings.AutoLoadImages), 'allow-javascript': Attribute(QWebEngineSettings.JavascriptEnabled), - 'javascript-can-open-windows': + 'javascript-can-open-windows-automatically': Attribute(QWebEngineSettings.JavascriptCanOpenWindows), 'javascript-can-access-clipboard': Attribute(QWebEngineSettings.JavascriptCanAccessClipboard), diff --git a/qutebrowser/browser/webkit/webkitsettings.py b/qutebrowser/browser/webkit/webkitsettings.py index d5af1dfd9..911a9709b 100644 --- a/qutebrowser/browser/webkit/webkitsettings.py +++ b/qutebrowser/browser/webkit/webkitsettings.py @@ -118,7 +118,7 @@ MAPPINGS = { Attribute(QWebSettings.AutoLoadImages), 'allow-javascript': Attribute(QWebSettings.JavascriptEnabled), - 'javascript-can-open-windows': + 'javascript-can-open-windows-automatically': Attribute(QWebSettings.JavascriptCanOpenWindows), 'javascript-can-close-windows': Attribute(QWebSettings.JavascriptCanCloseWindows), diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 636e3a4d0..e6aa3db7c 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -385,6 +385,8 @@ class ConfigManager(QObject): ('completion', 'history-length'): 'cmd-history-max-items', ('colors', 'downloads.fg'): 'downloads.fg.start', ('ui', 'show-keyhints'): 'keyhint-blacklist', + ('content', 'javascript-can-open-windows'): + 'javascript-can-open-windows-automatically', } DELETED_OPTIONS = [ ('colors', 'tab.separator'), diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index 89aee870f..533b354f8 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -808,9 +808,10 @@ def data(readonly=False): SettingValue(typ.BoolAsk(), 'ask'), "Allow websites to show notifications."), - ('javascript-can-open-windows', + ('javascript-can-open-windows-automatically', SettingValue(typ.Bool(), 'false'), - "Whether JavaScript programs can open new windows."), + "Whether JavaScript programs can open new windows without user " + "interaction."), ('javascript-can-close-windows', SettingValue(typ.Bool(), 'false', From 525d5ce9229a0d4577349840b8f996e13db0861c Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 17:10:30 +0200 Subject: [PATCH 32/34] Mark another flaky test with @qtwebengine_skip --- tests/end2end/features/hints.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/end2end/features/hints.feature b/tests/end2end/features/hints.feature index 5d0d0c88e..da0c1b603 100644 --- a/tests/end2end/features/hints.feature +++ b/tests/end2end/features/hints.feature @@ -9,6 +9,7 @@ Feature: Using hints And I hint with args "links normal" and follow xyz Then the error "No hint xyz!" should be shown + @qtwebengine_skip: Flaky because scrolling happens async Scenario: Following a link after scrolling down When I open data/scroll/simple.html And I run :hint links normal From 0b3656c44655b160ef2d409fbe44c67c9978d2bc Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 17:25:41 +0200 Subject: [PATCH 33/34] tests: Don't wait for nonexistant log message --- tests/end2end/features/javascript.feature | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/end2end/features/javascript.feature b/tests/end2end/features/javascript.feature index 11288c13b..1d716bb95 100644 --- a/tests/end2end/features/javascript.feature +++ b/tests/end2end/features/javascript.feature @@ -50,7 +50,6 @@ Feature: Javascript stuff And I run :tab-only And I open data/javascript/window_open.html in a new tab And I run :click-element id open-normal - And I wait for "WebDialog requested, but we don't support that!" in the log And I wait for "Changing title for idx 2 to 'about:blank'" in the log And I run :tab-focus 2 And I run :click-element id close-twice From 59300cb71e8417070b5e3225f6b10ff7b8337393 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 5 Sep 2016 17:25:52 +0200 Subject: [PATCH 34/34] Add tests for js-can-open-windows-automatically --- tests/end2end/features/javascript.feature | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/end2end/features/javascript.feature b/tests/end2end/features/javascript.feature index 1d716bb95..a86d88e20 100644 --- a/tests/end2end/features/javascript.feature +++ b/tests/end2end/features/javascript.feature @@ -55,3 +55,19 @@ Feature: Javascript stuff And I run :click-element id close-twice And I wait for "Focus object changed: *" in the log Then no crash should happen + + @qtwebengine_createWindow + Scenario: Opening window without user interaction with javascript-can-open-windows-automatically set to true + When I open data/hello.txt + And I set content -> javascript-can-open-windows-automatically to true + And I run :tab-only + And I run :jseval if (window.open('about:blank')) { console.log('window opened'); } else { console.log('error while opening window'); } + Then the javascript message "window opened" should be logged + + @qtwebengine_createWindow + Scenario: Opening window without user interaction with javascript-can-open-windows-automatically set to false + When I open data/hello.txt + And I set content -> javascript-can-open-windows-automatically to false + And I run :tab-only + And I run :jseval if (window.open('about:blank')) { console.log('window opened'); } else { console.log('error while opening window'); } + Then the javascript message "error while opening window" should be logged