feat: TUI widget primitives (colors, InputField, draw helpers)

Implement COLOR_* constants, initialization, box/centered drawing,
clamp utility, and InputField with handle_key/value logic for pure
text editing without live curses. All tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vlad Doloman
2026-06-24 00:00:52 +03:00
parent a2593b644e
commit 3a6d6aa125
2 changed files with 153 additions and 0 deletions

53
tests/test_widgets.py Normal file
View File

@@ -0,0 +1,53 @@
from unittest.mock import MagicMock
import curses as _curses
# Stub just enough of the curses API for InputField to import
_curses.color_pair = lambda x: 0
_curses.A_UNDERLINE = 0
_curses.A_BOLD = 0
_curses.KEY_BACKSPACE = 263
_curses.KEY_LEFT = 260
_curses.KEY_RIGHT = 261
_curses.KEY_HOME = 262
_curses.KEY_END = 360
_curses.KEY_DC = 330
from openvpncertupdate import InputField, clamp
def _field(initial="", mask=False):
win = MagicMock()
win.getmaxyx.return_value = (1, 80)
return InputField(win, 0, 0, 40, initial=initial, mask=mask)
def test_initial_value():
assert _field("hello").value == "hello"
def test_backspace_removes_last():
f = _field("hello")
f.handle_key(_curses.KEY_BACKSPACE)
assert f.value == "hell"
def test_type_appends():
f = _field("hi")
f.handle_key(ord("!"))
assert f.value == "hi!"
def test_left_then_insert():
f = _field("ac")
f.handle_key(_curses.KEY_LEFT)
f.handle_key(_curses.KEY_LEFT)
f.handle_key(ord("b"))
assert f.value == "bac"
def test_delete_key():
f = _field("abc")
f.handle_key(_curses.KEY_HOME)
f.handle_key(_curses.KEY_DC)
assert f.value == "bc"
def test_clamp_bounds():
assert clamp(5, 0, 10) == 5
assert clamp(-1, 0, 10) == 0
assert clamp(11, 0, 10) == 10