1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
# SPDX-FileCopyrightText: Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# SPDX-License-Identifier: GPL-3.0-or-later
"""pytest conftest file for javascript tests."""
import pathlib
import pytest
import jinja2
from qutebrowser.qt.core import QUrl
import qutebrowser
from qutebrowser.utils import usertypes
JS_DIR = pathlib.Path(__file__).parent
class JSTester:
"""Common subclass providing basic functionality for all JS testers.
Attributes:
tab: The tab object which is used.
qtbot: The QtBot fixture from pytest-qt.
_jinja_env: The jinja2 environment used to get templates.
"""
def __init__(self, tab, qtbot, config_stub):
self.tab = tab
self.qtbot = qtbot
loader = jinja2.FileSystemLoader(JS_DIR)
self._jinja_env = jinja2.Environment(loader=loader, autoescape=True)
# Make sure error logging via JS fails tests
config_stub.val.content.javascript.log = {
'info': 'info',
'error': 'error',
'unknown': 'error',
'warning': 'error'
}
def load(self, path, base_url=QUrl(), **kwargs):
"""Load and display the given jinja test data.
Args:
path: The path to the test file, relative to the javascript/
folder.
base_url: The url to pass to set_html.
**kwargs: Passed to jinja's template.render().
"""
template = self._jinja_env.get_template(path)
try:
with self.qtbot.wait_signal(self.tab.load_finished,
timeout=2000) as blocker:
self.tab.set_html(template.render(**kwargs), base_url=base_url)
except self.qtbot.TimeoutError:
# Sometimes this fails for some odd reason on macOS, let's just try
# again.
print("Trying to load page again...")
with self.qtbot.wait_signal(self.tab.load_finished,
timeout=2000) as blocker:
self.tab.set_html(template.render(**kwargs), base_url=base_url)
assert blocker.args == [True]
def load_file(self, path: str, force: bool = False):
"""Load a file from disk.
Args:
path: The string path from disk to load (relative to this file)
force: Whether to force loading even if the file is invalid.
"""
self.load_url(QUrl.fromLocalFile(
str(JS_DIR / path)), force)
def load_url(self, url: QUrl, force: bool = False):
"""Load a given QUrl.
Args:
url: The QUrl to load.
force: Whether to force loading even if the file is invalid.
"""
with self.qtbot.wait_signal(self.tab.load_finished,
timeout=2000) as blocker:
self.tab.load_url(url)
if not force:
assert blocker.args == [True]
def run_file(self, path: str, expected=None) -> None:
"""Run a javascript file.
Args:
path: The path to the JS file, relative to the qutebrowser package.
expected: The value expected return from the javascript execution
"""
base_path = pathlib.Path(qutebrowser.__file__).resolve().parent
source = (base_path / path).read_text(encoding='utf-8')
self.run(source, expected)
def run(self, source: str, expected=usertypes.UNSET, world=None) -> None:
"""Run the given javascript source.
Args:
source: The source to run as a string.
expected: The value expected return from the javascript execution
world: The scope the javascript will run in
"""
with self.qtbot.wait_callback() as callback:
self.tab.run_js_async(source, callback, world=world)
if expected is not usertypes.UNSET:
callback.assert_called_with(expected)
@pytest.fixture
def js_tester_webkit(webkit_tab, qtbot, config_stub):
"""Fixture to test javascript snippets in webkit."""
return JSTester(webkit_tab, qtbot, config_stub)
@pytest.fixture
def js_tester_webengine(webengine_tab, qtbot, config_stub):
"""Fixture to test javascript snippets in webengine."""
return JSTester(webengine_tab, qtbot, config_stub)
@pytest.fixture
def js_tester(web_tab, qtbot, config_stub):
"""Fixture to test javascript snippets with both backends."""
return JSTester(web_tab, qtbot, config_stub)
|