Files

143 lines
6.3 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
"""
test_focus_highlight.py — Comprehensive tests verifying active portion highlighting in MuseTUI:
1. Sidebar focused (focus_pane="sidebar", editor_mode="NORMAL") highlights sidebar header,
vertical pane divider, selected thread cursor, and bottom status bar hints.
2. Transcript focused (focus_pane="transcript", editor_mode="NORMAL") highlights transcript header,
header underline rule, vertical divider, and bottom status bar hints.
3. Composer active (editor_mode="INSERT") prominently highlights bottom composer divider
and status hints without distracting pane navigation highlights.
"""
import unittest
from unittest.mock import MagicMock
import importlib.util
from pathlib import Path
REPO_ROOT = Path("/home/super/Projects/NetVM")
TUI_PATH = REPO_ROOT / "bin" / "muse-tui.py"
spec = importlib.util.spec_from_file_location("muse_tui", str(TUI_PATH))
muse_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(muse_mod)
class TestActivePortionHighlighting(unittest.TestCase):
def setUp(self):
self.mock_stdscr = MagicMock()
self.mock_stdscr.getmaxyx.return_value = (30, 100)
self.tui = muse_mod.MuseTUI(self.mock_stdscr, initial_mode="muse", initial_node="muse")
self.calls = []
def record_addstr(win, y, x, text, attr=0):
self.calls.append((y, x, text, attr))
self.tui.safe_addstr = record_addstr
self.tui.toast_time = 0
self.tui.data.nodes = ["muse", "646", "pip"]
self.tui.data.active_node = "muse"
self.tui.data.active_thread_id = "test_thread"
self.tui.data.active_thread_title = "Work Thread"
self.tui.data.threads_cache["muse"] = [
{"session_id": "test_thread", "title": "Work Thread", "is_main": False},
{"session_id": "main_id", "title": "Main Chat", "is_main": True},
]
self.tui.data.history_cache[("muse", "test_thread")] = [
{"role": "user", "text": "Hello agent", "seq": 1, "message_id": "m1"},
{"role": "assistant", "text": "Hello user", "seq": 2, "message_id": "m2"},
]
def test_sidebar_focused_highlight(self):
self.tui.focus_pane = "sidebar"
self.tui.editor_mode = "NORMAL"
# 1. Render Muse View
self.calls.clear()
self.tui._render_muse_view(2, 0, 24, 100)
rendered_texts = [c[2] for c in self.calls]
full_text = " ".join(rendered_texts)
# Sidebar header has [● FOCUS] badge
self.assertTrue(any("[● FOCUS] FLEET AGENTS" in t for t in rendered_texts),
f"Expected [● FOCUS] in sidebar header. Got:\n{full_text}")
# Vertical divider has heavy vertical char ┃
self.assertTrue(any("┃" in t for t in rendered_texts),
"Expected vertical divider '┃' when pane is focused")
# Transcript header does NOT have [● FOCUSED] badge
self.assertFalse(any("[● FOCUSED]" in t for t in rendered_texts),
"Transcript header should not be [● FOCUSED] when sidebar is active")
# 2. Render Bottom Bar
self.calls.clear()
self.tui._render_bottom_bar(27, 0, 3, 100)
bottom_texts = [c[2] for c in self.calls]
# Active pane divider has SIDEBAR highlight
self.assertTrue(any("ACTIVE PANE: SIDEBAR" in t for t in bottom_texts),
f"Expected ACTIVE PANE: SIDEBAR in bottom divider. Got:\n{bottom_texts}")
# Status hints show SIDEBAR FOCUSED
self.assertTrue(any("SIDEBAR FOCUSED" in t for t in bottom_texts),
f"Expected SIDEBAR FOCUSED in hints. Got:\n{bottom_texts}")
def test_transcript_focused_highlight(self):
self.tui.focus_pane = "transcript"
self.tui.editor_mode = "NORMAL"
# 1. Render Muse View
self.calls.clear()
self.tui._render_muse_view(2, 0, 24, 100)
rendered_texts = [c[2] for c in self.calls]
# Transcript header has [● FOCUSED] badge
self.assertTrue(any("[● FOCUSED] Thread:" in t for t in rendered_texts),
f"Expected [● FOCUSED] in transcript header. Got:\n{rendered_texts}")
# Transcript horizontal divider has heavy rule ━
self.assertTrue(any("━" in t for t in rendered_texts),
"Expected transcript underline divider '━' when transcript is focused")
# Sidebar header does NOT have [● FOCUS] badge
self.assertFalse(any("[● FOCUS] FLEET AGENTS" in t for t in rendered_texts),
"Sidebar should not have [● FOCUS] when transcript is active")
# 2. Render Bottom Bar
self.calls.clear()
self.tui._render_bottom_bar(27, 0, 3, 100)
bottom_texts = [c[2] for c in self.calls]
self.assertTrue(any("ACTIVE PANE: TRANSCRIPT" in t for t in bottom_texts),
f"Expected ACTIVE PANE: TRANSCRIPT in bottom divider. Got:\n{bottom_texts}")
self.assertTrue(any("TRANSCRIPT FOCUSED" in t for t in bottom_texts),
f"Expected TRANSCRIPT FOCUSED in hints. Got:\n{bottom_texts}")
def test_insert_mode_composer_highlight(self):
self.tui.editor_mode = "INSERT"
# 1. Render Bottom Bar
self.calls.clear()
self.tui._render_bottom_bar(27, 0, 3, 100)
bottom_texts = [c[2] for c in self.calls]
self.assertTrue(any("COMPOSER: INSERT MODE ACTIVE" in t for t in bottom_texts),
f"Expected COMPOSER: INSERT MODE ACTIVE in divider. Got:\n{bottom_texts}")
self.assertTrue(any("INSERT ACTIVE" in t for t in bottom_texts),
f"Expected INSERT ACTIVE in hints. Got:\n{bottom_texts}")
# 2. Render Muse View - neither pane should show [● FOCUS] / [● FOCUSED]
self.calls.clear()
self.tui._render_muse_view(2, 0, 24, 100)
rendered_texts = [c[2] for c in self.calls]
self.assertFalse(any("[● FOCUS] FLEET AGENTS" in t for t in rendered_texts),
"Sidebar should not claim active focus in INSERT mode")
self.assertFalse(any("[● FOCUSED] Thread:" in t for t in rendered_texts),
"Transcript should not claim active focus in INSERT mode")
if __name__ == "__main__":
unittest.main()