Files

167 lines
5.7 KiB
Python

"""Tests for midea __init__.py."""
from unittest.mock import patch
from midealocal.const import DeviceType, ProtocolVersion
from homeassistant.components.midea.const import CONF_KEY, CONF_SUBTYPE, DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import (
CONF_DEVICE_ID,
CONF_IP_ADDRESS,
CONF_MODEL,
CONF_NAME,
CONF_PORT,
CONF_PROTOCOL,
CONF_TOKEN,
CONF_TYPE,
)
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from .conftest import DummyDevice
from .const import TEST_DEVICE_ID
from tests.common import MockConfigEntry
_ENTRY_DATA = {
CONF_DEVICE_ID: TEST_DEVICE_ID,
CONF_NAME: "m",
CONF_TYPE: DeviceType.AC,
CONF_IP_ADDRESS: "1.1.1.1",
CONF_PORT: 6444,
CONF_MODEL: "m",
CONF_PROTOCOL: ProtocolVersion.V2,
CONF_TOKEN: "",
CONF_KEY: "",
CONF_SUBTYPE: 0,
}
async def test_async_setup(hass: HomeAssistant) -> None:
"""Test the midea domain can be set up without any config entries."""
assert await async_setup_component(hass, DOMAIN, {})
async def test_unload_entry(hass: HomeAssistant) -> None:
"""Test async_unload_entry unloads platforms and closes the device."""
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA)
entry.add_to_hass(hass)
device = DummyDevice(DeviceType.AC)
with patch(
"homeassistant.components.midea.device_selector",
return_value=device,
):
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.LOADED
assert device.daemon is True
assert await hass.config_entries.async_unload(entry.entry_id)
assert entry.state is ConfigEntryState.NOT_LOADED
assert ("close",) in device.calls
async def test_async_setup_entry_paths(hass: HomeAssistant) -> None:
"""Test async_setup_entry for success and no-device return."""
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA)
entry.add_to_hass(hass)
with patch(
"homeassistant.components.midea.device_selector",
return_value=DummyDevice(DeviceType.AC),
):
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.LOADED
entry2 = MockConfigEntry(
domain=DOMAIN,
data={**_ENTRY_DATA, CONF_DEVICE_ID: TEST_DEVICE_ID + 1},
)
entry2.add_to_hass(hass)
with patch(
"homeassistant.components.midea.device_selector",
return_value=None,
):
await hass.config_entries.async_setup(entry2.entry_id)
assert entry2.state is ConfigEntryState.SETUP_ERROR
async def test_setup_entry_not_ready_on_connect_failure(
hass: HomeAssistant,
) -> None:
"""Test async_setup_entry raises ConfigEntryNotReady when connect returns False.
The real device.connect() already catches SocketException/AuthException
internally and reports failure by returning False; it never raises them.
It can also leave the socket open in that case (e.g. when authentication
fails), so the socket must be closed explicitly to avoid a ResourceWarning.
"""
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA)
entry.add_to_hass(hass)
device = DummyDevice(DeviceType.AC)
with (
patch(
"homeassistant.components.midea.device_selector",
return_value=device,
),
patch.object(device, "connect", return_value=False),
patch("homeassistant.components.midea.discover", return_value={}),
):
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.SETUP_RETRY
assert ("close_socket",) in device.calls
assert entry.data[CONF_IP_ADDRESS] == _ENTRY_DATA[CONF_IP_ADDRESS]
async def test_setup_entry_recovers_ip_on_connect_failure(
hass: HomeAssistant,
) -> None:
"""Test async_setup_entry loads successfully after discovering a moved device.
When the stored IP no longer answers, a device with the same device_id
found at a different address by the discovery broadcast should update
the config entry and connect there, finishing setup normally.
"""
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA)
entry.add_to_hass(hass)
stale_device = DummyDevice(DeviceType.AC)
recovered_device = DummyDevice(DeviceType.AC)
with (
patch(
"homeassistant.components.midea.device_selector",
side_effect=[stale_device, recovered_device],
),
patch.object(stale_device, "connect", return_value=False),
patch(
"homeassistant.components.midea.discover",
return_value={TEST_DEVICE_ID: {CONF_IP_ADDRESS: "2.2.2.2"}},
),
):
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.LOADED
assert entry.data[CONF_IP_ADDRESS] == "2.2.2.2"
assert recovered_device.daemon is True
assert ("open",) in recovered_device.calls
async def test_setup_entry_no_recovery_when_device_not_discovered(
hass: HomeAssistant,
) -> None:
"""Test the stored IP is left untouched when discovery finds no match."""
entry = MockConfigEntry(domain=DOMAIN, data=_ENTRY_DATA)
entry.add_to_hass(hass)
device = DummyDevice(DeviceType.AC)
with (
patch(
"homeassistant.components.midea.device_selector",
return_value=device,
),
patch.object(device, "connect", return_value=False),
patch(
"homeassistant.components.midea.discover",
return_value={TEST_DEVICE_ID + 1: {CONF_IP_ADDRESS: "2.2.2.2"}},
),
):
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.SETUP_RETRY
assert entry.data[CONF_IP_ADDRESS] == _ENTRY_DATA[CONF_IP_ADDRESS]