02cd9d519c
Lint & Test / test (push) Successful in 1m56s
- Rename Python package: wled_controller -> ledgrab - Rename env var prefix: WLED_ -> LEDGRAB_ (with auto-migration for old vars) - Rename localStorage key: wled_api_key -> ledgrab_api_key (with migration) - Rename HA integration domain: wled_screen_controller -> ledgrab - Update all imports, build scripts, Docker, installer, config, docs - Remove HA integration (moved to ledgrab-haos-integration repo) - Remove hacs.json (belongs in HA repo now) - Add startup warning for users with old WLED_ env vars - All tests pass (715/715), ruff clean, tsc clean, frontend builds
136 lines
4.3 KiB
Python
136 lines
4.3 KiB
Python
"""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() == {}
|