"""Fixtures fuer die Tests, die gegen eine Home-Assistant-Instanz laufen.""" from __future__ import annotations from collections.abc import Generator from copy import deepcopy from pathlib import Path from typing import Any from unittest.mock import AsyncMock, MagicMock, patch from homeassistant.const import CONF_HOST, CONF_TOKEN from homeassistant.core import HomeAssistant import pytest from pytest_homeassistant_custom_component.common import MockConfigEntry from custom_components.ninstrip.api import NinstripClient from custom_components.ninstrip.const import DOMAIN from tests_unit.samples import ( HOST_K1Y, INFO_K1Y, MAC_K1Y, PRESETS_K1Y, SETTINGS_COMPILED, STATE_K1Y, TOKEN, ) CLIENT_PATCH_TARGETS = [ "custom_components.ninstrip.NinstripClient", "custom_components.ninstrip.config_flow.NinstripClient", ] @pytest.fixture(autouse=True) def auto_enable_custom_integrations(enable_custom_integrations: None) -> Generator[None]: """custom_components/ in jedem Home-Assistant-Test laden.""" yield @pytest.fixture def strip_state() -> dict[str, Any]: return deepcopy(STATE_K1Y) @pytest.fixture def strip_info() -> dict[str, Any]: return deepcopy(INFO_K1Y) @pytest.fixture def strip_settings() -> dict[str, Any]: return deepcopy(SETTINGS_COMPILED) @pytest.fixture def strip_presets() -> dict[str, Any]: return deepcopy(PRESETS_K1Y) @pytest.fixture def mock_client( strip_state: dict[str, Any], strip_info: dict[str, Any], strip_settings: dict[str, Any], strip_presets: dict[str, Any], ) -> Generator[MagicMock]: """Ein Geraet, dessen Antworten den veraenderbaren strip_*-Fixtures folgen.""" client = MagicMock(spec=NinstripClient) client.host = HOST_K1Y client.get_state = AsyncMock(side_effect=lambda: deepcopy(strip_state)) client.get_info = AsyncMock(side_effect=lambda: deepcopy(strip_info)) client.get_settings = AsyncMock(side_effect=lambda: deepcopy(strip_settings)) client.get_presets = AsyncMock(side_effect=lambda: deepcopy(strip_presets)) async def set_state(**fields: Any) -> dict[str, Any]: strip_state.update(fields) return deepcopy(strip_state) client.set_state = AsyncMock(side_effect=set_state) async def set_sacn(**fields: Any) -> None: # Wie das Geraet: es merkt sich, was es annimmt, und der Aufrufer # liest den Block danach zurueck. strip_settings.setdefault("sacn", {}).update(fields) client.set_sacn = AsyncMock(side_effect=set_sacn) client.apply_preset = AsyncMock(return_value=None) client.save_preset = AsyncMock(return_value=None) client.reboot = AsyncMock(return_value=None) client.fw_update = AsyncMock(return_value=None) patches = [patch(target, return_value=client) for target in CLIENT_PATCH_TARGETS] for p in patches: p.start() yield client for p in patches: p.stop() @pytest.fixture def mock_config_entry() -> MockConfigEntry: return MockConfigEntry( domain=DOMAIN, title="ninstrip ad4c", unique_id=MAC_K1Y, data={CONF_HOST: HOST_K1Y, CONF_TOKEN: TOKEN}, ) @pytest.fixture async def init_integration( hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_client: MagicMock ) -> MockConfigEntry: mock_config_entry.add_to_hass(hass) assert await hass.config_entries.async_setup(mock_config_entry.entry_id) await hass.async_block_till_done() return mock_config_entry @pytest.fixture def mock_setup_entry() -> Generator[AsyncMock]: """Tests des Einrichtungsablaufs duerfen den Eintrag nicht wirklich aufsetzen.""" with patch("custom_components.ninstrip.async_setup_entry", return_value=True) as mock: yield mock @pytest.fixture(autouse=True) def firmware_dir(tmp_path: Path) -> Generator[Path]: """Jeder Test bekommt seinen eigenen, anfangs leeren Firmware-Ordner.""" verzeichnis = tmp_path / "ninstrip_firmware" with patch("custom_components.ninstrip.shared.firmware_directory", return_value=verzeichnis): yield verzeichnis