test: massive coverage expansion — 15 new test modules + assistant tool fixes + orthogonal testing
- 10 translate plugin test files (100% coverage on 12 modules) - assistant/handler tools: 85+ tests covering dispatch, registry, resolvers, routes, llm_planner, 13 tool handlers - clean release: artifact_catalog_loader, mappers, approval, publication tests - API routes: translate_helpers, validation_service extensions, datasets to 100% - notifications: providers/service tests - services: profile_preference_service - docs/orthogonal-test-report.md — full speckit.tests audit - Fixes: 3 git_base async mock failures, 4 assistant handler permission-check patches - .gitignore: coverage artifacts
This commit is contained in:
@@ -417,3 +417,626 @@ def test_dataset_item_has_metric_count(mock_deps):
|
||||
for ds in data["datasets"]:
|
||||
assert "metric_count" in ds
|
||||
assert isinstance(ds["metric_count"], int)
|
||||
|
||||
|
||||
# #region test_get_dataset_ids [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify GET /api/datasets/ids returns list of dataset IDs.
|
||||
def test_get_dataset_ids(mock_deps):
|
||||
response = client.get("/api/datasets/ids?env_id=ss-dev")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert "dataset_ids" in data
|
||||
assert isinstance(data["dataset_ids"], list)
|
||||
assert len(data["dataset_ids"]) == 3
|
||||
assert 1 in data["dataset_ids"]
|
||||
|
||||
|
||||
# #region test_get_dataset_ids_search [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify GET /api/datasets/ids with search filter.
|
||||
def test_get_dataset_ids_search(mock_deps):
|
||||
response = client.get("/api/datasets/ids?env_id=ss-dev&search=users")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["dataset_ids"] == [1]
|
||||
|
||||
|
||||
# #region test_get_dataset_ids_env_not_found [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 404 when env not found.
|
||||
def test_get_dataset_ids_env_not_found(mock_deps):
|
||||
response = client.get("/api/datasets/ids?env_id=nonexistent")
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
# #region test_get_dataset_ids_503 [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 503 when Superset fails.
|
||||
def test_get_dataset_ids_503(mock_deps):
|
||||
from src.dependencies import get_resource_service
|
||||
failing = MagicMock()
|
||||
failing.get_datasets_with_status = AsyncMock(
|
||||
side_effect=Exception("Superset unavailable")
|
||||
)
|
||||
app.dependency_overrides[get_resource_service] = lambda: failing
|
||||
try:
|
||||
response = client.get("/api/datasets/ids?env_id=ss-dev")
|
||||
assert response.status_code == 503
|
||||
finally:
|
||||
app.dependency_overrides[get_resource_service] = None
|
||||
|
||||
|
||||
# #region test_get_datasets_invalid_page [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 400 when page < 1.
|
||||
def test_get_datasets_invalid_page(mock_deps):
|
||||
response = client.get("/api/datasets?env_id=ss-dev&page=0")
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
# #region test_get_datasets_invalid_page_size [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 400 when page_size > 100.
|
||||
def test_get_datasets_invalid_page_size(mock_deps):
|
||||
response = client.get("/api/datasets?env_id=ss-dev&page_size=200")
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
# #region test_get_datasets_env_not_found [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 404 when environment not found.
|
||||
def test_get_datasets_env_not_found(mock_deps):
|
||||
response = client.get("/api/datasets?env_id=nonexistent&page=1&page_size=10")
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
# #region test_get_datasets_search_filter [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify search filter narrows results.
|
||||
def test_get_datasets_search_filter(mock_deps):
|
||||
response = client.get("/api/datasets?env_id=ss-dev&search=users&page=1&page_size=10")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["total"] == 1
|
||||
assert data["datasets"][0]["table_name"] == "users"
|
||||
|
||||
|
||||
# #region test_get_datasets_pagination [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify pagination works.
|
||||
def test_get_datasets_pagination(mock_deps):
|
||||
response = client.get("/api/datasets?env_id=ss-dev&page=1&page_size=2")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert len(data["datasets"]) == 2
|
||||
assert data["total_pages"] == 2
|
||||
|
||||
|
||||
# #region test_map_columns [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify POST /api/datasets/map-columns creates mapping task.
|
||||
def test_map_columns(mock_deps):
|
||||
from src.dependencies import get_task_manager
|
||||
task_manager_mock = MagicMock()
|
||||
task_obj = MagicMock()
|
||||
task_obj.id = "mapping-task-1"
|
||||
task_manager_mock.create_task = AsyncMock(return_value=task_obj)
|
||||
|
||||
overrides = {
|
||||
"plugin:mapper": MagicMock(),
|
||||
}
|
||||
|
||||
app.dependency_overrides[get_task_manager] = lambda: task_manager_mock
|
||||
|
||||
from src.dependencies import has_permission
|
||||
app.dependency_overrides[has_permission("plugin:mapper", "EXECUTE")] = lambda: True
|
||||
|
||||
try:
|
||||
response = client.post(
|
||||
"/api/datasets/map-columns",
|
||||
json={
|
||||
"env_id": "ss-dev",
|
||||
"dataset_ids": [1, 2],
|
||||
"source_type": "sqllab",
|
||||
"database_id": 42,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert "task_id" in data
|
||||
assert data["task_id"] == "mapping-task-1"
|
||||
finally:
|
||||
app.dependency_overrides[get_task_manager] = None
|
||||
app.dependency_overrides.pop(has_permission("plugin:mapper", "EXECUTE"), None)
|
||||
|
||||
|
||||
# #region test_map_columns_no_dataset_ids [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 400 when no dataset IDs provided.
|
||||
def test_map_columns_no_dataset_ids(mock_deps):
|
||||
from src.dependencies import has_permission
|
||||
app.dependency_overrides[has_permission("plugin:mapper", "EXECUTE")] = lambda: True
|
||||
|
||||
try:
|
||||
response = client.post(
|
||||
"/api/datasets/map-columns",
|
||||
json={"env_id": "ss-dev", "dataset_ids": [], "source_type": "sqllab"},
|
||||
)
|
||||
assert response.status_code == 400
|
||||
finally:
|
||||
app.dependency_overrides.pop(has_permission("plugin:mapper", "EXECUTE"), None)
|
||||
|
||||
|
||||
# #region test_map_columns_invalid_source_type [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 400 when invalid source type.
|
||||
def test_map_columns_invalid_source_type(mock_deps):
|
||||
from src.dependencies import has_permission
|
||||
app.dependency_overrides[has_permission("plugin:mapper", "EXECUTE")] = lambda: True
|
||||
|
||||
try:
|
||||
response = client.post(
|
||||
"/api/datasets/map-columns",
|
||||
json={"env_id": "ss-dev", "dataset_ids": [1], "source_type": "invalid"},
|
||||
)
|
||||
assert response.status_code == 400
|
||||
finally:
|
||||
app.dependency_overrides.pop(has_permission("plugin:mapper", "EXECUTE"), None)
|
||||
|
||||
|
||||
# #region test_map_columns_missing_database_id [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 400 when sqllab source without database_id.
|
||||
def test_map_columns_missing_database_id(mock_deps):
|
||||
from src.dependencies import has_permission
|
||||
app.dependency_overrides[has_permission("plugin:mapper", "EXECUTE")] = lambda: True
|
||||
|
||||
try:
|
||||
response = client.post(
|
||||
"/api/datasets/map-columns",
|
||||
json={"env_id": "ss-dev", "dataset_ids": [1], "source_type": "sqllab"},
|
||||
)
|
||||
assert response.status_code == 400
|
||||
finally:
|
||||
app.dependency_overrides.pop(has_permission("plugin:mapper", "EXECUTE"), None)
|
||||
|
||||
|
||||
# #region test_map_columns_env_not_found [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 404 when environment not found.
|
||||
def test_map_columns_env_not_found(mock_deps):
|
||||
from src.dependencies import has_permission
|
||||
app.dependency_overrides[has_permission("plugin:mapper", "EXECUTE")] = lambda: True
|
||||
|
||||
try:
|
||||
response = client.post(
|
||||
"/api/datasets/map-columns",
|
||||
json={
|
||||
"env_id": "nonexistent",
|
||||
"dataset_ids": [1],
|
||||
"source_type": "sqllab",
|
||||
"database_id": 42,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 404
|
||||
finally:
|
||||
app.dependency_overrides.pop(has_permission("plugin:mapper", "EXECUTE"), None)
|
||||
|
||||
|
||||
# #region test_map_columns_xlsx_source [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify xlsx source type works.
|
||||
def test_map_columns_xlsx_source(mock_deps):
|
||||
from src.dependencies import get_task_manager, has_permission
|
||||
task_manager_mock = MagicMock()
|
||||
task_obj = MagicMock()
|
||||
task_obj.id = "mapping-task-2"
|
||||
task_manager_mock.create_task = AsyncMock(return_value=task_obj)
|
||||
|
||||
app.dependency_overrides[get_task_manager] = lambda: task_manager_mock
|
||||
app.dependency_overrides[has_permission("plugin:mapper", "EXECUTE")] = lambda: True
|
||||
|
||||
try:
|
||||
response = client.post(
|
||||
"/api/datasets/map-columns",
|
||||
json={
|
||||
"env_id": "ss-dev",
|
||||
"dataset_ids": [1],
|
||||
"source_type": "xlsx",
|
||||
"file_data": "/tmp/test.xlsx",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json()["task_id"] == "mapping-task-2"
|
||||
finally:
|
||||
app.dependency_overrides[get_task_manager] = None
|
||||
app.dependency_overrides.pop(has_permission("plugin:mapper", "EXECUTE"), None)
|
||||
|
||||
|
||||
# #region test_map_columns_503 [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 503 when task creation fails.
|
||||
def test_map_columns_503(mock_deps):
|
||||
from src.dependencies import get_task_manager, has_permission
|
||||
task_manager_mock = MagicMock()
|
||||
task_manager_mock.create_task = AsyncMock(side_effect=Exception("Task creation failed"))
|
||||
|
||||
app.dependency_overrides[get_task_manager] = lambda: task_manager_mock
|
||||
app.dependency_overrides[has_permission("plugin:mapper", "EXECUTE")] = lambda: True
|
||||
|
||||
try:
|
||||
response = client.post(
|
||||
"/api/datasets/map-columns",
|
||||
json={
|
||||
"env_id": "ss-dev",
|
||||
"dataset_ids": [1],
|
||||
"source_type": "sqllab",
|
||||
"database_id": 42,
|
||||
},
|
||||
)
|
||||
assert response.status_code == 503
|
||||
finally:
|
||||
app.dependency_overrides[get_task_manager] = None
|
||||
app.dependency_overrides.pop(has_permission("plugin:mapper", "EXECUTE"), None)
|
||||
|
||||
|
||||
# #region test_generate_docs [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify POST /api/datasets/generate-docs creates doc generation task.
|
||||
def test_generate_docs(mock_deps):
|
||||
from src.dependencies import get_task_manager, has_permission
|
||||
task_manager_mock = MagicMock()
|
||||
task_obj = MagicMock()
|
||||
task_obj.id = "doc-task-1"
|
||||
task_manager_mock.create_task = AsyncMock(return_value=task_obj)
|
||||
|
||||
app.dependency_overrides[get_task_manager] = lambda: task_manager_mock
|
||||
app.dependency_overrides[has_permission("plugin:llm_analysis", "EXECUTE")] = lambda: True
|
||||
|
||||
try:
|
||||
response = client.post(
|
||||
"/api/datasets/generate-docs",
|
||||
json={
|
||||
"env_id": "ss-dev",
|
||||
"dataset_ids": [1],
|
||||
"llm_provider": "gpt-4",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["task_id"] == "doc-task-1"
|
||||
finally:
|
||||
app.dependency_overrides[get_task_manager] = None
|
||||
app.dependency_overrides.pop(has_permission("plugin:llm_analysis", "EXECUTE"), None)
|
||||
|
||||
|
||||
# #region test_generate_docs_no_dataset_ids [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 400 when no dataset IDs provided.
|
||||
def test_generate_docs_no_dataset_ids(mock_deps):
|
||||
from src.dependencies import has_permission
|
||||
app.dependency_overrides[has_permission("plugin:llm_analysis", "EXECUTE")] = lambda: True
|
||||
|
||||
try:
|
||||
response = client.post(
|
||||
"/api/datasets/generate-docs",
|
||||
json={"env_id": "ss-dev", "dataset_ids": [], "llm_provider": "gpt-4"},
|
||||
)
|
||||
assert response.status_code == 400
|
||||
finally:
|
||||
app.dependency_overrides.pop(has_permission("plugin:llm_analysis", "EXECUTE"), None)
|
||||
|
||||
|
||||
# #region test_generate_docs_env_not_found [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 404 when environment not found.
|
||||
def test_generate_docs_env_not_found(mock_deps):
|
||||
from src.dependencies import has_permission
|
||||
app.dependency_overrides[has_permission("plugin:llm_analysis", "EXECUTE")] = lambda: True
|
||||
|
||||
try:
|
||||
response = client.post(
|
||||
"/api/datasets/generate-docs",
|
||||
json={"env_id": "nonexistent", "dataset_ids": [1], "llm_provider": "gpt-4"},
|
||||
)
|
||||
assert response.status_code == 404
|
||||
finally:
|
||||
app.dependency_overrides.pop(has_permission("plugin:llm_analysis", "EXECUTE"), None)
|
||||
|
||||
|
||||
# #region test_generate_docs_503 [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 503 when task creation fails.
|
||||
def test_generate_docs_503(mock_deps):
|
||||
from src.dependencies import get_task_manager, has_permission
|
||||
task_manager_mock = MagicMock()
|
||||
task_manager_mock.create_task = AsyncMock(side_effect=Exception("Doc gen failed"))
|
||||
|
||||
app.dependency_overrides[get_task_manager] = lambda: task_manager_mock
|
||||
app.dependency_overrides[has_permission("plugin:llm_analysis", "EXECUTE")] = lambda: True
|
||||
|
||||
try:
|
||||
response = client.post(
|
||||
"/api/datasets/generate-docs",
|
||||
json={"env_id": "ss-dev", "dataset_ids": [1], "llm_provider": "gpt-4"},
|
||||
)
|
||||
assert response.status_code == 503
|
||||
finally:
|
||||
app.dependency_overrides[get_task_manager] = None
|
||||
app.dependency_overrides.pop(has_permission("plugin:llm_analysis", "EXECUTE"), None)
|
||||
|
||||
|
||||
# #region test_update_metric_description_not_found [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 404 when metric not found.
|
||||
def test_update_metric_description_not_found(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
|
||||
mock_client.get_dataset.return_value = {
|
||||
"id": 1,
|
||||
"result": {
|
||||
"id": 1,
|
||||
"columns": [],
|
||||
"metrics": [{"id": 100, "metric_name": "count", "description": ""}],
|
||||
},
|
||||
}
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/metrics/999/description?env_id=ss-dev",
|
||||
json={"description": "test"},
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
# #region test_update_metric_description_validation [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 400 when description exceeds max length for metric.
|
||||
def test_update_metric_description_validation(mock_deps):
|
||||
response = client.put(
|
||||
"/api/datasets/1/metrics/100/description?env_id=ss-dev",
|
||||
json={"description": "x" * 2001},
|
||||
)
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
# #region test_update_metric_description_superset_502_get [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 502 when Superset GET fails for metric.
|
||||
def test_update_metric_description_superset_502_get(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
mock_client.get_dataset.side_effect = Exception("Superset GET failed")
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/metrics/100/description?env_id=ss-dev",
|
||||
json={"description": "new desc"},
|
||||
)
|
||||
assert response.status_code == 502
|
||||
|
||||
|
||||
# #region test_update_metric_description_superset_502_put [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 502 when Superset PUT fails for metric.
|
||||
def test_update_metric_description_superset_502_put(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
mock_client.get_dataset.return_value = {
|
||||
"id": 1,
|
||||
"result": {
|
||||
"id": 1,
|
||||
"columns": [],
|
||||
"metrics": [{"id": 100, "metric_name": "count", "description": ""}],
|
||||
},
|
||||
}
|
||||
mock_client.update_dataset.side_effect = Exception("Superset PUT failed")
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/metrics/100/description?env_id=ss-dev",
|
||||
json={"description": "new desc"},
|
||||
)
|
||||
assert response.status_code == 502
|
||||
|
||||
|
||||
# #region test_update_column_description_env_not_found [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 404 when environment not found in update_column_description.
|
||||
def test_update_column_description_env_not_found(mock_deps):
|
||||
response = client.put(
|
||||
"/api/datasets/1/columns/10/description?env_id=nonexistent",
|
||||
json={"description": "test"},
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
# #region test_update_column_description_get_fails [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 502 when Superset GET fails in update_column_description.
|
||||
def test_update_column_description_get_fails(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
mock_client.get_dataset.side_effect = Exception("Superset GET error")
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/columns/10/description?env_id=ss-dev",
|
||||
json={"description": "new desc"},
|
||||
)
|
||||
assert response.status_code == 502
|
||||
|
||||
|
||||
# #region test_update_column_description_response_without_result_key [C:2] [TYPE Function]
|
||||
# @PURPOSE: Cover line 562: elif branch when response has no "result" key.
|
||||
def test_update_column_description_response_without_result_key(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
# Response has no "result" key
|
||||
mock_client.get_dataset.return_value = {"id": 1, "columns": [{"id": 10, "column_name": "id", "type": "INT", "description": ""}]}
|
||||
mock_client.update_dataset.return_value = {"id": 1}
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/columns/10/description?env_id=ss-dev",
|
||||
json={"description": "test"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
# #region test_update_column_description_dataset_not_found [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 404 when dataset has no id after GET.
|
||||
def test_update_column_description_dataset_not_found(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
mock_client.get_dataset.return_value = {"result": {}}
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/columns/10/description?env_id=ss-dev",
|
||||
json={"description": "test"},
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
# #region test_update_column_description_unexpected_error [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 500 on unexpected error.
|
||||
def test_update_column_description_unexpected_error(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
mock_client.get_dataset.side_effect = RuntimeError("Unexpected runtime error")
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/columns/10/description?env_id=ss-dev",
|
||||
json={"description": "test"},
|
||||
)
|
||||
assert response.status_code == 502 # Caught by the inner try/except for GET
|
||||
|
||||
|
||||
# #region test_update_metric_description_env_not_found [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 404 when env not found for metric update.
|
||||
def test_update_metric_description_env_not_found(mock_deps):
|
||||
response = client.put(
|
||||
"/api/datasets/1/metrics/100/description?env_id=nonexistent",
|
||||
json={"description": "test"},
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
# #region test_update_metric_description_no_result_key [C:2] [TYPE Function]
|
||||
# @PURPOSE: Cover line 650: elif branch when response has no "result" key for metric.
|
||||
def test_update_metric_description_no_result_key(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
mock_client.get_dataset.return_value = {"id": 1, "columns": [], "metrics": [{"id": 100, "metric_name": "count", "description": ""}]}
|
||||
mock_client.update_dataset.return_value = {"id": 1}
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/metrics/100/description?env_id=ss-dev",
|
||||
json={"description": "new desc"},
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
# #region test_update_metric_description_dataset_not_found [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 404 when dataset not found for metric update.
|
||||
def test_update_metric_description_dataset_not_found(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
mock_client.get_dataset.return_value = {"result": {"columns": []}}
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/metrics/100/description?env_id=ss-dev",
|
||||
json={"description": "test"},
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
# #region test_update_metric_description_unexpected_error [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 500 on unexpected error for metric update.
|
||||
def test_update_metric_description_unexpected_error(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
mock_client.get_dataset.side_effect = RuntimeError("Unexpected metric error")
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/metrics/100/description?env_id=ss-dev",
|
||||
json={"description": "test"},
|
||||
)
|
||||
assert response.status_code == 502 # Caught by inner try/except for GET
|
||||
|
||||
|
||||
# #region test_update_column_description_type_error [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 500 on TypeError in update_column_description (covers lines 597-599).
|
||||
def test_update_column_description_type_error(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
# Return non-dict that passes inner try but breaks on .get()
|
||||
mock_client.get_dataset.return_value = "not-a-dict"
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/columns/10/description?env_id=ss-dev",
|
||||
json={"description": "test"},
|
||||
)
|
||||
assert response.status_code == 500
|
||||
|
||||
|
||||
# #region test_update_metric_description_type_error [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 500 on TypeError in update_metric_description (covers lines 684-686).
|
||||
def test_update_metric_description_type_error(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
mock_client.get_dataset.return_value = 42 # non-dict triggers TypeError
|
||||
|
||||
response = client.put(
|
||||
"/api/datasets/1/metrics/100/description?env_id=ss-dev",
|
||||
json={"description": "test"},
|
||||
)
|
||||
assert response.status_code == 500
|
||||
|
||||
|
||||
# #region test_get_dataset_detail_database_object [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify database field normalization when it's a dict.
|
||||
def test_get_dataset_detail_database_object(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
|
||||
mock_client.get_dataset_detail.return_value = {
|
||||
"id": 1,
|
||||
"table_name": "users",
|
||||
"schema": "public",
|
||||
"database": {"database_name": "PostgreSQL", "id": 5},
|
||||
"columns": [],
|
||||
"column_count": 0,
|
||||
"metrics": [],
|
||||
"metric_count": 0,
|
||||
"sql": None,
|
||||
"linked_dashboards": [],
|
||||
"linked_dashboard_count": 0,
|
||||
"is_sqllab_view": False,
|
||||
}
|
||||
|
||||
response = client.get("/api/datasets/1?env_id=ss-dev")
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["database"] == "PostgreSQL"
|
||||
|
||||
|
||||
# #region test_get_dataset_detail_503 [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 503 when Superset fails for dataset detail.
|
||||
def test_get_dataset_detail_503(mock_deps):
|
||||
with patch("src.api.routes.datasets.AsyncSupersetClient") as MockClient:
|
||||
mock_client = AsyncMock()
|
||||
MockClient.return_value = mock_client
|
||||
mock_client.get_dataset_detail.side_effect = Exception("Superset error")
|
||||
|
||||
response = client.get("/api/datasets/1?env_id=ss-dev")
|
||||
assert response.status_code == 503
|
||||
|
||||
|
||||
# #region test_get_dataset_detail_env_not_found [C:2] [TYPE Function]
|
||||
# @PURPOSE: Verify 404 when env not found for dataset detail.
|
||||
def test_get_dataset_detail_env_not_found(mock_deps):
|
||||
response = client.get("/api/datasets/1?env_id=nonexistent")
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
# #region test_strip_html_tags_function [C:2] [TYPE Function]
|
||||
# @PURPOSE: Test _strip_html_tags directly.
|
||||
def test_strip_html_tags_empty():
|
||||
from src.api.routes.datasets import _strip_html_tags
|
||||
assert _strip_html_tags("") == ""
|
||||
|
||||
|
||||
def test_strip_html_tags_plain_text():
|
||||
from src.api.routes.datasets import _strip_html_tags
|
||||
assert _strip_html_tags("plain text") == "plain text"
|
||||
|
||||
|
||||
def test_strip_html_tags_with_html():
|
||||
from src.api.routes.datasets import _strip_html_tags
|
||||
result = _strip_html_tags("<b>bold</b> and <i>italic</i>")
|
||||
assert result == "bold and italic"
|
||||
|
||||
Reference in New Issue
Block a user