# #region Test.SessionEventLogger [C:2] [TYPE Module] [SEMANTICS test,dataset,event,logger,session,audit] # @BRIEF Tests for event_logger.py — session event logging and persistence. # @RELATION BINDS_TO -> [SessionEventLoggerModule] # @TEST_EDGE: log_event -> Persists event payload correctly # @TEST_EDGE: log_event_validation -> Empty fields raise ValueError # @TEST_EDGE: log_event_with_details -> Event details stored # @TEST_EDGE: log_for_session -> Convenience wrapper from session object from pathlib import Path import sys sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src")) from unittest.mock import MagicMock, patch import pytest class TestSessionEventPayload: """SessionEventPayload — dataclass contract.""" def test_payload_creation(self): from src.services.dataset_review.event_logger import SessionEventPayload payload = SessionEventPayload( session_id="sess-1", actor_user_id="user-1", event_type="session_started", event_summary="Session created", current_phase="RECOVERY", readiness_state="IMPORTING", event_details={"key": "val"}, ) assert payload.session_id == "sess-1" assert payload.event_type == "session_started" assert payload.event_details == {"key": "val"} class TestSessionEventLoggerLogEvent: """SessionEventLogger.log_event — persist event.""" @pytest.fixture def db(self): return MagicMock() @pytest.fixture def logger(self, db): from src.services.dataset_review.event_logger import SessionEventLogger return SessionEventLogger(db) def test_log_event_success(self, logger, db): from src.services.dataset_review.event_logger import SessionEventPayload # Mock SessionEvent mock_event = MagicMock() mock_event.session_event_id = "evt-1" mock_event.event_type = "session_started" db.add.return_value = None db.refresh.return_value = None payload = SessionEventPayload( session_id="sess-1", actor_user_id="user-1", event_type="session_started", event_summary="Session created", current_phase="RECOVERY", readiness_state="IMPORTING", event_details={"source": "superset"}, ) result = logger.log_event(payload) db.add.assert_called_once() db.commit.assert_called_once() db.refresh.assert_called_once() def test_log_event_minimal(self, logger, db): from src.services.dataset_review.event_logger import SessionEventPayload payload = SessionEventPayload( session_id="sess-1", actor_user_id="user-1", event_type="update", event_summary="Updated", ) result = logger.log_event(payload) db.add.assert_called_once() db.commit.assert_called_once() def test_empty_session_id_raises(self, logger, db): from src.services.dataset_review.event_logger import SessionEventPayload payload = SessionEventPayload( session_id="", actor_user_id="user-1", event_type="test", event_summary="test", ) with pytest.raises(ValueError, match="session_id"): logger.log_event(payload) db.add.assert_not_called() def test_empty_actor_user_id_raises(self, logger, db): from src.services.dataset_review.event_logger import SessionEventPayload payload = SessionEventPayload( session_id="sess-1", actor_user_id="", event_type="test", event_summary="test", ) with pytest.raises(ValueError, match="actor_user_id"): logger.log_event(payload) db.add.assert_not_called() def test_empty_event_type_raises(self, logger, db): from src.services.dataset_review.event_logger import SessionEventPayload payload = SessionEventPayload( session_id="sess-1", actor_user_id="user-1", event_type="", event_summary="test", ) with pytest.raises(ValueError, match="event_type"): logger.log_event(payload) db.add.assert_not_called() def test_empty_event_summary_raises(self, logger, db): from src.services.dataset_review.event_logger import SessionEventPayload payload = SessionEventPayload( session_id="sess-1", actor_user_id="user-1", event_type="test", event_summary="", ) with pytest.raises(ValueError, match="event_summary"): logger.log_event(payload) db.add.assert_not_called() def test_event_with_complex_details(self, logger, db): from src.services.dataset_review.event_logger import SessionEventPayload payload = SessionEventPayload( session_id="sess-1", actor_user_id="user-1", event_type="mapping_approved", event_summary="Mappings approved by assistant", event_details={ "mapping_ids": ["m-1", "m-2"], "count": 2, "nested": {"key": "value"}, }, ) result = logger.log_event(payload) db.add.assert_called_once() # Verify the event_details dict added = db.add.call_args[0][0] assert added.event_details["mapping_ids"] == ["m-1", "m-2"] class TestSessionEventLoggerLogForSession: """SessionEventLogger.log_for_session — convenience wrapper.""" def test_log_for_session(self): from src.services.dataset_review.event_logger import SessionEventLogger, SessionEventPayload from src.models.dataset_review import DatasetReviewSession, SessionPhase, ReadinessState db = MagicMock() session = MagicMock(spec=DatasetReviewSession) session.session_id = "sess-1" session.current_phase = MagicMock(value="review") session.readiness_state = MagicMock(value="review_ready") logger = SessionEventLogger(db) with patch.object(logger, "log_event") as mock_log: mock_log.return_value = MagicMock(session_event_id="evt-1") result = logger.log_for_session( session, actor_user_id="user-1", event_type="preview_generated", event_summary="Preview ready", event_details={"preview_id": "pv-1"}, ) mock_log.assert_called_once() payload = mock_log.call_args[0][0] assert payload.session_id == "sess-1" assert payload.event_type == "preview_generated" assert payload.current_phase == "review" assert payload.readiness_state == "review_ready" def test_log_for_session_no_details(self): from src.services.dataset_review.event_logger import SessionEventLogger from src.models.dataset_review import DatasetReviewSession db = MagicMock() session = MagicMock(spec=DatasetReviewSession) session.session_id = "sess-1" session.current_phase = None session.readiness_state = None logger = SessionEventLogger(db) with patch.object(logger, "log_event") as mock_log: mock_log.return_value = MagicMock(session_event_id="evt-1") logger.log_for_session( session, actor_user_id="user-1", event_type="test", event_summary="test", ) payload = mock_log.call_args[0][0] assert payload.current_phase is None assert payload.readiness_state is None # #endregion Test.SessionEventLogger