"""Test init of LCN integration.""" from unittest.mock import Mock, patch from pypck.connection import ( PchkAuthenticationError, PchkConnectionFailedError, PchkConnectionRefusedError, PchkLcnNotConnectedError, PchkLicenseError, ) from pypck.lcn_defs import LcnEvent import pytest from syrupy.assertion import SnapshotAssertion from homeassistant import config_entries from homeassistant.components.lcn.const import DOMAIN from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr, entity_registry as er from .conftest import ( MockConfigEntry, MockPchkConnectionManager, create_config_entry, init_integration, ) async def test_async_setup_entry(hass: HomeAssistant, entry: MockConfigEntry) -> None: """Test a successful setup entry and unload of entry.""" await init_integration(hass, entry) assert len(hass.config_entries.async_entries(DOMAIN)) == 1 assert entry.state is ConfigEntryState.LOADED assert await hass.config_entries.async_unload(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.NOT_LOADED assert not hass.data.get(DOMAIN) async def test_async_setup_multiple_entries( hass: HomeAssistant, entry: MockConfigEntry, entry2 ) -> None: """Test a successful setup and unload of multiple entries.""" hass.http = Mock() with patch( "homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager ): for config_entry in (entry, entry2): await init_integration(hass, config_entry) assert config_entry.state is ConfigEntryState.LOADED assert len(hass.config_entries.async_entries(DOMAIN)) == 2 for config_entry in (entry, entry2): assert await hass.config_entries.async_unload(config_entry.entry_id) await hass.async_block_till_done() assert config_entry.state is ConfigEntryState.NOT_LOADED assert not hass.data.get(DOMAIN) async def test_async_setup_entry_update( hass: HomeAssistant, device_registry: dr.DeviceRegistry, entity_registry: er.EntityRegistry, entry: MockConfigEntry, ) -> None: """Test a successful setup entry if entry with same id already exists.""" # setup first entry entry.source = config_entries.SOURCE_IMPORT entry.add_to_hass(hass) # create dummy entity for LCN platform as an orphan dummy_entity = entity_registry.async_get_or_create( "switch", DOMAIN, "dummy", config_entry=entry ) # create dummy device for LCN platform as an orphan dummy_device = device_registry.async_get_or_create( config_entry_id=entry.entry_id, identifiers={(DOMAIN, entry.entry_id, 0, 7, False)}, via_device=(DOMAIN, entry.entry_id), ) assert dummy_entity in entity_registry.entities.values() assert dummy_device in device_registry.devices.values() @pytest.mark.parametrize( "exception", [ PchkAuthenticationError, PchkLicenseError, PchkConnectionRefusedError, PchkConnectionFailedError, PchkLcnNotConnectedError, ], ) async def test_async_setup_entry_fails( hass: HomeAssistant, entry: MockConfigEntry, exception: Exception ) -> None: """Test that an error is handled properly.""" with ( patch( "homeassistant.components.lcn.PchkConnectionManager.async_connect", side_effect=exception, ), ): entry.add_to_hass(hass) await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() assert entry.state is ConfigEntryState.SETUP_RETRY @pytest.mark.parametrize( "event", [LcnEvent.CONNECTION_LOST, LcnEvent.PING_TIMEOUT, LcnEvent.BUS_DISCONNECTED], ) async def test_async_entry_reload_on_host_event_received( hass: HomeAssistant, entry: MockConfigEntry, event: LcnEvent ) -> None: """Test for config entry reload on certain host event received.""" lcn_connection = await init_integration(hass, entry) with patch( "homeassistant.config_entries.ConfigEntries.async_schedule_reload" ) as async_schedule_reload: lcn_connection.fire_event(event) async_schedule_reload.assert_called_with(entry.entry_id) @patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_migrate_1_1(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None: """Test migration config entry.""" entry_v1_1 = create_config_entry("pchk_v1_1", version=(1, 1)) await init_integration(hass, entry_v1_1) entry_migrated = hass.config_entries.async_get_entry(entry_v1_1.entry_id) assert entry_migrated.state is ConfigEntryState.LOADED assert entry_migrated.version == 3 assert entry_migrated.minor_version == 1 assert entry_migrated.data == snapshot @patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_migrate_1_2(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None: """Test migration config entry.""" entry_v1_2 = create_config_entry("pchk_v1_2", version=(1, 2)) await init_integration(hass, entry_v1_2) entry_migrated = hass.config_entries.async_get_entry(entry_v1_2.entry_id) assert entry_migrated.state is ConfigEntryState.LOADED assert entry_migrated.version == 3 assert entry_migrated.minor_version == 1 assert entry_migrated.data == snapshot @patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_migrate_2_1(hass: HomeAssistant, snapshot: SnapshotAssertion) -> None: """Test migration config entry.""" entry_v2_1 = create_config_entry("pchk_v2_1", version=(2, 1)) await init_integration(hass, entry_v2_1) entry_migrated = hass.config_entries.async_get_entry(entry_v2_1.entry_id) assert entry_migrated.state is ConfigEntryState.LOADED assert entry_migrated.version == 3 assert entry_migrated.minor_version == 1 assert entry_migrated.data == snapshot @pytest.mark.parametrize( ("entity_id", "replace"), [ ("climate.testmodule_climate1", ("-r1varsetpoint", "-var1.r1varsetpoint")), ("scene.testmodule_romantic", ("-00", "-0.0")), ], ) @patch("homeassistant.components.lcn.PchkConnectionManager", MockPchkConnectionManager) async def test_entity_migration_on_2_1( hass: HomeAssistant, entity_registry: er.EntityRegistry, entity_id, replace ) -> None: """Test entity.unique_id migration on config_entry migration from 2.1.""" entry_v2_1 = create_config_entry("pchk_v2_1", version=(2, 1)) await init_integration(hass, entry_v2_1) migrated_unique_id = entity_registry.async_get(entity_id).unique_id old_unique_id = migrated_unique_id.replace(*replace) entity_registry.async_update_entity(entity_id, new_unique_id=old_unique_id) assert entity_registry.async_get(entity_id).unique_id == old_unique_id await hass.config_entries.async_unload(entry_v2_1.entry_id) entry_v2_1 = create_config_entry("pchk_v2_1", version=(2, 1)) await init_integration(hass, entry_v2_1) assert entity_registry.async_get(entity_id).unique_id == migrated_unique_id