mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
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:
parent
192aa76cd7
commit
4858b2171e
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user