Unit test Completer.update_completion.
Validate update_completion sets the completions widget's model correctly based on the command text.
This commit is contained in:
parent
bd506b186b
commit
07edcce697
@ -255,6 +255,14 @@ def app_stub(stubs):
|
||||
objreg.delete('app')
|
||||
|
||||
|
||||
@pytest.yield_fixture
|
||||
def completion_widget_stub(win_registry):
|
||||
stub = unittest.mock.Mock()
|
||||
objreg.register('completion', stub, scope='window', window=0)
|
||||
yield stub
|
||||
objreg.delete('completion', scope='window', window=0)
|
||||
|
||||
|
||||
@pytest.fixture(scope='session')
|
||||
def stubs():
|
||||
"""Provide access to stub objects useful for testing."""
|
||||
|
@ -293,12 +293,13 @@ class FakeCommand:
|
||||
"""A simple command stub which has a description."""
|
||||
|
||||
def __init__(self, name='', desc='', hide=False, debug=False,
|
||||
deprecated=False):
|
||||
deprecated=False, completion=None):
|
||||
self.desc = desc
|
||||
self.name = name
|
||||
self.hide = hide
|
||||
self.debug = debug
|
||||
self.deprecated = deprecated
|
||||
self.completion = completion
|
||||
|
||||
|
||||
class FakeTimer(QObject):
|
||||
@ -359,6 +360,34 @@ class FakeConfigType:
|
||||
self.complete = lambda: [(val, '') for val in valid_values]
|
||||
|
||||
|
||||
class FakeStatusbarCommand(QObject):
|
||||
|
||||
"""Stub for the statusbar command prompt."""
|
||||
|
||||
got_cmd = pyqtSignal(str)
|
||||
clear_completion_selection = pyqtSignal()
|
||||
hide_completion = pyqtSignal()
|
||||
update_completion = pyqtSignal()
|
||||
show_cmd = pyqtSignal()
|
||||
hide_cmd = pyqtSignal()
|
||||
textChanged = pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None, name=None):
|
||||
super().__init__(parent)
|
||||
self._cursor_pos = 0
|
||||
self._text = ""
|
||||
self.cursorPosition = lambda: self._cursor_pos
|
||||
self.text = lambda: self._text
|
||||
self.prefix = lambda: self._text[0]
|
||||
self.setFocus = lambda: None
|
||||
|
||||
def setText(self, x):
|
||||
self._text = x
|
||||
|
||||
def setCursorPosition(self, x):
|
||||
self._cursor_pos = x
|
||||
|
||||
|
||||
class ConfigStub(QObject):
|
||||
|
||||
"""Stub for the config module.
|
||||
|
136
tests/unit/completion/test_completer.py
Normal file
136
tests/unit/completion/test_completer.py
Normal file
@ -0,0 +1,136 @@
|
||||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
|
||||
|
||||
# Copyright 2016 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 Completer Object."""
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from PyQt5.QtGui import QStandardItemModel
|
||||
|
||||
from qutebrowser.completion.completer import Completer
|
||||
from qutebrowser.utils.usertypes import Completion
|
||||
|
||||
|
||||
class FakeCompletionModel(QStandardItemModel):
|
||||
|
||||
"""Stub for a completion model."""
|
||||
|
||||
DUMB_SORT = Mock()
|
||||
|
||||
def __init__(self, kind, parent=None):
|
||||
super().__init__(parent)
|
||||
self.kind = kind
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cmd(stubs):
|
||||
"""Create the statusbar command prompt the completer uses."""
|
||||
return stubs.FakeStatusbarCommand()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def completer(qtbot, cmd, config_stub):
|
||||
"""Create the completer used for testing."""
|
||||
config_stub.data = {'completion': {'auto-open': False}}
|
||||
return Completer(cmd, 0)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def instances(monkeypatch):
|
||||
"""Mock the instances module so get returns a fake completion model."""
|
||||
# populate a model for each completion type, with a nested structure for
|
||||
# option and value completion
|
||||
instances = {kind: FakeCompletionModel(kind) for kind in Completion}
|
||||
instances[Completion.option] = {
|
||||
'general': FakeCompletionModel(Completion.option),
|
||||
}
|
||||
instances[Completion.value] = {
|
||||
'general': {
|
||||
'ignore-case': FakeCompletionModel(Completion.value),
|
||||
}
|
||||
}
|
||||
monkeypatch.setattr('qutebrowser.completion.completer.instances',
|
||||
instances)
|
||||
return instances
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cmdutils_patch(monkeypatch, stubs):
|
||||
"""Patch the cmdutils module to provide fake commands."""
|
||||
cmds = {
|
||||
'set': [Completion.section, Completion.option, Completion.value],
|
||||
'help': [Completion.helptopic],
|
||||
'quickmark-load': [Completion.quickmark_by_name],
|
||||
'bookmark-load': [Completion.bookmark_by_url],
|
||||
'open': [Completion.url],
|
||||
'buffer': [Completion.tab],
|
||||
'session-load': [Completion.sessions],
|
||||
'bind': [Completion.empty, Completion.command],
|
||||
}
|
||||
cmd_utils = stubs.FakeCmdUtils({
|
||||
name: stubs.FakeCommand(completion=compl)
|
||||
for name, compl in cmds.items()
|
||||
})
|
||||
monkeypatch.setattr('qutebrowser.completion.completer.cmdutils',
|
||||
cmd_utils)
|
||||
return cmd_utils
|
||||
|
||||
|
||||
@pytest.mark.parametrize('txt, expected', [
|
||||
(':nope|', Completion.command),
|
||||
(':nope |', None),
|
||||
(':set |', Completion.section),
|
||||
(':set gen|', Completion.section),
|
||||
(':set general |', Completion.option),
|
||||
(':set what |', None),
|
||||
(':set general ignore-case |', Completion.value),
|
||||
(':set general huh |', None),
|
||||
(':help |', Completion.helptopic),
|
||||
(':quickmark-load |', Completion.quickmark_by_name),
|
||||
(':bookmark-load |', Completion.bookmark_by_url),
|
||||
(':open |', Completion.url),
|
||||
(':buffer |', Completion.tab),
|
||||
(':session-load |', Completion.sessions),
|
||||
(':bind |', Completion.empty),
|
||||
(':bind <c-x> |', Completion.command),
|
||||
(':bind <c-x> foo|', Completion.command),
|
||||
(':bind <c-x>| foo', Completion.empty),
|
||||
(':set| general ', Completion.command),
|
||||
(':|set general ', Completion.command),
|
||||
(':set gene|ral ignore-case', Completion.section),
|
||||
(':|', Completion.command),
|
||||
(': |', Completion.command),
|
||||
(':bookmark-load |', Completion.bookmark_by_url),
|
||||
])
|
||||
def test_update_completion(txt, expected, cmd, completer, instances,
|
||||
cmdutils_patch, completion_widget_stub):
|
||||
"""Test setting the completion widget's model based on command text."""
|
||||
# this test uses | as a placeholder for the current cursor position
|
||||
cursor_pos = txt.index('|')
|
||||
cmd.setText(txt.replace('|', ''))
|
||||
cmd.setCursorPosition(cursor_pos)
|
||||
completer.update_completion()
|
||||
if expected is None:
|
||||
assert not completion_widget_stub.set_model.called
|
||||
else:
|
||||
assert completion_widget_stub.set_model.call_count == 1
|
||||
arg = completion_widget_stub.set_model.call_args[0][0]
|
||||
# the outer model is just for sorting; srcmodel is the completion model
|
||||
assert arg.srcmodel.kind == expected
|
Loading…
Reference in New Issue
Block a user