Files
ss-tools/backend/tests/services/dataset_review/test_event_logger.py

219 lines
7.6 KiB
Python

# #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