diff --git a/src/hqt/tui/app.py b/src/hqt/tui/app.py index 4df8d0b..dd2031d 100644 --- a/src/hqt/tui/app.py +++ b/src/hqt/tui/app.py @@ -72,6 +72,7 @@ class HqtApp(App): Binding("tab", "toggle_focus", "Switch Panel"), Binding("h", "focus_projects", "Projects"), Binding("l", "focus_sessions", "Sessions"), + Binding("x", "archive_session", "Archive"), Binding("d", "delete_session", "Delete Session"), Binding("enter", "attach_session", "Attach", priority=True), Binding("r", "rename_session", "Rename"), @@ -436,6 +437,17 @@ class HqtApp(App): self._run_service_worker(_do()) + def action_archive_session(self) -> None: + sid = self.query_one(SessionList).get_selected_session_id() + if not sid: + return + + async def _do() -> None: + await self._sessions().archive_session(sid) + await self._refresh_sessions() + + self._run_service_worker(_do()) + def action_schedule_prompt(self) -> None: sid = self.query_one(SessionList).get_selected_session_id() if sid is None: diff --git a/tests/test_tui.py b/tests/test_tui.py index b9bcf94..1afce4e 100644 --- a/tests/test_tui.py +++ b/tests/test_tui.py @@ -2035,3 +2035,56 @@ async def test_session_list_header_reflects_archived_mode(): sl.set_mode(archived=False) await pilot.pause() assert str(header.render()) == "Sessions" + + +@pytest.mark.asyncio +async def test_archive_session_binding_exists(): + bindings = {b.key: b for b in HqtApp.BINDINGS} + assert bindings["x"].action == "archive_session" + + +@pytest.mark.asyncio +async def test_archive_session_action_calls_service_and_refreshes(): + app = HqtApp() + async with app.run_test(size=(120, 40)) as pilot: + from hqt.db.models import Project, Harness, Session + from hqt.tui.widgets.session_list import SessionList + + seed_db = app._db_factory() + proj = Project(name="arch-proj", path="/tmp/arch-proj") + seed_db.add(proj) + seed_db.flush() + harness = seed_db.query(Harness).first() + sess = Session( + project_id=proj.id, + harness_id=harness.id, + tmux_session_name="hqt-arch-action", + archived=False, + ) + seed_db.add(sess) + seed_db.commit() + proj_id = proj.id + sess_id = sess.id + seed_db.close() + + app._selected_project_id = proj_id + await app._refresh_sessions() + await pilot.pause() + + sl = app.query_one(SessionList) + sl.query_one("#session-list").focus() + await pilot.press("down") + await pilot.pause() + assert sl.get_selected_session_id() == sess_id + + mock_service = MagicMock() + mock_service.archive_session = AsyncMock() + mock_service.list_sessions = AsyncMock(return_value=[]) + mock_service.sync_window_labels = AsyncMock(return_value=[]) + app._session_service = mock_service + + await app.run_action("archive_session") + await pilot.pause() + + mock_service.archive_session.assert_awaited_once_with(sess_id) + mock_service.list_sessions.assert_awaited()