summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2021-02-03 18:32:07 +0100
committerFlorian Bruhin <me@the-compiler.org>2021-02-03 18:32:07 +0100
commita6ac2793a39fd83e174e5b957f01e4e2888474c7 (patch)
tree1b704c68aae7c25c52655657336b8b41faa103d9
parent518763099a28caa8de03fb3010cb36812adbda01 (diff)
downloadqutebrowser-a6ac2793a39fd83e174e5b957f01e4e2888474c7.tar.gz
qutebrowser-a6ac2793a39fd83e174e5b957f01e4e2888474c7.zip
Adopt tests from master branch
-rw-r--r--tests/end2end/fixtures/webserver.py1
-rw-r--r--tests/end2end/fixtures/webserver_sub.py10
-rw-r--r--tests/end2end/test_invocations.py33
-rw-r--r--tests/helpers/utils.py2
-rw-r--r--tests/unit/browser/test_downloadview.py94
-rw-r--r--tests/unit/utils/test_utils.py65
6 files changed, 199 insertions, 6 deletions
diff --git a/tests/end2end/fixtures/webserver.py b/tests/end2end/fixtures/webserver.py
index 4677415f1..81a864c8e 100644
--- a/tests/end2end/fixtures/webserver.py
+++ b/tests/end2end/fixtures/webserver.py
@@ -75,6 +75,7 @@ class Request(testprocess.Line):
'/absolute-redirect': [HTTPStatus.FOUND],
'/cookies/set': [HTTPStatus.FOUND],
+ '/cookies/set-custom': [HTTPStatus.FOUND],
'/500-inline': [HTTPStatus.INTERNAL_SERVER_ERROR],
'/500': [HTTPStatus.INTERNAL_SERVER_ERROR],
diff --git a/tests/end2end/fixtures/webserver_sub.py b/tests/end2end/fixtures/webserver_sub.py
index b7999148f..a4f54e19c 100644
--- a/tests/end2end/fixtures/webserver_sub.py
+++ b/tests/end2end/fixtures/webserver_sub.py
@@ -199,6 +199,16 @@ def set_cookies():
return r
+@app.route('/cookies/set-custom')
+def set_custom_cookie():
+ """Set a cookie with a custom max_age/expires."""
+ r = app.make_response(flask.redirect(flask.url_for('view_cookies')))
+ max_age = flask.request.args.get('max_age')
+ r.set_cookie(key='cookie', value='value',
+ max_age=int(max_age) if max_age else None)
+ return r
+
+
@app.route('/basic-auth/<user>/<passwd>')
def basic_auth(user='user', passwd='passwd'):
"""Prompt the user for authorization using HTTP Basic Auth."""
diff --git a/tests/end2end/test_invocations.py b/tests/end2end/test_invocations.py
index b509e355b..4dfe137fc 100644
--- a/tests/end2end/test_invocations.py
+++ b/tests/end2end/test_invocations.py
@@ -490,3 +490,36 @@ def test_service_worker_workaround(
quteproc_new.ensure_not_logged(message='Removing service workers at *')
else:
assert not service_worker_dir.exists()
+
+
+@utils.qt513 # Qt 5.12 doesn't store cookies immediately
+@pytest.mark.parametrize('store', [True, False])
+def test_cookies_store(quteproc_new, request, short_tmpdir, store):
+ # Start test process
+ args = _base_args(request.config) + [
+ '--basedir', str(short_tmpdir),
+ '-s', 'content.cookies.store', str(store),
+ ]
+ quteproc_new.start(args)
+
+ # Set cookie and ensure it's set
+ quteproc_new.open_path('cookies/set-custom?max_age=30', wait=False)
+ quteproc_new.wait_for_load_finished('cookies')
+ content = quteproc_new.get_content()
+ data = json.loads(content)
+ assert data == {'cookies': {'cookie': 'value'}}
+
+ # Restart
+ quteproc_new.send_cmd(':quit')
+ quteproc_new.wait_for_quit()
+ quteproc_new.start(args)
+
+ # Check cookies
+ quteproc_new.open_path('cookies')
+ content = quteproc_new.get_content()
+ data = json.loads(content)
+ expected_cookies = {'cookie': 'value'} if store else {}
+ assert data == {'cookies': expected_cookies}
+
+ quteproc_new.send_cmd(':quit')
+ quteproc_new.wait_for_quit()
diff --git a/tests/helpers/utils.py b/tests/helpers/utils.py
index 41da08331..a6fd3c0e4 100644
--- a/tests/helpers/utils.py
+++ b/tests/helpers/utils.py
@@ -41,6 +41,8 @@ from qutebrowser.utils import qtutils, log
ON_CI = 'CI' in os.environ
+qt513 = pytest.mark.skipif(
+ not qtutils.version_check('5.13'), reason="Needs Qt 5.13 or newer")
qt514 = pytest.mark.skipif(
not qtutils.version_check('5.14'), reason="Needs Qt 5.14 or newer")
diff --git a/tests/unit/browser/test_downloadview.py b/tests/unit/browser/test_downloadview.py
new file mode 100644
index 000000000..84b50fad2
--- /dev/null
+++ b/tests/unit/browser/test_downloadview.py
@@ -0,0 +1,94 @@
+# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
+
+# Copyright 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/>.
+
+
+import pytest
+
+from PyQt5.QtCore import QUrl
+
+from qutebrowser.browser import downloads, qtnetworkdownloads, downloadview
+
+
+class FakeDownload(downloads.AbstractDownloadItem):
+
+ # As this is used for tests, we only override what's actually needed.
+ # pylint: disable=abstract-method
+
+ def __init__(self, done: bool, successful: bool = False) -> None:
+ super().__init__(manager=None)
+ self.done = done
+ self.successful = successful
+
+ def url(self) -> QUrl:
+ return QUrl('https://example.org/')
+
+
+@pytest.fixture
+def qtnetwork_manager(config_stub, cookiejar_and_cache):
+ """A QtNetwork-based download manager."""
+ return qtnetworkdownloads.DownloadManager()
+
+
+@pytest.fixture
+def model(qtnetwork_manager, qtmodeltester, qapp):
+ """A simple DownloadModel."""
+ model = downloads.DownloadModel(qtnetwork_manager)
+ qtmodeltester.check(model)
+ return model
+
+
+@pytest.fixture
+def view(model, qtbot):
+ """A DownloadView."""
+ dv = downloadview.DownloadView(model)
+ qtbot.add_widget(dv)
+ return dv
+
+
+@pytest.mark.parametrize('can_clear', [True, False])
+@pytest.mark.parametrize('item, expected', [
+ # Clicking outside of a download item
+ (None, []),
+
+ # Clicking a in-progress item
+ (FakeDownload(done=False), ["Cancel", "Copy URL"]),
+
+ # Clicking a successful item
+ (
+ FakeDownload(done=True, successful=True),
+ ["Open", "Open directory", "Remove", "Copy URL"],
+ ),
+
+ # Clicking an unsuccessful item
+ (
+ FakeDownload(done=True, successful=False),
+ ["Retry", "Remove", "Copy URL"],
+ ),
+])
+def test_get_menu_actions(can_clear, item, expected, view, qtnetwork_manager):
+ if can_clear:
+ qtnetwork_manager.downloads.append(FakeDownload(done=True))
+ expected = expected.copy() + [None, "Remove all finished"]
+ else:
+ assert not qtnetwork_manager.downloads
+ assert "Remove all finished" not in expected
+
+ actions = view._get_menu_actions(item)
+ texts = [action[0] for action in actions]
+ assert texts == expected
diff --git a/tests/unit/utils/test_utils.py b/tests/unit/utils/test_utils.py
index 415d04bd0..f6ac8039d 100644
--- a/tests/unit/utils/test_utils.py
+++ b/tests/unit/utils/test_utils.py
@@ -131,6 +131,10 @@ class TestReadFile:
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
@@ -140,18 +144,37 @@ class TestReadFile:
zip_path = tmp_path / 'qutebrowser.zip'
with zipfile.ZipFile(zip_path, 'w') as zf:
- for path in html_path.iterdir():
+ 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'
- def test_glob_resources_pathlib(self, html_path, package_path):
- files = sorted(utils._glob_resources(package_path, 'html', '.html'))
+ @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_zipfile(self, html_zip):
- files = sorted(utils._glob_resources(html_zip, '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."""
@@ -171,6 +194,36 @@ class TestReadFile:
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'),