"""Tests for the homewizard component.""" from asyncio import TimeoutError from unittest.mock import patch from homewizard_energy.errors import DisabledError, HomeWizardEnergyException from homeassistant import config_entries from homeassistant.components.homewizard.const import DOMAIN from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntryState from homeassistant.const import CONF_IP_ADDRESS from homeassistant.helpers import entity_registry as er from .generator import get_mock_device from tests.common import MockConfigEntry async def test_load_unload(aioclient_mock, hass): """Test loading and unloading of integration.""" device = get_mock_device() entry = MockConfigEntry( domain=DOMAIN, data={CONF_IP_ADDRESS: "1.1.1.1"}, unique_id=DOMAIN, ) entry.add_to_hass(hass) with patch( "homeassistant.components.homewizard.coordinator.HomeWizardEnergy", return_value=device, ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.LOADED await hass.config_entries.async_unload(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.NOT_LOADED async def test_load_failed_host_unavailable(aioclient_mock, hass): """Test setup handles unreachable host.""" def MockInitialize(): raise TimeoutError() device = get_mock_device() device.device.side_effect = MockInitialize entry = MockConfigEntry( domain=DOMAIN, data={CONF_IP_ADDRESS: "1.1.1.1"}, unique_id=DOMAIN, ) entry.add_to_hass(hass) with patch( "homeassistant.components.homewizard.coordinator.HomeWizardEnergy", return_value=device, ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.SETUP_RETRY async def test_init_accepts_and_migrates_old_entry(aioclient_mock, hass): """Test config flow accepts imported configuration.""" device = get_mock_device() # Add original entry original_entry = MockConfigEntry( domain="homewizard_energy", data={CONF_IP_ADDRESS: "1.2.3.4"}, entry_id="old_id", ) original_entry.add_to_hass(hass) # Give it some entities to see of they migrate properly ent_reg = er.async_get(hass) old_entity_active_power = ent_reg.async_get_or_create( "sensor", "homewizard_energy", "p1_active_power_unique_id", config_entry=original_entry, original_name="Active Power", suggested_object_id="p1_active_power", ) old_entity_switch = ent_reg.async_get_or_create( "switch", "homewizard_energy", "socket_switch_unique_id", config_entry=original_entry, original_name="Switch", suggested_object_id="socket_switch", ) old_entity_disabled_sensor = ent_reg.async_get_or_create( "sensor", "homewizard_energy", "socket_disabled_unique_id", config_entry=original_entry, original_name="Switch Disabled", suggested_object_id="socket_disabled", disabled_by=er.RegistryEntryDisabler.USER, ) # Update some user-customs ent_reg.async_update_entity(old_entity_active_power.entity_id, name="new_name") ent_reg.async_update_entity(old_entity_switch.entity_id, icon="new_icon") imported_entry = MockConfigEntry( domain=DOMAIN, data={CONF_IP_ADDRESS: "1.2.3.4", "old_config_entry_id": "old_id"}, source=config_entries.SOURCE_IMPORT, entry_id="new_id", ) imported_entry.add_to_hass(hass) assert imported_entry.domain == DOMAIN assert imported_entry.domain != original_entry.domain # Add the entry_id to trigger migration with patch( "homeassistant.components.homewizard.coordinator.HomeWizardEnergy", return_value=device, ): await hass.config_entries.async_setup(imported_entry.entry_id) await hass.async_block_till_done() assert original_entry.state is ConfigEntryState.NOT_LOADED assert imported_entry.state is ConfigEntryState.LOADED # Check if new entities are migrated new_entity_active_power = ent_reg.async_get(old_entity_active_power.entity_id) assert new_entity_active_power.platform == DOMAIN assert new_entity_active_power.name == "new_name" assert new_entity_active_power.icon is None assert new_entity_active_power.original_name == "Active Power" assert new_entity_active_power.unique_id == "p1_active_power_unique_id" assert new_entity_active_power.disabled_by is None new_entity_switch = ent_reg.async_get(old_entity_switch.entity_id) assert new_entity_switch.platform == DOMAIN assert new_entity_switch.name is None assert new_entity_switch.icon == "new_icon" assert new_entity_switch.original_name == "Switch" assert new_entity_switch.unique_id == "socket_switch_unique_id" assert new_entity_switch.disabled_by is None new_entity_disabled_sensor = ent_reg.async_get(old_entity_disabled_sensor.entity_id) assert new_entity_disabled_sensor.platform == DOMAIN assert new_entity_disabled_sensor.name is None assert new_entity_disabled_sensor.original_name == "Switch Disabled" assert new_entity_disabled_sensor.unique_id == "socket_disabled_unique_id" assert new_entity_disabled_sensor.disabled_by == er.RegistryEntryDisabler.USER async def test_load_detect_api_disabled(aioclient_mock, hass): """Test setup detects disabled API.""" def MockInitialize(): raise DisabledError() device = get_mock_device() device.device.side_effect = MockInitialize entry = MockConfigEntry( domain=DOMAIN, data={CONF_IP_ADDRESS: "1.1.1.1"}, unique_id=DOMAIN, ) entry.add_to_hass(hass) with patch( "homeassistant.components.homewizard.coordinator.HomeWizardEnergy", return_value=device, ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.SETUP_RETRY flows = hass.config_entries.flow.async_progress() assert len(flows) == 1 flow = flows[0] assert flow.get("step_id") == "reauth_confirm" assert flow.get("handler") == DOMAIN assert "context" in flow assert flow["context"].get("source") == SOURCE_REAUTH assert flow["context"].get("entry_id") == entry.entry_id async def test_load_removes_reauth_flow(aioclient_mock, hass): """Test setup removes reauth flow when API is enabled.""" device = get_mock_device() entry = MockConfigEntry( domain=DOMAIN, data={CONF_IP_ADDRESS: "1.1.1.1"}, unique_id=DOMAIN, ) entry.add_to_hass(hass) # Add reauth flow from 'previously' failed init entry.async_start_reauth(hass) await hass.async_block_till_done() flows = hass.config_entries.flow.async_progress_by_handler(DOMAIN) assert len(flows) == 1 # Initialize entry with patch( "homeassistant.components.homewizard.coordinator.HomeWizardEnergy", return_value=device, ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.LOADED # Flow should be removed flows = hass.config_entries.flow.async_progress_by_handler(DOMAIN) assert len(flows) == 0 async def test_load_handles_homewizardenergy_exception(aioclient_mock, hass): """Test setup handles exception from API.""" def MockInitialize(): raise HomeWizardEnergyException() device = get_mock_device() device.device.side_effect = MockInitialize entry = MockConfigEntry( domain=DOMAIN, data={CONF_IP_ADDRESS: "1.1.1.1"}, unique_id=DOMAIN, ) entry.add_to_hass(hass) with patch( "homeassistant.components.homewizard.coordinator.HomeWizardEnergy", return_value=device, ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.SETUP_RETRY or ConfigEntryState.SETUP_ERROR async def test_load_handles_generic_exception(aioclient_mock, hass): """Test setup handles global exception.""" def MockInitialize(): raise Exception() device = get_mock_device() device.device.side_effect = MockInitialize entry = MockConfigEntry( domain=DOMAIN, data={CONF_IP_ADDRESS: "1.1.1.1"}, unique_id=DOMAIN, ) entry.add_to_hass(hass) with patch( "homeassistant.components.homewizard.coordinator.HomeWizardEnergy", return_value=device, ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.SETUP_RETRY or ConfigEntryState.SETUP_ERROR async def test_load_handles_initialization_error(aioclient_mock, hass): """Test handles non-exception error.""" device = get_mock_device() device.device = None entry = MockConfigEntry( domain=DOMAIN, data={CONF_IP_ADDRESS: "1.1.1.1"}, unique_id=DOMAIN, ) entry.add_to_hass(hass) with patch( "homeassistant.components.homewizard.coordinator.HomeWizardEnergy", return_value=device, ): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.SETUP_RETRY or ConfigEntryState.SETUP_ERROR