fix(tui): harden all Box TUI tabs against nulls, boundary slices, and small screens
This commit is contained in:
@@ -16,6 +16,10 @@ spec = importlib.util.spec_from_file_location("muse_tui", str(BIN_DIR / "muse-tu
|
||||
muse_tui = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(muse_tui)
|
||||
|
||||
spec_fleet = importlib.util.spec_from_file_location("box_fleet_tui", str(BIN_DIR / "box-fleet-tui.py"))
|
||||
box_fleet_tui = importlib.util.module_from_spec(spec_fleet)
|
||||
spec_fleet.loader.exec_module(box_fleet_tui)
|
||||
|
||||
|
||||
class TestBoxTUIHeadless(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@@ -134,6 +138,146 @@ class TestBoxTUIHeadless(unittest.TestCase):
|
||||
app._handle_key(ord('\t'))
|
||||
mock_load.assert_called_with("pip", "upcoming")
|
||||
|
||||
def test_muse_tui_all_tabs_fuzz_dimensions_and_corrupt_data(self):
|
||||
dimensions = [(8, 20), (12, 40), (24, 80), (50, 160)]
|
||||
|
||||
corrupt_dataset = {
|
||||
"cognitive": {
|
||||
"muse": None,
|
||||
"pip": {"status": None, "cognitive_lock": None, "screen": None},
|
||||
"dev": {"status": "THINKING", "cognitive_lock": True, "screen": {"url": None, "title": None}}
|
||||
},
|
||||
"issues": [
|
||||
{"number": 1, "state": None, "title": None, "assignee": None, "labels": None},
|
||||
{"number": 2, "state": "open", "title": "Test", "assignee": {"username": None}, "labels": [None, {"name": None}]}
|
||||
],
|
||||
"prs": [
|
||||
{"number": 1, "state": None, "merged": False, "title": None, "head": None},
|
||||
{"number": 2, "state": "open", "merged": True, "title": "PR test", "head": {"ref": None}}
|
||||
],
|
||||
"approvals": [
|
||||
{"node": None, "status": None, "target": None},
|
||||
{"node": "pip", "status": "INPUT_WAIT", "input_waits": [None, {"task": None}]}
|
||||
],
|
||||
"jobs": [
|
||||
{"name": None, "agent": None, "schedule": None, "timeout": None, "description": None}
|
||||
],
|
||||
"tmux": ["", "invalid:session:colon"],
|
||||
"dm_logs": [
|
||||
{"type": None, "agent": None, "to": None, "target": None, "ts": None, "id": None}
|
||||
]
|
||||
}
|
||||
|
||||
for h, w in dimensions:
|
||||
stdscr = MagicMock()
|
||||
stdscr.getmaxyx.return_value = (h, w)
|
||||
stdscr.getch.return_value = -1
|
||||
|
||||
app = muse_tui.MuseTUI(stdscr, initial_mode="box", initial_tab="chat")
|
||||
app._term_dims = (h, w)
|
||||
|
||||
# Test with empty caches
|
||||
app.data.cognitive_cache = {}
|
||||
app.data.work_issues_cache = []
|
||||
app.data.work_prs_cache = []
|
||||
app.data.approvals_cache = []
|
||||
app.data.jobs_cache = []
|
||||
app.data.dm_logs_cache = []
|
||||
|
||||
content_h = max(1, h - 4)
|
||||
for tab_idx in range(8):
|
||||
app.box_tab = tab_idx
|
||||
if tab_idx == 0:
|
||||
app._render_muse_view(2, 0, content_h, w)
|
||||
elif tab_idx == 1:
|
||||
app._render_fleet_table(2, 0, content_h, w)
|
||||
elif tab_idx == 2:
|
||||
app._render_approvals_view(2, 0, content_h, w)
|
||||
elif tab_idx == 3:
|
||||
app._render_jobs_view(2, 0, content_h, w)
|
||||
elif tab_idx == 4:
|
||||
with patch("subprocess.run") as mock_sub:
|
||||
mock_sub.return_value = MagicMock(returncode=0, stdout="s1: 1 windows\n")
|
||||
app._render_tmux_view(2, 0, content_h, w)
|
||||
elif tab_idx == 5:
|
||||
app._render_dm_logs_view(2, 0, content_h, w)
|
||||
elif tab_idx == 6:
|
||||
app._render_ssh_view(2, 0, content_h, w)
|
||||
elif tab_idx == 7:
|
||||
app._render_work_view(2, 0, content_h, w)
|
||||
|
||||
# Test with corrupt / null caches
|
||||
app.data.cognitive_cache = corrupt_dataset["cognitive"]
|
||||
app.data.work_issues_cache = corrupt_dataset["issues"]
|
||||
app.data.work_prs_cache = corrupt_dataset["prs"]
|
||||
app.data.approvals_cache = corrupt_dataset["approvals"]
|
||||
app.data.jobs_cache = corrupt_dataset["jobs"]
|
||||
app.data.dm_logs_cache = corrupt_dataset["dm_logs"]
|
||||
|
||||
for tab_idx in range(8):
|
||||
app.box_tab = tab_idx
|
||||
if tab_idx == 0:
|
||||
app._render_muse_view(2, 0, content_h, w)
|
||||
elif tab_idx == 1:
|
||||
app._render_fleet_table(2, 0, content_h, w)
|
||||
elif tab_idx == 2:
|
||||
app._render_approvals_view(2, 0, content_h, w)
|
||||
elif tab_idx == 3:
|
||||
app._render_jobs_view(2, 0, content_h, w)
|
||||
elif tab_idx == 4:
|
||||
with patch("subprocess.run") as mock_sub:
|
||||
mock_sub.return_value = MagicMock(returncode=0, stdout="s1: 1 windows\n")
|
||||
app._render_tmux_view(2, 0, content_h, w)
|
||||
elif tab_idx == 5:
|
||||
app._render_dm_logs_view(2, 0, content_h, w)
|
||||
elif tab_idx == 6:
|
||||
app._render_ssh_view(2, 0, content_h, w)
|
||||
elif tab_idx == 7:
|
||||
app._render_work_view(2, 0, content_h, w)
|
||||
|
||||
def test_box_fleet_tui_all_tabs_fuzz_dimensions_and_corrupt_data(self):
|
||||
dimensions = [(8, 20), (12, 40), (24, 80), (50, 160)]
|
||||
for h, w in dimensions:
|
||||
stdscr = MagicMock()
|
||||
stdscr.getmaxyx.return_value = (h, w)
|
||||
stdscr.getch.return_value = -1
|
||||
|
||||
fleet_app = box_fleet_tui.BoxFleetTUI(stdscr)
|
||||
|
||||
# 1. Empty snapshot
|
||||
fleet_app.snapshot = {}
|
||||
renderers = [fleet_app._render_timers, fleet_app._render_harvest,
|
||||
fleet_app._render_followups, fleet_app._render_approvals,
|
||||
fleet_app._render_activity, fleet_app._render_runtimes,
|
||||
fleet_app._render_work]
|
||||
|
||||
for tab_idx, renderer in enumerate(renderers):
|
||||
fleet_app.current_tab = tab_idx
|
||||
renderer(h, w)
|
||||
|
||||
# 2. Corrupted / null snapshot
|
||||
fleet_app.snapshot = {
|
||||
"timers": {"rows": [{"timer": None, "next": None, "next_rel": None, "last": None, "last_rel": None, "activates": None}]},
|
||||
"harvest": {"rows": [{"freshness": None, "agent": None, "thread": None, "watermark": None, "last": None, "ago": None}]},
|
||||
"followups": {"counts": {"pending": 2}, "by_recipient": {"pip": 1}, "oldest_pending": None},
|
||||
"approvals": {"total_pending": 1, "checked": 1, "unreachable": [], "pending": [{"node": None, "status": None, "target": None, "title": None}]},
|
||||
"activity": {"rows": [{"freshness": None, "agent": None, "last": None, "last_rel": None, "source": None, "detail": None}]},
|
||||
"runtimes": {"agents": [{"live": True, "briefed": None, "enabled": True, "session": None, "hat": None, "pane": None, "state": None, "mode": None, "watcher": None}], "queue": {}, "plan": {}},
|
||||
"work": {
|
||||
"cognitive": {"dev": None},
|
||||
"issues": [{"number": None, "state": None, "assignee": None, "created_at": None, "title": None}],
|
||||
"loopback_active": True
|
||||
}
|
||||
}
|
||||
|
||||
for tab_idx, renderer in enumerate(renderers):
|
||||
fleet_app.current_tab = tab_idx
|
||||
renderer(h, w)
|
||||
|
||||
fleet_app._render_header(w)
|
||||
fleet_app._render_footer(h, w)
|
||||
fleet_app._render_help(h, w)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user