summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorLembrun <amadeusk7@free.fr>2021-03-11 19:11:06 +0100
committerLembrun <amadeusk7@free.fr>2021-03-11 19:11:06 +0100
commit3707234c3ae95c9ee7cc0721b668a5e96a9cfa6f (patch)
tree60c027d9fa59c1c24537fcd4284458e0c1751006 /tests
parentef5ba1a0360b39f9eff027fbdc57f363597c3c3b (diff)
parent40054ac944a988e02ca8f3de414581f1e77688d8 (diff)
downloadqutebrowser-3707234c3ae95c9ee7cc0721b668a5e96a9cfa6f.tar.gz
qutebrowser-3707234c3ae95c9ee7cc0721b668a5e96a9cfa6f.zip
Merge branch 'master' into pathlib-/unit/commands
Diffstat (limited to 'tests')
-rw-r--r--tests/end2end/test_invocations.py2
-rw-r--r--tests/unit/browser/test_pdfjs.py2
-rw-r--r--tests/unit/browser/test_qutescheme.py13
-rw-r--r--tests/unit/config/test_qtargs.py16
-rw-r--r--tests/unit/config/test_qtargs_locale_workaround.py11
-rw-r--r--tests/unit/utils/test_jinja.py6
-rw-r--r--tests/unit/utils/test_resources.py146
-rw-r--r--tests/unit/utils/test_utils.py222
-rw-r--r--tests/unit/utils/test_version.py76
9 files changed, 341 insertions, 153 deletions
diff --git a/tests/end2end/test_invocations.py b/tests/end2end/test_invocations.py
index f3d74d1f0..38e40f9b7 100644
--- a/tests/end2end/test_invocations.py
+++ b/tests/end2end/test_invocations.py
@@ -657,7 +657,7 @@ def test_dark_mode(webengine_versions, quteproc_new, request,
quteproc_new.start(args)
ver = webengine_versions.webengine
- minor_version = f'{ver.majorVersion()}.{ver.minorVersion()}'
+ minor_version = str(ver.strip_patch())
expected = colors.get(minor_version, colors[None])
quteproc_new.open_path(f'data/darkmode/{filename}.html')
diff --git a/tests/unit/browser/test_pdfjs.py b/tests/unit/browser/test_pdfjs.py
index 788209d6f..86b875be5 100644
--- a/tests/unit/browser/test_pdfjs.py
+++ b/tests/unit/browser/test_pdfjs.py
@@ -77,7 +77,7 @@ class TestResources:
@pytest.fixture
def read_file_mock(self, mocker):
- return mocker.patch.object(pdfjs.utils, 'read_file_binary', autospec=True)
+ return mocker.patch.object(pdfjs.resources, 'read_file_binary', autospec=True)
def test_get_pdfjs_res_system(self, read_system_mock):
read_system_mock.return_value = (b'content', 'path')
diff --git a/tests/unit/browser/test_qutescheme.py b/tests/unit/browser/test_qutescheme.py
index 213df4e0c..2ae939596 100644
--- a/tests/unit/browser/test_qutescheme.py
+++ b/tests/unit/browser/test_qutescheme.py
@@ -28,7 +28,7 @@ from PyQt5.QtCore import QUrl, QUrlQuery
import pytest
from qutebrowser.browser import qutescheme, pdfjs, downloads
-from qutebrowser.utils import utils
+from qutebrowser.utils import resources
class TestJavascriptHandler:
@@ -43,15 +43,15 @@ class TestJavascriptHandler:
@pytest.fixture(autouse=True)
def patch_read_file(self, monkeypatch):
- """Patch utils.read_file to return few fake JS files."""
+ """Patch resources.read_file to return few fake JS files."""
def _read_file(path):
- """Faked utils.read_file."""
+ """Faked resources.read_file."""
for filename, content in self.js_files:
if path == os.path.join('javascript', filename):
return content
raise OSError("File not found {}!".format(path))
- monkeypatch.setattr(utils, 'read_file', _read_file)
+ monkeypatch.setattr(resources, 'read_file', _read_file)
@pytest.mark.parametrize("filename, content", js_files)
def test_qutejavascript(self, filename, content):
@@ -165,8 +165,9 @@ class TestHelpHandler:
assert path == name
return data
- monkeypatch.setattr(qutescheme.utils, 'read_file', _read_file)
- monkeypatch.setattr(qutescheme.utils, 'read_file_binary', _read_file_binary)
+ monkeypatch.setattr(qutescheme.resources, 'read_file', _read_file)
+ monkeypatch.setattr(qutescheme.resources,
+ 'read_file_binary', _read_file_binary)
return _patch
def test_unknown_file_type(self, data_patcher):
diff --git a/tests/unit/config/test_qtargs.py b/tests/unit/config/test_qtargs.py
index e7dbd5d95..695649213 100644
--- a/tests/unit/config/test_qtargs.py
+++ b/tests/unit/config/test_qtargs.py
@@ -530,6 +530,22 @@ class TestWebEngineArgs:
for arg in expected:
assert arg in args
+ @pytest.mark.linux
+ def test_locale_workaround(self, config_stub, monkeypatch, version_patcher,
+ parser):
+ class FakeLocale:
+
+ def bcp47Name(self):
+ return 'de-CH'
+
+ monkeypatch.setattr(qtargs.objects, 'backend', usertypes.Backend.QtWebEngine)
+ monkeypatch.setattr(qtargs, 'QLocale', FakeLocale)
+ version_patcher('5.15.3')
+ config_stub.val.qt.workarounds.locale = True
+ parsed = parser.parse_args([])
+ args = qtargs.qt_args(parsed)
+ assert '--lang=de' in args
+
class TestEnvVars:
diff --git a/tests/unit/config/test_qtargs_locale_workaround.py b/tests/unit/config/test_qtargs_locale_workaround.py
index 977118198..7e313377b 100644
--- a/tests/unit/config/test_qtargs_locale_workaround.py
+++ b/tests/unit/config/test_qtargs_locale_workaround.py
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
+import os
import pathlib
import pytest
@@ -403,6 +404,7 @@ def qtwe_version():
("zh_XX.UTF-8", "zh-CN"), # locale not available on my system
("zu_ZA.UTF-8", "en-US"),
])
+@pytest.mark.linux
def test_lang_workaround_all_locales(lang, expected, qtwe_version):
locale_name = QLocale(lang).bcp47Name()
print(locale_name)
@@ -444,3 +446,12 @@ def test_non_linux(qtwe_version):
def test_disabled(qtwe_version, config_stub):
config_stub.val.qt.workarounds.locale = False
assert qtargs._get_lang_override(qtwe_version, "de-CH") is None
+
+
+@pytest.mark.fake_os('linux')
+def test_no_locales_available(qtwe_version, monkeypatch, caplog):
+ monkeypatch.setattr(qtargs.QLibraryInfo, 'location', lambda _path: '/doesnotexist')
+ assert qtargs._get_lang_override(qtwe_version, "de-CH") is None
+ assert caplog.messages == [
+ f"{os.sep}doesnotexist{os.sep}qtwebengine_locales not found, skipping "
+ "workaround!"]
diff --git a/tests/unit/utils/test_jinja.py b/tests/unit/utils/test_jinja.py
index 5555560bf..0ef03725c 100644
--- a/tests/unit/utils/test_jinja.py
+++ b/tests/unit/utils/test_jinja.py
@@ -33,7 +33,7 @@ from qutebrowser.config import configexc
@pytest.fixture(autouse=True)
def patch_read_file(monkeypatch):
- """pytest fixture to patch utils.read_file."""
+ """pytest fixture to patch resources.read_file."""
def _read_file(path):
"""A read_file which returns a simple template if the path is right."""
if path == os.path.join('html', 'test.html'):
@@ -55,8 +55,8 @@ def patch_read_file(monkeypatch):
else:
raise OSError("Invalid path {}!".format(path))
- monkeypatch.setattr(jinja.utils, 'read_file', _read_file)
- monkeypatch.setattr(jinja.utils, 'read_file_binary', _read_file_binary)
+ monkeypatch.setattr(jinja.resources, 'read_file', _read_file)
+ monkeypatch.setattr(jinja.resources, 'read_file_binary', _read_file_binary)
def test_simple_template():
diff --git a/tests/unit/utils/test_resources.py b/tests/unit/utils/test_resources.py
new file mode 100644
index 000000000..d8af64cb9
--- /dev/null
+++ b/tests/unit/utils/test_resources.py
@@ -0,0 +1,146 @@
+# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
+
+# Copyright 2014-2021 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
+#
+# This file is part of qutebrowser.
+#
+# qutebrowser is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# qutebrowser is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with qutebrowser. If not, see <https://www.gnu.org/licenses/>.
+
+"""Tests for qutebrowser.utils.resources."""
+
+import sys
+import os.path
+import zipfile
+import pytest
+import qutebrowser
+from qutebrowser.utils import utils, resources
+
+
+@pytest.fixture(params=[True, False])
+def freezer(request, monkeypatch):
+ if request.param and not getattr(sys, 'frozen', False):
+ monkeypatch.setattr(sys, 'frozen', True, raising=False)
+ monkeypatch.setattr(sys, 'executable', qutebrowser.__file__)
+ elif not request.param and getattr(sys, 'frozen', False):
+ # Want to test unfrozen tests, but we are frozen
+ pytest.skip("Can't run with sys.frozen = True!")
+
+
+@pytest.mark.usefixtures('freezer')
+class TestReadFile:
+
+ @pytest.fixture
+ def package_path(self, tmp_path):
+ return tmp_path / 'qutebrowser'
+
+ @pytest.fixture
+ def html_path(self, package_path):
+ path = package_path / 'html'
+ path.mkdir(parents=True)
+
+ for filename in ['test1.html', 'test2.html', 'README', 'unrelatedhtml']:
+ (path / filename).touch()
+
+ subdir = path / 'subdir'
+ subdir.mkdir()
+ (subdir / 'subdir-file.html').touch()
+
+ return path
+
+ @pytest.fixture
+ def html_zip(self, tmp_path, html_path):
+ if not hasattr(zipfile, 'Path'):
+ pytest.skip("Needs zipfile.Path")
+
+ zip_path = tmp_path / 'qutebrowser.zip'
+ with zipfile.ZipFile(zip_path, 'w') as zf:
+ for path in html_path.rglob('*'):
+ zf.write(path, path.relative_to(tmp_path))
+
+ assert sorted(zf.namelist()) == [
+ 'qutebrowser/html/README',
+ 'qutebrowser/html/subdir/',
+ 'qutebrowser/html/subdir/subdir-file.html',
+ 'qutebrowser/html/test1.html',
+ 'qutebrowser/html/test2.html',
+ 'qutebrowser/html/unrelatedhtml',
+ ]
+
+ yield zipfile.Path(zip_path) / 'qutebrowser'
+
+ @pytest.fixture(params=['pathlib', 'zipfile'])
+ def resource_root(self, request):
+ """Resource files packaged either directly or via a zip."""
+ if request.param == 'pathlib':
+ request.getfixturevalue('html_path')
+ return request.getfixturevalue('package_path')
+ elif request.param == 'zipfile':
+ return request.getfixturevalue('html_zip')
+ raise utils.Unreachable(request.param)
+
+ def test_glob_resources(self, resource_root):
+ files = sorted(resources._glob(resource_root, 'html', '.html'))
+ assert files == ['html/test1.html', 'html/test2.html']
+
+ def test_glob_resources_subdir(self, resource_root):
+ files = sorted(resources._glob(resource_root, 'html/subdir', '.html'))
+ assert files == ['html/subdir/subdir-file.html']
+
+ def test_readfile(self):
+ """Read a test file."""
+ content = resources.read_file(os.path.join('utils', 'testfile'))
+ assert content.splitlines()[0] == "Hello World!"
+
+ @pytest.mark.parametrize('filename', ['javascript/scroll.js',
+ 'html/error.html'])
+ def test_read_cached_file(self, mocker, filename):
+ resources.preload()
+ m = mocker.patch('qutebrowser.utils.resources.importlib_resources.files')
+ resources.read_file(filename)
+ m.assert_not_called()
+
+ def test_readfile_binary(self):
+ """Read a test file in binary mode."""
+ content = resources.read_file_binary(os.path.join('utils', 'testfile'))
+ assert content.splitlines()[0] == b"Hello World!"
+
+ @pytest.mark.parametrize('name', ['read_file', 'read_file_binary'])
+ @pytest.mark.parametrize('fake_exception', [KeyError, FileNotFoundError, None])
+ def test_not_found(self, name, fake_exception, monkeypatch):
+ """Test behavior when a resources file wasn't found.
+
+ With fake_exception, we emulate the rather odd error handling of certain Python
+ versions: https://bugs.python.org/issue43063
+ """
+ class BrokenFileFake:
+
+ def __init__(self, exc):
+ self.exc = exc
+
+ def read_bytes(self):
+ raise self.exc("File does not exist")
+
+ def read_text(self, encoding):
+ raise self.exc("File does not exist")
+
+ def __truediv__(self, _other):
+ return self
+
+ if fake_exception is not None:
+ monkeypatch.setattr(resources.importlib_resources, 'files',
+ lambda _pkg: BrokenFileFake(fake_exception))
+
+ meth = getattr(resources, name)
+ with pytest.raises(FileNotFoundError):
+ meth('doesnotexist')
diff --git a/tests/unit/utils/test_utils.py b/tests/unit/utils/test_utils.py
index 4cf60943c..b43638cb3 100644
--- a/tests/unit/utils/test_utils.py
+++ b/tests/unit/utils/test_utils.py
@@ -28,7 +28,7 @@ import functools
import re
import shlex
import math
-import zipfile
+import operator
from PyQt5.QtCore import QUrl, QRect
from PyQt5.QtGui import QClipboard
@@ -40,22 +40,117 @@ import yaml
import qutebrowser
import qutebrowser.utils # for test_qualname
from qutebrowser.utils import utils, version, usertypes
+from qutebrowser.utils.utils import VersionNumber
class TestVersionNumber:
- @pytest.mark.parametrize('args, expected', [
- ([5, 15, 2], 'VersionNumber(5, 15, 2)'),
- ([5, 15], 'VersionNumber(5, 15)'),
- ([5], 'VersionNumber(5)'),
+ @pytest.mark.parametrize('num, expected', [
+ (VersionNumber(5, 15, 2), 'VersionNumber(5, 15, 2)'),
+ (VersionNumber(5, 15), 'VersionNumber(5, 15)'),
+ (VersionNumber(5), 'VersionNumber(5)'),
])
- def test_repr(self, args, expected):
- num = utils.VersionNumber(*args)
+ def test_repr(self, num, expected):
assert repr(num) == expected
+ @pytest.mark.parametrize('num, expected', [
+ (VersionNumber(5, 15, 2), '5.15.2'),
+ (VersionNumber(5, 15), '5.15'),
+ (VersionNumber(5), '5'),
+ ])
+ def test_str(self, num, expected):
+ assert str(num) == expected
+
def test_not_normalized(self):
with pytest.raises(ValueError, match='Refusing to construct'):
- utils.VersionNumber(5, 15, 0)
+ VersionNumber(5, 15, 0)
+
+ @pytest.mark.parametrize('num, expected', [
+ (VersionNumber(5, 15, 2), VersionNumber(5, 15)),
+ (VersionNumber(5, 15), VersionNumber(5, 15)),
+ (VersionNumber(6), VersionNumber(6)),
+ ])
+ def test_strip_patch(self, num, expected):
+ assert num.strip_patch() == expected
+
+ @pytest.mark.parametrize('s, expected', [
+ ('1x6.2', VersionNumber(1)),
+ ('6', VersionNumber(6)),
+ ('5.15', VersionNumber(5, 15)),
+ ('5.15.3', VersionNumber(5, 15, 3)),
+ ('5.15.3.dev1234', VersionNumber(5, 15, 3)),
+ ])
+ def test_parse_valid(self, s, expected):
+ assert VersionNumber.parse(s) == expected
+
+ @pytest.mark.parametrize('s, message', [
+ ('foo6', "Failed to parse foo6"),
+ ('.6', "Failed to parse .6"),
+ ('0x6.2', "Can't construct a null version"),
+ ])
+ def test_parse_invalid(self, s, message):
+ with pytest.raises(ValueError, match=message):
+ VersionNumber.parse(s)
+
+ @pytest.mark.parametrize('lhs, op, rhs, outcome', [
+ # ==
+ (VersionNumber(6), operator.eq, VersionNumber(6), True),
+ (VersionNumber(6), operator.eq, object(), False),
+
+ # !=
+ (VersionNumber(6), operator.ne, VersionNumber(5), True),
+ (VersionNumber(6), operator.ne, object(), True),
+
+ # >=
+ (VersionNumber(5, 14), operator.ge, VersionNumber(5, 13, 5), True),
+ (VersionNumber(5, 14), operator.ge, VersionNumber(5, 14, 2), False),
+ (VersionNumber(5, 14, 3), operator.ge, VersionNumber(5, 14, 2), True),
+ (VersionNumber(5, 14, 3), operator.ge, VersionNumber(5, 14, 3), True),
+ (VersionNumber(5, 14), operator.ge, VersionNumber(5, 13), True),
+ (VersionNumber(5, 14), operator.ge, VersionNumber(5, 14), True),
+ (VersionNumber(5, 14), operator.ge, VersionNumber(5, 15), False),
+ (VersionNumber(5, 14), operator.ge, VersionNumber(4), True),
+ (VersionNumber(5, 14), operator.ge, VersionNumber(5), True),
+ (VersionNumber(5, 14), operator.ge, VersionNumber(6), False),
+
+ # >
+ (VersionNumber(5, 14), operator.gt, VersionNumber(5, 13, 5), True),
+ (VersionNumber(5, 14), operator.gt, VersionNumber(5, 14, 2), False),
+ (VersionNumber(5, 14, 3), operator.gt, VersionNumber(5, 14, 2), True),
+ (VersionNumber(5, 14, 3), operator.gt, VersionNumber(5, 14, 3), False),
+ (VersionNumber(5, 14), operator.gt, VersionNumber(5, 13), True),
+ (VersionNumber(5, 14), operator.gt, VersionNumber(5, 14), False),
+ (VersionNumber(5, 14), operator.gt, VersionNumber(5, 15), False),
+ (VersionNumber(5, 14), operator.gt, VersionNumber(4), True),
+ (VersionNumber(5, 14), operator.gt, VersionNumber(5), True),
+ (VersionNumber(5, 14), operator.gt, VersionNumber(6), False),
+
+ # <=
+ (VersionNumber(5, 14), operator.le, VersionNumber(5, 13, 5), False),
+ (VersionNumber(5, 14), operator.le, VersionNumber(5, 14, 2), True),
+ (VersionNumber(5, 14, 3), operator.le, VersionNumber(5, 14, 2), False),
+ (VersionNumber(5, 14, 3), operator.le, VersionNumber(5, 14, 3), True),
+ (VersionNumber(5, 14), operator.le, VersionNumber(5, 13), False),
+ (VersionNumber(5, 14), operator.le, VersionNumber(5, 14), True),
+ (VersionNumber(5, 14), operator.le, VersionNumber(5, 15), True),
+ (VersionNumber(5, 14), operator.le, VersionNumber(4), False),
+ (VersionNumber(5, 14), operator.le, VersionNumber(5), False),
+ (VersionNumber(5, 14), operator.le, VersionNumber(6), True),
+
+ # <
+ (VersionNumber(5, 14), operator.lt, VersionNumber(5, 13, 5), False),
+ (VersionNumber(5, 14), operator.lt, VersionNumber(5, 14, 2), True),
+ (VersionNumber(5, 14, 3), operator.lt, VersionNumber(5, 14, 2), False),
+ (VersionNumber(5, 14, 3), operator.lt, VersionNumber(5, 14, 3), False),
+ (VersionNumber(5, 14), operator.lt, VersionNumber(5, 13), False),
+ (VersionNumber(5, 14), operator.lt, VersionNumber(5, 14), False),
+ (VersionNumber(5, 14), operator.lt, VersionNumber(5, 15), True),
+ (VersionNumber(5, 14), operator.lt, VersionNumber(4), False),
+ (VersionNumber(5, 14), operator.lt, VersionNumber(5), False),
+ (VersionNumber(5, 14), operator.lt, VersionNumber(6), True),
+ ])
+ def test_comparisons(self, lhs, op, rhs, outcome):
+ assert op(lhs, rhs) == outcome
ELLIPSIS = '\u2026'
@@ -132,115 +227,6 @@ def freezer(request, monkeypatch):
pytest.skip("Can't run with sys.frozen = True!")
-@pytest.mark.usefixtures('freezer')
-class TestReadFile:
-
- @pytest.fixture
- def package_path(self, tmp_path):
- return tmp_path / 'qutebrowser'
-
- @pytest.fixture
- def html_path(self, package_path):
- path = package_path / 'html'
- path.mkdir(parents=True)
-
- for filename in ['test1.html', 'test2.html', 'README', 'unrelatedhtml']:
- (path / filename).touch()
-
- subdir = path / 'subdir'
- subdir.mkdir()
- (subdir / 'subdir-file.html').touch()
-
- return path
-
- @pytest.fixture
- def html_zip(self, tmp_path, html_path):
- if not hasattr(zipfile, 'Path'):
- pytest.skip("Needs zipfile.Path")
-
- zip_path = tmp_path / 'qutebrowser.zip'
- with zipfile.ZipFile(zip_path, 'w') as zf:
- for path in html_path.rglob('*'):
- zf.write(path, path.relative_to(tmp_path))
-
- assert sorted(zf.namelist()) == [
- 'qutebrowser/html/README',
- 'qutebrowser/html/subdir/',
- 'qutebrowser/html/subdir/subdir-file.html',
- 'qutebrowser/html/test1.html',
- 'qutebrowser/html/test2.html',
- 'qutebrowser/html/unrelatedhtml',
- ]
-
- yield zipfile.Path(zip_path) / 'qutebrowser'
-
- @pytest.fixture(params=['pathlib', 'zipfile'])
- def resource_root(self, request):
- """Resource files packaged either directly or via a zip."""
- if request.param == 'pathlib':
- request.getfixturevalue('html_path')
- return request.getfixturevalue('package_path')
- elif request.param == 'zipfile':
- return request.getfixturevalue('html_zip')
- raise utils.Unreachable(request.param)
-
- def test_glob_resources(self, resource_root):
- files = sorted(utils._glob_resources(resource_root, 'html', '.html'))
- assert files == ['html/test1.html', 'html/test2.html']
-
- def test_glob_resources_subdir(self, resource_root):
- files = sorted(utils._glob_resources(resource_root, 'html/subdir', '.html'))
- assert files == ['html/subdir/subdir-file.html']
-
- def test_readfile(self):
- """Read a test file."""
- content = utils.read_file(os.path.join('utils', 'testfile'))
- assert content.splitlines()[0] == "Hello World!"
-
- @pytest.mark.parametrize('filename', ['javascript/scroll.js',
- 'html/error.html'])
- def test_read_cached_file(self, mocker, filename):
- utils.preload_resources()
- m = mocker.patch('qutebrowser.utils.utils.importlib_resources.files')
- utils.read_file(filename)
- m.assert_not_called()
-
- def test_readfile_binary(self):
- """Read a test file in binary mode."""
- content = utils.read_file_binary(os.path.join('utils', 'testfile'))
- assert content.splitlines()[0] == b"Hello World!"
-
- @pytest.mark.parametrize('name', ['read_file', 'read_file_binary'])
- @pytest.mark.parametrize('fake_exception', [KeyError, FileNotFoundError, None])
- def test_not_found(self, name, fake_exception, monkeypatch):
- """Test behavior when a resources file wasn't found.
-
- With fake_exception, we emulate the rather odd error handling of certain Python
- versions: https://bugs.python.org/issue43063
- """
- class BrokenFileFake:
-
- def __init__(self, exc):
- self.exc = exc
-
- def read_bytes(self):
- raise self.exc("File does not exist")
-
- def read_text(self, encoding):
- raise self.exc("File does not exist")
-
- def __truediv__(self, _other):
- return self
-
- if fake_exception is not None:
- monkeypatch.setattr(utils.importlib_resources, 'files',
- lambda _pkg: BrokenFileFake(fake_exception))
-
- meth = getattr(utils, name)
- with pytest.raises(FileNotFoundError):
- meth('doesnotexist')
-
-
@pytest.mark.parametrize('seconds, out', [
(-1, '-0:01'),
(0, '0:00'),
@@ -784,7 +770,7 @@ class TestOpenFile:
info = version.DistributionInfo(
id='org.kde.Platform',
parsed=version.Distribution.kde_flatpak,
- version=utils.parse_version('5.12'),
+ version=VersionNumber.parse('5.12'),
pretty='Unknown')
monkeypatch.setattr(version, 'distribution',
lambda: info)
diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py
index f846c91ac..879f84a1f 100644
--- a/tests/unit/utils/test_version.py
+++ b/tests/unit/utils/test_version.py
@@ -357,14 +357,14 @@ class TestGitStr:
@pytest.fixture
def commit_file_mock(self, mocker):
- """Fixture providing a mock for utils.read_file for git-commit-id.
+ """Fixture providing a mock for resources.read_file for git-commit-id.
On fixture teardown, it makes sure it got called with git-commit-id as
argument.
"""
mocker.patch('qutebrowser.utils.version.subprocess',
side_effect=AssertionError)
- m = mocker.patch('qutebrowser.utils.version.utils.read_file')
+ m = mocker.patch('qutebrowser.utils.version.resources.read_file')
yield m
m.assert_called_with('git-commit-id')
@@ -413,7 +413,7 @@ class TestGitStr:
"""Test with things raising OSError."""
m = mocker.patch('qutebrowser.utils.version.os')
m.path.join.side_effect = OSError
- mocker.patch('qutebrowser.utils.version.utils.read_file',
+ mocker.patch('qutebrowser.utils.version.resources.read_file',
side_effect=OSError)
with caplog.at_level(logging.ERROR, 'misc'):
assert version._git_str() is None
@@ -956,10 +956,13 @@ class TestWebEngineVersions:
('5.14.2', '77.0.3865.129'),
('5.15.1', '80.0.3987.163'),
('5.15.2', '83.0.4103.122'),
+ ('5.15.3', '87.0.4280.144'),
+ ('5.15.4', '87.0.4280.144'),
+ ('5.15.5', '87.0.4280.144'),
])
def test_from_pyqt(self, qt_version, chromium_version):
expected = version.WebEngineVersions(
- webengine=utils.parse_version(qt_version),
+ webengine=utils.VersionNumber.parse(qt_version),
chromium=chromium_version,
source='PyQt',
)
@@ -982,15 +985,9 @@ class TestWebEngineVersions:
versions = version.WebEngineVersions.from_pyqt(pyqt_webengine_version)
- if pyqt_webengine_version == '5.15.3':
- # Transient situation - we expect to get QtWebEngine 5.15.3 soon,
- # so this will line up again.
- assert versions.chromium == '87.0.4280.144'
- pytest.xfail("Transient situation")
- else:
- from qutebrowser.browser.webengine import webenginesettings
- webenginesettings.init_user_agent()
- expected = webenginesettings.parsed_user_agent.upstream_browser_version
+ from qutebrowser.browser.webengine import webenginesettings
+ webenginesettings.init_user_agent()
+ expected = webenginesettings.parsed_user_agent.upstream_browser_version
assert versions.chromium == expected
@@ -1079,18 +1076,34 @@ class TestChromiumVersion:
import_fake.patch()
@pytest.fixture
- def patch_importlib_no_package(self, monkeypatch):
- """Simulate importlib not finding PyQtWebEngine-Qt."""
- try:
- import importlib.metadata as importlib_metadata
- except ImportError:
- importlib_metadata = pytest.importorskip("importlib_metadata")
-
- def _fake_version(name):
- assert name == 'PyQtWebEngine-Qt'
- raise importlib_metadata.PackageNotFoundError(name)
+ def importlib_patcher(self, monkeypatch):
+ """Patch the importlib module."""
+ def _patch(*, qt, qt5):
+ try:
+ import importlib.metadata as importlib_metadata
+ except ImportError:
+ importlib_metadata = pytest.importorskip("importlib_metadata")
+
+ def _fake_version(name):
+ if name == 'PyQtWebEngine-Qt':
+ outcome = qt
+ elif name == 'PyQtWebEngine-Qt5':
+ outcome = qt5
+ else:
+ raise utils.Unreachable(outcome)
+
+ if outcome is None:
+ raise importlib_metadata.PackageNotFoundError(name)
+ return outcome
+
+ monkeypatch.setattr(importlib_metadata, 'version', _fake_version)
+
+ return _patch
- monkeypatch.setattr(importlib_metadata, 'version', _fake_version)
+ @pytest.fixture
+ def patch_importlib_no_package(self, importlib_patcher):
+ """Simulate importlib not finding PyQtWebEngine-Qt[5]."""
+ importlib_patcher(qt=None, qt5=None)
@pytest.mark.parametrize('patches, sources', [
(['elf_fail'], ['importlib', 'PyQt', 'Qt']),
@@ -1114,6 +1127,21 @@ class TestChromiumVersion:
versions = version.qtwebengine_versions(avoid_init=True)
assert versions.source in sources
+ @pytest.mark.parametrize('qt, qt5, expected', [
+ (None, '5.15.4', utils.VersionNumber(5, 15, 4)),
+ ('5.15.3', None, utils.VersionNumber(5, 15, 3)),
+ ('5.15.3', '5.15.4', utils.VersionNumber(5, 15, 4)), # -Qt5 takes precedence
+ ])
+ def test_importlib(self, qt, qt5, expected, patch_elf_fail, importlib_patcher):
+ """Test the importlib version logic with different Qt packages.
+
+ With PyQtWebEngine 5.15.4, PyQtWebEngine-Qt was renamed to PyQtWebEngine-Qt5.
+ """
+ importlib_patcher(qt=qt, qt5=qt5)
+ versions = version.qtwebengine_versions(avoid_init=True)
+ assert versions.source == 'importlib'
+ assert versions.webengine == expected
+
@dataclasses.dataclass
class VersionParams: