"""Tests for app.session_manager module.""" from __future__ import annotations import time from unittest.mock import patch import pytest from app.session_manager import SessionManager @pytest.mark.unit class TestSessionManager: def test_new_session_not_expired(self, session_manager: SessionManager) -> None: session_manager.touch("thread-1") assert not session_manager.is_expired("thread-1") def test_unknown_session_is_expired(self, session_manager: SessionManager) -> None: assert session_manager.is_expired("unknown") def test_session_expires_after_ttl(self) -> None: mgr = SessionManager(session_ttl_seconds=1) mgr.touch("t1") with patch("app.session_manager.time") as mock_time: mock_time.time.return_value = time.time() + 2 assert mgr.is_expired("t1") def test_touch_resets_ttl(self) -> None: mgr = SessionManager(session_ttl_seconds=5) mgr.touch("t1") initial_state = mgr.get_state("t1") # Touch again after some time with patch("app.session_manager.time") as mock_time: mock_time.time.return_value = time.time() + 3 mgr.touch("t1") new_state = mgr.get_state("t1") assert new_state.last_activity > initial_state.last_activity def test_interrupt_suspends_expiration(self) -> None: mgr = SessionManager(session_ttl_seconds=1) mgr.touch("t1") mgr.extend_for_interrupt("t1") with patch("app.session_manager.time") as mock_time: mock_time.time.return_value = time.time() + 100 assert not mgr.is_expired("t1") def test_resolve_interrupt_resumes_ttl(self) -> None: mgr = SessionManager(session_ttl_seconds=1) mgr.touch("t1") mgr.extend_for_interrupt("t1") mgr.resolve_interrupt("t1") state = mgr.get_state("t1") assert not state.has_pending_interrupt def test_extend_for_nonexistent_creates_session(self) -> None: mgr = SessionManager() mgr.extend_for_interrupt("new-thread") state = mgr.get_state("new-thread") assert state is not None def test_remove_session(self, session_manager: SessionManager) -> None: session_manager.touch("t1") session_manager.remove("t1") assert session_manager.get_state("t1") is None def test_session_state_is_immutable(self, session_manager: SessionManager) -> None: state = session_manager.touch("t1") with pytest.raises(Exception): state.thread_id = "new"