diff --git a/homeassistant/components/velbus/__init__.py b/homeassistant/components/velbus/__init__.py index 0da64227fd3..ecb0636b029 100644 --- a/homeassistant/components/velbus/__init__.py +++ b/homeassistant/components/velbus/__init__.py @@ -194,3 +194,21 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: shutil.rmtree, hass.config.path(STORAGE_DIR, f"velbuscache-{entry.entry_id}"), ) + + +async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: + """Migrate old entry.""" + _LOGGER.debug("Migrating from version %s", config_entry.version) + cache_path = hass.config.path(STORAGE_DIR, f"velbuscache-{config_entry.entry_id}/") + if config_entry.version == 1: + # This is the config entry migration for adding the new program selection + # clean the velbusCache + if os.path.isdir(cache_path): + await hass.async_add_executor_job(shutil.rmtree, cache_path) + # set the new version + config_entry.version = 2 + # update the entry + hass.config_entries.async_update_entry(config_entry) + + _LOGGER.debug("Migration to version %s successful", config_entry.version) + return True diff --git a/homeassistant/components/velbus/config_flow.py b/homeassistant/components/velbus/config_flow.py index 32f1f3a500d..e0394e4787c 100644 --- a/homeassistant/components/velbus/config_flow.py +++ b/homeassistant/components/velbus/config_flow.py @@ -19,7 +19,7 @@ from .const import DOMAIN class VelbusConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): """Handle a config flow.""" - VERSION = 1 + VERSION = 2 def __init__(self) -> None: """Initialize the velbus config flow.""" diff --git a/homeassistant/components/velbus/manifest.json b/homeassistant/components/velbus/manifest.json index 86e67ca7767..9384947cb82 100644 --- a/homeassistant/components/velbus/manifest.json +++ b/homeassistant/components/velbus/manifest.json @@ -2,7 +2,7 @@ "domain": "velbus", "name": "Velbus", "documentation": "https://www.home-assistant.io/integrations/velbus", - "requirements": ["velbus-aio==2022.10.4"], + "requirements": ["velbus-aio==2022.12.0"], "config_flow": true, "codeowners": ["@Cereal2nd", "@brefra"], "dependencies": ["usb"], diff --git a/requirements_all.txt b/requirements_all.txt index 171d7c36e2e..e46e3728a21 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2524,7 +2524,7 @@ vallox-websocket-api==3.0.0 vehicle==0.4.0 # homeassistant.components.velbus -velbus-aio==2022.10.4 +velbus-aio==2022.12.0 # homeassistant.components.venstar venstarcolortouch==0.19 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 8b53e6e8538..a4c0da527a8 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1764,7 +1764,7 @@ vallox-websocket-api==3.0.0 vehicle==0.4.0 # homeassistant.components.velbus -velbus-aio==2022.10.4 +velbus-aio==2022.12.0 # homeassistant.components.venstar venstarcolortouch==0.19 diff --git a/tests/components/velbus/conftest.py b/tests/components/velbus/conftest.py index 62aa0d0b505..c5db7f0ec73 100644 --- a/tests/components/velbus/conftest.py +++ b/tests/components/velbus/conftest.py @@ -1,5 +1,6 @@ """Fixtures for the Velbus tests.""" -from unittest.mock import AsyncMock, patch +from collections.abc import Generator +from unittest.mock import MagicMock, patch import pytest @@ -14,10 +15,9 @@ from tests.common import MockConfigEntry @pytest.fixture(name="controller") -def mock_controller(): +def mock_controller() -> Generator[MagicMock, None, None]: """Mock a successful velbus controller.""" - controller = AsyncMock() - with patch("velbusaio.controller.Velbus", return_value=controller): + with patch("homeassistant.components.velbus.Velbus", autospec=True) as controller: yield controller diff --git a/tests/components/velbus/test_config_flow.py b/tests/components/velbus/test_config_flow.py index 454290b3581..af11f83adb3 100644 --- a/tests/components/velbus/test_config_flow.py +++ b/tests/components/velbus/test_config_flow.py @@ -1,4 +1,5 @@ """Tests for the Velbus config flow.""" +from collections.abc import Generator from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -36,8 +37,18 @@ def com_port(): return port +@pytest.fixture(name="controller") +def mock_controller() -> Generator[MagicMock, None, None]: + """Mock a successful velbus controller.""" + with patch( + "homeassistant.components.velbus.config_flow.velbusaio.controller.Velbus", + autospec=True, + ) as controller: + yield controller + + @pytest.fixture(autouse=True) -def override_async_setup_entry() -> AsyncMock: +def override_async_setup_entry() -> Generator[AsyncMock, None, None]: """Override async_setup_entry.""" with patch( "homeassistant.components.velbus.async_setup_entry", return_value=True @@ -74,6 +85,7 @@ async def test_user(hass: HomeAssistant): assert result.get("type") == data_entry_flow.FlowResultType.CREATE_ENTRY assert result.get("title") == "velbus_test_serial" data = result.get("data") + assert data assert data[CONF_PORT] == PORT_SERIAL # try with a ip:port combination @@ -86,6 +98,7 @@ async def test_user(hass: HomeAssistant): assert result.get("type") == data_entry_flow.FlowResultType.CREATE_ENTRY assert result.get("title") == "velbus_test_tcp" data = result.get("data") + assert data assert data[CONF_PORT] == PORT_TCP diff --git a/tests/components/velbus/test_init.py b/tests/components/velbus/test_init.py index dee00cce16b..7dfb573901a 100644 --- a/tests/components/velbus/test_init.py +++ b/tests/components/velbus/test_init.py @@ -1,11 +1,14 @@ """Tests for the Velbus component initialisation.""" +from unittest.mock import patch + import pytest from homeassistant.components.velbus.const import DOMAIN from homeassistant.config_entries import ConfigEntry, ConfigEntryState +from homeassistant.const import CONF_NAME, CONF_PORT from homeassistant.core import HomeAssistant -from tests.common import mock_device_registry +from tests.common import MockConfigEntry, mock_device_registry @pytest.mark.usefixtures("controller") @@ -15,12 +18,12 @@ async def test_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry): await hass.async_block_till_done() assert len(hass.config_entries.async_entries(DOMAIN)) == 1 - assert config_entry.state is ConfigEntryState.LOADED + assert config_entry.state == ConfigEntryState.LOADED 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 config_entry.state == ConfigEntryState.NOT_LOADED assert not hass.data.get(DOMAIN) @@ -35,22 +38,43 @@ async def test_device_identifier_migration( device_registry = mock_device_registry(hass) device_registry.async_get_or_create( config_entry_id=config_entry.entry_id, - identifiers=original_identifiers, + identifiers=original_identifiers, # type: ignore[arg-type] name="channel_name", manufacturer="Velleman", model="module_type_name", sw_version="module_sw_version", ) - assert device_registry.async_get_device(original_identifiers) + assert device_registry.async_get_device( + original_identifiers # type: ignore[arg-type] + ) assert not device_registry.async_get_device(target_identifiers) await hass.config_entries.async_setup(config_entry.entry_id) await hass.async_block_till_done() - assert not device_registry.async_get_device(original_identifiers) + assert not device_registry.async_get_device( + original_identifiers # type: ignore[arg-type] + ) device_entry = device_registry.async_get_device(target_identifiers) assert device_entry assert device_entry.name == "channel_name" assert device_entry.manufacturer == "Velleman" assert device_entry.model == "module_type_name" assert device_entry.sw_version == "module_sw_version" + + +@pytest.mark.usefixtures("controller") +async def test_migrate_config_entry(hass: HomeAssistant) -> None: + """Test successful migration of entry data.""" + legacy_config = {CONF_NAME: "fake_name", CONF_PORT: "1.2.3.4:5678"} + entry = MockConfigEntry(domain=DOMAIN, unique_id="my own id", data=legacy_config) + entry.add_to_hass(hass) + + assert dict(entry.data) == legacy_config + assert entry.version == 1 + + # test in case we do not have a cache + with patch("os.path.isdir", return_value=True), patch("shutil.rmtree"): + await hass.config_entries.async_setup(entry.entry_id) + assert dict(entry.data) == legacy_config + assert entry.version == 2