core/tests/components/tradfri/common.py

115 lines
3.6 KiB
Python
Raw Normal View History

"""Common tools used for the Tradfri test suite."""
from copy import deepcopy
from dataclasses import dataclass
from typing import Any
from pytradfri.command import Command
from pytradfri.const import ATTR_ID
from pytradfri.device import Device
from pytradfri.gateway import Gateway
from homeassistant.components import tradfri
from homeassistant.core import HomeAssistant
from . import GATEWAY_ID
from tests.common import MockConfigEntry
@dataclass
class CommandStore:
"""Store commands and command responses for the API."""
sent_commands: list[Command]
mock_responses: dict[str, Any]
def register_device(
self, gateway: Gateway, device_response: dict[str, Any]
) -> None:
"""Register device response."""
get_devices_command = gateway.get_devices()
self.register_response(get_devices_command, [device_response[ATTR_ID]])
get_device_command = gateway.get_device(device_response[ATTR_ID])
self.register_response(get_device_command, device_response)
def register_response(self, command: Command, response: Any) -> None:
"""Register command response."""
self.mock_responses[command.path_str] = response
def process_command(self, command: Command) -> Any | None:
"""Process command."""
response = self.mock_responses.get(command.path_str)
if response is None or command.process_result is None:
return None
return command.process_result(response)
async def trigger_observe_callback(
self,
hass: HomeAssistant,
device: Device,
new_device_state: dict[str, Any] | None = None,
) -> None:
"""Trigger the observe callback."""
observe_command = next(
(
command
for command in self.sent_commands
if command.path == device.path and command.observe
),
None,
)
assert observe_command
device_path = "/".join(str(v) for v in device.path)
device_state = deepcopy(device.raw)
# Create a default observed state based on the sent commands.
for command in self.sent_commands:
if (data := command.data) is None or command.path_str != device_path:
continue
device_state = modify_state(device_state, data)
# Allow the test to override the default observed state.
if new_device_state is not None:
device_state = modify_state(device_state, new_device_state)
observe_command.process_result(device_state)
await hass.async_block_till_done()
async def setup_integration(hass: HomeAssistant) -> MockConfigEntry:
"""Load the Tradfri integration with a mock gateway."""
entry = MockConfigEntry(
domain=tradfri.DOMAIN,
data={
"host": "mock-host",
"identity": "mock-identity",
"key": "mock-key",
"gateway_id": GATEWAY_ID,
},
)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
Implement coordinator class for Tradfri integration (#64166) * Initial commit coordinator * More coordinator implementation * More coordinator implementation * Allow integration reload * Move API calls to try/catch block * Move back fixture * Remove coordinator test file * Ensure unchanged file * Ensure unchanged conftest.py file * Remove coordinator key check * Apply suggestions from code review Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Import RequestError * Move async_setup_platforms to end of setup_entry * Remove centralised handling of device data and device controllers * Remove platform_type argument * Remove exception * Remove the correct exception * Refactor coordinator error handling * Apply suggestions from code review Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Remove platform type from base class * Remove timeout context manager * Refactor exception callback * Simplify starting device observation * Update test * Move observe start into update method * Remove await self.coordinator.async_request_refresh() * Refactor cover.py * Uncomment const.py * Add back extra_state_attributes * Update homeassistant/components/tradfri/coordinator.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Refactor switch platform * Expose switch state * Refactor sensor platform * Put back accidentally deleted code * Add set_hub_available * Apply suggestions from code review Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Fix tests for fan platform * Update homeassistant/components/tradfri/base_class.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Update homeassistant/components/tradfri/base_class.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Fix non-working tests * Refresh sensor state * Remove commented line * Add group coordinator * Add groups during setup * Refactor light platform * Fix tests * Move outside of try...except * Remove error handler * Remove unneeded methods * Update sensor * Update .coveragerc * Move signal * Add signals for groups * Fix signal Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
2022-01-27 10:12:52 +00:00
return entry
def modify_state(
state: dict[str, Any], partial_state: dict[str, Any]
) -> dict[str, Any]:
"""Modify a state with a partial state."""
for key, value in partial_state.items():
if isinstance(value, list):
for index, item in enumerate(value):
state[key][index] = modify_state(state[key][index], item)
elif isinstance(value, dict):
state[key] = modify_state(state[key], value)
else:
state[key] = value
return state