From bc77daf2ce7a1b268214a445fe3402253b36e768 Mon Sep 17 00:00:00 2001 From: Whitney Young Date: Sun, 19 Oct 2025 12:57:26 -0700 Subject: [PATCH] OpenUV: Add protection window tests (#154498) --- .../openuv/snapshots/test_binary_sensor.ambr | 6 +- tests/components/openuv/test_binary_sensor.py | 67 ++++++++++++++++--- 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/tests/components/openuv/snapshots/test_binary_sensor.ambr b/tests/components/openuv/snapshots/test_binary_sensor.ambr index 8c88392f7cc2..704c6b9f8f60 100644 --- a/tests/components/openuv/snapshots/test_binary_sensor.ambr +++ b/tests/components/openuv/snapshots/test_binary_sensor.ambr @@ -51,7 +51,7 @@ 'state': 'off', }) # --- -# name: test_protection_window_recalculation[after-protetction-state] +# name: test_protection_window_recalculation[after-protection-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'end_time': datetime.datetime(2018, 7, 30, 16, 47, 49, 750000, tzinfo=zoneinfo.ZoneInfo(key='America/Regina')), @@ -68,7 +68,7 @@ 'state': 'off', }) # --- -# name: test_protection_window_recalculation[before-protetction-state] +# name: test_protection_window_recalculation[before-protection-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'end_time': datetime.datetime(2018, 7, 30, 16, 47, 49, 750000, tzinfo=zoneinfo.ZoneInfo(key='America/Regina')), @@ -85,7 +85,7 @@ 'state': 'off', }) # --- -# name: test_protection_window_recalculation[during-protetction-state] +# name: test_protection_window_recalculation[during-protection-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'end_time': datetime.datetime(2018, 7, 30, 16, 47, 49, 750000, tzinfo=zoneinfo.ZoneInfo(key='America/Regina')), diff --git a/tests/components/openuv/test_binary_sensor.py b/tests/components/openuv/test_binary_sensor.py index 1885966c4f9b..6f25ebb04c5f 100644 --- a/tests/components/openuv/test_binary_sensor.py +++ b/tests/components/openuv/test_binary_sensor.py @@ -3,12 +3,14 @@ from unittest.mock import patch from freezegun.api import FrozenDateTimeFactory +import pytest from syrupy.assertion import SnapshotAssertion from homeassistant.components.homeassistant import ( DOMAIN as HOMEASSISTANT_DOMAIN, SERVICE_UPDATE_ENTITY, ) +from homeassistant.config_entries import ConfigEntryState from homeassistant.const import ATTR_ENTITY_ID, Platform from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr, entity_registry as er @@ -32,7 +34,7 @@ async def test_binary_sensors( await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id) -async def test_protetction_window_update( +async def test_protection_window_update( hass: HomeAssistant, set_time_zone, config, @@ -43,7 +45,7 @@ async def test_protetction_window_update( device_registry: dr.DeviceRegistry, entity_registry: er.EntityRegistry, ) -> None: - """Test that updating the protetection window makes an extra API call.""" + """Test that updating the protection window makes an extra API call.""" assert await async_setup_component(hass, HOMEASSISTANT_DOMAIN, {}) @@ -59,6 +61,55 @@ async def test_protetction_window_update( assert client.uv_protection_window.call_count == 2 +@pytest.mark.parametrize( + "data_protection_window", + [{"result": {"from_time": None, "from_uv": 0, "to_time": None, "to_uv": 0}}], +) +async def test_protection_window_null_value_response( + hass: HomeAssistant, + set_time_zone, + config, + client, + config_entry, + setup_config_entry, +) -> None: + """Test that null values in the protection window clears the state.""" + + entity_id = "binary_sensor.openuv_protection_window" + hass.states.async_set(entity_id, "on", {}) + + assert await async_setup_component(hass, HOMEASSISTANT_DOMAIN, {}) + + await hass.services.async_call( + HOMEASSISTANT_DOMAIN, + SERVICE_UPDATE_ENTITY, + {ATTR_ENTITY_ID: entity_id}, + blocking=True, + ) + + state = hass.states.get(entity_id) + assert state.state == "unknown" + + +@pytest.mark.parametrize( + "data_protection_window", + [{"result": {"error": "missing expected keys"}}], +) +async def test_protection_window_invalid_response( + hass: HomeAssistant, + set_time_zone, + config, + client, + config_entry, + mock_pyopenuv, +) -> None: + """Test that missing values in the protection window generate an error.""" + + assert await hass.config_entries.async_setup(config_entry.entry_id) is False + await hass.async_block_till_done() + assert config_entry.state is ConfigEntryState.SETUP_RETRY + + async def test_protection_window_recalculation( hass: HomeAssistant, config, @@ -71,7 +122,7 @@ async def test_protection_window_recalculation( device_registry: dr.DeviceRegistry, entity_registry: er.EntityRegistry, ) -> None: - """Test that protetction window updates automatically without extra API calls.""" + """Test that protection window updates automatically without extra API calls.""" freezer.move_to("2018-07-30T06:17:59-06:00") @@ -81,9 +132,9 @@ async def test_protection_window_recalculation( entity_id = "binary_sensor.openuv_protection_window" state = hass.states.get(entity_id) assert state.state == "off" - assert state == snapshot(name="before-protetction-state") + assert state == snapshot(name="before-protection-state") - # move to when the protetction window starts + # move to when the protection window starts freezer.move_to("2018-07-30T09:17:59-06:00") async_fire_time_changed(hass) await hass.async_block_till_done() @@ -91,9 +142,9 @@ async def test_protection_window_recalculation( entity_id = "binary_sensor.openuv_protection_window" state = hass.states.get(entity_id) assert state.state == "on" - assert state == snapshot(name="during-protetction-state") + assert state == snapshot(name="during-protection-state") - # move to when the protetction window ends + # move to when the protection window ends freezer.move_to("2018-07-30T16:47:59-06:00") async_fire_time_changed(hass) await hass.async_block_till_done() @@ -101,6 +152,6 @@ async def test_protection_window_recalculation( entity_id = "binary_sensor.openuv_protection_window" state = hass.states.get(entity_id) assert state.state == "off" - assert state == snapshot(name="after-protetction-state") + assert state == snapshot(name="after-protection-state") assert client.uv_protection_window.call_count == 1