From dadcabe7cd599fa7dfa2ec0eec472322fdd62058 Mon Sep 17 00:00:00 2001 From: G Johansson Date: Sat, 16 Aug 2025 15:37:10 +0000 Subject: [PATCH] Migration tests --- homeassistant/components/sql/__init__.py | 4 +- tests/components/sql/test_init.py | 94 +++++++++++++++++++++++- 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sql/__init__.py b/homeassistant/components/sql/__init__.py index cb026565cdd..dfca388e99e 100644 --- a/homeassistant/components/sql/__init__.py +++ b/homeassistant/components/sql/__init__.py @@ -127,7 +127,9 @@ async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: new_data = {} new_options: dict[str, Any] = {} - if (db_url := old_options.get(CONF_DB_URL)) != get_instance(hass).db_url: + if (db_url := old_options.get(CONF_DB_URL)) and db_url != get_instance( + hass + ).db_url: new_data[CONF_DB_URL] = db_url new_options[CONF_COLUMN_NAME] = old_options.get(CONF_COLUMN_NAME) diff --git a/tests/components/sql/test_init.py b/tests/components/sql/test_init.py index 3b847630336..7236b7212d3 100644 --- a/tests/components/sql/test_init.py +++ b/tests/components/sql/test_init.py @@ -7,15 +7,33 @@ from unittest.mock import patch import pytest import voluptuous as vol -from homeassistant.components.recorder import Recorder +from homeassistant.components.recorder import CONF_DB_URL, Recorder +from homeassistant.components.sensor import ( + CONF_STATE_CLASS, + SensorDeviceClass, + SensorStateClass, +) from homeassistant.components.sql import validate_sql_select -from homeassistant.components.sql.const import DOMAIN -from homeassistant.config_entries import ConfigEntryState +from homeassistant.components.sql.const import ( + CONF_ADVANCED_OPTIONS, + CONF_COLUMN_NAME, + CONF_QUERY, + DOMAIN, +) +from homeassistant.config_entries import SOURCE_USER, ConfigEntryState +from homeassistant.const import ( + CONF_DEVICE_CLASS, + CONF_NAME, + CONF_UNIT_OF_MEASUREMENT, + CONF_VALUE_TEMPLATE, +) from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component from . import YAML_CONFIG_INVALID, YAML_CONFIG_NO_DB, init_integration +from tests.common import MockConfigEntry + async def test_setup_entry(recorder_mock: Recorder, hass: HomeAssistant) -> None: """Test setup entry.""" @@ -83,3 +101,73 @@ async def test_multiple_queries(hass: HomeAssistant) -> None: """Test multiple queries.""" with pytest.raises(vol.Invalid): validate_sql_select("SELECT 5 as value; UPDATE states SET state = 10;") + + +async def test_migration_from_future( + recorder_mock: Recorder, hass: HomeAssistant +) -> None: + """Test migration from future version fails.""" + config_entry = MockConfigEntry( + title="Test future", + domain=DOMAIN, + source=SOURCE_USER, + data={}, + options={ + CONF_QUERY: "SELECT 5.01 as value", + CONF_COLUMN_NAME: "value", + CONF_ADVANCED_OPTIONS: {}, + }, + entry_id="1", + version=3, + ) + + config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert config_entry.state is ConfigEntryState.MIGRATION_ERROR + + +async def test_migration_from_v1_to_v2( + recorder_mock: Recorder, hass: HomeAssistant +) -> None: + """Test migration from version 1 to 2.""" + config_entry = MockConfigEntry( + title="Test migration", + domain=DOMAIN, + source=SOURCE_USER, + data={}, + options={ + CONF_DB_URL: "sqlite://", + CONF_NAME: "Test migration", + CONF_QUERY: "SELECT 5.01 as value", + CONF_COLUMN_NAME: "value", + CONF_VALUE_TEMPLATE: "{{ value | int }}", + CONF_UNIT_OF_MEASUREMENT: "MiB", + CONF_DEVICE_CLASS: SensorDeviceClass.DATA_SIZE, + CONF_STATE_CLASS: SensorStateClass.MEASUREMENT, + }, + entry_id="1", + version=1, + ) + + config_entry.add_to_hass(hass) + await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + assert config_entry.state is ConfigEntryState.LOADED + + assert config_entry.data == {} + assert config_entry.options == { + CONF_QUERY: "SELECT 5.01 as value", + CONF_COLUMN_NAME: "value", + CONF_ADVANCED_OPTIONS: { + CONF_VALUE_TEMPLATE: "{{ value | int }}", + CONF_UNIT_OF_MEASUREMENT: "MiB", + CONF_DEVICE_CLASS: SensorDeviceClass.DATA_SIZE, + CONF_STATE_CLASS: SensorStateClass.MEASUREMENT, + }, + } + + state = hass.states.get("sensor.test_migration") + assert state.state == "5"