Files
core/tests/components/midea/test_entity.py
T

164 lines
5.3 KiB
Python

"""Tests for midea entity behavior via loaded platforms."""
from collections.abc import Callable
from midealocal.devices.ac import DeviceAttributes as ACAttributes
from midealocal.exceptions import SocketException
import pytest
from homeassistant.components.midea.const import DOMAIN
from homeassistant.components.midea.entity import midea_api_call
from homeassistant.core import CoreState, HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import device_registry as dr
from . import setup_integration
from .conftest import DummyDevice, default_ac_device, entity_entries
from .const import TEST_DEVICE_ID, TEST_MAC_ADDRESS, TEST_MODEL, TEST_SERIAL_NUMBER
from tests.common import MockConfigEntry
def test_midea_api_call_translates_midea_local_error() -> None:
"""Test midea_api_call turns a midealocal error into a HomeAssistantError."""
with pytest.raises(HomeAssistantError) as exc_info, midea_api_call():
raise SocketException("offline")
assert exc_info.value.translation_domain == DOMAIN
assert exc_info.value.translation_key == "device_communication_error"
assert exc_info.value.translation_placeholders == {"error": "offline"}
@pytest.mark.parametrize(
(
"update",
"status",
"availability",
"expected_current_temp",
"expected_unavailable",
),
[
pytest.param(
{ACAttributes.indoor_temperature: 24.0},
{"available": True},
True,
24.0,
False,
id="temperature_update",
),
pytest.param(
{},
{"available": False},
False,
None,
True,
id="availability_update",
),
pytest.param(
{ACAttributes.indoor_temperature: 24.0},
{"power": True, ACAttributes.indoor_temperature: 24.0},
True,
24.0,
False,
id="attribute_update_without_available_key",
),
],
)
async def test_entity_updates_from_device_callback(
hass: HomeAssistant,
mock_config_entry: Callable[[DummyDevice], MockConfigEntry],
update: dict[str, float],
status: dict[str, bool | float],
availability: bool,
expected_current_temp: float | None,
expected_unavailable: bool,
) -> None:
"""Test entity callback updates state and availability."""
device = default_ac_device()
config_entry = mock_config_entry(device)
await setup_integration(hass, config_entry, device)
entity_entry = entity_entries(hass, config_entry)[f"{TEST_DEVICE_ID}_climate"]
assert (state := hass.states.get(entity_entry.entity_id))
assert state.attributes["current_temperature"] == 21.0
assert state.state != "unavailable"
device.attributes.update(update)
device.available = availability
device.notify_update(status)
await hass.async_block_till_done()
assert (state := hass.states.get(entity_entry.entity_id))
assert state.attributes.get("current_temperature") == expected_current_temp
assert (state.state == "unavailable") is expected_unavailable
@pytest.mark.parametrize(
("mac", "serial_number", "expected_connections", "expected_serial_number"),
[
pytest.param(
TEST_MAC_ADDRESS,
TEST_SERIAL_NUMBER,
{(dr.CONNECTION_NETWORK_MAC, TEST_MAC_ADDRESS)},
TEST_SERIAL_NUMBER,
id="populated",
),
pytest.param(
"",
"",
set(),
None,
id="absent",
),
],
)
async def test_device_info_optional_metadata(
hass: HomeAssistant,
device_registry: dr.DeviceRegistry,
mock_config_entry: Callable[[DummyDevice], MockConfigEntry],
mac: str,
serial_number: str,
expected_connections: set[tuple[str, str]],
expected_serial_number: str | None,
) -> None:
"""Test device registry entry reflects optional mac and serial number."""
device = default_ac_device()
device.mac = mac
device.serial_number = serial_number
config_entry = mock_config_entry(device)
await setup_integration(hass, config_entry, device)
assert (
device_entry := device_registry.async_get_device_by_identifier(
(DOMAIN, str(TEST_DEVICE_ID)), config_entry.entry_id
)
) is not None
assert device_entry.model_id == device.device_type.name
assert device_entry.hw_version == TEST_MODEL
assert device_entry.connections == expected_connections
assert device_entry.serial_number == expected_serial_number
async def test_entity_callback_ignored_while_hass_stopping(
hass: HomeAssistant,
mock_config_entry: Callable[[DummyDevice], MockConfigEntry],
) -> None:
"""Test update callback does not schedule updates while Home Assistant stops."""
device = default_ac_device()
config_entry = mock_config_entry(device)
await setup_integration(hass, config_entry, device)
entity_entry = entity_entries(hass, config_entry)[f"{TEST_DEVICE_ID}_climate"]
assert hass.states.get(entity_entry.entity_id) is not None
device.attributes[ACAttributes.indoor_temperature] = 25.0
hass.set_state(CoreState.stopping)
device.notify_update({"available": True})
await hass.async_block_till_done()
assert (state := hass.states.get(entity_entry.entity_id))
assert state.attributes["current_temperature"] == 21.0