qutebrowser/tests/unit/completion/test_completiondelegate.py
Ryan Roden-Corrent 28c8e5682a
Unit test CompletionItemDelegate.paint.
There were no unit tests for this whole module. It is difficult to test
due to all the private logic and Qt dependencies, but with a lot of
mocking we can at least validate some of the text handling.

This is a setup to start testing the solution to #4199.

I picked '{' and '}' as placeholders in the test data because they draw
the eye to the 'highlighted' part, and vim even highlights them with
python syntax highlighting. It could be confusing though, as they look
like format strings but are not used that way.
2018-09-15 13:34:07 -04:00

107 lines
3.3 KiB
Python

# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2018 Ryan Roden-Corrent (rcorre) <ryan@rcorre.net>
#
# 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/>.
"""Tests for the CompletionView Object."""
from unittest import mock
import pytest
from PyQt5.QtCore import QModelIndex
from PyQt5.QtWidgets import QStyleOptionViewItem, QStyledItemDelegate
from PyQt5.QtGui import QPainter
from qutebrowser.completion import completiondelegate
@pytest.fixture
def painter():
"""Create the CompletionView used for testing."""
return mock.Mock(spec=QPainter)
def _qt_mock(klass, mocker):
m = mocker.patch(
'qutebrowser.completion.completiondelegate.{}'.format(klass),
autospec=True)
return m
@pytest.fixture
def mock_style_option(mocker):
"""Create the CompletionView used for testing."""
return _qt_mock('QStyleOptionViewItem', mocker)
@pytest.fixture
def mock_text_document(mocker):
"""Create the CompletionView used for testing."""
return _qt_mock('QTextDocument', mocker)
@pytest.fixture
def view():
return mock.Mock()
@pytest.fixture
def delegate(mock_style_option, mock_text_document, config_stub, mocker, view):
_qt_mock('QStyle', mocker)
_qt_mock('QTextOption', mocker)
_qt_mock('QAbstractTextDocumentLayout', mocker)
completiondelegate._cached_stylesheet = mock.Mock()
delegate = completiondelegate.CompletionItemDelegate()
parent = mock.Mock()
parent.return_value = view
delegate.parent = parent
delegate.initStyleOption = mock.Mock()
delegate.setTextDirection = mock.Mock()
return delegate
@pytest.mark.parametrize('pat,txt_in,txt_out', [
# { and } represent the open/close html tags for highlighting
('foo', 'foo', '{foo}'),
('foo', 'foobar', '{foo}bar'),
('foo', 'barfoo', 'bar{foo}'),
('foo', 'barfoobaz', 'bar{foo}baz'),
('foo', 'barfoobazfoo', 'bar{foo}baz{foo}'),
('foo', 'foofoo', '{foo}{foo}'),
('a b', 'cadb', 'c{a}d{b}'),
('foo', '<foo>', '&lt;{foo}&gt;'),
('<a>', "<a>bc", '{&lt;a&gt;}bc'),
('foo', "'foo'", "&#x27;{foo}&#x27;"),
])
def test_paint(delegate, painter, view, mock_style_option, mock_text_document,
pat, txt_in, txt_out):
"""Ensure set_model actually sets the model and expands all categories."""
view.pattern = pat
mock_style_option().text = txt_in
index = mock.Mock()
index.column.return_value = 0
index.model.return_value.columns_to_filter.return_value = [0]
opt = mock_style_option()
delegate.paint(painter, opt, index)
expected = txt_out.replace(
'{', '<span class="highlight">'
).replace(
'}', '</span>'
)
mock_text_document().setHtml.assert_called_once_with(expected)