Add config flow to nws and remove yaml configuration (#34267)

* add config flow to nws and remove yaml

* Don't duplicate scan_time

Co-Authored-By: J. Nick Koston <nick@koston.org>

* Use _abort_if_unique_id_configured

Co-Authored-By: J. Nick Koston <nick@koston.org>

* fix abort

* Add unavailable tests

* update and use better strings

* lint

Co-authored-by: J. Nick Koston <nick@koston.org>
pull/34289/head
MatthewFlamm 2020-04-16 10:15:55 -04:00 committed by GitHub
parent 5617e6913b
commit 6d812bd957
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 401 additions and 155 deletions

View File

@ -0,0 +1,24 @@
{
"config": {
"abort": {
"already_configured": "Device is already configured"
},
"error": {
"cannot_connect": "Failed to connect, please try again",
"unknown": "Unexpected error"
},
"step": {
"user": {
"data": {
"api_key": "API key (email)",
"latitude": "Latitude",
"longitude": "Longitude",
"station": "METAR station code"
},
"description": "If a METAR station code is not specified, the latitude and longitude will be used to find the closest station.",
"title": "Connect to the National Weather Service"
}
}
},
"title": "National Weather Service (NWS)"
}

View File

@ -7,9 +7,9 @@ import aiohttp
from pynws import SimpleNWS
import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE
from homeassistant.core import HomeAssistant
from homeassistant.helpers import discovery
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_send
@ -52,38 +52,53 @@ def signal_unique_id(latitude, longitude):
async def async_setup(hass: HomeAssistant, config: dict):
"""Set up the National Weather Service integration."""
if DOMAIN not in config:
return True
hass.data[DOMAIN] = hass.data.get(DOMAIN, {})
for entry in config[DOMAIN]:
latitude = entry.get(CONF_LATITUDE, hass.config.latitude)
longitude = entry.get(CONF_LONGITUDE, hass.config.longitude)
api_key = entry[CONF_API_KEY]
client_session = async_get_clientsession(hass)
if base_unique_id(latitude, longitude) in hass.data[DOMAIN]:
_LOGGER.error(
"Duplicate entry in config: latitude %s latitude: %s",
latitude,
longitude,
)
continue
nws_data = NwsData(hass, latitude, longitude, api_key, client_session)
hass.data[DOMAIN][base_unique_id(latitude, longitude)] = nws_data
async_track_time_interval(hass, nws_data.async_update, DEFAULT_SCAN_INTERVAL)
for component in PLATFORMS:
hass.async_create_task(
discovery.async_load_platform(hass, component, DOMAIN, entry, config)
)
"""Set up the National Weather Service (NWS) component."""
hass.data.setdefault(DOMAIN, {})
return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Set up a National Weather Service entry."""
latitude = entry.data[CONF_LATITUDE]
longitude = entry.data[CONF_LONGITUDE]
api_key = entry.data[CONF_API_KEY]
station = entry.data[CONF_STATION]
client_session = async_get_clientsession(hass)
nws_data = NwsData(hass, latitude, longitude, api_key, client_session)
hass.data[DOMAIN][entry.entry_id] = nws_data
# async_set_station only does IO when station is None
await nws_data.async_set_station(station)
await nws_data.async_update()
async_track_time_interval(hass, nws_data.async_update, DEFAULT_SCAN_INTERVAL)
for component in PLATFORMS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, component)
)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Unload a config entry."""
unload_ok = all(
await asyncio.gather(
*[
hass.config_entries.async_forward_entry_unload(entry, component)
for component in PLATFORMS
]
)
)
if unload_ok:
hass.data[DOMAIN].pop(entry.entry_id)
if len(hass.data[DOMAIN]) == 0:
hass.data.pop(DOMAIN)
return unload_ok
class NwsData:
"""Data class for National Weather Service integration."""

View File

@ -0,0 +1,84 @@
"""Config flow for National Weather Service (NWS) integration."""
import logging
import aiohttp
import voluptuous as vol
from homeassistant import config_entries, core, exceptions
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from . import NwsData, base_unique_id
from .const import CONF_STATION, DOMAIN # pylint:disable=unused-import
_LOGGER = logging.getLogger(__name__)
async def validate_input(hass: core.HomeAssistant, data):
"""Validate the user input allows us to connect.
Data has the keys from DATA_SCHEMA with values provided by the user.
"""
latitude = data[CONF_LATITUDE]
longitude = data[CONF_LONGITUDE]
api_key = data[CONF_API_KEY]
station = data.get(CONF_STATION)
client_session = async_get_clientsession(hass)
ha_api_key = f"{api_key} homeassistant"
nws = NwsData(hass, latitude, longitude, ha_api_key, client_session)
try:
await nws.async_set_station(station)
except aiohttp.ClientError as err:
_LOGGER.error("Could not connect: %s", err)
raise CannotConnect
return {"title": nws.station}
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for National Weather Service (NWS)."""
VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
async def async_step_user(self, user_input=None):
"""Handle the initial step."""
errors = {}
if user_input is not None:
await self.async_set_unique_id(
base_unique_id(user_input[CONF_LATITUDE], user_input[CONF_LONGITUDE])
)
self._abort_if_unique_id_configured()
try:
info = await validate_input(self.hass, user_input)
user_input[CONF_STATION] = info["title"]
return self.async_create_entry(title=info["title"], data=user_input)
except CannotConnect:
errors["base"] = "cannot_connect"
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
data_schema = vol.Schema(
{
vol.Required(CONF_API_KEY): str,
vol.Required(
CONF_LATITUDE, default=self.hass.config.latitude
): cv.latitude,
vol.Required(
CONF_LONGITUDE, default=self.hass.config.longitude
): cv.longitude,
vol.Optional(CONF_STATION): str,
}
)
return self.async_show_form(
step_id="user", data_schema=data_schema, errors=errors
)
class CannotConnect(exceptions.HomeAssistantError):
"""Error to indicate we cannot connect."""

View File

@ -52,3 +52,6 @@ CONDITION_CLASSES = {
"cloudy": ["Mostly cloudy", "Overcast"],
"partlycloudy": ["A few clouds", "Partly cloudy"],
}
DAYNIGHT = "daynight"
HOURLY = "hourly"

View File

@ -4,5 +4,6 @@
"documentation": "https://www.home-assistant.io/integrations/nws",
"codeowners": ["@MatthewFlamm"],
"requirements": ["pynws==0.10.4"],
"quality_scale": "silver"
"quality_scale": "silver",
"config_flow": true
}

View File

@ -0,0 +1,24 @@
{
"title": "National Weather Service (NWS)",
"config": {
"step": {
"user": {
"description": "If a METAR station code is not specified, the latitude and longitude will be used to find the closest station.",
"title": "Connect to the National Weather Service",
"data": {
"api_key": "API key (email)",
"latitude": "Latitude",
"longitude": "Longitude",
"station": "METAR station code"
}
}
},
"error": {
"cannot_connect": "Failed to connect, please try again",
"unknown": "Unexpected error"
},
"abort": {
"already_configured": "Device is already configured"
}
}
}

View File

@ -1,9 +1,6 @@
"""Support for NWS weather service."""
import asyncio
import logging
import aiohttp
from homeassistant.components.weather import (
ATTR_FORECAST_CONDITION,
ATTR_FORECAST_TEMP,
@ -13,8 +10,6 @@ from homeassistant.components.weather import (
WeatherEntity,
)
from homeassistant.const import (
CONF_LATITUDE,
CONF_LONGITUDE,
LENGTH_KILOMETERS,
LENGTH_METERS,
LENGTH_MILES,
@ -25,8 +20,8 @@ from homeassistant.const import (
TEMP_FAHRENHEIT,
)
from homeassistant.core import callback
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
from homeassistant.util.distance import convert as convert_distance
from homeassistant.util.pressure import convert as convert_pressure
from homeassistant.util.temperature import convert as convert_temperature
@ -38,8 +33,9 @@ from .const import (
ATTR_FORECAST_PRECIP_PROB,
ATTRIBUTION,
CONDITION_CLASSES,
CONF_STATION,
DAYNIGHT,
DOMAIN,
HOURLY,
)
_LOGGER = logging.getLogger(__name__)
@ -73,28 +69,15 @@ def convert_condition(time, weather):
return cond, max(prec_probs)
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
async def async_setup_entry(
hass: HomeAssistantType, entry: ConfigType, async_add_entities
) -> None:
"""Set up the NWS weather platform."""
if discovery_info is None:
return
latitude = discovery_info.get(CONF_LATITUDE, hass.config.latitude)
longitude = discovery_info.get(CONF_LONGITUDE, hass.config.longitude)
station = discovery_info.get(CONF_STATION)
nws_data = hass.data[DOMAIN][base_unique_id(latitude, longitude)]
try:
await nws_data.async_set_station(station)
except (aiohttp.ClientError, asyncio.TimeoutError) as err:
_LOGGER.error("Error automatically setting station: %s", str(err))
raise PlatformNotReady
await nws_data.async_update()
nws_data = hass.data[DOMAIN][entry.entry_id]
async_add_entities(
[
NWSWeather(nws_data, "daynight", hass.config.units),
NWSWeather(nws_data, "hourly", hass.config.units),
NWSWeather(nws_data, DAYNIGHT, hass.config.units),
NWSWeather(nws_data, HOURLY, hass.config.units),
],
False,
)
@ -131,7 +114,7 @@ class NWSWeather(WeatherEntity):
def _update_callback(self) -> None:
"""Load data from integration."""
self.observation = self.nws.observation
if self.mode == "daynight":
if self.mode == DAYNIGHT:
self._forecast = self.nws.forecast
else:
self._forecast = self.nws.forecast_hourly
@ -259,7 +242,7 @@ class NWSWeather(WeatherEntity):
ATTR_FORECAST_TIME: forecast_entry.get("startTime"),
}
if self.mode == "daynight":
if self.mode == DAYNIGHT:
data[ATTR_FORECAST_DAYTIME] = forecast_entry.get("isDaytime")
time = forecast_entry.get("iconTime")
weather = forecast_entry.get("iconWeather")
@ -292,7 +275,7 @@ class NWSWeather(WeatherEntity):
@property
def available(self):
"""Return if state is available."""
if self.mode == "daynight":
if self.mode == DAYNIGHT:
return (
self.nws.update_observation_success and self.nws.update_forecast_success
)

View File

@ -85,6 +85,7 @@ FLOWS = [
"notion",
"nuheat",
"nut",
"nws",
"opentherm_gw",
"openuv",
"owntracks",

View File

@ -1,5 +1,5 @@
"""Helpers for interacting with pynws."""
from homeassistant.components.nws.const import DOMAIN
from homeassistant.components.nws.const import CONF_STATION
from homeassistant.components.nws.weather import ATTR_FORECAST_PRECIP_PROB
from homeassistant.components.weather import (
ATTR_FORECAST_CONDITION,
@ -16,6 +16,8 @@ from homeassistant.components.weather import (
)
from homeassistant.const import (
CONF_API_KEY,
CONF_LATITUDE,
CONF_LONGITUDE,
LENGTH_KILOMETERS,
LENGTH_METERS,
LENGTH_MILES,
@ -29,7 +31,12 @@ from homeassistant.util.distance import convert as convert_distance
from homeassistant.util.pressure import convert as convert_pressure
from homeassistant.util.temperature import convert as convert_temperature
MINIMAL_CONFIG = {DOMAIN: [{CONF_API_KEY: "test"}]}
NWS_CONFIG = {
CONF_API_KEY: "test",
CONF_LATITUDE: 35,
CONF_LONGITUDE: -75,
CONF_STATION: "ABC",
}
DEFAULT_STATIONS = ["ABC", "XYZ"]

View File

@ -0,0 +1,113 @@
"""Test the National Weather Service (NWS) config flow."""
import aiohttp
from asynctest import patch
from homeassistant import config_entries, setup
from homeassistant.components.nws.const import DOMAIN
async def test_form(hass, mock_simple_nws):
"""Test we get the form."""
hass.config.latitude = 35
hass.config.longitude = -90
await setup.async_setup_component(hass, "persistent_notification", {})
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
assert result["type"] == "form"
assert result["errors"] == {}
with patch(
"homeassistant.components.nws.async_setup", return_value=True
) as mock_setup, patch(
"homeassistant.components.nws.async_setup_entry", return_value=True,
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], {"api_key": "test"}
)
assert result2["type"] == "create_entry"
assert result2["title"] == "ABC"
assert result2["data"] == {
"api_key": "test",
"latitude": 35,
"longitude": -90,
"station": "ABC",
}
await hass.async_block_till_done()
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1
async def test_form_cannot_connect(hass, mock_simple_nws):
"""Test we handle cannot connect error."""
mock_instance = mock_simple_nws.return_value
mock_instance.set_station.side_effect = aiohttp.ClientError
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], {"api_key": "test"},
)
assert result2["type"] == "form"
assert result2["errors"] == {"base": "cannot_connect"}
async def test_form_unknown_error(hass, mock_simple_nws):
"""Test we handle unknown error."""
mock_instance = mock_simple_nws.return_value
mock_instance.set_station.side_effect = ValueError
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], {"api_key": "test"},
)
assert result2["type"] == "form"
assert result2["errors"] == {"base": "unknown"}
async def test_form_already_configured(hass, mock_simple_nws):
"""Test we handle duplicate entries."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"homeassistant.components.nws.async_setup", return_value=True
) as mock_setup, patch(
"homeassistant.components.nws.async_setup_entry", return_value=True,
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], {"api_key": "test"},
)
assert result2["type"] == "create_entry"
await hass.async_block_till_done()
assert len(mock_setup.mock_calls) == 1
assert len(mock_setup_entry.mock_calls) == 1
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"homeassistant.components.nws.async_setup", return_value=True
) as mock_setup, patch(
"homeassistant.components.nws.async_setup_entry", return_value=True,
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], {"api_key": "test"},
)
assert result2["type"] == "abort"
assert result2["reason"] == "already_configured"
await hass.async_block_till_done()
assert len(mock_setup.mock_calls) == 0
assert len(mock_setup_entry.mock_calls) == 0

View File

@ -1,92 +1,26 @@
"""Tests for init module."""
from homeassistant.components import nws
from homeassistant.components.nws.const import CONF_STATION, DOMAIN
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE
from homeassistant.setup import async_setup_component
from homeassistant.components.nws.const import DOMAIN
from homeassistant.components.weather import DOMAIN as WEATHER_DOMAIN
from tests.common import assert_setup_component
from tests.components.nws.const import MINIMAL_CONFIG
LATLON_CONFIG = {
DOMAIN: [{CONF_API_KEY: "test", CONF_LATITUDE: 45.0, CONF_LONGITUDE: -75.0}]
}
FULL_CONFIG = {
DOMAIN: [
{
CONF_API_KEY: "test",
CONF_LATITUDE: 45.0,
CONF_LONGITUDE: -75.0,
CONF_STATION: "XYZ",
}
]
}
DUPLICATE_CONFIG = {
DOMAIN: [
{CONF_API_KEY: "test", CONF_LATITUDE: 45.0, CONF_LONGITUDE: -75.0},
{CONF_API_KEY: "test", CONF_LATITUDE: 45.0, CONF_LONGITUDE: -75.0},
]
}
from tests.common import MockConfigEntry
from tests.components.nws.const import NWS_CONFIG
async def test_no_config(hass, mock_simple_nws):
"""Test that nws does not setup with no config."""
with assert_setup_component(0):
assert await async_setup_component(hass, DOMAIN, {})
await hass.async_block_till_done()
async def test_unload_entry(hass, mock_simple_nws):
"""Test that nws setup with config yaml."""
entry = MockConfigEntry(domain=DOMAIN, data=NWS_CONFIG,)
entry.add_to_hass(hass)
entity_registry = await hass.helpers.entity_registry.async_get_registry()
assert len(entity_registry.entities) == 0
assert DOMAIN not in hass.data
async def test_successful_minimal_config(hass, mock_simple_nws):
"""Test that nws setup with minimal config."""
hass.config.latitude = 40.0
hass.config.longitude = -75.0
with assert_setup_component(1, DOMAIN):
assert await async_setup_component(hass, DOMAIN, MINIMAL_CONFIG)
await hass.async_block_till_done()
entity_registry = await hass.helpers.entity_registry.async_get_registry()
assert len(entity_registry.entities) == 2
assert DOMAIN in hass.data
assert nws.base_unique_id(40.0, -75.0) in hass.data[DOMAIN]
async def test_successful_latlon_config(hass, mock_simple_nws):
"""Test that nws setup with latlon config."""
with assert_setup_component(1, DOMAIN):
assert await async_setup_component(hass, DOMAIN, LATLON_CONFIG)
await hass.async_block_till_done()
entity_registry = await hass.helpers.entity_registry.async_get_registry()
assert len(entity_registry.entities) == 2
assert DOMAIN in hass.data
assert nws.base_unique_id(45.0, -75.0) in hass.data[DOMAIN]
async def test_successful_full_config(hass, mock_simple_nws):
"""Test that nws setup with full config."""
with assert_setup_component(1, DOMAIN):
assert await async_setup_component(hass, DOMAIN, FULL_CONFIG)
await hass.async_block_till_done()
entity_registry = await hass.helpers.entity_registry.async_get_registry()
assert len(entity_registry.entities) == 2
assert DOMAIN in hass.data
assert nws.base_unique_id(45.0, -75.0) in hass.data[DOMAIN]
async def test_unsuccessful_duplicate_config(hass, mock_simple_nws):
"""Test that nws setup with duplicate config."""
assert await async_setup_component(hass, DOMAIN, DUPLICATE_CONFIG)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
entity_registry = await hass.helpers.entity_registry.async_get_registry()
assert len(entity_registry.entities) == 2
assert len(hass.states.async_entity_ids(WEATHER_DOMAIN)) == 2
assert DOMAIN in hass.data
assert len(hass.data[DOMAIN]) == 1
entries = hass.config_entries.async_entries(DOMAIN)
assert len(entries) == 1
assert await hass.config_entries.async_unload(entries[0].entry_id)
assert len(hass.states.async_entity_ids(WEATHER_DOMAIN)) == 0
assert DOMAIN not in hass.data

View File

@ -6,19 +6,18 @@ import pytest
from homeassistant.components import nws
from homeassistant.components.weather import ATTR_FORECAST
from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util
from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM
from tests.common import async_fire_time_changed
from tests.common import MockConfigEntry, async_fire_time_changed
from tests.components.nws.const import (
EXPECTED_FORECAST_IMPERIAL,
EXPECTED_FORECAST_METRIC,
EXPECTED_OBSERVATION_IMPERIAL,
EXPECTED_OBSERVATION_METRIC,
MINIMAL_CONFIG,
NONE_FORECAST,
NONE_OBSERVATION,
NWS_CONFIG,
)
@ -34,7 +33,9 @@ async def test_imperial_metric(
):
"""Test with imperial and metric units."""
hass.config.units = units
assert await async_setup_component(hass, nws.DOMAIN, MINIMAL_CONFIG)
entry = MockConfigEntry(domain=nws.DOMAIN, data=NWS_CONFIG,)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get("weather.abc_hourly")
@ -73,7 +74,9 @@ async def test_none_values(hass, mock_simple_nws):
instance.observation = NONE_OBSERVATION
instance.forecast = NONE_FORECAST
assert await async_setup_component(hass, nws.DOMAIN, MINIMAL_CONFIG)
entry = MockConfigEntry(domain=nws.DOMAIN, data=NWS_CONFIG,)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get("weather.abc_daynight")
@ -93,7 +96,9 @@ async def test_none(hass, mock_simple_nws):
instance.observation = None
instance.forecast = None
assert await async_setup_component(hass, nws.DOMAIN, MINIMAL_CONFIG)
entry = MockConfigEntry(domain=nws.DOMAIN, data=NWS_CONFIG,)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get("weather.abc_daynight")
@ -114,7 +119,9 @@ async def test_error_station(hass, mock_simple_nws):
instance = mock_simple_nws.return_value
instance.set_station.side_effect = aiohttp.ClientError
assert await async_setup_component(hass, nws.DOMAIN, MINIMAL_CONFIG) is True
entry = MockConfigEntry(domain=nws.DOMAIN, data=NWS_CONFIG,)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert hass.states.get("weather.abc_hourly") is None
@ -126,9 +133,21 @@ async def test_error_observation(hass, mock_simple_nws, caplog):
instance = mock_simple_nws.return_value
instance.update_observation.side_effect = aiohttp.ClientError
assert await async_setup_component(hass, nws.DOMAIN, MINIMAL_CONFIG)
entry = MockConfigEntry(domain=nws.DOMAIN, data=NWS_CONFIG,)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
instance.update_observation.assert_called_once()
state = hass.states.get("weather.abc_daynight")
assert state
assert state.state == "unavailable"
state = hass.states.get("weather.abc_hourly")
assert state
assert state.state == "unavailable"
assert "Error updating observation for station ABC" in caplog.text
assert "Success updating observation for station ABC" not in caplog.text
caplog.clear()
@ -139,6 +158,16 @@ async def test_error_observation(hass, mock_simple_nws, caplog):
async_fire_time_changed(hass, future_time)
await hass.async_block_till_done()
assert instance.update_observation.call_count == 2
state = hass.states.get("weather.abc_daynight")
assert state
assert state.state == "sunny"
state = hass.states.get("weather.abc_hourly")
assert state
assert state.state == "sunny"
assert "Error updating observation for station ABC" not in caplog.text
assert "Success updating observation for station ABC" in caplog.text
@ -148,9 +177,17 @@ async def test_error_forecast(hass, caplog, mock_simple_nws):
instance = mock_simple_nws.return_value
instance.update_forecast.side_effect = aiohttp.ClientError
assert await async_setup_component(hass, nws.DOMAIN, MINIMAL_CONFIG)
entry = MockConfigEntry(domain=nws.DOMAIN, data=NWS_CONFIG,)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
instance.update_forecast.assert_called_once()
state = hass.states.get("weather.abc_daynight")
assert state
assert state.state == "unavailable"
assert "Error updating forecast for station ABC" in caplog.text
assert "Success updating forecast for station ABC" not in caplog.text
caplog.clear()
@ -161,6 +198,12 @@ async def test_error_forecast(hass, caplog, mock_simple_nws):
async_fire_time_changed(hass, future_time)
await hass.async_block_till_done()
assert instance.update_forecast.call_count == 2
state = hass.states.get("weather.abc_daynight")
assert state
assert state.state == "sunny"
assert "Error updating forecast for station ABC" not in caplog.text
assert "Success updating forecast for station ABC" in caplog.text
@ -170,9 +213,17 @@ async def test_error_forecast_hourly(hass, caplog, mock_simple_nws):
instance = mock_simple_nws.return_value
instance.update_forecast_hourly.side_effect = aiohttp.ClientError
assert await async_setup_component(hass, nws.DOMAIN, MINIMAL_CONFIG)
entry = MockConfigEntry(domain=nws.DOMAIN, data=NWS_CONFIG,)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get("weather.abc_hourly")
assert state
assert state.state == "unavailable"
instance.update_forecast_hourly.assert_called_once()
assert "Error updating forecast_hourly for station ABC" in caplog.text
assert "Success updating forecast_hourly for station ABC" not in caplog.text
caplog.clear()
@ -183,5 +234,11 @@ async def test_error_forecast_hourly(hass, caplog, mock_simple_nws):
async_fire_time_changed(hass, future_time)
await hass.async_block_till_done()
assert instance.update_forecast_hourly.call_count == 2
state = hass.states.get("weather.abc_hourly")
assert state
assert state.state == "sunny"
assert "Error updating forecast_hourly for station ABC" not in caplog.text
assert "Success updating forecast_hourly for station ABC" in caplog.text