Files
ss-tools/backend/tests/scripts/test_test_dataset_dashboard_relations.py
root 632b730fff chore: migrate GRACE-Poly anchors to hierarchical dotted naming
Systematic rename of all semantic anchors (#region, [DEF], @RELATION)
across 1400+ files — backend Python, frontend Svelte/TS, specs, docs:
- Flat anchors become Namespace.Module.Entity
- @RELATION references updated to match new anchor paths
- Zero business logic changes
2026-07-22 11:48:15 +03:00

191 lines
8.1 KiB
Python

# #region Test.TestDatasetDashboardRelations.TestTestDatasetDashboardRelations [C:2] [TYPE Module] [SEMANTICS test,dataset,dashboard,superset]
# @BRIEF Tests for test_dataset_dashboard_relations script (mocked Superset API, no real connection).
# @RELATION BINDS_TO -> [Test.DatasetDashboardRelations.TestDatasetDashboardRelationsScript]
# @TEST_EDGE: script_has_if_name_guard -> Module executes only under __main__
# @TEST_EDGE: test_function_calls_client -> Verifies client authentication and API calls
# @TEST_EDGE: dashboard_response_parsing -> Handles slices in dashboard
# @TEST_EDGE: dataset_response_parsing -> Handles dataset structure
# @TEST_EDGE: related_objects_dashboards -> Parses dashboards from related_objects
# @TEST_EDGE: related_objects_wrapped_result -> Handles result wrapper
# @TEST_EDGE: no_slices_in_dashboard -> Warns when slices missing
# @TEST_EDGE: related_objects_exception -> Logs error without crashing
import sys
from pathlib import Path
from unittest.mock import MagicMock, patch, call
import json
import pytest
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))
class TestTestDatasetDashboardRelations:
"""Tests for test_dataset_dashboard_relations module."""
def test_module_has_if_name_guard(self):
"""Structural: module has __main__ guard."""
src_path = Path(__file__).parent.parent.parent / "src" / "scripts" / "test_dataset_dashboard_relations.py"
source = src_path.read_text(encoding="utf-8")
# Check that `if __name__ == "__main__":` or equivalent guard exists
assert 'if __name__ == "__main__":' in source, "Module must have if __name__ guard"
@patch("src.scripts.test_dataset_dashboard_relations.ConfigManager")
@patch("src.scripts.test_dataset_dashboard_relations.SupersetClient")
def test_test_function_calls_client_authenticate(
self, MockSupersetClient, MockConfigManager
):
"""Happy: test_dashboard_dataset_relations authenticates and fetches dashboard/dataset."""
from src.scripts.test_dataset_dashboard_relations import test_dashboard_dataset_relations
# Mock environments
env_mock = MagicMock()
env_mock.name = "test-env"
env_mock.url = "http://superset.test"
MockConfigManager.return_value.get_environments.return_value = [env_mock]
# Mock client
mock_client = MagicMock()
# Dashboard response with slices
mock_client.network.request.side_effect = [
# First call: GET /dashboard/13
{
"id": 13,
"dashboard_title": "Test Dashboard",
"published": True,
"slices": [
{"slice_id": 1, "slice_name": "Chart 1", "datasource_id": 26, "datasource_type": "table"}
],
"position_json": '{"DASHBOARD_VERSION_KEY": "v2"}',
},
# Second call: GET /dataset/26/related_objects
{
"dashboards": [
{"id": 13, "dashboard_title": "Test Dashboard"},
{"id": 14, "dashboard_title": "Another Dashboard"},
]
},
]
# get_dataset response
mock_client.get_dataset.return_value = {
"id": 26,
"table_name": "test_table",
"schema": "public",
"database": {"database_name": "test_db"},
}
MockSupersetClient.return_value = mock_client
# Patch sys.stdout to suppress prints
with patch("sys.stdout"):
test_dashboard_dataset_relations()
mock_client.authenticate.assert_called_once()
# Check that dashboard and dataset were fetched
assert mock_client.network.request.call_count >= 2
@patch("src.scripts.test_dataset_dashboard_relations.ConfigManager")
@patch("src.scripts.test_dataset_dashboard_relations.SupersetClient")
def test_no_slices_in_dashboard_warns(
self, MockSupersetClient, MockConfigManager
):
"""Edge: dashboard without slices field logs warning."""
from src.scripts.test_dataset_dashboard_relations import test_dashboard_dataset_relations
env_mock = MagicMock()
env_mock.name = "test-env"
env_mock.url = "http://superset.test"
MockConfigManager.return_value.get_environments.return_value = [env_mock]
mock_client = MagicMock()
mock_client.network.request.side_effect = [
# Dashboard without slices key
{
"id": 13,
"dashboard_title": "No Slices Dashboard",
"published": True,
},
# related_objects
{"dashboards": []},
]
mock_client.get_dataset.return_value = {
"id": 26,
"table_name": "test_table",
}
MockSupersetClient.return_value = mock_client
with patch("sys.stdout"):
test_dashboard_dataset_relations()
# Should not crash — just warns about missing slices
mock_client.authenticate.assert_called_once()
@patch("src.scripts.test_dataset_dashboard_relations.ConfigManager")
@patch("src.scripts.test_dataset_dashboard_relations.SupersetClient")
def test_related_objects_wrapped_in_result(
self, MockSupersetClient, MockConfigManager
):
"""Edge: related_objects response wrapped in 'result' key."""
from src.scripts.test_dataset_dashboard_relations import test_dashboard_dataset_relations
env_mock = MagicMock()
env_mock.name = "test-env"
MockConfigManager.return_value.get_environments.return_value = [env_mock]
mock_client = MagicMock()
mock_client.network.request.side_effect = [
{"id": 13, "dashboard_title": "Test", "slices": []},
{"result": {"dashboards": [{"id": 13, "dashboard_title": "Wrapped"}]}},
]
mock_client.get_dataset.return_value = {"id": 26, "table_name": "t"}
MockSupersetClient.return_value = mock_client
with patch("sys.stdout"):
test_dashboard_dataset_relations()
mock_client.authenticate.assert_called_once()
@patch("src.scripts.test_dataset_dashboard_relations.ConfigManager")
@patch("src.scripts.test_dataset_dashboard_relations.SupersetClient")
def test_related_objects_exception_handled(
self, MockSupersetClient, MockConfigManager
):
"""Edge: exception in related_objects fetch is caught, not propagated."""
from src.scripts.test_dataset_dashboard_relations import test_dashboard_dataset_relations
env_mock = MagicMock()
env_mock.name = "test-env"
MockConfigManager.return_value.get_environments.return_value = [env_mock]
mock_client = MagicMock()
def request_side_effect(method=None, endpoint=None, **kwargs):
if "related_objects" in (endpoint or ""):
raise RuntimeError("API unavailable")
return {"id": 13, "dashboard_title": "Test", "slices": []}
mock_client.network.request.side_effect = request_side_effect
mock_client.get_dataset.return_value = {"id": 26, "table_name": "t"}
MockSupersetClient.return_value = mock_client
with patch("sys.stdout"):
# Should not raise — exception is caught and logged
test_dashboard_dataset_relations()
mock_client.authenticate.assert_called_once()
@patch("src.scripts.test_dataset_dashboard_relations.ConfigManager")
@patch("src.scripts.test_dataset_dashboard_relations.SupersetClient")
def test_no_environments_logs_error(
self, MockSupersetClient, MockConfigManager
):
"""Edge: no configured environments logs error and returns."""
from src.scripts.test_dataset_dashboard_relations import test_dashboard_dataset_relations
MockConfigManager.return_value.get_environments.return_value = []
with patch("sys.stdout"):
test_dashboard_dataset_relations()
# Should not crash, but authenticate should NOT be called
MockSupersetClient.return_value.authenticate.assert_not_called()
# #endregion Test.TestDatasetDashboardRelations.TestTestDatasetDashboardRelations