Files
2024-12-17 14:36:15 -08:00

173 lines
5.4 KiB
Python

"""
Tests for the insults windowing module, L{twisted.conch.insults.window}.
"""
from __future__ import annotations
from typing import Callable
from twisted.conch.insults.insults import ServerProtocol
from twisted.conch.insults.window import (
ScrolledArea,
Selection,
TextOutput,
TopWindow,
Widget,
)
from twisted.trial.unittest import TestCase
class TopWindowTests(TestCase):
"""
Tests for L{TopWindow}, the root window container class.
"""
def test_paintScheduling(self) -> None:
"""
Verify that L{TopWindow.repaint} schedules an actual paint to occur
using the scheduling object passed to its initializer.
"""
paints: list[None] = []
scheduled: list[Callable[[], object]] = []
root = TopWindow(lambda: paints.append(None), scheduled.append)
# Nothing should have happened yet.
self.assertEqual(paints, [])
self.assertEqual(scheduled, [])
# Cause a paint to be scheduled.
root.repaint()
self.assertEqual(paints, [])
self.assertEqual(len(scheduled), 1)
# Do another one to verify nothing else happens as long as the previous
# one is still pending.
root.repaint()
self.assertEqual(paints, [])
self.assertEqual(len(scheduled), 1)
# Run the actual paint call.
scheduled.pop()()
self.assertEqual(len(paints), 1)
self.assertEqual(scheduled, [])
# Do one more to verify that now that the previous one is finished
# future paints will succeed.
root.repaint()
self.assertEqual(len(paints), 1)
self.assertEqual(len(scheduled), 1)
class ScrolledAreaTests(TestCase):
"""
Tests for L{ScrolledArea}, a widget which creates a viewport containing
another widget and can reposition that viewport using scrollbars.
"""
def test_parent(self) -> None:
"""
The parent of the widget passed to L{ScrolledArea} is set to a new
L{Viewport} created by the L{ScrolledArea} which itself has the
L{ScrolledArea} instance as its parent.
"""
widget = TextOutput()
scrolled = ScrolledArea(widget)
self.assertIs(widget.parent, scrolled._viewport)
self.assertIs(scrolled._viewport.parent, scrolled)
class SelectionTests(TestCase):
"""
Change focused entry in L{Selection} using function keys.
"""
def setUp(self) -> None:
"""
Create L{ScrolledArea} widget with 10 elements and position selection to 5th element.
"""
seq: list[bytes] = [f"{_num}".encode("ascii") for _num in range(10)]
self.widget = Selection(seq, None)
self.widget.height = 10
self.widget.focusedIndex = 5
def test_selectionDownArrow(self) -> None:
"""
Send DOWN_ARROW to select element just below the current one.
"""
self.widget.keystrokeReceived(ServerProtocol.DOWN_ARROW, None) # type: ignore[attr-defined]
self.assertIs(self.widget.focusedIndex, 6)
def test_selectionUpArrow(self) -> None:
"""
Send UP_ARROW to select element just above the current one.
"""
self.widget.keystrokeReceived(ServerProtocol.UP_ARROW, None) # type: ignore[attr-defined]
self.assertIs(self.widget.focusedIndex, 4)
def test_selectionPGDN(self) -> None:
"""
Send PGDN to select element one page down (here: last element).
"""
self.widget.keystrokeReceived(ServerProtocol.PGDN, None) # type: ignore[attr-defined]
self.assertIs(self.widget.focusedIndex, 9)
def test_selectionPGUP(self) -> None:
"""
Send PGUP to select element one page up (here: first element).
"""
self.widget.keystrokeReceived(ServerProtocol.PGUP, None) # type: ignore[attr-defined]
self.assertIs(self.widget.focusedIndex, 0)
class RecordingWidget(Widget):
"""
A dummy Widget implementation to test handling of function keys by
recording keyReceived events.
"""
def __init__(self) -> None:
Widget.__init__(self)
self.triggered: list[str] = []
def func_F1(self, modifier: str) -> None:
self.triggered.append("F1")
def func_HOME(self, modifier: str) -> None:
self.triggered.append("HOME")
def func_DOWN_ARROW(self, modifier: str) -> None:
self.triggered.append("DOWN_ARROW")
def func_UP_ARROW(self, modifier: str) -> None:
self.triggered.append("UP_ARROW")
def func_PGDN(self, modifier: str) -> None:
self.triggered.append("PGDN")
def func_PGUP(self, modifier: str) -> None:
self.triggered.append("PGUP")
class WidgetFunctionKeyTests(TestCase):
"""
Call functionKeyReceived with key values from insults.ServerProtocol
"""
def test_functionKeyReceivedDispatch(self) -> None:
"""
L{Widget.functionKeyReceived} dispatches its input, a constant on
ServerProtocol, to a matched C{func_KEY} method.
"""
widget = RecordingWidget()
def checkOneKey(key: str) -> None:
widget.functionKeyReceived(getattr(ServerProtocol, key), None)
self.assertEqual([key], widget.triggered)
widget.triggered.clear()
checkOneKey("F1")
checkOneKey("HOME")
checkOneKey("DOWN_ARROW")
checkOneKey("UP_ARROW")
checkOneKey("PGDN")
checkOneKey("PGUP")