"""Define tests for the Daikin init.""" import asyncio from datetime import timedelta from unittest.mock import AsyncMock, PropertyMock, patch from aiohttp import ClientConnectionError from freezegun.api import FrozenDateTimeFactory import pytest from homeassistant.components.daikin import DaikinApi, update_unique_id from homeassistant.components.daikin.const import DOMAIN, KEY_MAC from homeassistant.config_entries import ConfigEntryState from homeassistant.const import CONF_HOST from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr, entity_registry as er from .test_config_flow import HOST, MAC from tests.common import MockConfigEntry, async_fire_time_changed @pytest.fixture def mock_daikin(): """Mock pydaikin.""" async def mock_daikin_factory(*args, **kwargs): """Mock the init function in pydaikin.""" return Appliance with patch("homeassistant.components.daikin.Appliance") as Appliance: Appliance.factory.side_effect = mock_daikin_factory type(Appliance).update_status = AsyncMock() type(Appliance).device_ip = PropertyMock(return_value=HOST) type(Appliance).inside_temperature = PropertyMock(return_value=22) type(Appliance).target_temperature = PropertyMock(return_value=22) type(Appliance).zones = PropertyMock(return_value=[("Zone 1", "0", 0)]) type(Appliance).fan_rate = PropertyMock(return_value=[]) type(Appliance).swing_modes = PropertyMock(return_value=[]) yield Appliance DATA = { "ver": "1_1_8", "name": "DaikinAP00000", "mac": MAC, "model": "NOTSUPPORT", } INVALID_DATA = {**DATA, "name": None, "mac": HOST} async def test_duplicate_removal( hass: HomeAssistant, entity_registry: er.EntityRegistry, device_registry: dr.DeviceRegistry, mock_daikin, ) -> None: """Test duplicate device removal.""" config_entry = MockConfigEntry( domain=DOMAIN, unique_id=HOST, title=None, data={CONF_HOST: HOST, KEY_MAC: HOST}, ) config_entry.add_to_hass(hass) type(mock_daikin).mac = PropertyMock(return_value=HOST) type(mock_daikin).values = PropertyMock(return_value=INVALID_DATA) with patch( "homeassistant.components.daikin.async_migrate_unique_id", return_value=None ): assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.unique_id != MAC type(mock_daikin).mac = PropertyMock(return_value=MAC) type(mock_daikin).values = PropertyMock(return_value=DATA) assert await hass.config_entries.async_reload(config_entry.entry_id) await hass.async_block_till_done() assert ( device_registry.async_get_device({}, {(KEY_MAC, MAC)}).name == "DaikinAP00000" ) assert device_registry.async_get_device({}, {(KEY_MAC, HOST)}).name is None assert entity_registry.async_get("climate.daikin_127_0_0_1").unique_id == HOST assert entity_registry.async_get("switch.none_zone_1").unique_id.startswith( HOST ) assert entity_registry.async_get("climate.daikinap00000").unique_id == MAC assert entity_registry.async_get( "switch.daikinap00000_zone_1" ).unique_id.startswith(MAC) assert await hass.config_entries.async_reload(config_entry.entry_id) await hass.async_block_till_done() assert ( device_registry.async_get_device({}, {(KEY_MAC, MAC)}).name == "DaikinAP00000" ) assert entity_registry.async_get("climate.daikinap00000") is None assert entity_registry.async_get("switch.daikinap00000_zone_1") is None assert entity_registry.async_get("climate.daikin_127_0_0_1").unique_id == MAC assert entity_registry.async_get("switch.none_zone_1").unique_id.startswith(MAC) async def test_unique_id_migrate( hass: HomeAssistant, entity_registry: er.EntityRegistry, device_registry: dr.DeviceRegistry, mock_daikin, ) -> None: """Test unique id migration.""" config_entry = MockConfigEntry( domain=DOMAIN, unique_id=HOST, title=None, data={CONF_HOST: HOST, KEY_MAC: HOST}, ) config_entry.add_to_hass(hass) type(mock_daikin).mac = PropertyMock(return_value=HOST) type(mock_daikin).values = PropertyMock(return_value=INVALID_DATA) assert await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.unique_id == HOST assert device_registry.async_get_device(connections={(KEY_MAC, HOST)}).name is None entity = entity_registry.async_get("climate.daikin_127_0_0_1") assert entity.unique_id == HOST assert update_unique_id(entity, MAC) is not None assert entity_registry.async_get("switch.none_zone_1").unique_id.startswith(HOST) type(mock_daikin).mac = PropertyMock(return_value=MAC) type(mock_daikin).values = PropertyMock(return_value=DATA) assert config_entry.unique_id != MAC assert await hass.config_entries.async_reload(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.unique_id == MAC assert ( device_registry.async_get_device(connections={(KEY_MAC, MAC)}).name == "DaikinAP00000" ) entity = entity_registry.async_get("climate.daikin_127_0_0_1") assert entity.unique_id == MAC assert update_unique_id(entity, MAC) is None assert entity_registry.async_get("switch.none_zone_1").unique_id.startswith(MAC) async def test_client_update_connection_error( hass: HomeAssistant, mock_daikin, freezer: FrozenDateTimeFactory ) -> None: """Test client connection error on update.""" config_entry = MockConfigEntry( domain=DOMAIN, unique_id=MAC, data={CONF_HOST: HOST, KEY_MAC: MAC}, ) config_entry.add_to_hass(hass) type(mock_daikin).mac = PropertyMock(return_value=MAC) type(mock_daikin).values = PropertyMock(return_value=DATA) await hass.config_entries.async_setup(config_entry.entry_id) api: DaikinApi = hass.data[DOMAIN][config_entry.entry_id] assert api.available is True type(mock_daikin).update_status.side_effect = ClientConnectionError freezer.tick(timedelta(seconds=90)) async_fire_time_changed(hass) await hass.async_block_till_done() assert api.available is False assert mock_daikin.update_status.call_count == 2 async def test_client_connection_error(hass: HomeAssistant, mock_daikin) -> None: """Test client connection error on setup.""" config_entry = MockConfigEntry( domain=DOMAIN, unique_id=MAC, data={CONF_HOST: HOST, KEY_MAC: MAC}, ) config_entry.add_to_hass(hass) mock_daikin.factory.side_effect = ClientConnectionError await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.state == ConfigEntryState.SETUP_RETRY async def test_timeout_error(hass: HomeAssistant, mock_daikin) -> None: """Test timeout error on setup.""" config_entry = MockConfigEntry( domain=DOMAIN, unique_id=MAC, data={CONF_HOST: HOST, KEY_MAC: MAC}, ) config_entry.add_to_hass(hass) mock_daikin.factory.side_effect = asyncio.TimeoutError await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.state == ConfigEntryState.SETUP_RETRY