# #region Test.SupersetClientRegistry [C:3] [TYPE Module] [SEMANTICS test,registry,superset,client,async] # @BRIEF Tests for core/utils/client_registry.py — get_client, get_superset_client, get_semaphore, get_auth_lock, shutdown. # @RELATION BINDS_TO -> [SupersetClientRegistryModule] from pathlib import Path import sys sys.path.insert(0, str(Path(__file__).parent.parent / "src")) from unittest.mock import AsyncMock, MagicMock, patch import asyncio import pytest class TestBuildEnvId: """_build_env_id — stable identifier from env config.""" def test_env_with_id(self): from src.core.utils.client_registry import _build_env_id env = MagicMock() env.id = "env-1" env.base_url = "http://superset:8088" result = _build_env_id(env) assert "env-1" in result assert "superset" in result def test_env_without_id_uses_object_id(self): from src.core.utils.client_registry import _build_env_id env = {"base_url": "http://x.com", "username": "admin"} result = _build_env_id(env) assert "x.com" in result assert "admin" in result def test_dict_env_fallback(self): from src.core.utils.client_registry import _build_env_id env = {"base_url": "http://test:8080", "username": "user"} result = _build_env_id(env) assert result @pytest.mark.asyncio class TestGetClient: """get_client — create or return cached client.""" async def test_creates_new_client_from_model(self): from src.core.utils.client_registry import get_client, shutdown env = MagicMock() env.id = "env-1" env.url = "http://superset:8088" env.username = "admin" env.password = "pass" env.verify_ssl = False env.timeout = 30 with patch("src.core.utils.client_registry.AsyncAPIClient") as mock_client_cls: mock_client = AsyncMock() mock_client_cls.return_value = mock_client client = await get_client(env) assert client is mock_client mock_client_cls.assert_called_once() await shutdown() async def test_returns_cached_client(self): from src.core.utils.client_registry import get_client, shutdown, _registry env = MagicMock() env.id = "env-1" env.url = "http://superset:8088" env.username = "admin" env.password = "pass" env.verify_ssl = False env.timeout = 30 with patch("src.core.utils.client_registry.AsyncAPIClient") as mock_client_cls: mock_client = AsyncMock() mock_client_cls.return_value = mock_client client1 = await get_client(env) client2 = await get_client(env) assert client1 is client2 assert mock_client_cls.call_count == 1 await shutdown() async def test_dict_env(self): from src.core.utils.client_registry import get_client, shutdown env = {"base_url": "http://superset:8088", "username": "admin", "password": "pass"} with patch("src.core.utils.client_registry.AsyncAPIClient") as mock_client_cls: mock_client = AsyncMock() mock_client_cls.return_value = mock_client client = await get_client(env) assert client is mock_client await shutdown() async def test_unknown_env_type(self): from src.core.utils.client_registry import get_client, shutdown env = 42 # not a model or dict with patch("src.core.utils.client_registry.AsyncAPIClient") as mock_client_cls: mock_client = AsyncMock() mock_client_cls.return_value = mock_client client = await get_client(env) assert client is mock_client await shutdown() @pytest.mark.asyncio class TestGetSupersetClient: """get_superset_client — wraps AsyncAPIClient in SupersetClient.""" async def test_returns_superset_client(self): from src.core.utils.client_registry import get_superset_client, shutdown env = MagicMock() env.id = "env-1" env.url = "http://superset:8088" env.username = "admin" env.password = "pass" env.verify_ssl = False env.timeout = 30 mock_shared = AsyncMock() with ( patch("src.core.utils.client_registry.get_client", return_value=mock_shared), patch("src.core.superset_client.SupersetClient") as mock_sc_cls, ): mock_sc = MagicMock() mock_sc_cls.return_value = mock_sc client = await get_superset_client(env) assert client is mock_sc await shutdown() @pytest.mark.asyncio class TestGetSemaphoreAndLock: """get_semaphore and get_auth_lock — return shared resources.""" async def test_get_semaphore(self): from src.core.utils.client_registry import get_semaphore, get_client, shutdown env = MagicMock() env.id = "env-1" env.url = "http://superset:8088" env.username = "admin" env.password = "pass" env.verify_ssl = False env.timeout = 30 with patch("src.core.utils.client_registry.AsyncAPIClient") as mock_cls: mock_cls.return_value = AsyncMock() await get_client(env) sem = await get_semaphore(env) assert sem is not None await shutdown() async def test_get_auth_lock(self): from src.core.utils.client_registry import get_auth_lock, get_client, shutdown env = MagicMock() env.id = "env-1" env.url = "http://superset:8088" env.username = "admin" env.password = "pass" env.verify_ssl = False env.timeout = 30 with patch("src.core.utils.client_registry.AsyncAPIClient") as mock_cls: mock_cls.return_value = AsyncMock() await get_client(env) lock = await get_auth_lock(env) assert lock is not None await shutdown() async def test_get_semaphore_creates_client_if_missing(self): from src.core.utils.client_registry import get_semaphore, shutdown, _registry env = MagicMock() env.id = "env-1" env.url = "http://superset:8088" env.username = "admin" env.password = "pass" env.verify_ssl = False env.timeout = 30 _registry.clear() with patch("src.core.utils.client_registry.AsyncAPIClient") as mock_cls: mock_cls.return_value = AsyncMock() sem = await get_semaphore(env) assert sem is not None await shutdown() @pytest.mark.asyncio class TestShutdown: """shutdown — close all clients and clear registry.""" async def test_shutdown_closes_clients(self): from src.core.utils.client_registry import get_client, shutdown env = MagicMock() env.id = "env-1" env.url = "http://superset:8088" env.username = "admin" env.password = "pass" env.verify_ssl = False env.timeout = 30 with patch("src.core.utils.client_registry.AsyncAPIClient") as mock_cls: mock_client = AsyncMock() mock_cls.return_value = mock_client await get_client(env) await shutdown() mock_client.aclose.assert_called_once() async def test_shutdown_empty_registry(self): from src.core.utils.client_registry import shutdown, _registry _registry.clear() await shutdown() # should not raise async def test_shutdown_handles_close_error(self): from src.core.utils.client_registry import get_client, shutdown env = MagicMock() env.id = "env-1" env.url = "http://superset:8088" env.username = "admin" env.password = "pass" env.verify_ssl = False env.timeout = 30 with patch("src.core.utils.client_registry.AsyncAPIClient") as mock_cls: mock_client = AsyncMock() mock_client.aclose.side_effect = ConnectionError("Close failed") mock_cls.return_value = mock_client await get_client(env) await shutdown() # should not raise # #endregion Test.SupersetClientRegistry