Merge branch 'download-page-tests' of https://github.com/The-Compiler/qutebrowser into download-page
This commit is contained in:
commit
62b0c4d178
@ -48,6 +48,8 @@ Added
|
|||||||
* `colors -> downloads.bg.system`
|
* `colors -> downloads.bg.system`
|
||||||
- New command `:download-retry` to retry a failed download.
|
- New command `:download-retry` to retry a failed download.
|
||||||
- New command `:download-clear` which replaces `:download-remove --all`.
|
- New command `:download-clear` which replaces `:download-remove --all`.
|
||||||
|
- `:set-cmd-text` has a new `--append` argument to append to the current
|
||||||
|
statusbar text.
|
||||||
|
|
||||||
Changed
|
Changed
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
@ -82,6 +84,8 @@ Fixed
|
|||||||
- Fixed a crash when a website presents a very small favicon.
|
- Fixed a crash when a website presents a very small favicon.
|
||||||
- Fixed prompting for download directory when
|
- Fixed prompting for download directory when
|
||||||
`storage -> prompt-download-directory` was unset.
|
`storage -> prompt-download-directory` was unset.
|
||||||
|
- Fixed crash when using `:follow-hint` outside of hint mode.
|
||||||
|
- Fixed crash when using `:set foo bar?` with invalid section/option.
|
||||||
|
|
||||||
v0.4.1
|
v0.4.1
|
||||||
------
|
------
|
||||||
|
@ -140,9 +140,9 @@ Contributors, sorted by the number of commits in descending order:
|
|||||||
* Florian Bruhin
|
* Florian Bruhin
|
||||||
* Antoni Boucher
|
* Antoni Boucher
|
||||||
* Bruno Oliveira
|
* Bruno Oliveira
|
||||||
|
* Lamar Pavel
|
||||||
* Alexander Cogneau
|
* Alexander Cogneau
|
||||||
* Martin Tournoij
|
* Martin Tournoij
|
||||||
* Lamar Pavel
|
|
||||||
* Raphael Pierzina
|
* Raphael Pierzina
|
||||||
* Joel Torstensson
|
* Joel Torstensson
|
||||||
* Daniel
|
* Daniel
|
||||||
|
@ -577,7 +577,7 @@ If the option name ends with '?', the value of the option is shown instead. If t
|
|||||||
|
|
||||||
[[set-cmd-text]]
|
[[set-cmd-text]]
|
||||||
=== set-cmd-text
|
=== set-cmd-text
|
||||||
Syntax: +:set-cmd-text [*--space*] 'text'+
|
Syntax: +:set-cmd-text [*--space*] [*--append*] 'text'+
|
||||||
|
|
||||||
Preset the statusbar to some text.
|
Preset the statusbar to some text.
|
||||||
|
|
||||||
@ -586,6 +586,7 @@ Preset the statusbar to some text.
|
|||||||
|
|
||||||
==== optional arguments
|
==== optional arguments
|
||||||
* +*-s*+, +*--space*+: If given, a space is added to the end.
|
* +*-s*+, +*--space*+: If given, a space is added to the end.
|
||||||
|
* +*-a*+, +*--append*+: If given, the text is appended to the current text.
|
||||||
|
|
||||||
==== note
|
==== note
|
||||||
* This command does not split arguments after the last argument and handles quotes literally.
|
* This command does not split arguments after the last argument and handles quotes literally.
|
||||||
|
@ -35,3 +35,4 @@ qt_log_ignore =
|
|||||||
^Type conversion already registered from type .*
|
^Type conversion already registered from type .*
|
||||||
^QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once\.
|
^QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once\.
|
||||||
^QWaitCondition: Destroyed while threads are still waiting
|
^QWaitCondition: Destroyed while threads are still waiting
|
||||||
|
^QXcbXSettings::QXcbXSettings\(QXcbScreen\*\) Failed to get selection owner for XSETTINGS_S atom
|
||||||
|
@ -65,7 +65,8 @@ class DiskCache(QNetworkDiskCache):
|
|||||||
"""Update cache size/activated if the config was changed."""
|
"""Update cache size/activated if the config was changed."""
|
||||||
if (section, option) == ('storage', 'cache-size'):
|
if (section, option) == ('storage', 'cache-size'):
|
||||||
self.setMaximumCacheSize(config.get('storage', 'cache-size'))
|
self.setMaximumCacheSize(config.get('storage', 'cache-size'))
|
||||||
elif (section, option) == ('general', 'private-browsing'):
|
elif (section, option) == ('general', # pragma: no branch
|
||||||
|
'private-browsing'):
|
||||||
self._maybe_activate()
|
self._maybe_activate()
|
||||||
|
|
||||||
def cacheSize(self):
|
def cacheSize(self):
|
||||||
|
@ -810,10 +810,15 @@ class DownloadManager(QAbstractListModel):
|
|||||||
download = DownloadItem(reply, self._win_id, self)
|
download = DownloadItem(reply, self._win_id, self)
|
||||||
download.cancelled.connect(
|
download.cancelled.connect(
|
||||||
functools.partial(self.remove_item, download))
|
functools.partial(self.remove_item, download))
|
||||||
|
|
||||||
delay = config.get('ui', 'remove-finished-downloads')
|
delay = config.get('ui', 'remove-finished-downloads')
|
||||||
if delay > -1 or auto_remove:
|
if delay > -1:
|
||||||
download.finished.connect(
|
download.finished.connect(
|
||||||
functools.partial(self.remove_item_delayed, download, delay))
|
functools.partial(self.remove_item_delayed, download, delay))
|
||||||
|
elif auto_remove:
|
||||||
|
download.finished.connect(
|
||||||
|
functools.partial(self.remove_item, download))
|
||||||
|
|
||||||
download.data_changed.connect(
|
download.data_changed.connect(
|
||||||
functools.partial(self.on_data_changed, download))
|
functools.partial(self.on_data_changed, download))
|
||||||
download.error.connect(self.on_error)
|
download.error.connect(self.on_error)
|
||||||
|
@ -946,7 +946,8 @@ class HintManager(QObject):
|
|||||||
elems.label.setInnerXml(string)
|
elems.label.setInnerXml(string)
|
||||||
handler()
|
handler()
|
||||||
|
|
||||||
@cmdutils.register(instance='hintmanager', scope='tab', hide=True)
|
@cmdutils.register(instance='hintmanager', scope='tab', hide=True,
|
||||||
|
modes=[usertypes.KeyMode.hint])
|
||||||
def follow_hint(self, keystring=None):
|
def follow_hint(self, keystring=None):
|
||||||
"""Follow a hint.
|
"""Follow a hint.
|
||||||
|
|
||||||
@ -958,6 +959,8 @@ class HintManager(QObject):
|
|||||||
raise cmdexc.CommandError("No hint to follow")
|
raise cmdexc.CommandError("No hint to follow")
|
||||||
else:
|
else:
|
||||||
keystring = self._context.to_follow
|
keystring = self._context.to_follow
|
||||||
|
elif keystring not in self._context.elems:
|
||||||
|
raise cmdexc.CommandError("No hint {}!".format(keystring))
|
||||||
self.fire(keystring, force=True)
|
self.fire(keystring, force=True)
|
||||||
|
|
||||||
@pyqtSlot('QSize')
|
@pyqtSlot('QSize')
|
||||||
|
@ -360,17 +360,21 @@ class NetworkManager(QNetworkAccessManager):
|
|||||||
req.setRawHeader('DNT'.encode('ascii'), dnt)
|
req.setRawHeader('DNT'.encode('ascii'), dnt)
|
||||||
req.setRawHeader('X-Do-Not-Track'.encode('ascii'), dnt)
|
req.setRawHeader('X-Do-Not-Track'.encode('ascii'), dnt)
|
||||||
|
|
||||||
if self._tab_id is None:
|
# There are some scenarios where we can't figure out current_url:
|
||||||
current_url = QUrl() # generic NetworkManager, e.g. for downloads
|
# - There's a generic NetworkManager, e.g. for downloads
|
||||||
else:
|
# - The download was in a tab which is now closed.
|
||||||
|
current_url = QUrl()
|
||||||
|
|
||||||
|
if self._tab_id is not None:
|
||||||
try:
|
try:
|
||||||
webview = objreg.get('webview', scope='tab',
|
webview = objreg.get('webview', scope='tab',
|
||||||
window=self._win_id, tab=self._tab_id)
|
window=self._win_id, tab=self._tab_id)
|
||||||
except KeyError:
|
|
||||||
# https://github.com/The-Compiler/qutebrowser/issues/889
|
|
||||||
current_url = QUrl()
|
|
||||||
else:
|
|
||||||
current_url = webview.url()
|
current_url = webview.url()
|
||||||
|
except (KeyError, RuntimeError, TypeError):
|
||||||
|
# https://github.com/The-Compiler/qutebrowser/issues/889
|
||||||
|
# Catching RuntimeError and TypeError because we could be in
|
||||||
|
# the middle of the webpage shutdown here.
|
||||||
|
current_url = QUrl()
|
||||||
|
|
||||||
self.set_referer(req, current_url)
|
self.set_referer(req, current_url)
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ class WebView(QWebView):
|
|||||||
try:
|
try:
|
||||||
elem = webelem.focus_elem(self.page().currentFrame())
|
elem = webelem.focus_elem(self.page().currentFrame())
|
||||||
except (webelem.IsNullError, RuntimeError):
|
except (webelem.IsNullError, RuntimeError):
|
||||||
log.mouse.warning("Element/page vanished!")
|
log.mouse.debug("Element/page vanished!")
|
||||||
return
|
return
|
||||||
if elem.is_editable():
|
if elem.is_editable():
|
||||||
log.mouse.debug("Clicked editable element (delayed)!")
|
log.mouse.debug("Clicked editable element (delayed)!")
|
||||||
|
@ -29,6 +29,7 @@ import sys
|
|||||||
import os.path
|
import os.path
|
||||||
import functools
|
import functools
|
||||||
import configparser
|
import configparser
|
||||||
|
import contextlib
|
||||||
import collections
|
import collections
|
||||||
import collections.abc
|
import collections.abc
|
||||||
|
|
||||||
@ -666,6 +667,18 @@ class ConfigManager(QObject):
|
|||||||
newval = val.typ.transform(newval)
|
newval = val.typ.transform(newval)
|
||||||
return newval
|
return newval
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def _handle_config_error(self):
|
||||||
|
"""Catch errors in set_command and raise CommandError."""
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
except (configexc.NoOptionError, configexc.NoSectionError,
|
||||||
|
configexc.ValidationError) as e:
|
||||||
|
raise cmdexc.CommandError("set: {}".format(e))
|
||||||
|
except (configexc.Error, configparser.Error) as e:
|
||||||
|
raise cmdexc.CommandError("set: {} - {}".format(
|
||||||
|
e.__class__.__name__, e))
|
||||||
|
|
||||||
@cmdutils.register(name='set', instance='config', win_id='win_id',
|
@cmdutils.register(name='set', instance='config', win_id='win_id',
|
||||||
completion=[Completion.section, Completion.option,
|
completion=[Completion.section, Completion.option,
|
||||||
Completion.value])
|
Completion.value])
|
||||||
@ -699,12 +712,12 @@ class ConfigManager(QObject):
|
|||||||
tabbed_browser.openurl(QUrl('qute:settings'), newtab=False)
|
tabbed_browser.openurl(QUrl('qute:settings'), newtab=False)
|
||||||
return
|
return
|
||||||
|
|
||||||
if option.endswith('?'):
|
if option.endswith('?') and option != '?':
|
||||||
option = option[:-1]
|
option = option[:-1]
|
||||||
print_ = True
|
print_ = True
|
||||||
else:
|
else:
|
||||||
try:
|
with self._handle_config_error():
|
||||||
if option.endswith('!') and value is None:
|
if option.endswith('!') and option != '!' and value is None:
|
||||||
option = option[:-1]
|
option = option[:-1]
|
||||||
val = self.get(section_, option)
|
val = self.get(section_, option)
|
||||||
layer = 'temp' if temp else 'conf'
|
layer = 'temp' if temp else 'conf'
|
||||||
@ -719,12 +732,10 @@ class ConfigManager(QObject):
|
|||||||
else:
|
else:
|
||||||
raise cmdexc.CommandError("set: The following arguments "
|
raise cmdexc.CommandError("set: The following arguments "
|
||||||
"are required: value")
|
"are required: value")
|
||||||
except (configexc.Error, configparser.Error) as e:
|
|
||||||
raise cmdexc.CommandError("set: {} - {}".format(
|
|
||||||
e.__class__.__name__, e))
|
|
||||||
|
|
||||||
if print_:
|
if print_:
|
||||||
val = self.get(section_, option, transformed=False)
|
with self._handle_config_error():
|
||||||
|
val = self.get(section_, option, transformed=False)
|
||||||
message.info(win_id, "{} {} = {}".format(
|
message.info(win_id, "{} {} = {}".format(
|
||||||
section_, option, val), immediately=True)
|
section_, option, val), immediately=True)
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
|||||||
|
|
||||||
@cmdutils.register(instance='status-command', name='set-cmd-text',
|
@cmdutils.register(instance='status-command', name='set-cmd-text',
|
||||||
scope='window', maxsplit=0)
|
scope='window', maxsplit=0)
|
||||||
def set_cmd_text_command(self, text, space=False):
|
def set_cmd_text_command(self, text, space=False, append=False):
|
||||||
"""Preset the statusbar to some text.
|
"""Preset the statusbar to some text.
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -103,6 +103,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
|||||||
Args:
|
Args:
|
||||||
text: The commandline to set.
|
text: The commandline to set.
|
||||||
space: If given, a space is added to the end.
|
space: If given, a space is added to the end.
|
||||||
|
append: If given, the text is appended to the current text.
|
||||||
"""
|
"""
|
||||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||||
window=self._win_id)
|
window=self._win_id)
|
||||||
@ -122,8 +123,14 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
|||||||
# I'm not sure what's the best thing to do here
|
# I'm not sure what's the best thing to do here
|
||||||
# https://github.com/The-Compiler/qutebrowser/issues/123
|
# https://github.com/The-Compiler/qutebrowser/issues/123
|
||||||
text = text.replace('{url}', url)
|
text = text.replace('{url}', url)
|
||||||
|
|
||||||
if space:
|
if space:
|
||||||
text += ' '
|
text += ' '
|
||||||
|
if append:
|
||||||
|
if not self.text():
|
||||||
|
raise cmdexc.CommandError("No current text!")
|
||||||
|
text = self.text() + text
|
||||||
|
|
||||||
if not text or text[0] not in modeparsers.STARTCHARS:
|
if not text or text[0] not in modeparsers.STARTCHARS:
|
||||||
raise cmdexc.CommandError(
|
raise cmdexc.CommandError(
|
||||||
"Invalid command text '{}'.".format(text))
|
"Invalid command text '{}'.".format(text))
|
||||||
|
@ -82,7 +82,7 @@ class ExternalEditor(QObject):
|
|||||||
encoding = config.get('general', 'editor-encoding')
|
encoding = config.get('general', 'editor-encoding')
|
||||||
try:
|
try:
|
||||||
with open(self._filename, 'r', encoding=encoding) as f:
|
with open(self._filename, 'r', encoding=encoding) as f:
|
||||||
text = ''.join(f.readlines()) # pragma: no branch
|
text = f.read() # pragma: no branch
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
# NOTE: Do not replace this with "raise CommandError" as it's
|
# NOTE: Do not replace this with "raise CommandError" as it's
|
||||||
# executed async.
|
# executed async.
|
||||||
|
@ -213,9 +213,9 @@ class LineParser(BaseLineParser):
|
|||||||
"""Read the data from self._configfile."""
|
"""Read the data from self._configfile."""
|
||||||
with self._open('r') as f:
|
with self._open('r') as f:
|
||||||
if self._binary:
|
if self._binary:
|
||||||
self.data = [line.rstrip(b'\n') for line in f.readlines()]
|
self.data = [line.rstrip(b'\n') for line in f]
|
||||||
else:
|
else:
|
||||||
self.data = [line.rstrip('\n') for line in f.readlines()]
|
self.data = [line.rstrip('\n') for line in f]
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
"""Save the config file."""
|
"""Save the config file."""
|
||||||
|
@ -320,10 +320,14 @@ def qt_message_handler(msg_type, context, msg):
|
|||||||
level = logging.DEBUG
|
level = logging.DEBUG
|
||||||
else:
|
else:
|
||||||
level = qt_to_logging[msg_type]
|
level = qt_to_logging[msg_type]
|
||||||
|
|
||||||
if context.function is None:
|
if context.function is None:
|
||||||
func = 'none'
|
func = 'none'
|
||||||
|
elif ':' in context.function:
|
||||||
|
func = '"{}"'.format(context.function)
|
||||||
else:
|
else:
|
||||||
func = context.function
|
func = context.function
|
||||||
|
|
||||||
if context.category is None or context.category == 'default':
|
if context.category is None or context.category == 'default':
|
||||||
name = 'qt'
|
name = 'qt'
|
||||||
else:
|
else:
|
||||||
|
@ -112,7 +112,7 @@ def _release_info():
|
|||||||
for fn in glob.glob("/etc/*-release"):
|
for fn in glob.glob("/etc/*-release"):
|
||||||
try:
|
try:
|
||||||
with open(fn, 'r', encoding='utf-8') as f:
|
with open(fn, 'r', encoding='utf-8') as f:
|
||||||
data.append((fn, ''.join(f.readlines()))) # pragma: no branch
|
data.append((fn, f.read())) # pragma: no branch
|
||||||
except OSError:
|
except OSError:
|
||||||
log.misc.exception("Error while reading {}.".format(fn))
|
log.misc.exception("Error while reading {}.".format(fn))
|
||||||
return data
|
return data
|
||||||
|
@ -48,6 +48,8 @@ PERFECT_FILES = [
|
|||||||
('tests/unit/commands/test_argparser.py',
|
('tests/unit/commands/test_argparser.py',
|
||||||
'qutebrowser/commands/argparser.py'),
|
'qutebrowser/commands/argparser.py'),
|
||||||
|
|
||||||
|
('tests/unit/browser/test_cache.py',
|
||||||
|
'qutebrowser/browser/cache.py'),
|
||||||
('tests/unit/browser/test_cookies.py',
|
('tests/unit/browser/test_cookies.py',
|
||||||
'qutebrowser/browser/cookies.py'),
|
'qutebrowser/browser/cookies.py'),
|
||||||
('tests/unit/browser/test_tabhistory.py',
|
('tests/unit/browser/test_tabhistory.py',
|
||||||
@ -248,9 +250,9 @@ def main():
|
|||||||
"""
|
"""
|
||||||
utils.change_cwd()
|
utils.change_cwd()
|
||||||
if '--check-all' in sys.argv:
|
if '--check-all' in sys.argv:
|
||||||
main_check_all()
|
return main_check_all()
|
||||||
else:
|
else:
|
||||||
main_check()
|
return main_check()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -29,6 +29,7 @@ from helpers import utils # pylint: disable=import-error
|
|||||||
({'a': [1, 2, 3]}, {'a': [1]}),
|
({'a': [1, 2, 3]}, {'a': [1]}),
|
||||||
({'a': [1, 2, 3]}, {'a': [..., 2]}),
|
({'a': [1, 2, 3]}, {'a': [..., 2]}),
|
||||||
(1.0, 1.00000001),
|
(1.0, 1.00000001),
|
||||||
|
("foobarbaz", "foo*baz"),
|
||||||
])
|
])
|
||||||
def test_partial_compare_equal(val1, val2):
|
def test_partial_compare_equal(val1, val2):
|
||||||
assert utils.partial_compare(val1, val2)
|
assert utils.partial_compare(val1, val2)
|
||||||
@ -43,6 +44,7 @@ def test_partial_compare_equal(val1, val2):
|
|||||||
([1], {1: 2}),
|
([1], {1: 2}),
|
||||||
({1: 1}, {1: [1]}),
|
({1: 1}, {1: [1]}),
|
||||||
({'a': [1, 2, 3]}, {'a': [..., 3]}),
|
({'a': [1, 2, 3]}, {'a': [..., 3]}),
|
||||||
|
("foo*baz", "foobarbaz"),
|
||||||
])
|
])
|
||||||
def test_partial_compare_not_equal(val1, val2):
|
def test_partial_compare_not_equal(val1, val2):
|
||||||
assert not utils.partial_compare(val1, val2)
|
assert not utils.partial_compare(val1, val2)
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
"""Partial comparison of dicts/lists."""
|
"""Partial comparison of dicts/lists."""
|
||||||
|
|
||||||
|
|
||||||
|
import fnmatch
|
||||||
|
|
||||||
|
|
||||||
def _partial_compare_dict(val1, val2):
|
def _partial_compare_dict(val1, val2):
|
||||||
for key in val2:
|
for key in val2:
|
||||||
if key not in val1:
|
if key not in val1:
|
||||||
@ -71,6 +74,9 @@ def partial_compare(val1, val2):
|
|||||||
elif isinstance(val2, float):
|
elif isinstance(val2, float):
|
||||||
print("Doing float comparison")
|
print("Doing float comparison")
|
||||||
equal = abs(val1 - val2) < 0.00001
|
equal = abs(val1 - val2) < 0.00001
|
||||||
|
elif isinstance(val2, str):
|
||||||
|
print("Doing string comparison")
|
||||||
|
equal = fnmatch.fnmatchcase(val1, val2)
|
||||||
else:
|
else:
|
||||||
print("Comparing via ==")
|
print("Comparing via ==")
|
||||||
equal = val1 == val2
|
equal = val1 == val2
|
||||||
|
1
tests/integration/data/downloads/mhtml/simple/requests
Normal file
1
tests/integration/data/downloads/mhtml/simple/requests
Normal file
@ -0,0 +1 @@
|
|||||||
|
simple.html
|
10
tests/integration/data/downloads/mhtml/simple/simple.html
Normal file
10
tests/integration/data/downloads/mhtml/simple/simple.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Simple MHTML test</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a href="/">normal link to another page</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
20
tests/integration/data/downloads/mhtml/simple/simple.mht
Normal file
20
tests/integration/data/downloads/mhtml/simple/simple.mht
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
Content-Type: multipart/related; boundary="---=_qute-6d584056-b1e4-4882-91e6-d4a6d23adb67"
|
||||||
|
MIME-Version: 1.0
|
||||||
|
|
||||||
|
-----=_qute-6d584056-b1e4-4882-91e6-d4a6d23adb67
|
||||||
|
Content-Location: http://localhost:1234/data/downloads/mhtml/simple/simple.html
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/html; charset="UTF-8"
|
||||||
|
Content-Transfer-Encoding: quoted-printable
|
||||||
|
|
||||||
|
<!DOCTYPE=20html><html><head>
|
||||||
|
=20=20=20=20=20=20=20=20<meta=20charset=3D"utf-8">
|
||||||
|
=20=20=20=20=20=20=20=20<title>Simple=20MHTML=20test</title>
|
||||||
|
=20=20=20=20</head>
|
||||||
|
=20=20=20=20<body>
|
||||||
|
=20=20=20=20=20=20=20=20<a=20href=3D"/">normal=20link=20to=20another=20page=
|
||||||
|
</a>
|
||||||
|
=20=20=20=20
|
||||||
|
|
||||||
|
</body></html>
|
||||||
|
-----=_qute-6d584056-b1e4-4882-91e6-d4a6d23adb67--
|
10
tests/integration/data/hints/link.html
Normal file
10
tests/integration/data/hints/link.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>A link to use hints on</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a href="/data/hello.txt">Follow me!</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -4,6 +4,7 @@ Feature: Going back and forward.
|
|||||||
Scenario: Going back/forward
|
Scenario: Going back/forward
|
||||||
Given I open data/backforward/1.txt
|
Given I open data/backforward/1.txt
|
||||||
When I open data/backforward/2.txt
|
When I open data/backforward/2.txt
|
||||||
|
And I run :tab-only
|
||||||
And I run :back
|
And I run :back
|
||||||
And I wait until data/backforward/1.txt is loaded
|
And I wait until data/backforward/1.txt is loaded
|
||||||
And I reload
|
And I reload
|
||||||
@ -15,13 +16,81 @@ Feature: Going back and forward.
|
|||||||
data/backforward/2.txt
|
data/backforward/2.txt
|
||||||
data/backforward/1.txt
|
data/backforward/1.txt
|
||||||
data/backforward/2.txt
|
data/backforward/2.txt
|
||||||
|
And the session should look like:
|
||||||
|
windows:
|
||||||
|
- tabs:
|
||||||
|
- history:
|
||||||
|
- url: http://localhost:*/data/backforward/1.txt
|
||||||
|
- active: true
|
||||||
|
url: http://localhost:*/data/backforward/2.txt
|
||||||
|
|
||||||
Scenario: Going back without history
|
Scenario: Going back in a new tab
|
||||||
Given I open data/backforward/1.txt
|
Given I open data/backforward/1.txt
|
||||||
When I run :back
|
When I open data/backforward/2.txt
|
||||||
Then the error "At beginning of history." should be shown.
|
And I run :tab-only
|
||||||
|
And I run :back -t
|
||||||
|
And I wait until data/backforward/1.txt is loaded
|
||||||
|
Then the session should look like:
|
||||||
|
windows:
|
||||||
|
- tabs:
|
||||||
|
- history:
|
||||||
|
- url: http://localhost:*/data/backforward/1.txt
|
||||||
|
- active: true
|
||||||
|
url: http://localhost:*/data/backforward/2.txt
|
||||||
|
- active: true
|
||||||
|
history:
|
||||||
|
- active: true
|
||||||
|
url: http://localhost:*/data/backforward/1.txt
|
||||||
|
- url: http://localhost:*/data/backforward/2.txt
|
||||||
|
|
||||||
Scenario: Going forward without history
|
Scenario: Going back in a new background tab
|
||||||
Given I open data/backforward/1.txt
|
Given I open data/backforward/1.txt
|
||||||
When I run :forward
|
When I open data/backforward/2.txt
|
||||||
Then the error "At end of history." should be shown.
|
And I run :tab-only
|
||||||
|
And I run :back -b
|
||||||
|
And I wait until data/backforward/1.txt is loaded
|
||||||
|
Then the session should look like:
|
||||||
|
windows:
|
||||||
|
- tabs:
|
||||||
|
- active: true
|
||||||
|
history:
|
||||||
|
- url: http://localhost:*/data/backforward/1.txt
|
||||||
|
- active: true
|
||||||
|
url: http://localhost:*/data/backforward/2.txt
|
||||||
|
- history:
|
||||||
|
- active: true
|
||||||
|
url: http://localhost:*/data/backforward/1.txt
|
||||||
|
- url: http://localhost:*/data/backforward/2.txt
|
||||||
|
|
||||||
|
Scenario: Going back in a new window
|
||||||
|
Given I have a fresh instance
|
||||||
|
When I open data/backforward/1.txt
|
||||||
|
And I open data/backforward/2.txt
|
||||||
|
And I run :back -w
|
||||||
|
And I wait until data/backforward/1.txt is loaded
|
||||||
|
Then the session should look like:
|
||||||
|
windows:
|
||||||
|
- tabs:
|
||||||
|
- active: true
|
||||||
|
history:
|
||||||
|
- url: about:blank
|
||||||
|
- url: http://localhost:*/data/backforward/1.txt
|
||||||
|
- active: true
|
||||||
|
url: http://localhost:*/data/backforward/2.txt
|
||||||
|
- tabs:
|
||||||
|
- active: true
|
||||||
|
history:
|
||||||
|
- url: about:blank
|
||||||
|
- active: true
|
||||||
|
url: http://localhost:*/data/backforward/1.txt
|
||||||
|
- url: http://localhost:*/data/backforward/2.txt
|
||||||
|
|
||||||
|
Scenario: Going back without history
|
||||||
|
Given I open data/backforward/1.txt
|
||||||
|
When I run :back
|
||||||
|
Then the error "At beginning of history." should be shown.
|
||||||
|
|
||||||
|
Scenario: Going forward without history
|
||||||
|
Given I open data/backforward/1.txt
|
||||||
|
When I run :forward
|
||||||
|
Then the error "At end of history." should be shown.
|
||||||
|
@ -53,6 +53,13 @@ def run_command_given(quteproc, command):
|
|||||||
quteproc.send_cmd(command)
|
quteproc.send_cmd(command)
|
||||||
|
|
||||||
|
|
||||||
|
@bdd.given("I have a fresh instance")
|
||||||
|
def fresh_instance(quteproc):
|
||||||
|
"""Restart qutebrowser instance for tests needing a fresh state."""
|
||||||
|
quteproc.terminate()
|
||||||
|
quteproc.start()
|
||||||
|
|
||||||
|
|
||||||
@bdd.when(bdd.parsers.parse("I run {command}"))
|
@bdd.when(bdd.parsers.parse("I run {command}"))
|
||||||
def run_command_when(quteproc, httpbin, command):
|
def run_command_when(quteproc, httpbin, command):
|
||||||
command = command.replace('(port)', str(httpbin.port))
|
command = command.replace('(port)', str(httpbin.port))
|
||||||
|
20
tests/integration/features/hints.feature
Normal file
20
tests/integration/features/hints.feature
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
Feature: Using hints
|
||||||
|
|
||||||
|
Scenario: Following a hint.
|
||||||
|
When I open data/hints/link.html
|
||||||
|
And I run :hint links normal
|
||||||
|
And I run :follow-hint a
|
||||||
|
And I wait until data/hello.txt is loaded
|
||||||
|
Then the requests should be:
|
||||||
|
data/hints/link.html
|
||||||
|
data/hello.txt
|
||||||
|
|
||||||
|
Scenario: Using :follow-hint outside of hint mode (issue 1105)
|
||||||
|
When I run :follow-hint
|
||||||
|
Then the error "follow-hint: This command is only allowed in hint mode." should be shown.
|
||||||
|
|
||||||
|
Scenario: Using :follow-hint with an invalid index.
|
||||||
|
When I open data/hints/link.html
|
||||||
|
And I run :hint links normal
|
||||||
|
And I run :follow-hint xyz
|
||||||
|
Then the error "No hint xyz!" should be shown.
|
44
tests/integration/features/misc.feature
Normal file
44
tests/integration/features/misc.feature
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
Feature: Various utility commands.
|
||||||
|
|
||||||
|
Scenario: :set-cmd-text and :command-accept
|
||||||
|
When I run :set-cmd-text :message-info "Hello World"
|
||||||
|
And I run :command-accept
|
||||||
|
Then the message "Hello World" should be shown.
|
||||||
|
|
||||||
|
Scenario: :set-cmd-text with two commands
|
||||||
|
When I run :set-cmd-text :message-info test ;; message-error error
|
||||||
|
And I run :command-accept
|
||||||
|
Then the message "test" should be shown.
|
||||||
|
And the error "error" should be shown.
|
||||||
|
|
||||||
|
Scenario: :set-cmd-text with URL replacement
|
||||||
|
When I open data/hello.txt
|
||||||
|
When I run :set-cmd-text :message-info >{url}<
|
||||||
|
And I run :command-accept
|
||||||
|
Then the message ">http://localhost:*/hello.txt<" should be shown.
|
||||||
|
|
||||||
|
Scenario: :set-cmd-text with -s and -a
|
||||||
|
When I run :set-cmd-text -s :message-info "foo
|
||||||
|
And I run :set-cmd-text -a bar"
|
||||||
|
And I run :command-accept
|
||||||
|
Then the message "foo bar" should be shown.
|
||||||
|
|
||||||
|
Scenario: :set-cmd-text with -a but without text
|
||||||
|
When I run :set-cmd-text -a foo
|
||||||
|
Then the error "No current text!" should be shown.
|
||||||
|
|
||||||
|
Scenario: :set-cmd-text with invalid command
|
||||||
|
When I run :set-cmd-text foo
|
||||||
|
Then the error "Invalid command text 'foo'." should be shown.
|
||||||
|
|
||||||
|
Scenario: :message-error
|
||||||
|
When I run :message-error "Hello World"
|
||||||
|
Then the error "Hello World" should be shown.
|
||||||
|
|
||||||
|
Scenario: :message-info
|
||||||
|
When I run :message-info "Hello World"
|
||||||
|
Then the message "Hello World" should be shown.
|
||||||
|
|
||||||
|
Scenario: :message-warning
|
||||||
|
When I run :message-warning "Hello World"
|
||||||
|
Then the warning "Hello World" should be shown.
|
101
tests/integration/features/set.feature
Normal file
101
tests/integration/features/set.feature
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
Feature: Setting settings.
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given I set ui -> message-timeout to 100
|
||||||
|
|
||||||
|
Scenario: Using :set
|
||||||
|
When I run :set colors statusbar.bg magenta
|
||||||
|
Then colors -> statusbar.bg should be magenta
|
||||||
|
|
||||||
|
Scenario: Only a section
|
||||||
|
When I run :set colors
|
||||||
|
Then the error "set: Either both section and option have to be given, or neither!" should be shown.
|
||||||
|
|
||||||
|
Scenario: Without value
|
||||||
|
When I run :set colors statusbar.bg
|
||||||
|
Then the error "set: The following arguments are required: value" should be shown.
|
||||||
|
|
||||||
|
Scenario: Invalid section
|
||||||
|
When I run :set blah blub foo
|
||||||
|
Then the error "set: Section 'blah' does not exist!" should be shown.
|
||||||
|
|
||||||
|
Scenario: Invalid option
|
||||||
|
When I run :set general blub foo
|
||||||
|
Then the error "set: No option 'blub' in section 'general'" should be shown.
|
||||||
|
|
||||||
|
Scenario: Toggling an option
|
||||||
|
When I run :set general auto-save-config false
|
||||||
|
And I run :set general auto-save-config!
|
||||||
|
Then general -> auto-save-config should be True
|
||||||
|
|
||||||
|
Scenario: Toggling a non-bool option
|
||||||
|
When I run :set colors statusbar.bg!
|
||||||
|
Then the error "set: Attempted inversion of non-boolean value." should be shown.
|
||||||
|
|
||||||
|
Scenario: Getting an option
|
||||||
|
When I run :set colors statusbar.bg magenta
|
||||||
|
And I run :set colors statusbar.bg?
|
||||||
|
Then the message "colors statusbar.bg = magenta" should be shown.
|
||||||
|
|
||||||
|
Scenario: Using -p
|
||||||
|
When I run :set -p colors statusbar.bg red
|
||||||
|
Then the message "colors statusbar.bg = red" should be shown.
|
||||||
|
|
||||||
|
Scenario: Using ! and -p
|
||||||
|
When I run :set general auto-save-config false
|
||||||
|
And I run :set -p general auto-save-config!
|
||||||
|
Then the message "general auto-save-config = True" should be shown.
|
||||||
|
|
||||||
|
Scenario: Setting an invalid value
|
||||||
|
When I run :set general auto-save-config blah
|
||||||
|
Then the error "set: Invalid value 'blah' - must be a boolean!" should be shown.
|
||||||
|
|
||||||
|
Scenario: Setting a temporary option
|
||||||
|
# We don't actually check if the option is temporary as this isn't easy
|
||||||
|
# to check.
|
||||||
|
When I run :set -t colors statusbar.bg green
|
||||||
|
Then colors -> statusbar.bg should be green
|
||||||
|
|
||||||
|
Scenario: Opening qute:settings
|
||||||
|
When I run :set
|
||||||
|
And I wait for "load status for <qutebrowser.browser.webview.WebView tab_id=0 url='qute:settings'>: LoadStatus.success" in the log
|
||||||
|
Then the session should look like:
|
||||||
|
windows:
|
||||||
|
- tabs:
|
||||||
|
- active: true
|
||||||
|
history:
|
||||||
|
- url: about:blank
|
||||||
|
- active: true
|
||||||
|
url: qute:settings
|
||||||
|
|
||||||
|
Scenario: Empty option with ? (issue 1109)
|
||||||
|
When I run :set general ?
|
||||||
|
Then the error "set: The following arguments are required: value" should be shown.
|
||||||
|
|
||||||
|
Scenario: Invalid section and empty option with ? (issue 1109)
|
||||||
|
When I run :set blah ?
|
||||||
|
Then the error "set: The following arguments are required: value" should be shown.
|
||||||
|
|
||||||
|
Scenario: Invalid option with ? (issue 1109)
|
||||||
|
When I run :set general foo?
|
||||||
|
Then the error "set: No option 'foo' in section 'general'" should be shown.
|
||||||
|
|
||||||
|
Scenario: Invalid section/option with ? (issue 1109)
|
||||||
|
When I run :set blah foo ?
|
||||||
|
Then the error "set: Section 'blah' does not exist!" should be shown.
|
||||||
|
|
||||||
|
Scenario: Empty option with !
|
||||||
|
When I run :set general !
|
||||||
|
Then the error "set: The following arguments are required: value" should be shown.
|
||||||
|
|
||||||
|
Scenario: Invalid section and empty option with !
|
||||||
|
When I run :set blah !
|
||||||
|
Then the error "set: The following arguments are required: value" should be shown.
|
||||||
|
|
||||||
|
Scenario: Invalid option with !
|
||||||
|
When I run :set general foo!
|
||||||
|
Then the error "set: No option 'foo' in section 'general'" should be shown.
|
||||||
|
|
||||||
|
Scenario: Invalid section/option with !
|
||||||
|
When I run :set blah foo !
|
||||||
|
Then the error "set: Section 'blah' does not exist!" should be shown.
|
21
tests/integration/features/test_hints.py
Normal file
21
tests/integration/features/test_hints.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||||
|
|
||||||
|
# Copyright 2015 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import pytest_bdd as bdd
|
||||||
|
bdd.scenarios('hints.feature')
|
21
tests/integration/features/test_misc.py
Normal file
21
tests/integration/features/test_misc.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||||
|
|
||||||
|
# Copyright 2015 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import pytest_bdd as bdd
|
||||||
|
bdd.scenarios('misc.feature')
|
32
tests/integration/features/test_set.py
Normal file
32
tests/integration/features/test_set.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||||
|
|
||||||
|
# Copyright 2015 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import pytest_bdd as bdd
|
||||||
|
bdd.scenarios('set.feature')
|
||||||
|
|
||||||
|
|
||||||
|
@bdd.then(bdd.parsers.parse("{section} -> {option} should be {value}"))
|
||||||
|
def check_option(quteproc, section, option, value):
|
||||||
|
quteproc.send_cmd(':set {} {}?'.format(section, option))
|
||||||
|
msg = quteproc.wait_for(loglevel=logging.INFO, category='message',
|
||||||
|
message='{} {} = *'.format(section, option))
|
||||||
|
actual_value = msg.message.split(' = ')[1]
|
||||||
|
assert actual_value == value
|
@ -68,7 +68,9 @@ class LogLine(testprocess.Line):
|
|||||||
(?P<timestamp>\d\d:\d\d:\d\d)
|
(?P<timestamp>\d\d:\d\d:\d\d)
|
||||||
\ (?P<loglevel>VDEBUG|DEBUG|INFO|WARNING|ERROR)
|
\ (?P<loglevel>VDEBUG|DEBUG|INFO|WARNING|ERROR)
|
||||||
\ +(?P<category>\w+)
|
\ +(?P<category>\w+)
|
||||||
\ +(?P<module>(\w+|Unknown\ module)):(?P<function>\w+):(?P<line>\d+)
|
\ +(?P<module>(\w+|Unknown\ module)):
|
||||||
|
(?P<function>[^"][^:]*|"[^"]+"):
|
||||||
|
(?P<line>\d+)
|
||||||
\ (?P<message>.+)
|
\ (?P<message>.+)
|
||||||
""", re.VERBOSE)
|
""", re.VERBOSE)
|
||||||
|
|
||||||
@ -94,9 +96,22 @@ class LogLine(testprocess.Line):
|
|||||||
else:
|
else:
|
||||||
self.module = module
|
self.module = module
|
||||||
|
|
||||||
self.function = match.group('function')
|
function = match.group('function')
|
||||||
self.line = int(match.group('line'))
|
if function == 'none':
|
||||||
self.message = match.group('message')
|
self.function = None
|
||||||
|
else:
|
||||||
|
self.function = function.strip('"')
|
||||||
|
|
||||||
|
line = int(match.group('line'))
|
||||||
|
if self.function is None and line == 0:
|
||||||
|
self.line = None
|
||||||
|
else:
|
||||||
|
self.line = line
|
||||||
|
|
||||||
|
msg_match = re.match(r'^(\[(?P<prefix>\d+s ago)\] )?(?P<message>.*)',
|
||||||
|
match.group('message'))
|
||||||
|
self.prefix = msg_match.group('prefix')
|
||||||
|
self.message = msg_match.group('message')
|
||||||
|
|
||||||
self.expected = is_ignored_qt_message(self.message)
|
self.expected = is_ignored_qt_message(self.message)
|
||||||
|
|
||||||
@ -177,7 +192,7 @@ class QuteProc(testprocess.Process):
|
|||||||
ipc.send_to_running_instance(self._ipc_socket, [command],
|
ipc.send_to_running_instance(self._ipc_socket, [command],
|
||||||
target_arg='')
|
target_arg='')
|
||||||
self.wait_for(category='commands', module='command', function='run',
|
self.wait_for(category='commands', module='command', function='run',
|
||||||
message='Calling *')
|
message='command called: *')
|
||||||
|
|
||||||
def set_setting(self, sect, opt, value):
|
def set_setting(self, sect, opt, value):
|
||||||
self.send_cmd(':set "{}" "{}" "{}"'.format(sect, opt, value))
|
self.send_cmd(':set "{}" "{}" "{}"'.format(sect, opt, value))
|
||||||
@ -197,7 +212,7 @@ class QuteProc(testprocess.Process):
|
|||||||
message=message)
|
message=message)
|
||||||
line.expected = True
|
line.expected = True
|
||||||
|
|
||||||
def wait_for(self, timeout=15000, **kwargs):
|
def wait_for(self, timeout=None, **kwargs):
|
||||||
"""Override testprocess.wait_for to check past messages.
|
"""Override testprocess.wait_for to check past messages.
|
||||||
|
|
||||||
self._data is cleared after every test to provide at least some
|
self._data is cleared after every test to provide at least some
|
||||||
|
103
tests/integration/test_mhtml_e2e.py
Normal file
103
tests/integration/test_mhtml_e2e.py
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||||
|
|
||||||
|
# Copyright 2015 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""Test mhtml downloads based on sample files."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
def collect_tests():
|
||||||
|
basedir = os.path.dirname(__file__)
|
||||||
|
datadir = os.path.join(basedir, 'data', 'downloads', 'mhtml')
|
||||||
|
files = os.listdir(datadir)
|
||||||
|
return files
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_line(line):
|
||||||
|
line = line.rstrip('\n')
|
||||||
|
line = re.sub('boundary="---=_qute-[0-9a-f-]+"',
|
||||||
|
'boundary="---=_qute-UUID"', line)
|
||||||
|
line = re.sub('^-----=_qute-[0-9a-f-]+$', '-----=_qute-UUID', line)
|
||||||
|
line = re.sub(r'localhost:\d{1,5}', 'localhost:(port)', line)
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
class DownloadDir:
|
||||||
|
|
||||||
|
"""Abstraction over a download directory."""
|
||||||
|
|
||||||
|
def __init__(self, tmpdir):
|
||||||
|
self._tmpdir = tmpdir
|
||||||
|
self.location = str(tmpdir)
|
||||||
|
|
||||||
|
def read_file(self):
|
||||||
|
files = self._tmpdir.listdir()
|
||||||
|
assert len(files) == 1
|
||||||
|
|
||||||
|
with open(str(files[0]), 'r', encoding='utf-8') as f:
|
||||||
|
return f.readlines()
|
||||||
|
|
||||||
|
def compare_mhtml(self, filename):
|
||||||
|
with open(filename, 'r', encoding='utf-8') as f:
|
||||||
|
expected_data = [normalize_line(line) for line in f]
|
||||||
|
actual_data = self.read_file()
|
||||||
|
actual_data = [normalize_line(line) for line in actual_data]
|
||||||
|
assert actual_data == expected_data
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def download_dir(tmpdir):
|
||||||
|
return DownloadDir(tmpdir)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('test_name', collect_tests())
|
||||||
|
def test_mhtml(test_name, download_dir, quteproc, httpbin):
|
||||||
|
quteproc.set_setting('storage', 'download-directory',
|
||||||
|
download_dir.location)
|
||||||
|
quteproc.set_setting('storage', 'prompt-download-directory', 'false')
|
||||||
|
|
||||||
|
test_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
||||||
|
'data', 'downloads', 'mhtml', test_name)
|
||||||
|
test_path = 'data/downloads/mhtml/{}'.format(test_name)
|
||||||
|
|
||||||
|
quteproc.open_path('{}/{}.html'.format(test_path, test_name))
|
||||||
|
download_dest = os.path.join(download_dir.location,
|
||||||
|
'{}-downloaded.mht'.format(test_name))
|
||||||
|
quteproc.send_cmd(':download --mhtml --dest "{}"'.format(download_dest))
|
||||||
|
quteproc.wait_for(category='downloads', module='mhtml',
|
||||||
|
function='finish_file',
|
||||||
|
message='All assets downloaded, ready to finish off!')
|
||||||
|
|
||||||
|
expected_file = os.path.join(test_dir, '{}.mht'.format(test_name))
|
||||||
|
download_dir.compare_mhtml(expected_file)
|
||||||
|
|
||||||
|
with open(os.path.join(test_dir, 'requests'), encoding='utf-8') as f:
|
||||||
|
expected_requests = []
|
||||||
|
for line in f:
|
||||||
|
if line.startswith('#'):
|
||||||
|
continue
|
||||||
|
path = '/{}/{}'.format(test_path, line.strip())
|
||||||
|
expected_requests.append(httpbin.Request('GET', path))
|
||||||
|
|
||||||
|
actual_requests = httpbin.get_requests()
|
||||||
|
assert sorted(actual_requests) == sorted(expected_requests)
|
@ -19,8 +19,14 @@
|
|||||||
|
|
||||||
"""Test the quteproc fixture used for tests."""
|
"""Test the quteproc fixture used for tests."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import datetime
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
import quteprocess
|
||||||
|
from qutebrowser.utils import log
|
||||||
|
|
||||||
|
|
||||||
def test_quteproc_error_message(qtbot, quteproc):
|
def test_quteproc_error_message(qtbot, quteproc):
|
||||||
"""Make sure the test fails with an unexpected error message."""
|
"""Make sure the test fails with an unexpected error message."""
|
||||||
@ -36,3 +42,76 @@ def test_qt_log_ignore(qtbot, quteproc):
|
|||||||
"""Make sure the test passes when logging a qt_log_ignore message."""
|
"""Make sure the test passes when logging a qt_log_ignore message."""
|
||||||
with qtbot.waitSignal(quteproc.got_error, raising=True):
|
with qtbot.waitSignal(quteproc.got_error, raising=True):
|
||||||
quteproc.send_cmd(':message-error "SpellCheck: test"')
|
quteproc.send_cmd(':message-error "SpellCheck: test"')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('data, attrs', [
|
||||||
|
(
|
||||||
|
# Normal message
|
||||||
|
'01:02:03 DEBUG init earlyinit:init_log:280 Log initialized.',
|
||||||
|
{
|
||||||
|
'timestamp': datetime.datetime(year=1900, month=1, day=1,
|
||||||
|
hour=1, minute=2, second=3),
|
||||||
|
'loglevel': logging.DEBUG,
|
||||||
|
'category': 'init',
|
||||||
|
'module': 'earlyinit',
|
||||||
|
'function': 'init_log',
|
||||||
|
'line': 280,
|
||||||
|
'message': 'Log initialized.',
|
||||||
|
'expected': False,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
(
|
||||||
|
# VDEBUG
|
||||||
|
'00:00:00 VDEBUG foo foo:foo:0 test',
|
||||||
|
{'loglevel': log.VDEBUG_LEVEL}
|
||||||
|
),
|
||||||
|
(
|
||||||
|
# Unknown module
|
||||||
|
'00:00:00 WARNING qt Unknown module:none:0 test',
|
||||||
|
{'module': None, 'function': None, 'line': None},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
# Expected message
|
||||||
|
'00:00:00 VDEBUG foo foo:foo:0 SpellCheck: test',
|
||||||
|
{'expected': True},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
# Weird Qt location
|
||||||
|
'00:00:00 DEBUG qt qnetworkreplyhttpimpl:"void '
|
||||||
|
'QNetworkReplyHttpImplPrivate::error(QNetworkReply::NetworkError, '
|
||||||
|
'const QString&)":1929 QNetworkReplyImplPrivate::error: Internal '
|
||||||
|
'problem, this method must only be called once.',
|
||||||
|
{
|
||||||
|
'module': 'qnetworkreplyhttpimpl',
|
||||||
|
'function': 'void QNetworkReplyHttpImplPrivate::error('
|
||||||
|
'QNetworkReply::NetworkError, const QString&)',
|
||||||
|
'line': 1929
|
||||||
|
}
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'00:00:00 WARNING qt qxcbxsettings:"QXcbXSettings::'
|
||||||
|
'QXcbXSettings(QXcbScreen*)":233 '
|
||||||
|
'QXcbXSettings::QXcbXSettings(QXcbScreen*) Failed to get selection '
|
||||||
|
'owner for XSETTINGS_S atom ',
|
||||||
|
{
|
||||||
|
'module': 'qxcbxsettings',
|
||||||
|
'function': 'QXcbXSettings::QXcbXSettings(QXcbScreen*)',
|
||||||
|
'line': 233,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
(
|
||||||
|
# With [2s ago] marker
|
||||||
|
'00:00:00 DEBUG foo foo:foo:0 [2s ago] test',
|
||||||
|
{'prefix': '2s ago', 'message': 'test'}
|
||||||
|
),
|
||||||
|
])
|
||||||
|
def test_log_line_parse(data, attrs):
|
||||||
|
line = quteprocess.LogLine(data)
|
||||||
|
for name, expected in attrs.items():
|
||||||
|
actual = getattr(line, name)
|
||||||
|
assert actual == expected, name
|
||||||
|
|
||||||
|
|
||||||
|
def test_log_line_no_match():
|
||||||
|
with pytest.raises(quteprocess.NoLineMatch):
|
||||||
|
quteprocess.LogLine("Hello World!")
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"""Base class for a subprocess run for tests.."""
|
"""Base class for a subprocess run for tests.."""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import os
|
||||||
import time
|
import time
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
|
||||||
@ -136,7 +137,9 @@ class Process(QObject):
|
|||||||
print("INVALID: {}".format(line))
|
print("INVALID: {}".format(line))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if parsed is not None:
|
if parsed is None:
|
||||||
|
print("IGNORED: {}".format(line))
|
||||||
|
else:
|
||||||
self._data.append(parsed)
|
self._data.append(parsed)
|
||||||
self.new_data.emit(parsed)
|
self.new_data.emit(parsed)
|
||||||
|
|
||||||
@ -213,7 +216,7 @@ class Process(QObject):
|
|||||||
else:
|
else:
|
||||||
return value == expected
|
return value == expected
|
||||||
|
|
||||||
def wait_for(self, timeout=15000, **kwargs):
|
def wait_for(self, timeout=None, **kwargs):
|
||||||
"""Wait until a given value is found in the data.
|
"""Wait until a given value is found in the data.
|
||||||
|
|
||||||
Keyword arguments to this function get interpreted as attributes of the
|
Keyword arguments to this function get interpreted as attributes of the
|
||||||
@ -223,6 +226,11 @@ class Process(QObject):
|
|||||||
Return:
|
Return:
|
||||||
The matched line.
|
The matched line.
|
||||||
"""
|
"""
|
||||||
|
if timeout is None:
|
||||||
|
if 'CI' in os.environ:
|
||||||
|
timeout = 15000
|
||||||
|
else:
|
||||||
|
timeout = 5000
|
||||||
# Search existing messages
|
# Search existing messages
|
||||||
for line in self._data:
|
for line in self._data:
|
||||||
matches = []
|
matches = []
|
||||||
|
@ -35,6 +35,55 @@ def preload_cache(cache, url='http://www.example.com/', content=b'foobar'):
|
|||||||
cache.insert(device)
|
cache.insert(device)
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_config_change_cache_size(config_stub, tmpdir):
|
||||||
|
"""Change cache size and emit signal to trigger on_config_changed."""
|
||||||
|
max_cache_size = 1024
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': max_cache_size},
|
||||||
|
'general': {'private-browsing': False}
|
||||||
|
}
|
||||||
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
|
assert disk_cache.maximumCacheSize() == max_cache_size
|
||||||
|
|
||||||
|
config_stub.set('storage', 'cache-size', max_cache_size * 2)
|
||||||
|
assert disk_cache.maximumCacheSize() == max_cache_size * 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_config_enable_private_browsing(config_stub, tmpdir):
|
||||||
|
"""Change private-browsing config to True and emit signal."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': False}
|
||||||
|
}
|
||||||
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
|
assert disk_cache.cacheSize() == 0
|
||||||
|
preload_cache(disk_cache)
|
||||||
|
assert disk_cache.cacheSize() > 0
|
||||||
|
|
||||||
|
config_stub.set('general', 'private-browsing', True)
|
||||||
|
assert disk_cache.cacheSize() == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_config_disable_private_browsing(config_stub, tmpdir):
|
||||||
|
"""Change private-browsing config to False and emit signal."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': True}
|
||||||
|
}
|
||||||
|
url = 'http://qutebrowser.org'
|
||||||
|
metadata = QNetworkCacheMetaData()
|
||||||
|
metadata.setUrl(QUrl(url))
|
||||||
|
assert metadata.isValid()
|
||||||
|
|
||||||
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
|
assert disk_cache.prepare(metadata) is None
|
||||||
|
|
||||||
|
config_stub.set('general', 'private-browsing', False)
|
||||||
|
content = b'cute'
|
||||||
|
preload_cache(disk_cache, url, content)
|
||||||
|
assert disk_cache.data(QUrl(url)).readAll() == content
|
||||||
|
|
||||||
|
|
||||||
def test_cache_size_leq_max_cache_size(config_stub, tmpdir):
|
def test_cache_size_leq_max_cache_size(config_stub, tmpdir):
|
||||||
"""Test cacheSize <= MaximumCacheSize when cache is activated."""
|
"""Test cacheSize <= MaximumCacheSize when cache is activated."""
|
||||||
limit = 100
|
limit = 100
|
||||||
@ -54,6 +103,63 @@ def test_cache_size_leq_max_cache_size(config_stub, tmpdir):
|
|||||||
assert disk_cache.cacheSize() < limit+100
|
assert disk_cache.cacheSize() < limit+100
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_size_deactivated(config_stub, tmpdir):
|
||||||
|
"""Confirm that the cache size returns 0 when deactivated."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': True}
|
||||||
|
}
|
||||||
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
|
assert disk_cache.cacheSize() == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_existing_metadata_file(config_stub, tmpdir):
|
||||||
|
"""Test querying existing meta data file from activated cache."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': False}
|
||||||
|
}
|
||||||
|
url = 'http://qutebrowser.org'
|
||||||
|
content = b'foobar'
|
||||||
|
|
||||||
|
metadata = QNetworkCacheMetaData()
|
||||||
|
metadata.setUrl(QUrl(url))
|
||||||
|
assert metadata.isValid()
|
||||||
|
|
||||||
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
|
device = disk_cache.prepare(metadata)
|
||||||
|
assert device is not None
|
||||||
|
device.write(content)
|
||||||
|
disk_cache.insert(device)
|
||||||
|
disk_cache.updateMetaData(metadata)
|
||||||
|
|
||||||
|
files = list(tmpdir.visit(fil=lambda path: path.isfile()))
|
||||||
|
assert len(files) == 1
|
||||||
|
assert disk_cache.fileMetaData(str(files[0])) == metadata
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_nonexistent_metadata_file(config_stub, tmpdir):
|
||||||
|
"""Test querying nonexistent meta data file from activated cache."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': False}
|
||||||
|
}
|
||||||
|
|
||||||
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
|
cache_file = disk_cache.fileMetaData("nosuchfile")
|
||||||
|
assert cache_file.isValid() == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_deactivated_metadata_file(config_stub, tmpdir):
|
||||||
|
"""Test querying meta data file when cache is deactivated."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': True}
|
||||||
|
}
|
||||||
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
|
assert disk_cache.fileMetaData("foo") == QNetworkCacheMetaData()
|
||||||
|
|
||||||
|
|
||||||
def test_cache_deactivated_private_browsing(config_stub, tmpdir):
|
def test_cache_deactivated_private_browsing(config_stub, tmpdir):
|
||||||
"""Test if cache is deactivated in private-browsing mode."""
|
"""Test if cache is deactivated in private-browsing mode."""
|
||||||
config_stub.data = {
|
config_stub.data = {
|
||||||
@ -104,12 +210,15 @@ def test_cache_deactivated_remove_data(config_stub, tmpdir):
|
|||||||
assert disk_cache.remove(url) == False
|
assert disk_cache.remove(url) == False
|
||||||
|
|
||||||
|
|
||||||
def test_cache_insert_data(tmpdir):
|
def test_cache_insert_data(config_stub, tmpdir):
|
||||||
"""Test if entries inserted into the cache are actually there."""
|
"""Test if entries inserted into the cache are actually there."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': False}
|
||||||
|
}
|
||||||
url = 'http://qutebrowser.org'
|
url = 'http://qutebrowser.org'
|
||||||
content = b'foobar'
|
content = b'foobar'
|
||||||
disk_cache = QNetworkDiskCache()
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
disk_cache.setCacheDirectory(str(tmpdir))
|
|
||||||
assert disk_cache.cacheSize() == 0
|
assert disk_cache.cacheSize() == 0
|
||||||
|
|
||||||
preload_cache(disk_cache, url, content)
|
preload_cache(disk_cache, url, content)
|
||||||
@ -118,11 +227,37 @@ def test_cache_insert_data(tmpdir):
|
|||||||
assert disk_cache.data(QUrl(url)).readAll() == content
|
assert disk_cache.data(QUrl(url)).readAll() == content
|
||||||
|
|
||||||
|
|
||||||
def test_cache_remove_data(tmpdir):
|
def test_cache_deactivated_insert_data(config_stub, tmpdir):
|
||||||
"""Test if a previously inserted entry can be removed from the cache."""
|
"""Insert data when cache is deactivated."""
|
||||||
|
# First create QNetworkDiskCache just to get a valid QIODevice from it
|
||||||
url = 'http://qutebrowser.org'
|
url = 'http://qutebrowser.org'
|
||||||
disk_cache = QNetworkDiskCache()
|
disk_cache = QNetworkDiskCache()
|
||||||
disk_cache.setCacheDirectory(str(tmpdir))
|
disk_cache.setCacheDirectory(str(tmpdir))
|
||||||
|
metadata = QNetworkCacheMetaData()
|
||||||
|
metadata.setUrl(QUrl(url))
|
||||||
|
device = disk_cache.prepare(metadata)
|
||||||
|
assert device is not None
|
||||||
|
|
||||||
|
# Now create a deactivated DiskCache and insert the valid device created
|
||||||
|
# above (there probably is a better way to get a valid QIODevice...)
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': True}
|
||||||
|
}
|
||||||
|
|
||||||
|
deactivated_cache = cache.DiskCache(str(tmpdir))
|
||||||
|
assert deactivated_cache.insert(device) is None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_remove_data(config_stub, tmpdir):
|
||||||
|
"""Test if a previously inserted entry can be removed from the cache."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': False}
|
||||||
|
}
|
||||||
|
url = 'http://qutebrowser.org'
|
||||||
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
preload_cache(disk_cache, url)
|
preload_cache(disk_cache, url)
|
||||||
assert disk_cache.cacheSize() > 0
|
assert disk_cache.cacheSize() > 0
|
||||||
|
|
||||||
@ -146,14 +281,27 @@ def test_cache_clear_activated(config_stub, tmpdir):
|
|||||||
assert disk_cache.cacheSize() == 0
|
assert disk_cache.cacheSize() == 0
|
||||||
|
|
||||||
|
|
||||||
def test_cache_metadata(tmpdir):
|
def test_cache_clear_deactivated(config_stub, tmpdir):
|
||||||
|
"""Test method clear() on deactivated cache."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': True}
|
||||||
|
}
|
||||||
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
|
assert disk_cache.clear() is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_metadata(config_stub, tmpdir):
|
||||||
"""Ensure that DiskCache.metaData() returns exactly what was inserted."""
|
"""Ensure that DiskCache.metaData() returns exactly what was inserted."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': False}
|
||||||
|
}
|
||||||
url = 'http://qutebrowser.org'
|
url = 'http://qutebrowser.org'
|
||||||
metadata = QNetworkCacheMetaData()
|
metadata = QNetworkCacheMetaData()
|
||||||
metadata.setUrl(QUrl(url))
|
metadata.setUrl(QUrl(url))
|
||||||
assert metadata.isValid()
|
assert metadata.isValid()
|
||||||
disk_cache = QNetworkDiskCache()
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
disk_cache.setCacheDirectory(str(tmpdir))
|
|
||||||
device = disk_cache.prepare(metadata)
|
device = disk_cache.prepare(metadata)
|
||||||
device.write(b'foobar')
|
device.write(b'foobar')
|
||||||
disk_cache.insert(device)
|
disk_cache.insert(device)
|
||||||
@ -161,11 +309,26 @@ def test_cache_metadata(tmpdir):
|
|||||||
assert disk_cache.metaData(QUrl(url)) == metadata
|
assert disk_cache.metaData(QUrl(url)) == metadata
|
||||||
|
|
||||||
|
|
||||||
def test_cache_update_metadata(tmpdir):
|
def test_cache_deactivated_metadata(config_stub, tmpdir):
|
||||||
"""Test updating the meta data for an existing cache entry."""
|
"""Test querying metaData() on not activated cache."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': True}
|
||||||
|
}
|
||||||
url = 'http://qutebrowser.org'
|
url = 'http://qutebrowser.org'
|
||||||
disk_cache = QNetworkDiskCache()
|
|
||||||
disk_cache.setCacheDirectory(str(tmpdir))
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
|
assert disk_cache.metaData(QUrl(url)) == QNetworkCacheMetaData()
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_update_metadata(config_stub, tmpdir):
|
||||||
|
"""Test updating the meta data for an existing cache entry."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': False}
|
||||||
|
}
|
||||||
|
url = 'http://qutebrowser.org'
|
||||||
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
preload_cache(disk_cache, url, b'foo')
|
preload_cache(disk_cache, url, b'foo')
|
||||||
assert disk_cache.cacheSize() > 0
|
assert disk_cache.cacheSize() > 0
|
||||||
|
|
||||||
@ -176,6 +339,21 @@ def test_cache_update_metadata(tmpdir):
|
|||||||
assert disk_cache.metaData(QUrl(url)) == metadata
|
assert disk_cache.metaData(QUrl(url)) == metadata
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_deactivated_update_metadata(config_stub, tmpdir):
|
||||||
|
"""Test updating the meta data when cache is not activated."""
|
||||||
|
config_stub.data = {
|
||||||
|
'storage': {'cache-size': 1024},
|
||||||
|
'general': {'private-browsing': True}
|
||||||
|
}
|
||||||
|
url = 'http://qutebrowser.org'
|
||||||
|
disk_cache = cache.DiskCache(str(tmpdir))
|
||||||
|
|
||||||
|
metadata = QNetworkCacheMetaData()
|
||||||
|
metadata.setUrl(QUrl(url))
|
||||||
|
assert metadata.isValid()
|
||||||
|
assert disk_cache.updateMetaData(metadata) is None
|
||||||
|
|
||||||
|
|
||||||
def test_cache_full(config_stub, tmpdir):
|
def test_cache_full(config_stub, tmpdir):
|
||||||
"""Do a sanity test involving everything."""
|
"""Do a sanity test involving everything."""
|
||||||
config_stub.data = {
|
config_stub.data = {
|
||||||
|
@ -520,11 +520,13 @@ def test_unset_organization(qapp, orgname, expected):
|
|||||||
assert qapp.organizationName() == expected
|
assert qapp.organizationName() == expected
|
||||||
|
|
||||||
|
|
||||||
if test_file is not None:
|
if test_file is not None and sys.platform != 'darwin':
|
||||||
# If we were able to import Python's test_file module, we run some code
|
# If we were able to import Python's test_file module, we run some code
|
||||||
# here which defines unittest TestCases to run the python tests over
|
# here which defines unittest TestCases to run the python tests over
|
||||||
# PyQIODevice.
|
# PyQIODevice.
|
||||||
|
|
||||||
|
# Those are not run on OS X because that seems to cause a hang sometimes.
|
||||||
|
|
||||||
@pytest.yield_fixture(scope='session', autouse=True)
|
@pytest.yield_fixture(scope='session', autouse=True)
|
||||||
def clean_up_python_testfile():
|
def clean_up_python_testfile():
|
||||||
"""Clean up the python testfile after tests if tests didn't."""
|
"""Clean up the python testfile after tests if tests didn't."""
|
||||||
|
Loading…
Reference in New Issue
Block a user