# #region Test.Assistant.DatasetReviewExtended [C:2] [TYPE Module] [SEMANTICS test,assistant,dataset,review,edge] # @BRIEF Edge-case coverage for _dataset_review.py and _dataset_review_dispatch.py uncovered lines. # @RELATION BINDS_TO -> [AssistantDatasetReview] # @RELATION BINDS_TO -> [AssistantDatasetReviewDispatch] from pathlib import Path import sys sys.path.insert(0, str(Path(__file__).parent.parent / "src")) from datetime import UTC, datetime from unittest.mock import MagicMock, AsyncMock, patch import pytest from fastapi import HTTPException class TestMatchDatasetReviewFieldExtended: """_match_dataset_review_field — field_name and verbose_name matching paths.""" def test_match_by_field_name(self): from src.api.routes.assistant._dataset_review import _match_dataset_review_field ctx = {"semantic_fields": [{"field_id": "fld-1", "field_name": "region", "verbose_name": "Region"}]} result = _match_dataset_review_field(ctx, "update the region field please") assert result is not None assert result["field_name"] == "region" def test_match_by_verbose_name(self): from src.api.routes.assistant._dataset_review import _match_dataset_review_field ctx = {"semantic_fields": [{"field_id": "fld-1", "field_name": "rgn", "verbose_name": "Region Name"}]} result = _match_dataset_review_field(ctx, "change Region Name") assert result is not None assert result["verbose_name"] == "Region Name" def test_match_by_field_id_lowercase_in_message(self): """Match field when field_id appears in message text.""" from src.api.routes.assistant._dataset_review import _match_dataset_review_field ctx = {"semantic_fields": [{"field_id": "FLD-001", "field_name": "sales", "verbose_name": "Sales"}]} # field_id "fld-001" does not appear in message — should try field_name/verbose result = _match_dataset_review_field(ctx, "about sales data") assert result is not None assert result["field_name"] == "sales" class TestPlanDatasetReviewIntentExtended: """_plan_dataset_review_intent — uncovered branches.""" @pytest.fixture def context(self): return { "session_id": "sess-1", "version": 5, "readiness_state": "REVIEW_READY", "recommended_action": "REVIEW_DOCUMENTATION", "mappings": [], "findings": [{"code": "TEST"}], "imported_filters": [{"filter_name": "region"}], "preview": {"preview_status": "missing"}, "semantic_fields": [ { "field_id": "fld-1", "field_name": "region", "verbose_name": "Region", "candidates": [{"candidate_id": "cand-1"}], } ], } def test_set_field_semantics_accept_candidate(self, context): """Accept first candidate via message keywords.""" from src.api.routes.assistant._dataset_review import _plan_dataset_review_intent result = _plan_dataset_review_intent( 'apply field semantics target:field=fld-1 accept candidate', context, ) assert result is not None assert result["operation"] == "dataset_review_set_field_semantics" assert result["entities"]["candidate_id"] == "cand-1" def test_set_field_semantics_with_label(self, context): """Set verbose_name via 'label' keyword (matches regex alternation).""" from src.api.routes.assistant._dataset_review import _plan_dataset_review_intent result = _plan_dataset_review_intent( 'set field semantics target:field=fld-1 label="Country"', context, ) assert result is not None assert result["entities"]["verbose_name"] == "Country" def test_set_field_semantics_with_description(self, context): """Set description via 'desc' keyword.""" from src.api.routes.assistant._dataset_review import _plan_dataset_review_intent result = _plan_dataset_review_intent( 'set field semantics target:field=fld-1 desc="The country field"', context, ) assert result is not None assert result["entities"]["description"] == "The country field" def test_set_field_semantics_no_attributes_returns_none(self, context): """No candidate, verbose_name, description, or display_format returns None.""" from src.api.routes.assistant._dataset_review import _plan_dataset_review_intent result = _plan_dataset_review_intent( 'set field semantics target:field=fld-1', context, ) assert result is None def test_set_field_semantics_with_lock(self, context): """Lock field when message contains lock keywords.""" from src.api.routes.assistant._dataset_review import _plan_dataset_review_intent result = _plan_dataset_review_intent( 'update semantic field target:field=fld-1 lock it desc="Locked"', context, ) assert result is not None assert result["entities"]["lock_field"] is True class TestDispatchDatasetReviewIntentExtended: """_dispatch_dataset_review_intent — uncovered branches.""" @pytest.fixture def user(self): from src.schemas.auth import User return User(id="user-1", username="test", email="test@x.com", is_active=True, auth_source="internal", created_at=datetime.now(UTC), last_login=datetime.now(UTC), roles=[]) @pytest.fixture def config_manager(self): cm = MagicMock() cm.get_environments = MagicMock(return_value=[]) return cm def _make_session_mock(self, **overrides): from src.models.dataset_review import ReadinessState, RecommendedAction, SessionStatus, SessionPhase s = MagicMock() s.session_id = overrides.get("session_id", "sess-1") s.version = overrides.get("version", 5) s.user_id = overrides.get("user_id", "user-1") s.readiness_state = overrides.get("readiness_state", MagicMock(value=ReadinessState.MAPPING_REVIEW_NEEDED.value)) s.recommended_action = overrides.get("recommended_action", MagicMock(value=RecommendedAction.REVIEW_DOCUMENTATION.value)) s.execution_mappings = overrides.get("execution_mappings", []) s.semantic_fields = overrides.get("semantic_fields", []) s.last_activity_at = None return s def _make_mapping_mock(self, **overrides): from src.models.dataset_review import ApprovalState m = MagicMock() m.mapping_id = overrides.get("mapping_id", "m-1") m.approval_state = overrides.get("approval_state", ApprovalState.PENDING) m.requires_explicit_approval = overrides.get("requires_explicit_approval", True) return m def _make_field_mock(self, **overrides): f = MagicMock() f.field_id = overrides.get("field_id", "fld-1") f.field_name = overrides.get("field_name", "region") return f def test_approve_mappings_updates_readiness_state(self, user, config_manager): """When MAPPING_REVIEW_NEEDED, recommended_action changes to GENERATE_SQL_PREVIEW.""" from src.api.routes.assistant._dataset_review_dispatch import _dispatch_dataset_review_intent from src.models.dataset_review import ApprovalState mapping = self._make_mapping_mock(mapping_id="m-1", approval_state=ApprovalState.PENDING, requires_explicit_approval=True) session = self._make_session_mock(execution_mappings=[mapping], user_id="user-1") intent = { "operation": "dataset_review_approve_mappings", "entities": { "dataset_review_session_id": "sess-1", "session_version": 5, "mapping_ids": ["m-1"], }, } db = MagicMock() with patch("src.api.routes.assistant._dataset_review_dispatch.DatasetReviewSessionRepository") as mock_repo_cls: mock_repo = MagicMock() mock_repo_cls.return_value = mock_repo mock_repo.load_session_detail.return_value = session mock_repo.require_session_version.return_value = None mock_repo.bump_session_version.return_value = None mock_repo.db = MagicMock() mock_repo.event_logger = MagicMock() text, task_id, actions = ( __import__("asyncio").run(_dispatch_dataset_review_intent(intent, user, config_manager, db)) ) assert "Approved" in text def test_set_field_semantics_value_error(self, user, config_manager): """ValueError from _update_semantic_field_state becomes 400.""" from src.api.routes.assistant._dataset_review_dispatch import _dispatch_dataset_review_intent field = self._make_field_mock() session = self._make_session_mock(semantic_fields=[field], user_id="user-1") intent = { "operation": "dataset_review_set_field_semantics", "entities": { "dataset_review_session_id": "sess-1", "session_version": 5, "field_id": "fld-1", "lock_field": True, }, } db = MagicMock() with patch("src.api.routes.assistant._dataset_review_dispatch.DatasetReviewSessionRepository") as mock_repo_cls: mock_repo = MagicMock() mock_repo_cls.return_value = mock_repo mock_repo.load_session_detail.return_value = session mock_repo.require_session_version.return_value = None with patch("src.api.routes.assistant._dataset_review_dispatch._update_semantic_field_state", side_effect=ValueError("Invalid field value")): with pytest.raises(HTTPException) as exc: __import__("asyncio").run( _dispatch_dataset_review_intent(intent, user, config_manager, db) ) assert exc.value.status_code == 400 assert "Invalid" in str(exc.value.detail) def test_set_field_semantics_field_not_found(self, user, config_manager): """Field not found in session raises 404.""" from src.api.routes.assistant._dataset_review_dispatch import _dispatch_dataset_review_intent session = self._make_session_mock(semantic_fields=[], user_id="user-1") intent = { "operation": "dataset_review_set_field_semantics", "entities": { "dataset_review_session_id": "sess-1", "session_version": 5, "field_id": "nonexistent", }, } db = MagicMock() with patch("src.api.routes.assistant._dataset_review_dispatch.DatasetReviewSessionRepository") as mock_repo_cls: mock_repo = MagicMock() mock_repo_cls.return_value = mock_repo mock_repo.load_session_detail.return_value = session mock_repo.require_session_version.return_value = None with pytest.raises(HTTPException) as exc: __import__("asyncio").run( _dispatch_dataset_review_intent(intent, user, config_manager, db) ) assert exc.value.status_code == 404 # #endregion Test.Assistant.DatasetReviewExtended