Reorganize test_history

This commit is contained in:
Florian Bruhin 2018-08-31 22:24:57 +02:00
parent 9fb794656b
commit c2f8b6531d

View File

@ -42,22 +42,16 @@ def hist(tmpdir):
return history.WebHistory() return history.WebHistory()
@pytest.fixture() class TestSpecialMethods:
def mock_time(mocker):
m = mocker.patch('qutebrowser.browser.history.time')
m.time.return_value = 12345
return 12345
def test_iter(self, hist):
def test_iter(hist):
urlstr = 'http://www.example.com/' urlstr = 'http://www.example.com/'
url = QUrl(urlstr) url = QUrl(urlstr)
hist.add_url(url, atime=12345) hist.add_url(url, atime=12345)
assert list(hist) == [(urlstr, '', 12345, False)] assert list(hist) == [(urlstr, '', 12345, False)]
def test_len(self, hist):
def test_len(hist):
assert len(hist) == 0 assert len(hist) == 0
url = QUrl('http://www.example.com/') url = QUrl('http://www.example.com/')
@ -65,16 +59,18 @@ def test_len(hist):
assert len(hist) == 1 assert len(hist) == 1
def test_contains(self, hist):
def test_contains(hist): hist.add_url(QUrl('http://www.example.com/'), title='Title',
hist.add_url(QUrl('http://www.example.com/'), title='Title', atime=12345) atime=12345)
assert 'http://www.example.com/' in hist assert 'http://www.example.com/' in hist
assert 'www.example.com' not in hist assert 'www.example.com' not in hist
assert 'Title' not in hist assert 'Title' not in hist
assert 12345 not in hist assert 12345 not in hist
def test_get_recent(hist): class TestGetting:
def test_get_recent(self, hist):
hist.add_url(QUrl('http://www.qutebrowser.org/'), atime=67890) hist.add_url(QUrl('http://www.qutebrowser.org/'), atime=67890)
hist.add_url(QUrl('http://example.com/'), atime=12345) hist.add_url(QUrl('http://example.com/'), atime=12345)
assert list(hist.get_recent()) == [ assert list(hist.get_recent()) == [
@ -82,8 +78,7 @@ def test_get_recent(hist):
('http://example.com/', '', 12345, False), ('http://example.com/', '', 12345, False),
] ]
def test_entries_between(self, hist):
def test_entries_between(hist):
hist.add_url(QUrl('http://www.example.com/1'), atime=12345) hist.add_url(QUrl('http://www.example.com/1'), atime=12345)
hist.add_url(QUrl('http://www.example.com/2'), atime=12346) hist.add_url(QUrl('http://www.example.com/2'), atime=12346)
hist.add_url(QUrl('http://www.example.com/3'), atime=12347) hist.add_url(QUrl('http://www.example.com/3'), atime=12347)
@ -95,8 +90,7 @@ def test_entries_between(hist):
times = [x.atime for x in hist.entries_between(12346, 12349)] times = [x.atime for x in hist.entries_between(12346, 12349)]
assert times == [12349, 12348, 12348, 12347] assert times == [12349, 12348, 12348, 12347]
def test_entries_before(self, hist):
def test_entries_before(hist):
hist.add_url(QUrl('http://www.example.com/1'), atime=12346) hist.add_url(QUrl('http://www.example.com/1'), atime=12346)
hist.add_url(QUrl('http://www.example.com/2'), atime=12346) hist.add_url(QUrl('http://www.example.com/2'), atime=12346)
hist.add_url(QUrl('http://www.example.com/3'), atime=12347) hist.add_url(QUrl('http://www.example.com/3'), atime=12347)
@ -106,11 +100,14 @@ def test_entries_before(hist):
hist.add_url(QUrl('http://www.example.com/7'), atime=12349) hist.add_url(QUrl('http://www.example.com/7'), atime=12349)
hist.add_url(QUrl('http://www.example.com/8'), atime=12349) hist.add_url(QUrl('http://www.example.com/8'), atime=12349)
times = [x.atime for x in hist.entries_before(12348, limit=3, offset=2)] times = [x.atime for x in
hist.entries_before(12348, limit=3, offset=2)]
assert times == [12348, 12347, 12346] assert times == [12348, 12347, 12346]
def test_clear(qtbot, tmpdir, hist, mocker): class TestDelete:
def test_clear(self, qtbot, tmpdir, hist, mocker):
hist.add_url(QUrl('http://example.com/')) hist.add_url(QUrl('http://example.com/'))
hist.add_url(QUrl('http://www.qutebrowser.org/')) hist.add_url(QUrl('http://www.qutebrowser.org/'))
@ -119,20 +116,18 @@ def test_clear(qtbot, tmpdir, hist, mocker):
hist.clear() hist.clear()
assert m.called assert m.called
def test_clear_force(self, qtbot, tmpdir, hist):
def test_clear_force(qtbot, tmpdir, hist):
hist.add_url(QUrl('http://example.com/')) hist.add_url(QUrl('http://example.com/'))
hist.add_url(QUrl('http://www.qutebrowser.org/')) hist.add_url(QUrl('http://www.qutebrowser.org/'))
hist.clear(force=True) hist.clear(force=True)
assert not len(hist) assert not len(hist)
assert not len(hist.completion) assert not len(hist.completion)
@pytest.mark.parametrize('raw, escaped', [ @pytest.mark.parametrize('raw, escaped', [
('http://example.com/1', 'http://example.com/1'), ('http://example.com/1', 'http://example.com/1'),
('http://example.com/1 2', 'http://example.com/1%202'), ('http://example.com/1 2', 'http://example.com/1%202'),
]) ])
def test_delete_url(hist, raw, escaped): def test_delete_url(self, hist, raw, escaped):
hist.add_url(QUrl('http://example.com/'), atime=0) hist.add_url(QUrl('http://example.com/'), atime=0)
hist.add_url(QUrl(escaped), atime=0) hist.add_url(QUrl(escaped), atime=0)
hist.add_url(QUrl('http://example.com/2'), atime=0) hist.add_url(QUrl('http://example.com/2'), atime=0)
@ -149,9 +144,16 @@ def test_delete_url(hist, raw, escaped):
assert completion_diff == {(raw, '', 0)} assert completion_diff == {(raw, '', 0)}
class TestAdd:
@pytest.fixture()
def mock_time(self, mocker):
m = mocker.patch('qutebrowser.browser.history.time')
m.time.return_value = 12345
return 12345
@pytest.mark.parametrize( @pytest.mark.parametrize(
'url, atime, title, redirect, history_url, completion_url', [ 'url, atime, title, redirect, history_url, completion_url', [
('http://www.example.com', 12346, 'the title', False, ('http://www.example.com', 12346, 'the title', False,
'http://www.example.com', 'http://www.example.com'), 'http://www.example.com', 'http://www.example.com'),
('http://www.example.com', 12346, 'the title', True, ('http://www.example.com', 12346, 'the title', True,
@ -162,8 +164,8 @@ def test_delete_url(hist, raw, escaped):
'https://user@example.com', 'https://user@example.com'), 'https://user@example.com', 'https://user@example.com'),
] ]
) )
def test_add_url(qtbot, hist, url, atime, title, redirect, history_url, def test_add_url(self, qtbot, hist,
completion_url): url, atime, title, redirect, history_url, completion_url):
hist.add_url(QUrl(url), atime=atime, title=title, redirect=redirect) hist.add_url(QUrl(url), atime=atime, title=title, redirect=redirect)
assert list(hist) == [(history_url, title, atime, redirect)] assert list(hist) == [(history_url, title, atime, redirect)]
if completion_url is None: if completion_url is None:
@ -171,17 +173,15 @@ def test_add_url(qtbot, hist, url, atime, title, redirect, history_url,
else: else:
assert list(hist.completion) == [(completion_url, title, atime)] assert list(hist.completion) == [(completion_url, title, atime)]
def test_invalid(self, qtbot, hist, caplog):
def test_add_url_invalid(qtbot, hist, caplog):
with caplog.at_level(logging.WARNING): with caplog.at_level(logging.WARNING):
hist.add_url(QUrl()) hist.add_url(QUrl())
assert not list(hist) assert not list(hist)
assert not list(hist.completion) assert not list(hist.completion)
@pytest.mark.parametrize('environmental', [True, False]) @pytest.mark.parametrize('environmental', [True, False])
@pytest.mark.parametrize('completion', [True, False]) @pytest.mark.parametrize('completion', [True, False])
def test_add_url_error(monkeypatch, hist, message_mock, caplog, def test_error(self, monkeypatch, hist, message_mock, caplog,
environmental, completion): environmental, completion):
def raise_error(url, replace=False): def raise_error(url, replace=False):
raise sql.SqlError("Error message", environmental=environmental) raise sql.SqlError("Error message", environmental=environmental)
@ -200,7 +200,6 @@ def test_add_url_error(monkeypatch, hist, message_mock, caplog,
with pytest.raises(sql.SqlError): with pytest.raises(sql.SqlError):
hist.add_url(QUrl('https://www.example.org/')) hist.add_url(QUrl('https://www.example.org/'))
@pytest.mark.parametrize('level, url, req_url, expected', [ @pytest.mark.parametrize('level, url, req_url, expected', [
(logging.DEBUG, 'a.com', 'a.com', [('a.com', 'title', 12345, False)]), (logging.DEBUG, 'a.com', 'a.com', [('a.com', 'title', 12345, False)]),
(logging.DEBUG, 'a.com', 'b.com', [('a.com', 'title', 12345, False), (logging.DEBUG, 'a.com', 'b.com', [('a.com', 'title', 12345, False),
@ -210,14 +209,17 @@ def test_add_url_error(monkeypatch, hist, message_mock, caplog,
(logging.WARNING, 'data:foo', '', []), (logging.WARNING, 'data:foo', '', []),
(logging.WARNING, 'a.com', 'data:foo', []), (logging.WARNING, 'a.com', 'data:foo', []),
]) ])
def test_add_from_tab(hist, level, url, req_url, expected, mock_time, caplog): def test_from_tab(self, hist, caplog, mock_time,
level, url, req_url, expected):
with caplog.at_level(level): with caplog.at_level(level):
hist.add_from_tab(QUrl(url), QUrl(req_url), 'title') hist.add_from_tab(QUrl(url), QUrl(req_url), 'title')
assert set(hist) == set(expected) assert set(hist) == set(expected)
class TestHistoryInterface:
@pytest.fixture @pytest.fixture
def hist_interface(hist): def hist_interface(self, hist):
# pylint: disable=invalid-name # pylint: disable=invalid-name
QtWebKit = pytest.importorskip('PyQt5.QtWebKit') QtWebKit = pytest.importorskip('PyQt5.QtWebKit')
from qutebrowser.browser.webkit import webkithistory from qutebrowser.browser.webkit import webkithistory
@ -229,16 +231,17 @@ def hist_interface(hist):
yield yield
QWebHistoryInterface.setDefaultInterface(None) QWebHistoryInterface.setDefaultInterface(None)
def test_history_interface(self, qtbot, webview, hist_interface):
def test_history_interface(qtbot, webview, hist_interface):
html = b"<a href='about:blank'>foo</a>" html = b"<a href='about:blank'>foo</a>"
url = urlutils.data_url('text/html', html) url = urlutils.data_url('text/html', html)
with qtbot.waitSignal(webview.loadFinished): with qtbot.waitSignal(webview.loadFinished):
webview.load(url) webview.load(url)
class TestInit:
@pytest.fixture @pytest.fixture
def cleanup_init(): def cleanup_init(self):
# prevent test_init from leaking state # prevent test_init from leaking state
yield yield
hist = objreg.get('web-history', None) hist = objreg.get('web-history', None)
@ -251,10 +254,9 @@ def cleanup_init():
except ImportError: except ImportError:
pass pass
@pytest.mark.parametrize('backend', [usertypes.Backend.QtWebEngine, @pytest.mark.parametrize('backend', [usertypes.Backend.QtWebEngine,
usertypes.Backend.QtWebKit]) usertypes.Backend.QtWebKit])
def test_init(backend, qapp, tmpdir, monkeypatch, cleanup_init): def test_init(self, backend, qapp, tmpdir, monkeypatch, cleanup_init):
if backend == usertypes.Backend.QtWebKit: if backend == usertypes.Backend.QtWebKit:
pytest.importorskip('PyQt5.QtWebKitWidgets') pytest.importorskip('PyQt5.QtWebKitWidgets')
else: else:
@ -279,12 +281,15 @@ def test_init(backend, qapp, tmpdir, monkeypatch, cleanup_init):
default_interface = None default_interface = None
else: else:
default_interface = QWebHistoryInterface.defaultInterface() default_interface = QWebHistoryInterface.defaultInterface()
# For this to work, nothing can ever have called setDefaultInterface # For this to work, nothing can ever have called
# before (so we need to test webengine before webkit) # setDefaultInterface before (so we need to test webengine before
# webkit)
assert default_interface is None assert default_interface is None
def test_import_txt(hist, data_tmpdir, monkeypatch, stubs): class TestImport:
def test_import_txt(self, hist, data_tmpdir, monkeypatch, stubs):
monkeypatch.setattr(history, 'QTimer', stubs.InstaTimer) monkeypatch.setattr(history, 'QTimer', stubs.InstaTimer)
histfile = data_tmpdir / 'history' histfile = data_tmpdir / 'history'
# empty line is deliberate, to test skipping empty lines # empty line is deliberate, to test skipping empty lines
@ -306,8 +311,7 @@ def test_import_txt(hist, data_tmpdir, monkeypatch, stubs):
assert not histfile.exists() assert not histfile.exists()
assert (data_tmpdir / 'history.bak').exists() assert (data_tmpdir / 'history.bak').exists()
def test_existing_backup(self, hist, data_tmpdir, monkeypatch, stubs):
def test_import_txt_existing_backup(hist, data_tmpdir, monkeypatch, stubs):
monkeypatch.setattr(history, 'QTimer', stubs.InstaTimer) monkeypatch.setattr(history, 'QTimer', stubs.InstaTimer)
histfile = data_tmpdir / 'history' histfile = data_tmpdir / 'history'
bakfile = data_tmpdir / 'history.bak' bakfile = data_tmpdir / 'history.bak'
@ -322,7 +326,6 @@ def test_import_txt_existing_backup(hist, data_tmpdir, monkeypatch, stubs):
assert bakfile.read().split('\n') == ['12346 http://qutebrowser.org/', assert bakfile.read().split('\n') == ['12346 http://qutebrowser.org/',
'12345 http://example.com/ title'] '12345 http://example.com/ title']
@pytest.mark.parametrize('line', [ @pytest.mark.parametrize('line', [
'', '',
'#12345 http://example.com/commented', '#12345 http://example.com/commented',
@ -334,9 +337,10 @@ def test_import_txt_existing_backup(hist, data_tmpdir, monkeypatch, stubs):
'12345 https://www..com/', '12345 https://www..com/',
# issue #2646 # issue #2646
'12345 data:text/html;charset=UTF-8,%3C%21DOCTYPE%20html%20PUBLIC%20%22-', ('12345 data:text/html;'
'charset=UTF-8,%3C%21DOCTYPE%20html%20PUBLIC%20%22-'),
]) ])
def test_import_txt_skip(hist, data_tmpdir, line, monkeypatch, stubs): def test_skip(self, hist, data_tmpdir, monkeypatch, stubs, line):
"""import_txt should skip certain lines silently.""" """import_txt should skip certain lines silently."""
monkeypatch.setattr(history, 'QTimer', stubs.InstaTimer) monkeypatch.setattr(history, 'QTimer', stubs.InstaTimer)
histfile = data_tmpdir / 'history' histfile = data_tmpdir / 'history'
@ -347,7 +351,6 @@ def test_import_txt_skip(hist, data_tmpdir, line, monkeypatch, stubs):
assert not histfile.exists() assert not histfile.exists()
assert not len(hist) assert not len(hist)
@pytest.mark.parametrize('line', [ @pytest.mark.parametrize('line', [
'xyz http://example.com/bad-timestamp', 'xyz http://example.com/bad-timestamp',
'12345', '12345',
@ -356,8 +359,8 @@ def test_import_txt_skip(hist, data_tmpdir, line, monkeypatch, stubs):
'68891-x http://example.com/bad-flag', '68891-x http://example.com/bad-flag',
'68891 http://.com', '68891 http://.com',
]) ])
def test_import_txt_invalid(hist, data_tmpdir, line, monkeypatch, stubs, def test_invalid(self, hist, data_tmpdir, monkeypatch, stubs, caplog,
caplog): line):
"""import_txt should fail on certain lines.""" """import_txt should fail on certain lines."""
monkeypatch.setattr(history, 'QTimer', stubs.InstaTimer) monkeypatch.setattr(history, 'QTimer', stubs.InstaTimer)
histfile = data_tmpdir / 'history' histfile = data_tmpdir / 'history'
@ -371,14 +374,15 @@ def test_import_txt_invalid(hist, data_tmpdir, line, monkeypatch, stubs,
assert histfile.exists() assert histfile.exists()
def test_nonexistent(self, hist, data_tmpdir, monkeypatch, stubs):
def test_import_txt_nonexistent(hist, data_tmpdir, monkeypatch, stubs):
"""import_txt should do nothing if the history file doesn't exist.""" """import_txt should do nothing if the history file doesn't exist."""
monkeypatch.setattr(history, 'QTimer', stubs.InstaTimer) monkeypatch.setattr(history, 'QTimer', stubs.InstaTimer)
hist.import_txt() hist.import_txt()
def test_debug_dump_history(hist, tmpdir): class TestDump:
def test_debug_dump_history(self, hist, tmpdir):
hist.add_url(QUrl('http://example.com/1'), title="Title1", atime=12345) hist.add_url(QUrl('http://example.com/1'), title="Title1", atime=12345)
hist.add_url(QUrl('http://example.com/2'), title="Title2", atime=12346) hist.add_url(QUrl('http://example.com/2'), title="Title2", atime=12346)
hist.add_url(QUrl('http://example.com/3'), title="Title3", atime=12347) hist.add_url(QUrl('http://example.com/3'), title="Title3", atime=12347)
@ -392,14 +396,15 @@ def test_debug_dump_history(hist, tmpdir):
'12348-r http://example.com/4 Title4'] '12348-r http://example.com/4 Title4']
assert histfile.read() == '\n'.join(expected) assert histfile.read() == '\n'.join(expected)
def test_nonexistent(self, hist, tmpdir):
def test_debug_dump_history_nonexistent(hist, tmpdir):
histfile = tmpdir / 'nonexistent' / 'history' histfile = tmpdir / 'nonexistent' / 'history'
with pytest.raises(cmdexc.CommandError): with pytest.raises(cmdexc.CommandError):
hist.debug_dump_history(str(histfile)) hist.debug_dump_history(str(histfile))
def test_rebuild_completion(hist): class TestRebuild:
def test_delete(self, hist):
hist.insert({'url': 'example.com/1', 'title': 'example1', hist.insert({'url': 'example.com/1', 'title': 'example1',
'redirect': False, 'atime': 1}) 'redirect': False, 'atime': 1})
hist.insert({'url': 'example.com/1', 'title': 'example1', hist.insert({'url': 'example.com/1', 'title': 'example1',
@ -418,9 +423,8 @@ def test_rebuild_completion(hist):
('example.com/2 3', 'example2', 5), ('example.com/2 3', 'example2', 5),
] ]
def test_no_rebuild(self, hist):
def test_no_rebuild_completion(hist): """Ensure that completion is not regenerated unless empty."""
"""Ensure that completion is not regenerated unless completely empty."""
hist.add_url(QUrl('example.com/1'), redirect=False, atime=1) hist.add_url(QUrl('example.com/1'), redirect=False, atime=1)
hist.add_url(QUrl('example.com/2'), redirect=False, atime=2) hist.add_url(QUrl('example.com/2'), redirect=False, atime=2)
hist.completion.delete('url', 'example.com/2') hist.completion.delete('url', 'example.com/2')
@ -428,9 +432,8 @@ def test_no_rebuild_completion(hist):
hist2 = history.WebHistory() hist2 = history.WebHistory()
assert list(hist2.completion) == [('example.com/1', '', 1)] assert list(hist2.completion) == [('example.com/1', '', 1)]
def test_user_version(self, hist, monkeypatch):
def test_user_version(hist, monkeypatch): """Ensure that completion is regenerated if user_version changes."""
"""Ensure that completion is regenerated if user_version is incremented."""
hist.add_url(QUrl('example.com/1'), redirect=False, atime=1) hist.add_url(QUrl('example.com/1'), redirect=False, atime=1)
hist.add_url(QUrl('example.com/2'), redirect=False, atime=2) hist.add_url(QUrl('example.com/2'), redirect=False, atime=2)
hist.completion.delete('url', 'example.com/2') hist.completion.delete('url', 'example.com/2')
@ -438,15 +441,15 @@ def test_user_version(hist, monkeypatch):
hist2 = history.WebHistory() hist2 = history.WebHistory()
assert list(hist2.completion) == [('example.com/1', '', 1)] assert list(hist2.completion) == [('example.com/1', '', 1)]
monkeypatch.setattr(history, '_USER_VERSION', history._USER_VERSION + 1) monkeypatch.setattr(history, '_USER_VERSION',
history._USER_VERSION + 1)
hist3 = history.WebHistory() hist3 = history.WebHistory()
assert list(hist3.completion) == [ assert list(hist3.completion) == [
('example.com/1', '', 1), ('example.com/1', '', 1),
('example.com/2', '', 2), ('example.com/2', '', 2),
] ]
def test_force_rebuild(self, hist):
def test_force_rebuild(hist):
"""Ensure that completion is regenerated if we force a rebuild.""" """Ensure that completion is regenerated if we force a rebuild."""
hist.add_url(QUrl('example.com/1'), redirect=False, atime=1) hist.add_url(QUrl('example.com/1'), redirect=False, atime=1)
hist.add_url(QUrl('example.com/2'), redirect=False, atime=2) hist.add_url(QUrl('example.com/2'), redirect=False, atime=2)