mirror of
https://github.com/jdejaegh/irm-kmi-ha.git
synced 2025-06-27 11:39:26 +02:00
Add tests for weather radar data
This commit is contained in:
parent
f392e8b004
commit
aae39d8ddc
11 changed files with 1512 additions and 170 deletions
|
@ -1,5 +1,4 @@
|
||||||
"""Create a radar view for IRM KMI weather"""
|
"""Create a radar view for IRM KMI weather"""
|
||||||
# File inspired by https://github.com/jodur/imagesdirectory-camera/blob/main/custom_components/imagedirectory/camera.py
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -47,7 +46,7 @@ class IrmKmiRadar(CoordinatorEntity, Camera):
|
||||||
|
|
||||||
self._image_index = 0
|
self._image_index = 0
|
||||||
|
|
||||||
@property # Baseclass Camera property override
|
@property
|
||||||
def frame_interval(self) -> float:
|
def frame_interval(self) -> float:
|
||||||
"""Return the interval between frames of the mjpeg stream"""
|
"""Return the interval between frames of the mjpeg stream"""
|
||||||
return 0.3
|
return 0.3
|
||||||
|
|
|
@ -102,7 +102,10 @@ class IrmKmiCoordinator(DataUpdateCoordinator):
|
||||||
|
|
||||||
async def download_images_from_api(self, animation_data, country, localisation_layer_url):
|
async def download_images_from_api(self, animation_data, country, localisation_layer_url):
|
||||||
coroutines = list()
|
coroutines = list()
|
||||||
coroutines.append(self._api_client.get_image(f"{localisation_layer_url}&th={'d' if country == 'NL' else 'n'}"))
|
coroutines.append(
|
||||||
|
self._api_client.get_image(localisation_layer_url,
|
||||||
|
params={'th': 'd' if country == 'NL' else 'n'}))
|
||||||
|
|
||||||
for frame in animation_data:
|
for frame in animation_data:
|
||||||
if frame.get('uri', None) is not None:
|
if frame.get('uri', None) is not None:
|
||||||
coroutines.append(self._api_client.get_image(frame.get('uri')))
|
coroutines.append(self._api_client.get_image(frame.get('uri')))
|
||||||
|
@ -184,6 +187,7 @@ class IrmKmiCoordinator(DataUpdateCoordinator):
|
||||||
for current in hourly_forecast_data[:2]:
|
for current in hourly_forecast_data[:2]:
|
||||||
if datetime.now().strftime('%H') == current['hour']:
|
if datetime.now().strftime('%H') == current['hour']:
|
||||||
now_hourly = current
|
now_hourly = current
|
||||||
|
break
|
||||||
# Get UV index
|
# Get UV index
|
||||||
module_data = api_data.get('module', None)
|
module_data = api_data.get('module', None)
|
||||||
uv_index = None
|
uv_index = None
|
||||||
|
@ -192,13 +196,33 @@ class IrmKmiCoordinator(DataUpdateCoordinator):
|
||||||
if module.get('type', None) == 'uv':
|
if module.get('type', None) == 'uv':
|
||||||
uv_index = module.get('data', {}).get('levelValue')
|
uv_index = module.get('data', {}).get('levelValue')
|
||||||
|
|
||||||
|
try:
|
||||||
|
pressure = float(now_hourly.get('pressure', None)) if now_hourly is not None else None
|
||||||
|
except TypeError:
|
||||||
|
pressure = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
wind_speed = float(now_hourly.get('windSpeedKm', None)) if now_hourly is not None else None
|
||||||
|
except TypeError:
|
||||||
|
wind_speed = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
wind_gust_speed = float(now_hourly.get('windPeakSpeedKm', None)) if now_hourly is not None else None
|
||||||
|
except TypeError:
|
||||||
|
wind_gust_speed = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
temperature = float(api_data.get('obs', {}).get('temp'))
|
||||||
|
except TypeError:
|
||||||
|
temperature = None
|
||||||
|
|
||||||
current_weather = CurrentWeatherData(
|
current_weather = CurrentWeatherData(
|
||||||
condition=CDT_MAP.get((api_data.get('obs', {}).get('ww'), api_data.get('obs', {}).get('dayNight')), None),
|
condition=CDT_MAP.get((api_data.get('obs', {}).get('ww'), api_data.get('obs', {}).get('dayNight')), None),
|
||||||
temperature=api_data.get('obs', {}).get('temp'),
|
temperature=temperature,
|
||||||
wind_speed=now_hourly.get('windSpeedKm', None) if now_hourly is not None else None,
|
wind_speed=wind_speed,
|
||||||
wind_gust_speed=now_hourly.get('windPeakSpeedKm', None) if now_hourly is not None else None,
|
wind_gust_speed=wind_gust_speed,
|
||||||
wind_bearing=now_hourly.get('windDirectionText', {}).get('en') if now_hourly is not None else None,
|
wind_bearing=now_hourly.get('windDirectionText', {}).get('en') if now_hourly is not None else None,
|
||||||
pressure=now_hourly.get('pressure', None) if now_hourly is not None else None,
|
pressure=pressure,
|
||||||
uv_index=uv_index
|
uv_index=uv_index
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,6 @@ def mock_irm_kmi_api(request: pytest.FixtureRequest) -> Generator[None, MagicMoc
|
||||||
fixture: str = "forecast.json"
|
fixture: str = "forecast.json"
|
||||||
|
|
||||||
forecast = json.loads(load_fixture(fixture))
|
forecast = json.loads(load_fixture(fixture))
|
||||||
print(type(forecast))
|
|
||||||
with patch(
|
with patch(
|
||||||
"custom_components.irm_kmi.coordinator.IrmKmiApiClient", autospec=True
|
"custom_components.irm_kmi.coordinator.IrmKmiApiClient", autospec=True
|
||||||
) as irm_kmi_api_mock:
|
) as irm_kmi_api_mock:
|
||||||
|
@ -81,8 +80,35 @@ def mock_exception_irm_kmi_api(request: pytest.FixtureRequest) -> Generator[None
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def mock_coordinator(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
def mock_image_irm_kmi_api(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
||||||
"""Return a mocked IrmKmi api client."""
|
"""Return a mocked IrmKmi api client."""
|
||||||
|
|
||||||
|
async def patched(url: str, params: dict | None = None) -> bytes:
|
||||||
|
if "cdn.knmi.nl" in url:
|
||||||
|
file_name = "tests/fixtures/clouds_nl.png"
|
||||||
|
elif "app.meteo.be/services/appv4/?s=getIncaImage" in url:
|
||||||
|
file_name = "tests/fixtures/clouds_be.png"
|
||||||
|
elif "getLocalizationLayerBE" in url:
|
||||||
|
file_name = "tests/fixtures/loc_layer_be_n.png"
|
||||||
|
elif "getLocalizationLayerNL" in url:
|
||||||
|
file_name = "tests/fixtures/loc_layer_nl_d.png"
|
||||||
|
else:
|
||||||
|
raise ValueError("Not a valid parameter for the mock")
|
||||||
|
|
||||||
|
with open(file_name, "rb") as file:
|
||||||
|
return file.read()
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"custom_components.irm_kmi.coordinator.IrmKmiApiClient", autospec=True
|
||||||
|
) as irm_kmi_api_mock:
|
||||||
|
irm_kmi = irm_kmi_api_mock.return_value
|
||||||
|
irm_kmi.get_image.side_effect = patched
|
||||||
|
yield irm_kmi
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def mock_coordinator(request: pytest.FixtureRequest) -> Generator[None, MagicMock, None]:
|
||||||
|
"""Return a mocked coordinator."""
|
||||||
with patch(
|
with patch(
|
||||||
"custom_components.irm_kmi.IrmKmiCoordinator", autospec=True
|
"custom_components.irm_kmi.IrmKmiCoordinator", autospec=True
|
||||||
) as coordinator_mock:
|
) as coordinator_mock:
|
||||||
|
|
BIN
tests/fixtures/clouds_be.png
vendored
Normal file
BIN
tests/fixtures/clouds_be.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
BIN
tests/fixtures/clouds_nl.png
vendored
Normal file
BIN
tests/fixtures/clouds_nl.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.3 KiB |
154
tests/fixtures/forecast.json
vendored
154
tests/fixtures/forecast.json
vendored
|
@ -1359,7 +1359,7 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"animation": {
|
"animation": {
|
||||||
"localisationLayer": "https:\/\/app.meteo.be\/services\/appv4\/?s=getLocalizationLayer&ins=92094&f=2&k=2c886c51e74b671c8fc3865f4a0e9318",
|
"localisationLayer": "https:\/\/app.meteo.be\/services\/appv4\/?s=getLocalizationLayerBE&ins=92094&f=2&k=2c886c51e74b671c8fc3865f4a0e9318",
|
||||||
"localisationLayerRatioX": 0.6667,
|
"localisationLayerRatioX": 0.6667,
|
||||||
"localisationLayerRatioY": 0.523,
|
"localisationLayerRatioY": 0.523,
|
||||||
"speed": 0.3,
|
"speed": 0.3,
|
||||||
|
@ -1459,158 +1459,6 @@
|
||||||
"position": 0,
|
"position": 0,
|
||||||
"positionLower": 0,
|
"positionLower": 0,
|
||||||
"positionHigher": 0
|
"positionHigher": 0
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T18:50:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261800&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T19:00:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261810&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T19:10:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261820&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T19:20:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261830&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T19:30:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261840&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T19:40:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261850&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T19:50:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261900&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T20:00:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261910&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T20:10:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261920&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T20:20:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261930&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T20:30:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261940&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T20:40:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312261950&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T20:50:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312262000&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T21:00:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312262010&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T21:10:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312262020&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T21:20:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312262030&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T21:30:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312262040&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T21:40:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312262050&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "2023-12-26T21:50:00+01:00",
|
|
||||||
"uri": "https:\/\/app.meteo.be\/services\/appv4\/?s=getIncaImage&i=202312262100&f=2&k=4a71be18d6cb09f98c49c53f59902f8c&d=202312261720",
|
|
||||||
"value": 0,
|
|
||||||
"position": 0,
|
|
||||||
"positionLower": 0,
|
|
||||||
"positionHigher": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"threshold": [],
|
"threshold": [],
|
||||||
|
|
1355
tests/fixtures/forecast_nl.json
vendored
Normal file
1355
tests/fixtures/forecast_nl.json
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
tests/fixtures/loc_layer_be_n.png
vendored
Normal file
BIN
tests/fixtures/loc_layer_be_n.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
tests/fixtures/loc_layer_nl_d.png
vendored
Normal file
BIN
tests/fixtures/loc_layer_nl_d.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
|
@ -1,24 +1,29 @@
|
||||||
import json
|
import json
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from io import BytesIO
|
||||||
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
|
import pytz
|
||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
from homeassistant.components.weather import (ATTR_CONDITION_CLOUDY,
|
from homeassistant.components.weather import (ATTR_CONDITION_CLOUDY,
|
||||||
ATTR_CONDITION_PARTLYCLOUDY,
|
ATTR_CONDITION_PARTLYCLOUDY,
|
||||||
ATTR_CONDITION_RAINY, Forecast)
|
ATTR_CONDITION_RAINY, Forecast)
|
||||||
|
from homeassistant.components.zone import Zone
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
from pytest_homeassistant_custom_component.common import load_fixture
|
from pytest_homeassistant_custom_component.common import load_fixture
|
||||||
|
|
||||||
from custom_components.irm_kmi.coordinator import IrmKmiCoordinator
|
from custom_components.irm_kmi.coordinator import IrmKmiCoordinator
|
||||||
from custom_components.irm_kmi.data import CurrentWeatherData, IrmKmiForecast
|
from custom_components.irm_kmi.data import CurrentWeatherData, IrmKmiForecast
|
||||||
|
|
||||||
|
|
||||||
def get_api_data() -> dict:
|
def get_api_data(fixture: str) -> dict:
|
||||||
fixture: str = "forecast.json"
|
|
||||||
return json.loads(load_fixture(fixture))
|
return json.loads(load_fixture(fixture))
|
||||||
|
|
||||||
|
|
||||||
@freeze_time(datetime.fromisoformat('2023-12-26T18:30:00.028724'))
|
@freeze_time(datetime.fromisoformat('2023-12-26T18:30:00'))
|
||||||
def test_current_weather() -> None:
|
def test_current_weather_be() -> None:
|
||||||
api_data = get_api_data()
|
api_data = get_api_data("forecast.json")
|
||||||
result = IrmKmiCoordinator.current_weather_from_data(api_data)
|
result = IrmKmiCoordinator.current_weather_from_data(api_data)
|
||||||
|
|
||||||
expected = CurrentWeatherData(
|
expected = CurrentWeatherData(
|
||||||
|
@ -34,9 +39,27 @@ def test_current_weather() -> None:
|
||||||
assert result == expected
|
assert result == expected
|
||||||
|
|
||||||
|
|
||||||
|
@freeze_time(datetime.fromisoformat("2023-12-28T15:30:00"))
|
||||||
|
def test_current_weather_nl() -> None:
|
||||||
|
api_data = get_api_data("forecast_nl.json")
|
||||||
|
result = IrmKmiCoordinator.current_weather_from_data(api_data)
|
||||||
|
|
||||||
|
expected = CurrentWeatherData(
|
||||||
|
condition=ATTR_CONDITION_CLOUDY,
|
||||||
|
temperature=11,
|
||||||
|
wind_speed=40,
|
||||||
|
wind_gust_speed=None,
|
||||||
|
wind_bearing='SW',
|
||||||
|
pressure=1008,
|
||||||
|
uv_index=1
|
||||||
|
)
|
||||||
|
|
||||||
|
assert expected == result
|
||||||
|
|
||||||
|
|
||||||
@freeze_time(datetime.fromisoformat('2023-12-26T18:30:00.028724'))
|
@freeze_time(datetime.fromisoformat('2023-12-26T18:30:00.028724'))
|
||||||
def test_daily_forecast() -> None:
|
def test_daily_forecast() -> None:
|
||||||
api_data = get_api_data().get('for', {}).get('daily')
|
api_data = get_api_data("forecast.json").get('for', {}).get('daily')
|
||||||
result = IrmKmiCoordinator.daily_list_to_forecast(api_data)
|
result = IrmKmiCoordinator.daily_list_to_forecast(api_data)
|
||||||
|
|
||||||
assert isinstance(result, list)
|
assert isinstance(result, list)
|
||||||
|
@ -62,7 +85,7 @@ def test_daily_forecast() -> None:
|
||||||
|
|
||||||
@freeze_time(datetime.fromisoformat('2023-12-26T18:30:00.028724'))
|
@freeze_time(datetime.fromisoformat('2023-12-26T18:30:00.028724'))
|
||||||
def test_hourly_forecast() -> None:
|
def test_hourly_forecast() -> None:
|
||||||
api_data = get_api_data().get('for', {}).get('hourly')
|
api_data = get_api_data("forecast.json").get('for', {}).get('hourly')
|
||||||
result = IrmKmiCoordinator.hourly_list_to_forecast(api_data)
|
result = IrmKmiCoordinator.hourly_list_to_forecast(api_data)
|
||||||
|
|
||||||
assert isinstance(result, list)
|
assert isinstance(result, list)
|
||||||
|
@ -83,3 +106,70 @@ def test_hourly_forecast() -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result[8] == expected
|
assert result[8] == expected
|
||||||
|
|
||||||
|
|
||||||
|
@freeze_time(datetime.fromisoformat("2023-12-28T15:30:00+01:00"))
|
||||||
|
async def test_get_image_nl(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_image_irm_kmi_api: AsyncMock) -> None:
|
||||||
|
api_data = get_api_data("forecast_nl.json")
|
||||||
|
coordinator = IrmKmiCoordinator(hass, Zone({}))
|
||||||
|
|
||||||
|
result = await coordinator._async_animation_data(api_data)
|
||||||
|
|
||||||
|
# Construct the expected image for the most recent one
|
||||||
|
tz = pytz.timezone(hass.config.time_zone)
|
||||||
|
background = Image.open("custom_components/irm_kmi/resources/nl.png").convert('RGBA')
|
||||||
|
layer = Image.open("tests/fixtures/clouds_nl.png").convert('RGBA')
|
||||||
|
localisation = Image.open("tests/fixtures/loc_layer_nl_d.png").convert('RGBA')
|
||||||
|
temp = Image.alpha_composite(background, layer)
|
||||||
|
expected = Image.alpha_composite(temp, localisation)
|
||||||
|
draw = ImageDraw.Draw(expected)
|
||||||
|
font = ImageFont.truetype("custom_components/irm_kmi/resources/roboto_medium.ttf", 16)
|
||||||
|
time_image = (datetime.fromisoformat("2023-12-28T14:25:00+00:00")
|
||||||
|
.astimezone(tz=tz))
|
||||||
|
time_str = time_image.isoformat(sep=' ', timespec='minutes')
|
||||||
|
draw.text((4, 4), time_str, (0, 0, 0), font=font)
|
||||||
|
|
||||||
|
result_image = Image.open(BytesIO(result['sequence'][-1]['image'])).convert('RGBA')
|
||||||
|
|
||||||
|
assert list(result_image.getdata()) == list(expected.getdata())
|
||||||
|
|
||||||
|
thumb_image = Image.open(BytesIO(result['most_recent_image'])).convert('RGBA')
|
||||||
|
assert list(thumb_image.getdata()) == list(expected.getdata())
|
||||||
|
|
||||||
|
assert result['hint'] == "No rain forecasted shortly"
|
||||||
|
|
||||||
|
|
||||||
|
@freeze_time(datetime.fromisoformat("2023-12-26T18:31:00+01:00"))
|
||||||
|
async def test_get_image_be(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_image_irm_kmi_api: AsyncMock,
|
||||||
|
) -> None:
|
||||||
|
api_data = get_api_data("forecast.json")
|
||||||
|
coordinator = IrmKmiCoordinator(hass, Zone({}))
|
||||||
|
|
||||||
|
result = await coordinator._async_animation_data(api_data)
|
||||||
|
|
||||||
|
# Construct the expected image for the most recent one
|
||||||
|
tz = pytz.timezone(hass.config.time_zone)
|
||||||
|
background = Image.open("custom_components/irm_kmi/resources/be_bw.png").convert('RGBA')
|
||||||
|
layer = Image.open("tests/fixtures/clouds_be.png").convert('RGBA')
|
||||||
|
localisation = Image.open("tests/fixtures/loc_layer_be_n.png").convert('RGBA')
|
||||||
|
temp = Image.alpha_composite(background, layer)
|
||||||
|
expected = Image.alpha_composite(temp, localisation)
|
||||||
|
draw = ImageDraw.Draw(expected)
|
||||||
|
font = ImageFont.truetype("custom_components/irm_kmi/resources/roboto_medium.ttf", 16)
|
||||||
|
time_image = (datetime.fromisoformat("2023-12-26T18:30:00+01:00")
|
||||||
|
.astimezone(tz=tz))
|
||||||
|
time_str = time_image.isoformat(sep=' ', timespec='minutes')
|
||||||
|
draw.text((4, 4), time_str, (255, 255, 255), font=font)
|
||||||
|
|
||||||
|
result_image = Image.open(BytesIO(result['sequence'][9]['image'])).convert('RGBA')
|
||||||
|
|
||||||
|
assert list(result_image.getdata()) == list(expected.getdata())
|
||||||
|
|
||||||
|
thumb_image = Image.open(BytesIO(result['most_recent_image'])).convert('RGBA')
|
||||||
|
assert list(thumb_image.getdata()) == list(expected.getdata())
|
||||||
|
|
||||||
|
assert result['hint'] == "No rain forecasted shortly"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Tests for the IRM KMI integration."""
|
"""Tests for the IRM KMI integration."""
|
||||||
|
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
|
Loading…
Add table
Reference in a new issue