diff options
author | Lembrun <amadeusk7@free.fr> | 2021-03-09 21:08:39 +0100 |
---|---|---|
committer | Lembrun <amadeusk7@free.fr> | 2021-03-09 21:08:39 +0100 |
commit | 6d9c28ce10832aa727de1a326d9459a035ff3aba (patch) | |
tree | 86215f5abcfcbc6253f484f55ab77af991d3eb34 /tests | |
parent | 8130c0316a737ddea1624351fa60b1812d0d2015 (diff) | |
parent | 0a38fff4c675b384289728a4d45f9c1fe1f9d4fc (diff) | |
download | qutebrowser-6d9c28ce10832aa727de1a326d9459a035ff3aba.tar.gz qutebrowser-6d9c28ce10832aa727de1a326d9459a035ff3aba.zip |
Merge branch 'master' into Add-utils/resources.py
Diffstat (limited to 'tests')
-rw-r--r-- | tests/conftest.py | 6 | ||||
-rw-r--r-- | tests/end2end/features/misc.feature | 12 | ||||
-rw-r--r-- | tests/end2end/features/qutescheme.feature | 2 | ||||
-rw-r--r-- | tests/unit/browser/webengine/test_webenginetab.py | 94 | ||||
-rw-r--r-- | tests/unit/javascript/conftest.py | 7 | ||||
-rw-r--r-- | tests/unit/javascript/test_greasemonkey.py | 189 |
6 files changed, 158 insertions, 152 deletions
diff --git a/tests/conftest.py b/tests/conftest.py index ea7381a2f..ee945ac4c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -109,12 +109,6 @@ def _apply_platform_markers(config, item): pytest.mark.skipif, sys.getfilesystemencoding() == 'ascii', "Skipped because of ASCII locale"), - - ('qtwebkit6021_xfail', - pytest.mark.xfail, - version.qWebKitVersion and # type: ignore[unreachable] - version.qWebKitVersion() == '602.1', - "Broken on WebKit 602.1") ] for searched_marker, new_marker_kind, condition, default_reason in markers: diff --git a/tests/end2end/features/misc.feature b/tests/end2end/features/misc.feature index 351135fab..e6a02e038 100644 --- a/tests/end2end/features/misc.feature +++ b/tests/end2end/features/misc.feature @@ -140,7 +140,7 @@ Feature: Various utility commands. Scenario: :jseval --file using a file that doesn't exist as js-code When I run :jseval --file /nonexistentfile - Then the error "[Errno 2] No such file or directory: '/nonexistentfile'" should be shown + Then the error "[Errno 2] *: '/nonexistentfile'" should be shown And "No output or error" should not be logged # :debug-webaction @@ -528,13 +528,13 @@ Feature: Various utility commands. @qtwebkit_skip @no_invalid_lines @posix Scenario: Renderer crash When I run :open -t chrome://crash - Then "Renderer process crashed" should be logged + Then "Renderer process crashed (status *)" should be logged And "* 'Error loading chrome://crash/'" should be logged @qtwebkit_skip @no_invalid_lines @flaky Scenario: Renderer kill When I run :open -t chrome://kill - Then "Renderer process was killed" should be logged + Then "Renderer process was killed (status *)" should be logged And "* 'Error loading chrome://kill/'" should be logged # https://github.com/qutebrowser/qutebrowser/issues/2290 @@ -544,7 +544,7 @@ Feature: Various utility commands. And I open data/numbers/1.txt And I open data/numbers/2.txt in a new tab And I run :open chrome://kill - And I wait for "Renderer process was killed" in the log + And I wait for "Renderer process was killed (status *)" in the log And I open data/numbers/3.txt Then no crash should happen @@ -554,11 +554,11 @@ Feature: Various utility commands. When I open data/crashers/webrtc.html in a new tab And I run :reload And I wait until data/crashers/webrtc.html is loaded - Then "Renderer process crashed" should not be logged + Then "Renderer process crashed (status *)" should not be logged Scenario: InstalledApps crash When I open data/crashers/installedapp.html in a new tab - Then "Renderer process was killed" should not be logged + Then "Renderer process was killed (status *)" should not be logged ## Other diff --git a/tests/end2end/features/qutescheme.feature b/tests/end2end/features/qutescheme.feature index 286f8f80a..1424bbf09 100644 --- a/tests/end2end/features/qutescheme.feature +++ b/tests/end2end/features/qutescheme.feature @@ -215,7 +215,7 @@ Feature: Special qute:// pages Scenario: Running :pyeval --file using a non existing file When I run :debug-pyeval --file nonexistentfile - Then the error "[Errno 2] No such file or directory: 'nonexistentfile'" should be shown + Then the error "[Errno 2] *: 'nonexistentfile'" should be shown Scenario: Running :pyeval with --quiet When I run :debug-pyeval --quiet 1+1 diff --git a/tests/unit/browser/webengine/test_webenginetab.py b/tests/unit/browser/webengine/test_webenginetab.py index 7827c379b..156f7d26f 100644 --- a/tests/unit/browser/webengine/test_webenginetab.py +++ b/tests/unit/browser/webengine/test_webenginetab.py @@ -20,6 +20,7 @@ """Test webenginetab.""" import logging +import textwrap import pytest QtWebEngineWidgets = pytest.importorskip("PyQt5.QtWebEngineWidgets") @@ -35,15 +36,38 @@ webenginetab = pytest.importorskip( pytestmark = pytest.mark.usefixtures('greasemonkey_manager') +class ScriptsHelper: + + """Helper to get the processed (usually Greasemonkey) scripts.""" + + def __init__(self, tab): + self._tab = tab + + def get_scripts(self, prefix='GM-'): + return [ + s for s in self._tab._widget.page().scripts().toList() + if s.name().startswith(prefix) + ] + + def get_script(self): + scripts = self.get_scripts() + assert len(scripts) == 1 + return scripts[0] + + def inject(self, scripts): + self._tab._scripts._inject_greasemonkey_scripts(scripts) + return self.get_scripts() + + class TestWebengineScripts: """Test the _WebEngineScripts utility class.""" @pytest.fixture - def webengine_scripts(self, webengine_tab): - return webengine_tab._scripts + def scripts_helper(self, webengine_tab): + return ScriptsHelper(webengine_tab) - def test_greasemonkey_undefined_world(self, webengine_scripts, caplog): + def test_greasemonkey_undefined_world(self, scripts_helper, caplog): """Make sure scripts with non-existent worlds are rejected.""" scripts = [ greasemonkey.GreasemonkeyScript( @@ -51,18 +75,16 @@ class TestWebengineScripts: ] with caplog.at_level(logging.ERROR, 'greasemonkey'): - webengine_scripts._inject_greasemonkey_scripts(scripts) + injected = scripts_helper.inject(scripts) assert len(caplog.records) == 1 msg = caplog.messages[0] assert "has invalid value for '@qute-js-world': Mars" in msg - collection = webengine_scripts._widget.page().scripts().toList() - assert not any(script.name().startswith('GM-') - for script in collection) + + assert not injected @pytest.mark.parametrize("worldid", [-1, 257]) - def test_greasemonkey_out_of_range_world(self, worldid, webengine_scripts, - caplog): + def test_greasemonkey_out_of_range_world(self, worldid, scripts_helper, caplog): """Make sure scripts with out-of-range worlds are rejected.""" scripts = [ greasemonkey.GreasemonkeyScript( @@ -70,19 +92,18 @@ class TestWebengineScripts: ] with caplog.at_level(logging.ERROR, 'greasemonkey'): - webengine_scripts._inject_greasemonkey_scripts(scripts) + injected = scripts_helper.inject(scripts) assert len(caplog.records) == 1 msg = caplog.messages[0] assert "has invalid value for '@qute-js-world': " in msg assert "should be between 0 and" in msg - collection = webengine_scripts._widget.page().scripts().toList() - assert not any(script.name().startswith('GM-') - for script in collection) + + assert not injected @pytest.mark.parametrize("worldid", [0, 10]) def test_greasemonkey_good_worlds_are_passed(self, worldid, - webengine_scripts, caplog): + scripts_helper, caplog): """Make sure scripts with valid worlds have it set.""" scripts = [ greasemonkey.GreasemonkeyScript( @@ -91,13 +112,11 @@ class TestWebengineScripts: ] with caplog.at_level(logging.ERROR, 'greasemonkey'): - webengine_scripts._inject_greasemonkey_scripts(scripts) + scripts_helper.inject(scripts) - collection = webengine_scripts._widget.page().scripts() - assert collection.toList()[-1].worldId() == worldid + assert scripts_helper.get_script().worldId() == worldid - def test_greasemonkey_document_end_workaround(self, monkeypatch, - webengine_scripts): + def test_greasemonkey_document_end_workaround(self, monkeypatch, scripts_helper): """Make sure document-end is forced when needed.""" monkeypatch.setattr(greasemonkey.objects, 'backend', usertypes.Backend.QtWebEngine) @@ -109,13 +128,42 @@ class TestWebengineScripts: ('run-at', 'document-start'), ], None) ] + scripts_helper.inject(scripts) - webengine_scripts._inject_greasemonkey_scripts(scripts) - - collection = webengine_scripts._widget.page().scripts() - script = collection.toList()[-1] + script = scripts_helper.get_script() assert script.injectionPoint() == QWebEngineScript.DocumentReady + @pytest.mark.parametrize('run_at, expected', [ + # UserScript::DocumentElementCreation + ('document-start', QWebEngineScript.DocumentCreation), + # UserScript::DocumentLoadFinished + ('document-end', QWebEngineScript.DocumentReady), + # UserScript::AfterLoad + ('document-idle', QWebEngineScript.Deferred), + # default according to https://wiki.greasespot.net/Metadata_Block#.40run-at + (None, QWebEngineScript.DocumentReady), + ]) + def test_greasemonkey_run_at_values(self, scripts_helper, run_at, expected): + if run_at is None: + script = """ + // ==UserScript== + // @name qutebrowser test userscript + // ==/UserScript== + """ + else: + script = f""" + // ==UserScript== + // @name qutebrowser test userscript + // @run-at {run_at} + // ==/UserScript== + """ + + script = textwrap.dedent(script.lstrip('\n')) + scripts = [greasemonkey.GreasemonkeyScript.parse(script)] + scripts_helper.inject(scripts) + + assert scripts_helper.get_script().injectionPoint() == expected + def test_notification_permission_workaround(): """Make sure the value for QWebEnginePage::Notifications is correct.""" diff --git a/tests/unit/javascript/conftest.py b/tests/unit/javascript/conftest.py index 47884687d..85d5ebe0a 100644 --- a/tests/unit/javascript/conftest.py +++ b/tests/unit/javascript/conftest.py @@ -28,6 +28,7 @@ import jinja2 from PyQt5.QtCore import QUrl import qutebrowser +from qutebrowser.utils import usertypes class JSTester: @@ -113,7 +114,7 @@ class JSTester: source = f.read() self.run(source, expected) - def run(self, source: str, expected, world=None) -> None: + def run(self, source: str, expected=usertypes.UNSET, world=None) -> None: """Run the given javascript source. Args: @@ -123,7 +124,9 @@ class JSTester: """ with self.qtbot.wait_callback() as callback: self.tab.run_js_async(source, callback, world=world) - callback.assert_called_with(expected) + + if expected is not usertypes.UNSET: + callback.assert_called_with(expected) @pytest.fixture diff --git a/tests/unit/javascript/test_greasemonkey.py b/tests/unit/javascript/test_greasemonkey.py index c28b9c8f7..3a3ea0294 100644 --- a/tests/unit/javascript/test_greasemonkey.py +++ b/tests/unit/javascript/test_greasemonkey.py @@ -25,7 +25,7 @@ import pytest import py.path # pylint: disable=no-name-in-module from PyQt5.QtCore import QUrl -from qutebrowser.utils import usertypes +from qutebrowser.utils import usertypes, version from qutebrowser.browser import greasemonkey from qutebrowser.misc import objects @@ -77,8 +77,7 @@ def test_get_scripts_by_url(url, expected_matches): gm_manager = greasemonkey.GreasemonkeyManager() scripts = gm_manager.scripts_for(QUrl(url)) - assert (len(scripts.start + scripts.end + scripts.idle) == - expected_matches) + assert len(scripts.start + scripts.end + scripts.idle) == expected_matches @pytest.mark.parametrize("url, expected_matches", [ @@ -102,8 +101,7 @@ def test_regex_includes_scripts_for(url, expected_matches): gm_manager = greasemonkey.GreasemonkeyManager() scripts = gm_manager.scripts_for(QUrl(url)) - assert (len(scripts.start + scripts.end + scripts.idle) == - expected_matches) + assert len(scripts.start + scripts.end + scripts.idle) == expected_matches def test_no_metadata(caplog): @@ -229,124 +227,87 @@ def test_required_scripts_are_included(download_stub, tmpdir): assert scripts[0].excludes -class TestWindowIsolation: +def test_window_isolation(js_tester, request): """Check that greasemonkey scripts get a shadowed global scope.""" + # Change something in the global scope + setup_script = "window.$ = 'global'" - @pytest.fixture - def setup(self): - # pylint: disable=attribute-defined-outside-init - class SetupData: - pass - ret = SetupData() - - # Change something in the global scope - ret.setup_script = "window.$ = 'global'" - - # Greasemonkey script to report back on its scope. - test_script = greasemonkey.GreasemonkeyScript.parse( - textwrap.dedent(""" - // ==UserScript== - // @name scopetest - // ==/UserScript== - // Check the thing the page set is set to the expected type - result.push(window.$); - result.push($); - // Now overwrite it - window.$ = 'shadowed'; - // And check everything is how the script would expect it to be - // after just writing to the "global" scope - result.push(window.$); - result.push($); - """) - ) - - # The compiled source of that scripts with some additional setup - # bookending it. - ret.test_script = "\n".join([ - """ - const result = []; - """, - test_script.code(), - """ - // Now check that the actual global scope has - // not been overwritten + # Greasemonkey script to report back on its scope. + test_gm_script = greasemonkey.GreasemonkeyScript.parse( + textwrap.dedent(""" + // ==UserScript== + // @name scopetest + // ==/UserScript== + // Check the thing the page set is set to the expected type + result.push(window.$); + result.push($); + // Now overwrite it + window.$ = 'shadowed'; + // And check everything is how the script would expect it to be + // after just writing to the "global" scope result.push(window.$); result.push($); - // And return our findings - result; - """ - ]) + """) + ) + + # The compiled source of that scripts with some additional setup + # bookending it. + test_script = "\n".join([ + """ + const result = []; + """, + test_gm_script.code(), + """ + // Now check that the actual global scope has + // not been overwritten + result.push(window.$); + result.push($); + // And return our findings + result; + """ + ]) - # What we expect the script to report back. - ret.expected = ["global", "global", - "shadowed", "shadowed", - "global", "global"] - return ret + # What we expect the script to report back. + expected = ["global", "global", "shadowed", "shadowed", "global", "global"] - def test_webengine(self, qtbot, webengineview, setup): - page = webengineview.page() - page.runJavaScript(setup.setup_script) + # The JSCore in 602.1 doesn't fully support Proxy. + xfail = False + if (js_tester.tab.backend == usertypes.Backend.QtWebKit and + version.qWebKitVersion() == '602.1'): + expected[-1] = 'shadowed' + expected[-2] = 'shadowed' + xfail = True - with qtbot.wait_callback() as callback: - page.runJavaScript(setup.test_script, callback) - callback.assert_called_with(setup.expected) + js_tester.run(setup_script) + js_tester.run(test_script, expected=expected) - # The JSCore in 602.1 doesn't fully support Proxy. - @pytest.mark.qtwebkit6021_xfail - def test_webkit(self, webview, setup): - elem = webview.page().mainFrame().documentElement() - elem.evaluateJavaScript(setup.setup_script) - result = elem.evaluateJavaScript(setup.test_script) - assert result == setup.expected + if xfail: + pytest.xfail("Broken on WebKit 602.1") -class TestSharedWindowProxy: +def test_shared_window_proxy(js_tester): """Check that all scripts have access to the same window proxy.""" + # Greasemonkey script to add a property to the window proxy. + test_script_a = greasemonkey.GreasemonkeyScript.parse( + textwrap.dedent(""" + // ==UserScript== + // @name a + // ==/UserScript== + // Set a value from script a + window.$ = 'test'; + """) + ).code() + + # Greasemonkey script to retrieve a property from the window proxy. + test_script_b = greasemonkey.GreasemonkeyScript.parse( + textwrap.dedent(""" + // ==UserScript== + // @name b + // ==/UserScript== + // Check that the value is accessible from script b + return [window.$, $]; + """) + ).code() - @pytest.fixture - def setup(self): - # pylint: disable=attribute-defined-outside-init - class SetupData: - pass - ret = SetupData() - - # Greasemonkey script to add a property to the window proxy. - ret.test_script_a = greasemonkey.GreasemonkeyScript.parse( - textwrap.dedent(""" - // ==UserScript== - // @name a - // ==/UserScript== - // Set a value from script a - window.$ = 'test'; - """) - ).code() - - # Greasemonkey script to retrieve a property from the window proxy. - ret.test_script_b = greasemonkey.GreasemonkeyScript.parse( - textwrap.dedent(""" - // ==UserScript== - // @name b - // ==/UserScript== - // Check that the value is accessible from script b - return [window.$, $]; - """) - ).code() - - # What we expect the script to report back. - ret.expected = ["test", "test"] - return ret - - def test_webengine(self, qtbot, webengineview, setup): - page = webengineview.page() - - with qtbot.wait_callback() as callback: - page.runJavaScript(setup.test_script_a, callback) - with qtbot.wait_callback() as callback: - page.runJavaScript(setup.test_script_b, callback) - callback.assert_called_with(setup.expected) - - def test_webkit(self, webview, setup): - elem = webview.page().mainFrame().documentElement() - elem.evaluateJavaScript(setup.test_script_a) - result = elem.evaluateJavaScript(setup.test_script_b) - assert result == setup.expected + js_tester.run(test_script_a) + js_tester.run(test_script_b, expected=["test", "test"]) |