Modernize tests for smhi (#139334)

* Modernize tests for smhi

* Fixes

* Mods

* Fix weather

* Coverage 100%

* Fix init test

* Fixes

* Fixes

* Remove waits
This commit is contained in:
G Johansson 2025-05-28 10:56:07 +02:00 committed by GitHub
parent 192aa76cd7
commit 4858b2171e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 336 additions and 349 deletions

View File

@ -1,25 +1,137 @@
"""Provide common smhi fixtures."""
from __future__ import annotations
from collections.abc import AsyncGenerator, Generator
import json
from typing import Any
from unittest.mock import AsyncMock, MagicMock, patch
from pysmhi.smhi_forecast import SMHIForecast, SMHIPointForecast
import pytest
from homeassistant.components.smhi import PLATFORMS
from homeassistant.components.smhi.const import DOMAIN
from homeassistant.const import CONF_LATITUDE, CONF_LOCATION, CONF_LONGITUDE, Platform
from homeassistant.core import HomeAssistant
from tests.common import load_fixture
from . import TEST_CONFIG
from tests.common import MockConfigEntry, load_fixture
from tests.test_util.aiohttp import AiohttpClientMocker
@pytest.fixture(scope="package")
def api_response():
"""Return an API response."""
return load_fixture("smhi.json", DOMAIN)
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.smhi.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry
@pytest.fixture(scope="package")
def api_response_night():
"""Return an API response for night only."""
return load_fixture("smhi_night.json", DOMAIN)
@pytest.fixture(name="load_platforms")
async def patch_platform_constant() -> list[Platform]:
"""Return list of platforms to load."""
return PLATFORMS
@pytest.fixture(scope="package")
def api_response_lack_data():
"""Return an API response."""
return load_fixture("smhi_short.json", DOMAIN)
@pytest.fixture
async def load_int(
hass: HomeAssistant,
mock_client: SMHIPointForecast,
load_platforms: list[Platform],
) -> MockConfigEntry:
"""Set up the SMHI integration."""
hass.config.latitude = "59.32624"
hass.config.longitude = "17.84197"
config_entry = MockConfigEntry(
domain=DOMAIN,
data=TEST_CONFIG,
entry_id="01JMZDH8N5PFHGJNYKKYCSCWER",
unique_id="59.32624-17.84197",
version=3,
title="Test",
)
config_entry.add_to_hass(hass)
with patch("homeassistant.components.smhi.PLATFORMS", load_platforms):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
return config_entry
@pytest.fixture(name="mock_client")
async def get_client(
hass: HomeAssistant,
get_data: tuple[list[SMHIForecast], list[SMHIForecast], list[SMHIForecast]],
) -> AsyncGenerator[MagicMock]:
"""Mock SMHIPointForecast client."""
with (
patch(
"homeassistant.components.smhi.coordinator.SMHIPointForecast",
autospec=True,
) as mock_client,
patch(
"homeassistant.components.smhi.config_flow.SMHIPointForecast",
return_value=mock_client.return_value,
),
):
client = mock_client.return_value
client.async_get_daily_forecast.return_value = get_data[0]
client.async_get_twice_daily_forecast.return_value = get_data[1]
client.async_get_hourly_forecast.return_value = get_data[2]
yield client
@pytest.fixture(name="get_data")
async def get_data_from_library(
hass: HomeAssistant,
aioclient_mock: AiohttpClientMocker,
load_json: dict[str, Any],
) -> AsyncGenerator[tuple[list[SMHIForecast], list[SMHIForecast], list[SMHIForecast]]]:
"""Get data from api."""
client = SMHIPointForecast(
TEST_CONFIG[CONF_LOCATION][CONF_LONGITUDE],
TEST_CONFIG[CONF_LOCATION][CONF_LATITUDE],
aioclient_mock.create_session(hass.loop),
)
with patch.object(
client._api,
"async_get_data",
return_value=load_json,
):
data_daily = await client.async_get_daily_forecast()
data_twice_daily = await client.async_get_twice_daily_forecast()
data_hourly = await client.async_get_hourly_forecast()
yield (data_daily, data_twice_daily, data_hourly)
await client._api._session.close()
@pytest.fixture(name="load_json")
def load_json_from_fixture(
load_data: tuple[str, str, str],
to_load: int,
) -> dict[str, Any]:
"""Load fixture with json data and return."""
return json.loads(load_data[to_load])
@pytest.fixture(name="load_data", scope="package")
def load_data_from_fixture() -> tuple[str, str, str]:
"""Load fixture with fixture data and return."""
return (
load_fixture("smhi.json", "smhi"),
load_fixture("smhi_night.json", "smhi"),
load_fixture("smhi_short.json", "smhi"),
)
@pytest.fixture
def to_load() -> int:
"""Fixture to load."""
return 0

View File

@ -1,5 +1,5 @@
# serializer version: 1
# name: test_clear_night[clear-night_forecast]
# name: test_clear_night[1][clear-night_forecast]
dict({
'weather.smhi_test': dict({
'forecast': list([
@ -59,11 +59,11 @@
}),
})
# ---
# name: test_clear_night[clear_night]
# name: test_clear_night[1][clear_night]
ReadOnlyDict({
'attribution': 'Swedish weather institute (SMHI)',
'cloud_coverage': 100,
'friendly_name': 'test',
'friendly_name': 'Test',
'humidity': 100,
'precipitation_unit': <UnitOfPrecipitationDepth.MILLIMETERS: 'mm'>,
'pressure': 992.4,
@ -80,7 +80,7 @@
'wind_speed_unit': <UnitOfSpeed.KILOMETERS_PER_HOUR: 'km/h'>,
})
# ---
# name: test_forecast_service[get_forecasts]
# name: test_forecast_service[load_platforms0]
dict({
'weather.smhi_test': dict({
'forecast': list([
@ -218,7 +218,7 @@
}),
})
# ---
# name: test_forecast_services
# name: test_forecast_services[load_platforms0]
dict({
'cloud_coverage': 100,
'condition': 'cloudy',
@ -233,7 +233,7 @@
'wind_speed': 10.08,
})
# ---
# name: test_forecast_services.1
# name: test_forecast_services[load_platforms0].1
dict({
'cloud_coverage': 75,
'condition': 'partlycloudy',
@ -248,7 +248,7 @@
'wind_speed': 14.76,
})
# ---
# name: test_forecast_services.2
# name: test_forecast_services[load_platforms0].2
dict({
'cloud_coverage': 100,
'condition': 'fog',
@ -263,7 +263,7 @@
'wind_speed': 9.72,
})
# ---
# name: test_forecast_services.3
# name: test_forecast_services[load_platforms0].3
dict({
'cloud_coverage': 100,
'condition': 'cloudy',
@ -278,11 +278,11 @@
'wind_speed': 12.24,
})
# ---
# name: test_setup_hass
# name: test_setup_hass[load_platforms0]
ReadOnlyDict({
'attribution': 'Swedish weather institute (SMHI)',
'cloud_coverage': 100,
'friendly_name': 'test',
'friendly_name': 'Test',
'humidity': 100,
'precipitation_unit': <UnitOfPrecipitationDepth.MILLIMETERS: 'mm'>,
'pressure': 992.4,

View File

@ -2,9 +2,10 @@
from __future__ import annotations
from unittest.mock import patch
from unittest.mock import MagicMock, patch
from pysmhi import SmhiForecastException
import pytest
from homeassistant import config_entries
from homeassistant.components.smhi.const import DOMAIN
@ -16,8 +17,13 @@ from homeassistant.helpers import device_registry as dr, entity_registry as er
from tests.common import MockConfigEntry
pytestmark = pytest.mark.usefixtures("mock_setup_entry")
async def test_form(hass: HomeAssistant) -> None:
async def test_form(
hass: HomeAssistant,
mock_client: MagicMock,
) -> None:
"""Test we get the form and create an entry."""
hass.config.latitude = 0.0
@ -29,17 +35,11 @@ async def test_form(hass: HomeAssistant) -> None:
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
with (
patch(
"homeassistant.components.smhi.config_flow.SMHIPointForecast.async_get_daily_forecast",
return_value={"test": "something", "test2": "something else"},
),
patch(
"homeassistant.components.smhi.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
result2 = await hass.config_entries.flow.async_configure(
with patch(
"homeassistant.components.smhi.async_setup_entry",
return_value=True,
) as mock_setup_entry:
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
@ -48,11 +48,11 @@ async def test_form(hass: HomeAssistant) -> None:
}
},
)
await hass.async_block_till_done()
assert result2["type"] is FlowResultType.CREATE_ENTRY
assert result2["title"] == "Home"
assert result2["data"] == {
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Home"
assert result["result"].unique_id == "0.0-0.0"
assert result["data"] == {
"location": {
"latitude": 0.0,
"longitude": 0.0,
@ -61,33 +61,22 @@ async def test_form(hass: HomeAssistant) -> None:
assert len(mock_setup_entry.mock_calls) == 1
# Check title is "Weather" when not home coordinates
result3 = await hass.config_entries.flow.async_init(
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with (
patch(
"homeassistant.components.smhi.config_flow.SMHIPointForecast.async_get_daily_forecast",
return_value={"test": "something", "test2": "something else"},
),
patch(
"homeassistant.components.smhi.async_setup_entry",
return_value=True,
),
):
result4 = await hass.config_entries.flow.async_configure(
result3["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 1.0,
CONF_LONGITUDE: 1.0,
}
},
)
await hass.async_block_till_done()
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 1.0,
CONF_LONGITUDE: 1.0,
}
},
)
assert result4["type"] is FlowResultType.CREATE_ENTRY
assert result4["title"] == "Weather 1.0 1.0"
assert result4["data"] == {
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Weather 1.0 1.0"
assert result["data"] == {
"location": {
"latitude": 1.0,
"longitude": 1.0,
@ -95,55 +84,45 @@ async def test_form(hass: HomeAssistant) -> None:
}
async def test_form_invalid_coordinates(hass: HomeAssistant) -> None:
async def test_form_invalid_coordinates(
hass: HomeAssistant,
mock_client: MagicMock,
) -> None:
"""Test we handle invalid coordinates."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"homeassistant.components.smhi.config_flow.SMHIPointForecast.async_get_daily_forecast",
side_effect=SmhiForecastException,
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 0.0,
CONF_LONGITUDE: 0.0,
}
},
)
await hass.async_block_till_done()
mock_client.async_get_daily_forecast.side_effect = SmhiForecastException
assert result2["type"] is FlowResultType.FORM
assert result2["errors"] == {"base": "wrong_location"}
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 0.0,
CONF_LONGITUDE: 0.0,
}
},
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": "wrong_location"}
# Continue flow with new coordinates
with (
patch(
"homeassistant.components.smhi.config_flow.SMHIPointForecast.async_get_daily_forecast",
return_value={"test": "something", "test2": "something else"},
),
patch(
"homeassistant.components.smhi.async_setup_entry",
return_value=True,
),
):
result3 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 2.0,
CONF_LONGITUDE: 2.0,
}
},
)
await hass.async_block_till_done()
mock_client.async_get_daily_forecast.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 2.0,
CONF_LONGITUDE: 2.0,
}
},
)
assert result3["type"] is FlowResultType.CREATE_ENTRY
assert result3["title"] == "Weather 2.0 2.0"
assert result3["data"] == {
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Weather 2.0 2.0"
assert result["data"] == {
"location": {
"latitude": 2.0,
"longitude": 2.0,
@ -151,7 +130,10 @@ async def test_form_invalid_coordinates(hass: HomeAssistant) -> None:
}
async def test_form_unique_id_exist(hass: HomeAssistant) -> None:
async def test_form_unique_id_exist(
hass: HomeAssistant,
mock_client: MagicMock,
) -> None:
"""Test we handle unique id already exist."""
entry = MockConfigEntry(
domain=DOMAIN,
@ -169,27 +151,23 @@ async def test_form_unique_id_exist(hass: HomeAssistant) -> None:
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)
with patch(
"homeassistant.components.smhi.config_flow.SMHIPointForecast.async_get_daily_forecast",
return_value={"test": "something", "test2": "something else"},
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 1.0,
CONF_LONGITUDE: 1.0,
}
},
)
await hass.async_block_till_done()
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 1.0,
CONF_LONGITUDE: 1.0,
}
},
)
assert result2["type"] is FlowResultType.ABORT
assert result2["reason"] == "already_configured"
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
async def test_reconfigure_flow(
hass: HomeAssistant,
mock_client: MagicMock,
entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry,
) -> None:
@ -217,44 +195,32 @@ async def test_reconfigure_flow(
result = await entry.start_reconfigure_flow(hass)
assert result["type"] is FlowResultType.FORM
with patch(
"homeassistant.components.smhi.config_flow.SMHIPointForecast.async_get_daily_forecast",
side_effect=SmhiForecastException,
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 0.0,
CONF_LONGITUDE: 0.0,
}
},
)
await hass.async_block_till_done()
mock_client.async_get_daily_forecast.side_effect = SmhiForecastException
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 0.0,
CONF_LONGITUDE: 0.0,
}
},
)
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {"base": "wrong_location"}
with (
patch(
"homeassistant.components.smhi.config_flow.SMHIPointForecast.async_get_daily_forecast",
return_value={"test": "something", "test2": "something else"},
),
patch(
"homeassistant.components.smhi.async_setup_entry",
return_value=True,
) as mock_setup_entry,
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 58.2898,
CONF_LONGITUDE: 14.6304,
}
},
)
await hass.async_block_till_done()
mock_client.async_get_daily_forecast.side_effect = None
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
CONF_LOCATION: {
CONF_LATITUDE: 58.2898,
CONF_LONGITUDE: 14.6304,
}
},
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "reconfigure_successful"
@ -273,4 +239,3 @@ async def test_reconfigure_flow(
device = device_registry.async_get(device.id)
assert device
assert device.identifiers == {(DOMAIN, "58.2898, 14.6304")}
assert len(mock_setup_entry.mock_calls) == 1

View File

@ -1,71 +1,42 @@
"""Test SMHI component setup process."""
from pysmhi.const import API_POINT_FORECAST
from pysmhi import SMHIPointForecast
from homeassistant.components.smhi.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import ENTITY_ID, TEST_CONFIG, TEST_CONFIG_MIGRATE
from tests.common import MockConfigEntry
from tests.test_util.aiohttp import AiohttpClientMocker
async def test_setup_entry(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, api_response: str
) -> None:
"""Test setup entry."""
uri = API_POINT_FORECAST.format(
TEST_CONFIG["location"]["longitude"], TEST_CONFIG["location"]["latitude"]
)
aioclient_mock.get(uri, text=api_response)
entry = MockConfigEntry(domain=DOMAIN, title="test", data=TEST_CONFIG, version=3)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
assert state
async def test_remove_entry(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, api_response: str
async def test_load_and_unload_config_entry(
hass: HomeAssistant, load_int: MockConfigEntry
) -> None:
"""Test remove entry."""
uri = API_POINT_FORECAST.format(
TEST_CONFIG["location"]["longitude"], TEST_CONFIG["location"]["latitude"]
)
aioclient_mock.get(uri, text=api_response)
entry = MockConfigEntry(domain=DOMAIN, title="test", data=TEST_CONFIG, version=3)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert load_int.state is ConfigEntryState.LOADED
state = hass.states.get(ENTITY_ID)
assert state
await hass.config_entries.async_remove(entry.entry_id)
await hass.config_entries.async_unload(load_int.entry_id)
await hass.async_block_till_done()
assert load_int.state is ConfigEntryState.NOT_LOADED
state = hass.states.get(ENTITY_ID)
assert not state
assert state.state == STATE_UNAVAILABLE
async def test_migrate_entry(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
aioclient_mock: AiohttpClientMocker,
api_response: str,
mock_client: SMHIPointForecast,
) -> None:
"""Test migrate entry data."""
uri = API_POINT_FORECAST.format(
TEST_CONFIG_MIGRATE["longitude"], TEST_CONFIG_MIGRATE["latitude"]
)
aioclient_mock.get(uri, text=api_response)
entry = MockConfigEntry(domain=DOMAIN, data=TEST_CONFIG_MIGRATE)
entry.add_to_hass(hass)
assert entry.version == 1
@ -94,13 +65,9 @@ async def test_migrate_entry(
async def test_migrate_from_future_version(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, api_response: str
hass: HomeAssistant, mock_client: SMHIPointForecast
) -> None:
"""Test migrate entry not possible from future version."""
uri = API_POINT_FORECAST.format(
TEST_CONFIG_MIGRATE["longitude"], TEST_CONFIG_MIGRATE["latitude"]
)
aioclient_mock.get(uri, text=api_response)
entry = MockConfigEntry(domain=DOMAIN, data=TEST_CONFIG_MIGRATE, version=4)
entry.add_to_hass(hass)
assert entry.version == 4

View File

@ -1,16 +1,19 @@
"""Test for the smhi weather entity."""
from datetime import datetime, timedelta
from unittest.mock import patch
from unittest.mock import MagicMock
from freezegun import freeze_time
from freezegun.api import FrozenDateTimeFactory
from pysmhi import SMHIForecast, SmhiForecastException
from pysmhi.const import API_POINT_FORECAST
from pysmhi import SMHIForecast, SmhiForecastException, SMHIPointForecast
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.smhi.weather import CONDITION_CLASSES
from homeassistant.components.smhi.const import DOMAIN
from homeassistant.components.smhi.weather import (
ATTR_SMHI_THUNDER_PROBABILITY,
CONDITION_CLASSES,
)
from homeassistant.components.weather import (
ATTR_CONDITION_CLEAR_NIGHT,
ATTR_FORECAST_CONDITION,
@ -23,6 +26,7 @@ from homeassistant.const import (
ATTR_ATTRIBUTION,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
Platform,
UnitOfSpeed,
)
from homeassistant.core import HomeAssistant
@ -32,31 +36,20 @@ from homeassistant.util import dt as dt_util
from . import ENTITY_ID, TEST_CONFIG
from tests.common import MockConfigEntry, async_fire_time_changed
from tests.test_util.aiohttp import AiohttpClientMocker
from tests.typing import WebSocketGenerator
@pytest.mark.parametrize(
"load_platforms",
[[Platform.WEATHER]],
)
async def test_setup_hass(
hass: HomeAssistant,
aioclient_mock: AiohttpClientMocker,
api_response: str,
load_int: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test for successfully setting up the smhi integration."""
uri = API_POINT_FORECAST.format(
TEST_CONFIG["location"]["longitude"], TEST_CONFIG["location"]["latitude"]
)
aioclient_mock.get(uri, text=api_response)
entry = MockConfigEntry(domain="smhi", title="test", data=TEST_CONFIG, version=3)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert aioclient_mock.call_count == 1
# Testing the actual entity state for
# deeper testing than normal unity test
state = hass.states.get(ENTITY_ID)
assert state
@ -64,27 +57,30 @@ async def test_setup_hass(
assert state.attributes == snapshot
@pytest.mark.parametrize(
"to_load",
[1],
)
@freeze_time(datetime(2023, 8, 7, 1, tzinfo=dt_util.UTC))
async def test_clear_night(
hass: HomeAssistant,
aioclient_mock: AiohttpClientMocker,
api_response_night: str,
mock_client: SMHIPointForecast,
snapshot: SnapshotAssertion,
) -> None:
"""Test for successfully setting up the smhi integration."""
hass.config.latitude = "59.32624"
hass.config.longitude = "17.84197"
uri = API_POINT_FORECAST.format(
TEST_CONFIG["location"]["longitude"], TEST_CONFIG["location"]["latitude"]
config_entry = MockConfigEntry(
domain=DOMAIN,
data=TEST_CONFIG,
entry_id="01JMZDH8N5PFHGJNYKKYCSCWER",
unique_id="59.32624-17.84197",
version=3,
title="Test",
)
aioclient_mock.get(uri, text=api_response_night)
entry = MockConfigEntry(domain="smhi", title="test", data=TEST_CONFIG, version=3)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert aioclient_mock.call_count == 1
state = hass.states.get(ENTITY_ID)
@ -104,39 +100,43 @@ async def test_clear_night(
async def test_properties_no_data(
hass: HomeAssistant,
aioclient_mock: AiohttpClientMocker,
api_response: str,
load_int: MockConfigEntry,
mock_client: MagicMock,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test properties when no API data available."""
uri = API_POINT_FORECAST.format(
TEST_CONFIG["location"]["longitude"], TEST_CONFIG["location"]["latitude"]
)
aioclient_mock.get(uri, text=api_response)
entry = MockConfigEntry(domain="smhi", title="test", data=TEST_CONFIG, version=3)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
mock_client.async_get_daily_forecast.side_effect = SmhiForecastException("boom")
freezer.tick(timedelta(minutes=35))
async_fire_time_changed(hass)
await hass.async_block_till_done()
with patch(
"homeassistant.components.smhi.coordinator.SMHIPointForecast.async_get_daily_forecast",
side_effect=SmhiForecastException("boom"),
):
freezer.tick(timedelta(minutes=35))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
assert state
assert state.name == "test"
assert state.name == "Test"
assert state.state == STATE_UNAVAILABLE
assert state.attributes[ATTR_ATTRIBUTION] == "Swedish weather institute (SMHI)"
mock_client.async_get_daily_forecast.side_effect = None
mock_client.async_get_daily_forecast.return_value = None
freezer.tick(timedelta(minutes=35))
async_fire_time_changed(hass)
await hass.async_block_till_done()
async def test_properties_unknown_symbol(hass: HomeAssistant) -> None:
state = hass.states.get(ENTITY_ID)
assert state
assert state.name == "Test"
assert state.state == "fog"
assert ATTR_SMHI_THUNDER_PROBABILITY not in state.attributes
assert state.attributes[ATTR_ATTRIBUTION] == "Swedish weather institute (SMHI)"
async def test_properties_unknown_symbol(
hass: HomeAssistant,
mock_client: MagicMock,
) -> None:
"""Test behaviour when unknown symbol from API."""
data = SMHIForecast(
frozen_precipitation=0,
@ -213,21 +213,13 @@ async def test_properties_unknown_symbol(hass: HomeAssistant) -> None:
testdata = [data, data2, data3]
mock_client.async_get_daily_forecast.return_value = testdata
entry = MockConfigEntry(domain="smhi", title="test", data=TEST_CONFIG, version=3)
entry.add_to_hass(hass)
with (
patch(
"homeassistant.components.smhi.coordinator.SMHIPointForecast.async_get_daily_forecast",
return_value=testdata,
),
patch(
"homeassistant.components.smhi.coordinator.SMHIPointForecast.async_get_hourly_forecast",
return_value=None,
),
):
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
@ -251,45 +243,33 @@ async def test_properties_unknown_symbol(hass: HomeAssistant) -> None:
async def test_refresh_weather_forecast_retry(
hass: HomeAssistant,
error: Exception,
aioclient_mock: AiohttpClientMocker,
api_response: str,
load_int: MockConfigEntry,
mock_client: MagicMock,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test the refresh weather forecast function."""
uri = API_POINT_FORECAST.format(
TEST_CONFIG["location"]["longitude"], TEST_CONFIG["location"]["latitude"]
)
aioclient_mock.get(uri, text=api_response)
entry = MockConfigEntry(domain="smhi", title="test", data=TEST_CONFIG, version=3)
entry.add_to_hass(hass)
mock_client.async_get_daily_forecast.side_effect = error
await hass.config_entries.async_setup(entry.entry_id)
freezer.tick(timedelta(minutes=35))
async_fire_time_changed(hass)
await hass.async_block_till_done()
with patch(
"homeassistant.components.smhi.coordinator.SMHIPointForecast.async_get_daily_forecast",
side_effect=error,
) as mock_get_forecast:
freezer.tick(timedelta(minutes=35))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
state = hass.states.get(ENTITY_ID)
assert state
assert state.name == "Test"
assert state.state == STATE_UNAVAILABLE
assert mock_client.async_get_daily_forecast.call_count == 2
assert state
assert state.name == "test"
assert state.state == STATE_UNAVAILABLE
assert mock_get_forecast.call_count == 1
freezer.tick(timedelta(minutes=35))
async_fire_time_changed(hass)
await hass.async_block_till_done()
freezer.tick(timedelta(minutes=35))
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
assert state
assert state.state == STATE_UNAVAILABLE
assert mock_get_forecast.call_count == 2
state = hass.states.get(ENTITY_ID)
assert state
assert state.state == STATE_UNAVAILABLE
assert mock_client.async_get_daily_forecast.call_count == 3
def test_condition_class() -> None:
@ -361,25 +341,13 @@ def test_condition_class() -> None:
async def test_custom_speed_unit(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
aioclient_mock: AiohttpClientMocker,
api_response: str,
load_int: MockConfigEntry,
) -> None:
"""Test Wind Gust speed with custom unit."""
uri = API_POINT_FORECAST.format(
TEST_CONFIG["location"]["longitude"], TEST_CONFIG["location"]["latitude"]
)
aioclient_mock.get(uri, text=api_response)
entry = MockConfigEntry(domain="smhi", title="test", data=TEST_CONFIG, version=3)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get(ENTITY_ID)
assert state
assert state.name == "test"
assert state.name == "Test"
assert state.attributes[ATTR_WEATHER_WIND_GUST_SPEED] == 22.32
entity_registry.async_update_entity_options(
@ -394,25 +362,17 @@ async def test_custom_speed_unit(
assert state.attributes[ATTR_WEATHER_WIND_GUST_SPEED] == 6.2
@pytest.mark.parametrize(
"load_platforms",
[[Platform.WEATHER]],
)
async def test_forecast_services(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
aioclient_mock: AiohttpClientMocker,
api_response: str,
load_int: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test multiple forecast."""
uri = API_POINT_FORECAST.format(
TEST_CONFIG["location"]["longitude"], TEST_CONFIG["location"]["latitude"]
)
aioclient_mock.get(uri, text=api_response)
entry = MockConfigEntry(domain="smhi", title="test", data=TEST_CONFIG, version=3)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
client = await hass_ws_client(hass)
await client.send_json_auto_id(
@ -458,25 +418,21 @@ async def test_forecast_services(
assert forecast1[6] == snapshot
@pytest.mark.parametrize(
"load_platforms",
[[Platform.WEATHER]],
)
@pytest.mark.parametrize(
"to_load",
[2],
)
async def test_forecast_services_lack_of_data(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
aioclient_mock: AiohttpClientMocker,
api_response_lack_data: str,
load_int: MockConfigEntry,
snapshot: SnapshotAssertion,
) -> None:
"""Test forecast lacking data."""
uri = API_POINT_FORECAST.format(
TEST_CONFIG["location"]["longitude"], TEST_CONFIG["location"]["latitude"]
)
aioclient_mock.get(uri, text=api_response_lack_data)
entry = MockConfigEntry(domain="smhi", title="test", data=TEST_CONFIG, version=3)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
client = await hass_ws_client(hass)
await client.send_json_auto_id(
@ -500,31 +456,18 @@ async def test_forecast_services_lack_of_data(
@pytest.mark.parametrize(
("service"),
[SERVICE_GET_FORECASTS],
"load_platforms",
[[Platform.WEATHER]],
)
async def test_forecast_service(
hass: HomeAssistant,
aioclient_mock: AiohttpClientMocker,
api_response: str,
load_int: MockConfigEntry,
snapshot: SnapshotAssertion,
service: str,
) -> None:
"""Test forecast service."""
uri = API_POINT_FORECAST.format(
TEST_CONFIG["location"]["longitude"], TEST_CONFIG["location"]["latitude"]
)
aioclient_mock.get(uri, text=api_response)
entry = MockConfigEntry(domain="smhi", title="test", data=TEST_CONFIG, version=3)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
response = await hass.services.async_call(
WEATHER_DOMAIN,
service,
SERVICE_GET_FORECASTS,
{"entity_id": ENTITY_ID, "type": "daily"},
blocking=True,
return_response=True,