core/tests/components/harmony/conftest.py

192 lines
5.6 KiB
Python

"""Fixtures for harmony tests."""
from collections.abc import Generator
from unittest.mock import AsyncMock, MagicMock, PropertyMock, patch
from aioharmony.const import ClientCallbackType
import pytest
from homeassistant.components.harmony.const import ACTIVITY_POWER_OFF, DOMAIN
from homeassistant.const import CONF_HOST, CONF_NAME
from .const import (
HUB_NAME,
NILE_TV_ACTIVITY_ID,
PLAY_MUSIC_ACTIVITY_ID,
WATCH_TV_ACTIVITY_ID,
)
from tests.common import MockConfigEntry
ACTIVITIES_TO_IDS = {
ACTIVITY_POWER_OFF: -1,
"Watch TV": WATCH_TV_ACTIVITY_ID,
"Play Music": PLAY_MUSIC_ACTIVITY_ID,
"Nile-TV": NILE_TV_ACTIVITY_ID,
}
IDS_TO_ACTIVITIES = {
-1: ACTIVITY_POWER_OFF,
WATCH_TV_ACTIVITY_ID: "Watch TV",
PLAY_MUSIC_ACTIVITY_ID: "Play Music",
NILE_TV_ACTIVITY_ID: "Nile-TV",
}
TV_DEVICE_ID = 1234
TV_DEVICE_NAME = "My TV"
DEVICES_TO_IDS = {
TV_DEVICE_NAME: TV_DEVICE_ID,
}
IDS_TO_DEVICES = {
TV_DEVICE_ID: TV_DEVICE_NAME,
}
class FakeHarmonyClient:
"""FakeHarmonyClient to mock away network calls."""
_callbacks: ClientCallbackType
def __init__(self) -> None:
"""Initialize FakeHarmonyClient class to capture callbacks."""
self._activity_name = "Watch TV"
self.close = AsyncMock()
self.send_commands = AsyncMock()
self.change_channel = AsyncMock()
self.sync = AsyncMock()
self.fw_version = "123.456"
async def connect(self):
"""Connect and call the appropriate callbacks."""
self._callbacks.connect(None)
return AsyncMock(return_value=(True))
def get_activity_name(self, activity_id):
"""Return the activity name with the given activity_id."""
return IDS_TO_ACTIVITIES.get(activity_id)
def get_activity_id(self, activity_name):
"""Return the mapping of an activity name to the internal id."""
return ACTIVITIES_TO_IDS.get(activity_name)
def get_device_name(self, device_id):
"""Return the device name with the given device_id."""
return IDS_TO_DEVICES.get(device_id)
def get_device_id(self, device_name):
"""Return the device id with the given device_name."""
return DEVICES_TO_IDS.get(device_name)
async def start_activity(self, activity_id):
"""Update the current activity and call the appropriate callbacks."""
self._activity_name = IDS_TO_ACTIVITIES.get(int(activity_id))
activity_tuple = (activity_id, self._activity_name)
self._callbacks.new_activity_starting(activity_tuple)
self._callbacks.new_activity(activity_tuple)
return AsyncMock(return_value=(True, "unused message"))
async def power_off(self):
"""Power off all activities."""
await self.start_activity(-1)
@property
def current_activity(self):
"""Return the current activity tuple."""
return (
self.get_activity_id(self._activity_name),
self._activity_name,
)
@property
def config(self):
"""Return the config object."""
return self.hub_config.config
@property
def json_config(self):
"""Return the json config as a dict."""
return {}
@property
def hub_config(self):
"""Return the client_config type."""
config = MagicMock()
type(config).activities = PropertyMock(
return_value=[
{"name": "Watch TV", "id": WATCH_TV_ACTIVITY_ID},
{"name": "Play Music", "id": PLAY_MUSIC_ACTIVITY_ID},
{"name": "Nile-TV", "id": NILE_TV_ACTIVITY_ID},
]
)
type(config).devices = PropertyMock(
return_value=[{"name": TV_DEVICE_NAME, "id": TV_DEVICE_ID}]
)
type(config).info = PropertyMock(return_value={})
type(config).hub_state = PropertyMock(return_value={})
type(config).config = PropertyMock(
return_value={
"activity": [
{"id": 10000, "label": None},
{"id": -1, "label": "PowerOff"},
{"id": WATCH_TV_ACTIVITY_ID, "label": "Watch TV"},
{"id": PLAY_MUSIC_ACTIVITY_ID, "label": "Play Music"},
{"id": NILE_TV_ACTIVITY_ID, "label": "Nile-TV"},
]
}
)
return config
def mock_reconnection(self):
"""Simulate reconnection to the hub."""
self._callbacks.connect(None)
def mock_disconnection(self):
"""Simulate disconnection to the hub."""
self._callbacks.disconnect(None)
@pytest.fixture
def harmony_client() -> FakeHarmonyClient:
"""Create the FakeHarmonyClient instance."""
return FakeHarmonyClient()
@pytest.fixture
def mock_hc(harmony_client: FakeHarmonyClient) -> Generator[None]:
"""Patch the real HarmonyClient with initialization side effect."""
def _on_create_instance(
ip_address: str, callbacks: ClientCallbackType
) -> FakeHarmonyClient:
"""Set client callbacks on instance creation."""
harmony_client._callbacks = callbacks
return harmony_client
with patch(
"homeassistant.components.harmony.data.HarmonyClient",
side_effect=_on_create_instance,
):
yield
@pytest.fixture
def mock_write_config():
"""Patches write_config_file to remove side effects."""
with patch(
"homeassistant.components.harmony.remote.HarmonyRemote.write_config_file",
) as mock:
yield mock
@pytest.fixture
def mock_config_entry() -> MockConfigEntry:
"""Return mock config entry."""
return MockConfigEntry(
domain=DOMAIN,
unique_id="123",
data={CONF_HOST: "192.0.2.0", CONF_NAME: HUB_NAME},
)