# #region Test.DatasetReviewSessionModels [C:3] [TYPE Module] [SEMANTICS test,sqlalchemy,dataset,review,session,model] # @BRIEF Verify DatasetReviewSession and SessionCollaborator SQLAlchemy models — construction, defaults, FK constraints, relationships. # @RELATION BINDS_TO -> [DatasetReviewSessionModels] # @TEST_EDGE: missing_session_id -> session_id auto-generated as UUID # @TEST_EDGE: invalid_enum -> SQLEnum rejects bad values # @TEST_EDGE: cascade_delete -> Session delete cascades to collaborators # @TEST_EDGE: optimistic_lock -> version column starts at 0 and increments import uuid from datetime import UTC, datetime from sqlalchemy import create_engine, text from sqlalchemy.orm import Session as SASession import pytest from src.models.dataset_review_pkg._enums import ( ReadinessState, RecommendedAction, SessionCollaboratorRole, SessionPhase, SessionStatus, ) from src.models.dataset_review_pkg._session_models import ( Base, DatasetReviewSession, SessionCollaborator, ) from src.models.mapping import Environment @pytest.fixture(scope="function") def db_session(): """Fresh in-memory SQLite with FK enforcement using single connection (avoids per-connection isolation).""" engine = create_engine("sqlite:///:memory:", connect_args={"check_same_thread": False}) conn = engine.connect() conn.execute(text("PRAGMA foreign_keys=ON")) # Create the raw users table FIRST — multiple model tables FK-reference it conn.execute(text("CREATE TABLE IF NOT EXISTS users (id VARCHAR PRIMARY KEY)")) from src.models.mapping import Base as MappingBase MappingBase.metadata.create_all(conn) Base.metadata.create_all(conn) conn.commit() session = SASession(bind=conn) env = Environment(id="env-1", name="Test", url="https://superset.example.com", credentials_id="cred-1") session.add(env) session.execute(text("INSERT OR IGNORE INTO users (id) VALUES ('user-1')")) session.commit() yield session session.close() conn.close() class TestDatasetReviewSession: """Verify DatasetReviewSession model construction and defaults.""" def test_create_minimal(self, db_session): """Minimal required fields produce a valid session with defaults.""" review = DatasetReviewSession( user_id="user-1", environment_id="env-1", source_kind="superset", source_input="SELECT * FROM orders", dataset_ref="dataset_42", ) db_session.add(review) db_session.flush() assert review.session_id is not None assert isinstance(review.session_id, str) # Check UUID format uuid.UUID(review.session_id) assert review.user_id == "user-1" assert review.environment_id == "env-1" assert review.source_kind == "superset" assert review.dataset_ref == "dataset_42" # Default values assert review.readiness_state == ReadinessState.EMPTY assert review.recommended_action == RecommendedAction.IMPORT_FROM_SUPERSET assert review.version == 0 assert review.status == SessionStatus.ACTIVE assert review.current_phase == SessionPhase.INTAKE assert review.dataset_id is None assert review.dashboard_id is None assert review.active_task_id is None assert review.last_preview_id is None assert review.last_run_context_id is None assert review.closed_at is None assert review.created_at is not None assert review.updated_at is not None assert review.last_activity_at is not None def test_all_fields(self, db_session): """All fields populated explicitly.""" created = datetime.now(UTC) review = DatasetReviewSession( user_id="user-1", environment_id="env-1", source_kind="superset", source_input="SELECT 1", dataset_ref="ds_1", dataset_id=100, dashboard_id=42, readiness_state=ReadinessState.RUN_READY, recommended_action=RecommendedAction.LAUNCH_DATASET, version=5, status=SessionStatus.ACTIVE, current_phase=SessionPhase.LAUNCH, active_task_id="task-abc", last_preview_id="prev-xyz", last_run_context_id="ctx-123", created_at=created, ) db_session.add(review) db_session.flush() assert review.dataset_id == 100 assert review.dashboard_id == 42 assert review.readiness_state == ReadinessState.RUN_READY assert review.recommended_action == RecommendedAction.LAUNCH_DATASET assert review.version == 5 assert review.current_phase == SessionPhase.LAUNCH assert review.active_task_id == "task-abc" assert review.last_preview_id == "prev-xyz" assert review.last_run_context_id == "ctx-123" def test_optimistic_lock_default(self, db_session): """Version column starts at 0 (optimistic locking).""" review = DatasetReviewSession( user_id="user-1", environment_id="env-1", source_kind="a", source_input="b", dataset_ref="c", ) db_session.add(review) db_session.flush() assert review.version == 0 def test_nullable_fields(self, db_session): """Fields marked nullable accept None.""" review = DatasetReviewSession( user_id="user-1", environment_id="env-1", source_kind="a", source_input="b", dataset_ref="c", ) db_session.add(review) db_session.flush() assert review.dataset_id is None assert review.dashboard_id is None assert review.closed_at is None assert review.active_task_id is None def test_foreign_key_violation(self, db_session): """Invalid environment_id FK raises IntegrityError.""" from sqlalchemy.exc import IntegrityError review = DatasetReviewSession( user_id="user-1", environment_id="nonexistent", source_kind="a", source_input="b", dataset_ref="c", ) db_session.add(review) with pytest.raises(IntegrityError): db_session.flush() def test_repr(self, db_session): """Session id string representation is printable.""" review = DatasetReviewSession( user_id="user-1", environment_id="env-1", source_kind="a", source_input="b", dataset_ref="c", ) db_session.add(review) db_session.flush() assert repr(review) is not None assert len(str(review)) > 0 class TestSessionCollaborator: """Verify SessionCollaborator model.""" def test_create_collaborator(self, db_session): """Create collaborator linked to a session.""" review = self._create_session(db_session) collab = SessionCollaborator( session_id=review.session_id, user_id="user-1", role=SessionCollaboratorRole.REVIEWER, ) db_session.add(collab) db_session.flush() assert collab.id is not None assert collab.session_id == review.session_id assert collab.user_id == "user-1" assert collab.role == SessionCollaboratorRole.REVIEWER assert collab.added_at is not None def test_default_role_values(self, db_session): """All collaborator roles are valid.""" review = self._create_session(db_session) for role in SessionCollaboratorRole: collab = SessionCollaborator( session_id=review.session_id, user_id="user-1", role=role, ) db_session.add(collab) db_session.flush() assert db_session.query(SessionCollaborator).count() == len(SessionCollaboratorRole) def test_cascade_delete(self, db_session): """Deleting a session cascades to its collaborators.""" review = self._create_session(db_session) collab = SessionCollaborator( session_id=review.session_id, user_id="user-1", role=SessionCollaboratorRole.VIEWER, ) db_session.add(collab) db_session.flush() db_session.delete(review) db_session.flush() assert db_session.query(SessionCollaborator).count() == 0 def test_relationship_navigation(self, db_session): """Navigate session -> collaborators and collaborator -> session.""" review = self._create_session(db_session) collab = SessionCollaborator( session_id=review.session_id, user_id="user-1", role=SessionCollaboratorRole.APPROVER, ) db_session.add(collab) db_session.flush() assert len(review.collaborators) == 1 assert review.collaborators[0].role == SessionCollaboratorRole.APPROVER assert collab.session is review assert collab.session.session_id == review.session_id def _create_session(self, db_session) -> DatasetReviewSession: review = DatasetReviewSession( user_id="user-1", environment_id="env-1", source_kind="a", source_input="b", dataset_ref="c", ) db_session.add(review) db_session.flush() return review # #endregion Test.DatasetReviewSessionModels