Fix #2: distinguish Shift+N from Caps Lock

This commit is contained in:
Philip Henning 2026-09-06 17:01:27 +02:00
parent f2e2d45480
commit 4615aed580
7 changed files with 176 additions and 5 deletions

View file

@ -10,6 +10,7 @@ from unittest.mock import Mock, patch
import pytest
from rich.cells import cell_len
from textual.app import SuspendNotSupported
from textual.events import Key
from textual.widgets import Button, Input, RadioButton, Static
from src.hosts.core.filters import FilterOptions
@ -20,6 +21,8 @@ from src.hosts.tui.backup_restore_modal import BackupRestoreModal
from src.hosts.tui.filter_modal import FilterModal
from src.hosts.tui.help_modal import HelpModal
from src.hosts.tui.add_entry_modal import AddEntryModal
from src.hosts.tui.keyboard_protocol import HostsXTermParser
from src.hosts.tui.keyboard_driver import HostsKeyboardDriver
from src.hosts.tui.privilege_prompt import (
render_sudo_authentication_notice,
sudo_authentication_screen,
@ -49,6 +52,11 @@ def app_with_filterable_entries() -> HostsManagerApp:
return app
def test_app_uses_the_modifier_preserving_keyboard_driver():
"""The live terminal app receives enhanced keyboard events through the adapter."""
assert HostsManagerApp().driver_class is HostsKeyboardDriver
@pytest.mark.asyncio
async def test_filter_shortcut_opens_modal_and_applies_the_selected_filter():
"""The filter shortcut opens a modal whose Apply action changes the view state."""
@ -134,6 +142,47 @@ async def test_new_from_selected_prefills_the_highlighted_visible_entry():
assert not source.is_active
def test_enhanced_shift_n_preserves_the_shift_modifier():
"""Kitty Shift+N remains distinct from an uppercase text character."""
event = list(HostsXTermParser().feed("\x1b[110;2;78u"))[0]
assert isinstance(event, Key)
assert event.key == "shift+n"
assert event.character == "N"
def test_enhanced_caps_lock_n_does_not_become_shift_n():
"""Caps Lock does not invoke the New from selected binding."""
event = list(HostsXTermParser().feed("\x1b[110;65;78u"))[0]
assert isinstance(event, Key)
assert event.key == "caps_lock+n"
assert event.character == "N"
@pytest.mark.asyncio
async def test_enhanced_shift_n_opens_new_from_selected_but_caps_lock_n_does_not():
"""The real enhanced-key events distinguish Shift from Caps Lock at the app."""
app = app_with_filterable_entries()
app.edit_mode = True
async with app.run_test(size=(120, 40)) as pilot:
app.table_handler.populate_entries_table()
app.query_one("#entries-table").focus()
shift_n = list(HostsXTermParser().feed("\x1b[110;2;78u"))[0]
app.post_message(shift_n)
await pilot.pause()
assert isinstance(app.screen, AddEntryModal)
await pilot.press("escape")
await pilot.pause()
caps_lock_n = list(HostsXTermParser().feed("\x1b[110;65;78u"))[0]
app.post_message(caps_lock_n)
await pilot.pause()
assert not isinstance(app.screen, AddEntryModal)
@pytest.mark.asyncio
async def test_new_from_selected_requires_a_visible_host_entry():
"""Shift+N does not reuse a stale selection when filters hide every entry."""