Improve config entry migration for edge cases in Alexa Devices (#151788)

This commit is contained in:
Simone Chemelli
2025-09-12 20:18:12 +00:00
committed by Franck Nijhof
parent 9dafc0e02f
commit 1b27acdde0
6 changed files with 102 additions and 15 deletions
@@ -5,7 +5,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers import aiohttp_client, config_validation as cv
from homeassistant.helpers.typing import ConfigType
from .const import _LOGGER, CONF_LOGIN_DATA, COUNTRY_DOMAINS, DOMAIN
from .const import _LOGGER, CONF_LOGIN_DATA, CONF_SITE, COUNTRY_DOMAINS, DOMAIN
from .coordinator import AmazonConfigEntry, AmazonDevicesCoordinator
from .services import async_setup_services
@@ -42,7 +42,23 @@ async def async_setup_entry(hass: HomeAssistant, entry: AmazonConfigEntry) -> bo
async def async_migrate_entry(hass: HomeAssistant, entry: AmazonConfigEntry) -> bool:
"""Migrate old entry."""
if entry.version == 1 and entry.minor_version == 1:
if entry.version == 1 and entry.minor_version < 3:
if CONF_SITE in entry.data:
# Site in data (wrong place), just move to login data
new_data = entry.data.copy()
new_data[CONF_LOGIN_DATA][CONF_SITE] = new_data[CONF_SITE]
new_data.pop(CONF_SITE)
hass.config_entries.async_update_entry(
entry, data=new_data, version=1, minor_version=3
)
return True
if CONF_SITE in entry.data[CONF_LOGIN_DATA]:
# Site is there, just update version to avoid future migrations
hass.config_entries.async_update_entry(entry, version=1, minor_version=3)
return True
_LOGGER.debug(
"Migrating from version %s.%s", entry.version, entry.minor_version
)
@@ -53,10 +69,10 @@ async def async_migrate_entry(hass: HomeAssistant, entry: AmazonConfigEntry) ->
# Add site to login data
new_data = entry.data.copy()
new_data[CONF_LOGIN_DATA]["site"] = f"https://www.amazon.{domain}"
new_data[CONF_LOGIN_DATA][CONF_SITE] = f"https://www.amazon.{domain}"
hass.config_entries.async_update_entry(
entry, data=new_data, version=1, minor_version=2
entry, data=new_data, version=1, minor_version=3
)
_LOGGER.info(
@@ -52,7 +52,7 @@ class AmazonDevicesConfigFlow(ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Alexa Devices."""
VERSION = 1
MINOR_VERSION = 2
MINOR_VERSION = 3
async def async_step_user(
self, user_input: dict[str, Any] | None = None
@@ -6,6 +6,7 @@ _LOGGER = logging.getLogger(__package__)
DOMAIN = "alexa_devices"
CONF_LOGIN_DATA = "login_data"
CONF_SITE = "site"
DEFAULT_DOMAIN = "com"
COUNTRY_DOMAINS = {
+10 -3
View File
@@ -7,7 +7,11 @@ from aioamazondevices.api import AmazonDevice, AmazonDeviceSensor
from aioamazondevices.const import DEVICE_TYPE_TO_MODEL
import pytest
from homeassistant.components.alexa_devices.const import CONF_LOGIN_DATA, DOMAIN
from homeassistant.components.alexa_devices.const import (
CONF_LOGIN_DATA,
CONF_SITE,
DOMAIN,
)
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from .const import TEST_PASSWORD, TEST_SERIAL_NUMBER, TEST_USERNAME
@@ -81,9 +85,12 @@ def mock_config_entry() -> MockConfigEntry:
data={
CONF_USERNAME: TEST_USERNAME,
CONF_PASSWORD: TEST_PASSWORD,
CONF_LOGIN_DATA: {"session": "test-session"},
CONF_LOGIN_DATA: {
"session": "test-session",
CONF_SITE: "https://www.amazon.com",
},
},
unique_id=TEST_USERNAME,
version=1,
minor_version=2,
minor_version=3,
)
@@ -49,6 +49,7 @@
'data': dict({
'login_data': dict({
'session': 'test-session',
'site': 'https://www.amazon.com',
}),
'password': '**REDACTED**',
'username': '**REDACTED**',
@@ -57,7 +58,7 @@
'discovery_keys': dict({
}),
'domain': 'alexa_devices',
'minor_version': 2,
'minor_version': 3,
'options': dict({
}),
'pref_disable_new_entities': False,
+68 -6
View File
@@ -2,9 +2,14 @@
from unittest.mock import AsyncMock
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.alexa_devices.const import CONF_LOGIN_DATA, DOMAIN
from homeassistant.components.alexa_devices.const import (
CONF_LOGIN_DATA,
CONF_SITE,
DOMAIN,
)
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_COUNTRY, CONF_PASSWORD, CONF_USERNAME
from homeassistant.core import HomeAssistant
@@ -32,24 +37,81 @@ async def test_device_info(
assert device_entry == snapshot
@pytest.mark.parametrize(
("minor_version", "extra_data"),
[
# Standard migration case
(
1,
{
CONF_COUNTRY: "US",
CONF_LOGIN_DATA: {
"session": "test-session",
},
},
),
# Edge case #1: no country, site already in login data, minor version 1
(
1,
{
CONF_LOGIN_DATA: {
"session": "test-session",
CONF_SITE: "https://www.amazon.com",
},
},
),
# Edge case #2: no country, site in data (wrong place), minor version 1
(
1,
{
CONF_SITE: "https://www.amazon.com",
CONF_LOGIN_DATA: {
"session": "test-session",
},
},
),
# Edge case #3: no country, site already in login data, minor version 2
(
2,
{
CONF_LOGIN_DATA: {
"session": "test-session",
CONF_SITE: "https://www.amazon.com",
},
},
),
# Edge case #4: no country, site in data (wrong place), minor version 2
(
2,
{
CONF_SITE: "https://www.amazon.com",
CONF_LOGIN_DATA: {
"session": "test-session",
},
},
),
],
)
async def test_migrate_entry(
hass: HomeAssistant,
mock_amazon_devices_client: AsyncMock,
mock_config_entry: MockConfigEntry,
minor_version: int,
extra_data: dict[str, str],
) -> None:
"""Test successful migration of entry data."""
config_entry = MockConfigEntry(
domain=DOMAIN,
title="Amazon Test Account",
data={
CONF_COUNTRY: "US", # country should be in COUNTRY_DOMAINS exceptions
CONF_USERNAME: TEST_USERNAME,
CONF_PASSWORD: TEST_PASSWORD,
CONF_LOGIN_DATA: {"session": "test-session"},
**(extra_data),
},
unique_id=TEST_USERNAME,
version=1,
minor_version=1,
minor_version=minor_version,
)
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
@@ -57,5 +119,5 @@ async def test_migrate_entry(
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
assert config_entry.state is ConfigEntryState.LOADED
assert config_entry.minor_version == 2
assert config_entry.data[CONF_LOGIN_DATA]["site"] == "https://www.amazon.com"
assert config_entry.minor_version == 3
assert config_entry.data[CONF_LOGIN_DATA][CONF_SITE] == "https://www.amazon.com"