From 9de90ca7d522c8cdbf86c7abfa0027cba4938fe7 Mon Sep 17 00:00:00 2001 From: Jeef Date: Wed, 21 Aug 2024 08:16:16 -0600 Subject: [PATCH] Fix Weatherflow Cloud lightning (#124082) * Adding a error condition and a fix for missing lightning epoch values * adding parentheses around the lambda * Updating PR * removed the dumb test * Updated tests to support good stuff * Updated snapshots --- .../components/weatherflow_cloud/sensor.py | 8 +- .../components/weatherflow_cloud/conftest.py | 36 +++++++ .../fixtures/station_observation_error.json | 99 +++++++++++++++++++ .../weatherflow_cloud/test_sensor.py | 52 +++++++++- 4 files changed, 191 insertions(+), 4 deletions(-) create mode 100644 tests/components/weatherflow_cloud/fixtures/station_observation_error.json diff --git a/homeassistant/components/weatherflow_cloud/sensor.py b/homeassistant/components/weatherflow_cloud/sensor.py index 9314c77a65c4bf..1c7fa5fb377f80 100644 --- a/homeassistant/components/weatherflow_cloud/sensor.py +++ b/homeassistant/components/weatherflow_cloud/sensor.py @@ -158,8 +158,12 @@ class WeatherFlowCloudSensorEntityDescription( key="lightning_strike_last_epoch", translation_key="lightning_strike_last_epoch", device_class=SensorDeviceClass.TIMESTAMP, - value_fn=lambda data: datetime.fromtimestamp( - data.lightning_strike_last_epoch, tz=UTC + value_fn=( + lambda data: datetime.fromtimestamp( + data.lightning_strike_last_epoch, tz=UTC + ) + if data.lightning_strike_last_epoch is not None + else None ), ), ) diff --git a/tests/components/weatherflow_cloud/conftest.py b/tests/components/weatherflow_cloud/conftest.py index 36b42bf24a83b5..d83ee082b262de 100644 --- a/tests/components/weatherflow_cloud/conftest.py +++ b/tests/components/weatherflow_cloud/conftest.py @@ -113,3 +113,39 @@ def mock_api(): mock_api_class.return_value = mock_api yield mock_api + + +# +# @pytest.fixture +# def mock_api_with_lightning_error(): +# """Fixture for Mock WeatherFlowRestAPI.""" +# get_stations_response_data = StationsResponseREST.from_json( +# load_fixture("stations.json", DOMAIN) +# ) +# get_forecast_response_data = WeatherDataForecastREST.from_json( +# load_fixture("forecast.json", DOMAIN) +# ) +# get_observation_response_data = ObservationStationREST.from_json( +# load_fixture("station_observation_error.json", DOMAIN) +# ) +# +# data = { +# 24432: WeatherFlowDataREST( +# weather=get_forecast_response_data, +# observation=get_observation_response_data, +# station=get_stations_response_data.stations[0], +# device_observations=None, +# ) +# } +# +# with patch( +# "homeassistant.components.weatherflow_cloud.coordinator.WeatherFlowRestAPI", +# autospec=True, +# ) as mock_api_class: +# # Create an instance of AsyncMock for the API +# mock_api = AsyncMock() +# mock_api.get_all_data.return_value = data +# # Patch the class to return our mock_api instance +# mock_api_class.return_value = mock_api +# +# yield mock_api diff --git a/tests/components/weatherflow_cloud/fixtures/station_observation_error.json b/tests/components/weatherflow_cloud/fixtures/station_observation_error.json new file mode 100644 index 00000000000000..41bb452c91151b --- /dev/null +++ b/tests/components/weatherflow_cloud/fixtures/station_observation_error.json @@ -0,0 +1,99 @@ +{ + "elevation": 2063.150146484375, + "is_public": true, + "latitude": 43.94962, + "longitude": -102.86831, + "obs": [ + { + "air_density": 0.96139, + "air_temperature": 10.5, + "barometric_pressure": 782.8, + "brightness": 757, + "delta_t": 8.4, + "dew_point": -10.4, + "feels_like": 10.5, + "heat_index": 10.5, + "lightning_strike_count": 0, + "lightning_strike_count_last_1hr": 0, + "lightning_strike_count_last_3hr": 0, + "lightning_strike_last_distance": 26, + "precip": 0.0, + "precip_accum_last_1hr": 0.0, + "precip_accum_local_day": 0.0, + "precip_accum_local_day_final": 0.0, + "precip_accum_local_yesterday": 0.0, + "precip_accum_local_yesterday_final": 0.0, + "precip_analysis_type_yesterday": 0, + "precip_minutes_local_day": 0, + "precip_minutes_local_yesterday": 0, + "precip_minutes_local_yesterday_final": 0, + "pressure_trend": "steady", + "relative_humidity": 22, + "sea_level_pressure": 1006.2, + "solar_radiation": 6, + "station_pressure": 782.8, + "timestamp": 1708994629, + "uv": 0.03, + "wet_bulb_globe_temperature": 4.6, + "wet_bulb_temperature": 2.1, + "wind_avg": 1.4, + "wind_chill": 10.5, + "wind_direction": 203, + "wind_gust": 3.2, + "wind_lull": 0.3 + } + ], + "outdoor_keys": [ + "timestamp", + "air_temperature", + "barometric_pressure", + "station_pressure", + "pressure_trend", + "sea_level_pressure", + "relative_humidity", + "precip", + "precip_accum_last_1hr", + "precip_accum_local_day", + "precip_accum_local_day_final", + "precip_accum_local_yesterday_final", + "precip_minutes_local_day", + "precip_minutes_local_yesterday_final", + "wind_avg", + "wind_direction", + "wind_gust", + "wind_lull", + "solar_radiation", + "uv", + "brightness", + "lightning_strike_last_epoch", + "lightning_strike_last_distance", + "lightning_strike_count", + "lightning_strike_count_last_1hr", + "lightning_strike_count_last_3hr", + "feels_like", + "heat_index", + "wind_chill", + "dew_point", + "wet_bulb_temperature", + "wet_bulb_globe_temperature", + "delta_t", + "air_density" + ], + "public_name": "My Home Station", + "station_id": 24432, + "station_name": "My Home Station", + "station_units": { + "units_direction": "degrees", + "units_distance": "mi", + "units_other": "metric", + "units_precip": "in", + "units_pressure": "hpa", + "units_temp": "f", + "units_wind": "bft" + }, + "status": { + "status_code": 0, + "status_message": "SUCCESS" + }, + "timezone": "America/Denver" +} diff --git a/tests/components/weatherflow_cloud/test_sensor.py b/tests/components/weatherflow_cloud/test_sensor.py index 35ce098f5a7883..4d6ff0c8c9f713 100644 --- a/tests/components/weatherflow_cloud/test_sensor.py +++ b/tests/components/weatherflow_cloud/test_sensor.py @@ -1,16 +1,25 @@ """Tests for the WeatherFlow Cloud sensor platform.""" +from datetime import timedelta from unittest.mock import AsyncMock, patch +from freezegun.api import FrozenDateTimeFactory from syrupy import SnapshotAssertion +from weatherflow4py.models.rest.observation import ObservationStationREST -from homeassistant.const import Platform +from homeassistant.components.weatherflow_cloud import DOMAIN +from homeassistant.const import STATE_UNKNOWN, Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry as er from . import setup_integration -from tests.common import MockConfigEntry, snapshot_platform +from tests.common import ( + MockConfigEntry, + async_fire_time_changed, + load_fixture, + snapshot_platform, +) async def test_all_entities( @@ -27,3 +36,42 @@ async def test_all_entities( await setup_integration(hass, mock_config_entry) await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id) + + +async def test_all_entities_with_lightning_error( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + entity_registry: er.EntityRegistry, + mock_api: AsyncMock, + freezer: FrozenDateTimeFactory, +) -> None: + """Test all entities.""" + + get_observation_response_data = ObservationStationREST.from_json( + load_fixture("station_observation_error.json", DOMAIN) + ) + + with patch( + "homeassistant.components.weatherflow_cloud.PLATFORMS", [Platform.SENSOR] + ): + await setup_integration(hass, mock_config_entry) + + assert ( + hass.states.get("sensor.my_home_station_lightning_last_strike").state + == "2024-02-07T23:01:15+00:00" + ) + + # Update the data in our API + all_data = await mock_api.get_all_data() + all_data[24432].observation = get_observation_response_data + mock_api.get_all_data.return_value = all_data + + # Move time forward + freezer.tick(timedelta(minutes=5)) + async_fire_time_changed(hass) + await hass.async_block_till_done() + + assert ( + hass.states.get("sensor.my_home_station_lightning_last_strike").state + == STATE_UNKNOWN + )