From c17f08a3f543e63da66d5a10156776ee150c5f11 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Thu, 17 Aug 2023 19:41:11 +0200 Subject: [PATCH] Create a single entity for new met.no config entries (#98098) * Create a single entity for new met.no config entries * Fix lying docstring * Fix test --- homeassistant/components/met/weather.py | 55 +++++++++++++++---------- tests/components/met/test_weather.py | 50 ++++++++++++---------- 2 files changed, 61 insertions(+), 44 deletions(-) diff --git a/homeassistant/components/met/weather.py b/homeassistant/components/met/weather.py index 2fcde1e05f0..e7aea21875a 100644 --- a/homeassistant/components/met/weather.py +++ b/homeassistant/components/met/weather.py @@ -15,6 +15,7 @@ from homeassistant.components.weather import ( ATTR_WEATHER_WIND_BEARING, ATTR_WEATHER_WIND_GUST_SPEED, ATTR_WEATHER_WIND_SPEED, + DOMAIN as WEATHER_DOMAIN, Forecast, WeatherEntity, WeatherEntityFeature, @@ -30,6 +31,7 @@ from homeassistant.const import ( UnitOfTemperature, ) from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers import entity_registry as er from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity @@ -48,19 +50,38 @@ async def async_setup_entry( ) -> None: """Add a weather entity from a config_entry.""" coordinator: MetDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id] - async_add_entities( - [ - MetWeather( - coordinator, - config_entry.data, - hass.config.units is METRIC_SYSTEM, - False, - ), + entity_registry = er.async_get(hass) + + entities = [ + MetWeather( + coordinator, config_entry.data, hass.config.units is METRIC_SYSTEM, False + ) + ] + + # Add hourly entity to legacy config entries + if entity_registry.async_get_entity_id( + WEATHER_DOMAIN, + DOMAIN, + _calculate_unique_id(config_entry.data, True), + ): + entities.append( MetWeather( coordinator, config_entry.data, hass.config.units is METRIC_SYSTEM, True - ), - ] - ) + ) + ) + + async_add_entities(entities) + + +def _calculate_unique_id(config: MappingProxyType[str, Any], hourly: bool) -> str: + """Calculate unique ID.""" + name_appendix = "" + if hourly: + name_appendix = "-hourly" + if config.get(CONF_TRACK_HOME): + return f"home{name_appendix}" + + return f"{config[CONF_LATITUDE]}-{config[CONF_LONGITUDE]}{name_appendix}" def format_condition(condition: str) -> str: @@ -96,6 +117,7 @@ class MetWeather(CoordinatorEntity[MetDataUpdateCoordinator], WeatherEntity): ) -> None: """Initialise the platform with a data instance and site.""" super().__init__(coordinator) + self._attr_unique_id = _calculate_unique_id(config, hourly) self._config = config self._is_metric = is_metric self._hourly = hourly @@ -105,17 +127,6 @@ class MetWeather(CoordinatorEntity[MetDataUpdateCoordinator], WeatherEntity): """Return if we are tracking home.""" return self._config.get(CONF_TRACK_HOME, False) - @property - def unique_id(self) -> str: - """Return unique ID.""" - name_appendix = "" - if self._hourly: - name_appendix = "-hourly" - if self.track_home: - return f"home{name_appendix}" - - return f"{self._config[CONF_LATITUDE]}-{self._config[CONF_LONGITUDE]}{name_appendix}" - @property def name(self) -> str: """Return the name of the sensor.""" diff --git a/tests/components/met/test_weather.py b/tests/components/met/test_weather.py index 2941935fcfc..5a28b8eceb0 100644 --- a/tests/components/met/test_weather.py +++ b/tests/components/met/test_weather.py @@ -6,6 +6,33 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er +async def test_new_config_entry(hass: HomeAssistant, mock_weather) -> None: + """Test the expected entities are created.""" + registry = er.async_get(hass) + await hass.config_entries.flow.async_init("met", context={"source": "onboarding"}) + await hass.async_block_till_done() + assert len(hass.states.async_entity_ids("weather")) == 1 + + entry = hass.config_entries.async_entries()[0] + assert len(er.async_entries_for_config_entry(registry, entry.entry_id)) == 1 + + +async def test_legacy_config_entry(hass: HomeAssistant, mock_weather) -> None: + """Test the expected entities are created.""" + registry = er.async_get(hass) + registry.async_get_or_create( + WEATHER_DOMAIN, + DOMAIN, + "home-hourly", + ) + await hass.config_entries.flow.async_init("met", context={"source": "onboarding"}) + await hass.async_block_till_done() + assert len(hass.states.async_entity_ids("weather")) == 2 + + entry = hass.config_entries.async_entries()[0] + assert len(er.async_entries_for_config_entry(registry, entry.entry_id)) == 2 + + async def test_tracking_home(hass: HomeAssistant, mock_weather) -> None: """Test we track home.""" await hass.config_entries.flow.async_init("met", context={"source": "onboarding"}) @@ -13,17 +40,6 @@ async def test_tracking_home(hass: HomeAssistant, mock_weather) -> None: assert len(hass.states.async_entity_ids("weather")) == 1 assert len(mock_weather.mock_calls) == 4 - # Test the hourly sensor is disabled by default - registry = er.async_get(hass) - - state = hass.states.get("weather.forecast_test_home_hourly") - assert state is None - - entry = registry.async_get("weather.forecast_test_home_hourly") - assert entry - assert entry.disabled - assert entry.disabled_by is er.RegistryEntryDisabler.INTEGRATION - # Test we track config await hass.config.async_update(latitude=10, longitude=20) await hass.async_block_till_done() @@ -44,23 +60,13 @@ async def test_tracking_home(hass: HomeAssistant, mock_weather) -> None: async def test_not_tracking_home(hass: HomeAssistant, mock_weather) -> None: """Test when we not track home.""" - # Pre-create registry entry for disabled by default hourly weather - registry = er.async_get(hass) - registry.async_get_or_create( - WEATHER_DOMAIN, - DOMAIN, - "10-20-hourly", - suggested_object_id="forecast_somewhere_hourly", - disabled_by=None, - ) - await hass.config_entries.flow.async_init( "met", context={"source": config_entries.SOURCE_USER}, data={"name": "Somewhere", "latitude": 10, "longitude": 20, "elevation": 0}, ) await hass.async_block_till_done() - assert len(hass.states.async_entity_ids("weather")) == 2 + assert len(hass.states.async_entity_ids("weather")) == 1 assert len(mock_weather.mock_calls) == 4 # Test we do not track config