116 lines
3.1 KiB
Python
116 lines
3.1 KiB
Python
import unittest
|
|
from unittest import mock
|
|
|
|
from sbp.tui import frame
|
|
from sbp.tui.term import Term
|
|
|
|
|
|
class FakeScreen:
|
|
def __init__(self, height: int = 24, width: int = 80) -> None:
|
|
self.height = height
|
|
self.width = width
|
|
self.writes: list[tuple[int, int, str]] = []
|
|
|
|
def getmaxyx(self):
|
|
return self.height, self.width
|
|
|
|
def addstr(self, y, x, text, attr=0):
|
|
if y >= self.height or x + len(text) > self.width:
|
|
raise AssertionError(f"write out of bounds: y={y} x={x} len={len(text)}")
|
|
self.writes.append((y, x, text))
|
|
|
|
def erase(self):
|
|
self.writes.clear()
|
|
|
|
def refresh(self):
|
|
pass
|
|
|
|
def keypad(self, flag):
|
|
pass
|
|
|
|
def getch(self):
|
|
return -1
|
|
|
|
def text(self) -> str:
|
|
return "\n".join(text for _, _, text in self.writes)
|
|
|
|
|
|
def make_term(screen: FakeScreen) -> Term:
|
|
with mock.patch.object(frame_term_curses(), "has_colors", return_value=False), \
|
|
mock.patch.object(frame_term_curses(), "curs_set", return_value=None):
|
|
return Term(screen)
|
|
|
|
|
|
def frame_term_curses():
|
|
import sbp.tui.term as module
|
|
|
|
return module.curses
|
|
|
|
|
|
class WindowOffsetTest(unittest.TestCase):
|
|
def test_no_scroll_when_everything_fits(self) -> None:
|
|
self.assertEqual(frame.window_offset(3, 5, 10), 0)
|
|
|
|
def test_keeps_selection_visible(self) -> None:
|
|
self.assertEqual(frame.window_offset(7, 20, 5), 3)
|
|
|
|
def test_clamps_to_last_page(self) -> None:
|
|
self.assertEqual(frame.window_offset(19, 20, 5), 15)
|
|
|
|
|
|
class SidebarWidthTest(unittest.TestCase):
|
|
def test_minimum(self) -> None:
|
|
self.assertEqual(frame.sidebar_width(["A"]), frame.SIDEBAR_MIN)
|
|
|
|
def test_grows_with_titles(self) -> None:
|
|
self.assertGreater(
|
|
frame.sidebar_width(["VeryLongSectionName"]), frame.sidebar_width(["A"])
|
|
)
|
|
|
|
def test_capped(self) -> None:
|
|
self.assertEqual(frame.sidebar_width(["x" * 100]), frame.SIDEBAR_MAX)
|
|
|
|
|
|
class DrawTest(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.screen = FakeScreen()
|
|
self.term = make_term(self.screen)
|
|
|
|
def draw(self, rows=None, index=0, width=80):
|
|
rows = rows or [frame.Row("first", action=lambda app: None), frame.Row("second")]
|
|
frame.draw(
|
|
self.term,
|
|
title="sbp 2.0.0",
|
|
subtitle="host active",
|
|
sidebar=["Dashboard", "Protocols", "Users", "Settings", "Logs"],
|
|
sidebar_index=1,
|
|
sidebar_focused=False,
|
|
content_title="Protocols",
|
|
rows=rows,
|
|
index=index,
|
|
content_focused=True,
|
|
footer="keys",
|
|
)
|
|
|
|
def test_draws_both_panes(self) -> None:
|
|
self.draw()
|
|
text = self.screen.text()
|
|
for word in ("Dashboard", "Protocols", "Users", "Settings", "Logs", "first", "second", "keys"):
|
|
self.assertIn(word, text)
|
|
|
|
def test_selected_row_is_padded_for_highlight(self) -> None:
|
|
self.draw(index=1)
|
|
row = [text for y, _, text in self.screen.writes if text.startswith("second")]
|
|
self.assertTrue(row)
|
|
self.assertGreater(len(row[0]), len("second"))
|
|
|
|
def test_small_terminal_shows_hint(self) -> None:
|
|
self.screen = FakeScreen(height=8, width=40)
|
|
self.term.screen = self.screen
|
|
self.draw()
|
|
self.assertIn("terminal too small", self.screen.text())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|