#!/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()