144 lines
4.6 KiB
Python
144 lines
4.6 KiB
Python
# SPDX-FileCopyrightText: Florian Bruhin (The Compiler) <mail@qutebrowser.org>:
|
||
#
|
||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
||
"""Tests for mode parsers."""
|
||
|
||
from qutebrowser.qt.core import Qt
|
||
from qutebrowser.qt.gui import QKeySequence
|
||
|
||
import pytest
|
||
|
||
from qutebrowser.keyinput import modeparsers, keyutils
|
||
from qutebrowser.config import configexc
|
||
|
||
|
||
@pytest.fixture
|
||
def commandrunner(stubs):
|
||
return stubs.FakeCommandRunner()
|
||
|
||
|
||
class TestsNormalKeyParser:
|
||
|
||
@pytest.fixture(autouse=True)
|
||
def patch_stuff(self, monkeypatch, stubs, keyinput_bindings):
|
||
"""Set up mocks and read the test config."""
|
||
monkeypatch.setattr(
|
||
'qutebrowser.keyinput.basekeyparser.usertypes.Timer',
|
||
stubs.FakeTimer)
|
||
|
||
@pytest.fixture
|
||
def keyparser(self, commandrunner):
|
||
kp = modeparsers.NormalKeyParser(win_id=0, commandrunner=commandrunner)
|
||
return kp
|
||
|
||
def test_keychain(self, keyparser, commandrunner):
|
||
"""Test valid keychain."""
|
||
# Press 'z' which is ignored because of no match
|
||
# Then start the real chain
|
||
chain = keyutils.KeySequence.parse('zba')
|
||
for info in chain:
|
||
keyparser.handle(info.to_event())
|
||
assert commandrunner.commands == [('message-info ba', None)]
|
||
assert not keyparser._sequence
|
||
|
||
|
||
class TestHintKeyParser:
|
||
|
||
@pytest.fixture
|
||
def hintmanager(self, stubs):
|
||
return stubs.FakeHintManager()
|
||
|
||
@pytest.fixture
|
||
def keyparser(self, config_stub, key_config_stub, commandrunner,
|
||
hintmanager):
|
||
return modeparsers.HintKeyParser(win_id=0,
|
||
hintmanager=hintmanager,
|
||
commandrunner=commandrunner)
|
||
|
||
@pytest.mark.parametrize('bindings, keychain, prefix, hint', [
|
||
(
|
||
['aa', 'as'],
|
||
'as',
|
||
'a',
|
||
'as'
|
||
),
|
||
(
|
||
['21', '22'],
|
||
'<Num+2><Num+2>',
|
||
'2',
|
||
'22'
|
||
),
|
||
(
|
||
['äa', 'äs'],
|
||
'äs',
|
||
'ä',
|
||
'äs'
|
||
),
|
||
(
|
||
['не', 'на'],
|
||
'не',
|
||
'<Н>',
|
||
'не',
|
||
),
|
||
])
|
||
def test_match(self, keyparser, hintmanager,
|
||
bindings, keychain, prefix, hint, pyqt_enum_workaround):
|
||
with pyqt_enum_workaround(keyutils.KeyParseError):
|
||
keyparser.update_bindings(bindings)
|
||
|
||
seq = keyutils.KeySequence.parse(keychain)
|
||
assert len(seq) == 2
|
||
|
||
# pylint: disable-next=no-member
|
||
match = keyparser.handle(seq[0].to_event())
|
||
assert match == QKeySequence.SequenceMatch.PartialMatch
|
||
assert hintmanager.keystr == prefix
|
||
|
||
# pylint: disable-next=no-member
|
||
match = keyparser.handle(seq[1].to_event())
|
||
assert match == QKeySequence.SequenceMatch.ExactMatch
|
||
assert hintmanager.keystr == hint
|
||
|
||
def test_match_key_mappings(self, config_stub, keyparser, hintmanager,
|
||
pyqt_enum_workaround):
|
||
with pyqt_enum_workaround(configexc.ValidationError):
|
||
config_stub.val.bindings.key_mappings = {'α': 'a', 'σ': 's'}
|
||
keyparser.update_bindings(['aa', 'as'])
|
||
|
||
seq = keyutils.KeySequence.parse('ασ')
|
||
assert len(seq) == 2
|
||
|
||
# pylint: disable-next=no-member
|
||
match = keyparser.handle(seq[0].to_event())
|
||
assert match == QKeySequence.SequenceMatch.PartialMatch
|
||
assert hintmanager.keystr == 'a'
|
||
|
||
# pylint: disable-next=no-member
|
||
match = keyparser.handle(seq[1].to_event())
|
||
assert match == QKeySequence.SequenceMatch.ExactMatch
|
||
assert hintmanager.keystr == 'as'
|
||
|
||
def test_command(self, keyparser, config_stub, hintmanager, commandrunner):
|
||
config_stub.val.bindings.commands = {
|
||
'hint': {'abc': 'message-info abc'}
|
||
}
|
||
|
||
keyparser.update_bindings(['xabcy'])
|
||
|
||
steps = [
|
||
(Qt.Key.Key_X, QKeySequence.SequenceMatch.PartialMatch, 'x'),
|
||
(Qt.Key.Key_A, QKeySequence.SequenceMatch.PartialMatch, ''),
|
||
(Qt.Key.Key_B, QKeySequence.SequenceMatch.PartialMatch, ''),
|
||
(Qt.Key.Key_C, QKeySequence.SequenceMatch.ExactMatch, ''),
|
||
]
|
||
for key, expected_match, keystr in steps:
|
||
info = keyutils.KeyInfo(key, Qt.KeyboardModifier.NoModifier)
|
||
match = keyparser.handle(info.to_event())
|
||
assert match == expected_match
|
||
assert hintmanager.keystr == keystr
|
||
if key != Qt.Key.Key_C:
|
||
assert not commandrunner.commands
|
||
|
||
assert commandrunner.commands == [('message-info abc', None)]
|