# [DEF:backend.src.api.routes.__tests__.test_datasets:Module] # @TIER: STANDARD # @PURPOSE: Unit tests for Datasets API endpoints # @LAYER: API # @RELATION: TESTS -> backend.src.api.routes.datasets import pytest from unittest.mock import MagicMock, patch, AsyncMock from fastapi.testclient import TestClient from src.app import app from src.api.routes.datasets import DatasetsResponse, DatasetDetailResponse client = TestClient(app) # [DEF:test_get_datasets_success:Function] # @TEST: GET /api/datasets returns 200 and valid schema # @PRE: env_id exists # @POST: Response matches DatasetsResponse schema def test_get_datasets_success(): with patch("src.api.routes.datasets.get_config_manager") as mock_config, \ patch("src.api.routes.datasets.get_resource_service") as mock_service, \ patch("src.api.routes.datasets.has_permission") as mock_perm: # Mock environment mock_env = MagicMock() mock_env.id = "prod" mock_config.return_value.get_environments.return_value = [mock_env] # Mock resource service response mock_service.return_value.get_datasets_with_status.return_value = AsyncMock()( return_value=[ { "id": 1, "table_name": "sales_data", "schema": "public", "database": "sales_db", "mapped_fields": {"total": 10, "mapped": 5}, "last_task": {"task_id": "task-1", "status": "SUCCESS"} } ] ) # Mock permission mock_perm.return_value = lambda: True response = client.get("/api/datasets?env_id=prod") assert response.status_code == 200 data = response.json() assert "datasets" in data assert len(data["datasets"]) >= 0 # Validate against Pydantic model DatasetsResponse(**data) # [/DEF:test_get_datasets_success:Function] # [DEF:test_get_datasets_env_not_found:Function] # @TEST: GET /api/datasets returns 404 if env_id missing # @PRE: env_id does not exist # @POST: Returns 404 error def test_get_datasets_env_not_found(): with patch("src.api.routes.datasets.get_config_manager") as mock_config, \ patch("src.api.routes.datasets.has_permission") as mock_perm: mock_config.return_value.get_environments.return_value = [] mock_perm.return_value = lambda: True response = client.get("/api/datasets?env_id=nonexistent") assert response.status_code == 404 assert "Environment not found" in response.json()["detail"] # [/DEF:test_get_datasets_env_not_found:Function] # [DEF:test_get_datasets_invalid_pagination:Function] # @TEST: GET /api/datasets returns 400 for invalid page/page_size # @PRE: page < 1 or page_size > 100 # @POST: Returns 400 error def test_get_datasets_invalid_pagination(): with patch("src.api.routes.datasets.get_config_manager") as mock_config, \ patch("src.api.routes.datasets.has_permission") as mock_perm: mock_env = MagicMock() mock_env.id = "prod" mock_config.return_value.get_environments.return_value = [mock_env] mock_perm.return_value = lambda: True # Invalid page response = client.get("/api/datasets?env_id=prod&page=0") assert response.status_code == 400 assert "Page must be >= 1" in response.json()["detail"] # Invalid page_size response = client.get("/api/datasets?env_id=prod&page_size=0") assert response.status_code == 400 assert "Page size must be between 1 and 100" in response.json()["detail"] # [/DEF:test_get_datasets_invalid_pagination:Function] # [DEF:test_map_columns_success:Function] # @TEST: POST /api/datasets/map-columns creates mapping task # @PRE: Valid env_id, dataset_ids, source_type # @POST: Returns task_id def test_map_columns_success(): with patch("src.api.routes.datasets.get_config_manager") as mock_config, \ patch("src.api.routes.datasets.get_task_manager") as mock_task_mgr, \ patch("src.api.routes.datasets.has_permission") as mock_perm: # Mock environment mock_env = MagicMock() mock_env.id = "prod" mock_config.return_value.get_environments.return_value = [mock_env] # Mock task manager mock_task = MagicMock() mock_task.id = "task-123" mock_task_mgr.return_value.create_task = AsyncMock(return_value=mock_task) # Mock permission mock_perm.return_value = lambda: True response = client.post( "/api/datasets/map-columns", json={ "env_id": "prod", "dataset_ids": [1, 2, 3], "source_type": "postgresql" } ) assert response.status_code == 200 data = response.json() assert "task_id" in data # [/DEF:test_map_columns_success:Function] # [DEF:test_map_columns_invalid_source_type:Function] # @TEST: POST /api/datasets/map-columns returns 400 for invalid source_type # @PRE: source_type is not 'postgresql' or 'xlsx' # @POST: Returns 400 error def test_map_columns_invalid_source_type(): with patch("src.api.routes.datasets.has_permission") as mock_perm: mock_perm.return_value = lambda: True response = client.post( "/api/datasets/map-columns", json={ "env_id": "prod", "dataset_ids": [1], "source_type": "invalid" } ) assert response.status_code == 400 assert "Source type must be 'postgresql' or 'xlsx'" in response.json()["detail"] # [/DEF:test_map_columns_invalid_source_type:Function] # [DEF:test_generate_docs_success:Function] # @TEST: POST /api/datasets/generate-docs creates doc generation task # @PRE: Valid env_id, dataset_ids, llm_provider # @POST: Returns task_id def test_generate_docs_success(): with patch("src.api.routes.datasets.get_config_manager") as mock_config, \ patch("src.api.routes.datasets.get_task_manager") as mock_task_mgr, \ patch("src.api.routes.datasets.has_permission") as mock_perm: # Mock environment mock_env = MagicMock() mock_env.id = "prod" mock_config.return_value.get_environments.return_value = [mock_env] # Mock task manager mock_task = MagicMock() mock_task.id = "task-456" mock_task_mgr.return_value.create_task = AsyncMock(return_value=mock_task) # Mock permission mock_perm.return_value = lambda: True response = client.post( "/api/datasets/generate-docs", json={ "env_id": "prod", "dataset_ids": [1], "llm_provider": "openai" } ) assert response.status_code == 200 data = response.json() assert "task_id" in data # [/DEF:test_generate_docs_success:Function] # [/DEF:backend.src.api.routes.__tests__.test_datasets:Module]