"""Tests for AdapterRegistry — register, get, duplicates, clear.""" from typing import Any import pytest from ledgrab.core.game_integration.adapter_registry import AdapterRegistry from ledgrab.core.game_integration.base_adapter import GameAdapter from ledgrab.core.game_integration.events import GameEvent class FakeAdapter(GameAdapter): ADAPTER_TYPE = "fake_game" DISPLAY_NAME = "Fake Game" GAME_NAME = "FakeGame" SUPPORTED_EVENTS = ["health", "kill"] @classmethod def parse_payload( cls, payload: dict[str, Any], adapter_config: dict[str, Any], prev_state: dict[str, Any], ) -> tuple[list[GameEvent], dict[str, Any]]: return [], prev_state @classmethod def validate_auth( cls, headers: dict[str, str], payload: dict[str, Any], adapter_config: dict[str, Any], ) -> bool: return True class AnotherAdapter(GameAdapter): ADAPTER_TYPE = "another_game" DISPLAY_NAME = "Another Game" GAME_NAME = "AnotherGame" SUPPORTED_EVENTS = ["mana"] @classmethod def parse_payload( cls, payload: dict[str, Any], adapter_config: dict[str, Any], prev_state: dict[str, Any], ) -> tuple[list[GameEvent], dict[str, Any]]: return [], prev_state @classmethod def validate_auth( cls, headers: dict[str, str], payload: dict[str, Any], adapter_config: dict[str, Any], ) -> bool: return True @pytest.fixture(autouse=True) def _clean_registry(): """Ensure a clean registry for each test.""" AdapterRegistry.clear_registry() yield AdapterRegistry.clear_registry() class TestRegister: def test_register_and_get(self) -> None: AdapterRegistry.register(FakeAdapter) assert AdapterRegistry.get_adapter("fake_game") is FakeAdapter def test_register_multiple(self) -> None: AdapterRegistry.register(FakeAdapter) AdapterRegistry.register(AnotherAdapter) assert AdapterRegistry.get_adapter("fake_game") is FakeAdapter assert AdapterRegistry.get_adapter("another_game") is AnotherAdapter def test_register_duplicate_overwrites(self) -> None: AdapterRegistry.register(FakeAdapter) # Re-registering the same type should overwrite without error AdapterRegistry.register(FakeAdapter) assert AdapterRegistry.get_adapter("fake_game") is FakeAdapter def test_register_non_subclass_raises(self) -> None: with pytest.raises(ValueError, match="must be a subclass"): AdapterRegistry.register(str) # type: ignore[arg-type] def test_register_base_type_raises(self) -> None: with pytest.raises(ValueError, match="reserved type"): AdapterRegistry.register(GameAdapter) # type: ignore[arg-type] class TestGetAdapter: def test_get_unknown_raises(self) -> None: with pytest.raises(ValueError, match="Unknown adapter type"): AdapterRegistry.get_adapter("nonexistent") def test_get_unknown_shows_available(self) -> None: AdapterRegistry.register(FakeAdapter) with pytest.raises(ValueError, match="fake_game"): AdapterRegistry.get_adapter("nonexistent") class TestGetAll: def test_get_all_returns_copy(self) -> None: AdapterRegistry.register(FakeAdapter) all_adapters = AdapterRegistry.get_all_adapters() assert "fake_game" in all_adapters # Mutating the copy should not affect the registry all_adapters.pop("fake_game") assert AdapterRegistry.get_adapter("fake_game") is FakeAdapter def test_get_available_adapters_metadata(self) -> None: AdapterRegistry.register(FakeAdapter) available = AdapterRegistry.get_available_adapters() assert len(available) == 1 meta = available[0] assert meta["adapter_type"] == "fake_game" assert meta["display_name"] == "Fake Game" assert meta["game_name"] == "FakeGame" assert meta["supported_events"] == ["health", "kill"] class TestClear: def test_clear_removes_all(self) -> None: AdapterRegistry.register(FakeAdapter) AdapterRegistry.register(AnotherAdapter) AdapterRegistry.clear_registry() assert AdapterRegistry.get_all_adapters() == {}