From 6ec8e17e7b09449cd2a25f80c21732e8753b1e71 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 7 Apr 2021 09:39:39 +0200 Subject: [PATCH] Do not activate Met.no without setting a Home coordinates (#48741) --- homeassistant/components/met/__init__.py | 21 ++++++++++++- homeassistant/components/met/config_flow.py | 16 +++++++++- homeassistant/components/met/const.py | 3 ++ homeassistant/components/met/strings.json | 7 ++++- tests/components/met/__init__.py | 12 +++++--- tests/components/met/test_config_flow.py | 20 ++++++++++++ tests/components/met/test_init.py | 34 +++++++++++++++++++-- 7 files changed, 104 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/met/__init__.py b/homeassistant/components/met/__init__.py index d89ab3242d8..47d946b92e7 100644 --- a/homeassistant/components/met/__init__.py +++ b/homeassistant/components/met/__init__.py @@ -19,7 +19,12 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, Upda from homeassistant.util.distance import convert as convert_distance import homeassistant.util.dt as dt_util -from .const import CONF_TRACK_HOME, DOMAIN +from .const import ( + CONF_TRACK_HOME, + DEFAULT_HOME_LATITUDE, + DEFAULT_HOME_LONGITUDE, + DOMAIN, +) URL = "https://aa015h6buqvih86i1.api.met.no/weatherapi/locationforecast/2.0/complete" @@ -35,6 +40,20 @@ async def async_setup(hass: HomeAssistant, config: Config) -> bool: async def async_setup_entry(hass, config_entry): """Set up Met as config entry.""" + # Don't setup if tracking home location and latitude or longitude isn't set. + # Also, filters out our onboarding default location. + if config_entry.data.get(CONF_TRACK_HOME, False) and ( + (not hass.config.latitude and not hass.config.longitude) + or ( + hass.config.latitude == DEFAULT_HOME_LATITUDE + and hass.config.longitude == DEFAULT_HOME_LONGITUDE + ) + ): + _LOGGER.warning( + "Skip setting up met.no integration; No Home location has been set" + ) + return False + coordinator = MetDataUpdateCoordinator(hass, config_entry) await coordinator.async_config_entry_first_refresh() diff --git a/homeassistant/components/met/config_flow.py b/homeassistant/components/met/config_flow.py index b9d50ba59a5..5cfd71ea801 100644 --- a/homeassistant/components/met/config_flow.py +++ b/homeassistant/components/met/config_flow.py @@ -10,7 +10,13 @@ from homeassistant.const import CONF_ELEVATION, CONF_LATITUDE, CONF_LONGITUDE, C from homeassistant.core import callback import homeassistant.helpers.config_validation as cv -from .const import CONF_TRACK_HOME, DOMAIN, HOME_LOCATION_NAME +from .const import ( + CONF_TRACK_HOME, + DEFAULT_HOME_LATITUDE, + DEFAULT_HOME_LONGITUDE, + DOMAIN, + HOME_LOCATION_NAME, +) @callback @@ -81,6 +87,14 @@ class MetFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): async def async_step_onboarding(self, data=None): """Handle a flow initialized by onboarding.""" + # Don't create entry if latitude or longitude isn't set. + # Also, filters out our onboarding default location. + if (not self.hass.config.latitude and not self.hass.config.longitude) or ( + self.hass.config.latitude == DEFAULT_HOME_LATITUDE + and self.hass.config.longitude == DEFAULT_HOME_LONGITUDE + ): + return self.async_abort(reason="no_home") + return self.async_create_entry( title=HOME_LOCATION_NAME, data={CONF_TRACK_HOME: True} ) diff --git a/homeassistant/components/met/const.py b/homeassistant/components/met/const.py index b78c412393d..0f4c22dbba3 100644 --- a/homeassistant/components/met/const.py +++ b/homeassistant/components/met/const.py @@ -34,6 +34,9 @@ HOME_LOCATION_NAME = "Home" CONF_TRACK_HOME = "track_home" +DEFAULT_HOME_LATITUDE = 52.3731339 +DEFAULT_HOME_LONGITUDE = 4.8903147 + ENTITY_ID_SENSOR_FORMAT_HOME = f"{WEATHER_DOMAIN}.met_{HOME_LOCATION_NAME}" CONDITIONS_MAP = { diff --git a/homeassistant/components/met/strings.json b/homeassistant/components/met/strings.json index b9e94aba865..b9d251e21d8 100644 --- a/homeassistant/components/met/strings.json +++ b/homeassistant/components/met/strings.json @@ -12,6 +12,11 @@ } } }, - "error": { "already_configured": "[%key:common::config_flow::abort::already_configured_service%]" } + "error": { + "already_configured": "[%key:common::config_flow::abort::already_configured_service%]" + }, + "abort": { + "no_home": "No home coordinates are set in the Home Assistant configuration" + } } } diff --git a/tests/components/met/__init__.py b/tests/components/met/__init__.py index 13b186f3b47..0a17b415965 100644 --- a/tests/components/met/__init__.py +++ b/tests/components/met/__init__.py @@ -1,20 +1,24 @@ """Tests for Met.no.""" from unittest.mock import patch -from homeassistant.components.met.const import DOMAIN +from homeassistant.components.met.const import CONF_TRACK_HOME, DOMAIN from homeassistant.const import CONF_ELEVATION, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME from tests.common import MockConfigEntry -async def init_integration(hass) -> MockConfigEntry: +async def init_integration(hass, track_home=False) -> MockConfigEntry: """Set up the Met integration in Home Assistant.""" entry_data = { CONF_NAME: "test", CONF_LATITUDE: 0, - CONF_LONGITUDE: 0, - CONF_ELEVATION: 0, + CONF_LONGITUDE: 1.0, + CONF_ELEVATION: 1.0, } + + if track_home: + entry_data = {CONF_TRACK_HOME: True} + entry = MockConfigEntry(domain=DOMAIN, data=entry_data) with patch( "homeassistant.components.met.metno.MetWeatherData.fetching_data", diff --git a/tests/components/met/test_config_flow.py b/tests/components/met/test_config_flow.py index 622475e8376..25e123f67e8 100644 --- a/tests/components/met/test_config_flow.py +++ b/tests/components/met/test_config_flow.py @@ -4,6 +4,7 @@ from unittest.mock import patch import pytest from homeassistant.components.met.const import DOMAIN, HOME_LOCATION_NAME +from homeassistant.config import async_process_ha_core_config from homeassistant.const import CONF_ELEVATION, CONF_LATITUDE, CONF_LONGITUDE from tests.common import MockConfigEntry @@ -106,6 +107,25 @@ async def test_onboarding_step(hass): assert result["data"] == {"track_home": True} +@pytest.mark.parametrize("latitude,longitude", [(52.3731339, 4.8903147), (0.0, 0.0)]) +async def test_onboarding_step_abort_no_home(hass, latitude, longitude): + """Test entry not created when default step fails.""" + await async_process_ha_core_config( + hass, + {"latitude": latitude, "longitude": longitude}, + ) + + assert hass.config.latitude == latitude + assert hass.config.longitude == longitude + + result = await hass.config_entries.flow.async_init( + DOMAIN, context={"source": "onboarding"}, data={} + ) + + assert result["type"] == "abort" + assert result["reason"] == "no_home" + + async def test_import_step(hass): """Test initializing via import step.""" test_data = { diff --git a/tests/components/met/test_init.py b/tests/components/met/test_init.py index a3323f01565..074293249c8 100644 --- a/tests/components/met/test_init.py +++ b/tests/components/met/test_init.py @@ -1,6 +1,15 @@ """Test the Met integration init.""" -from homeassistant.components.met.const import DOMAIN -from homeassistant.config_entries import ENTRY_STATE_LOADED, ENTRY_STATE_NOT_LOADED +from homeassistant.components.met.const import ( + DEFAULT_HOME_LATITUDE, + DEFAULT_HOME_LONGITUDE, + DOMAIN, +) +from homeassistant.config import async_process_ha_core_config +from homeassistant.config_entries import ( + ENTRY_STATE_LOADED, + ENTRY_STATE_NOT_LOADED, + ENTRY_STATE_SETUP_ERROR, +) from . import init_integration @@ -17,3 +26,24 @@ async def test_unload_entry(hass): assert entry.state == ENTRY_STATE_NOT_LOADED assert not hass.data.get(DOMAIN) + + +async def test_fail_default_home_entry(hass, caplog): + """Test abort setup of default home location.""" + await async_process_ha_core_config( + hass, + {"latitude": 52.3731339, "longitude": 4.8903147}, + ) + + assert hass.config.latitude == DEFAULT_HOME_LATITUDE + assert hass.config.longitude == DEFAULT_HOME_LONGITUDE + + entry = await init_integration(hass, track_home=True) + + assert len(hass.config_entries.async_entries(DOMAIN)) == 1 + assert entry.state == ENTRY_STATE_SETUP_ERROR + + assert ( + "Skip setting up met.no integration; No Home location has been set" + in caplog.text + )