diff --git a/homeassistant/components/pi_hole/update.py b/homeassistant/components/pi_hole/update.py index db78d3ab0a5..c1a435f628c 100644 --- a/homeassistant/components/pi_hole/update.py +++ b/homeassistant/components/pi_hole/update.py @@ -22,6 +22,7 @@ class PiHoleUpdateEntityDescription(UpdateEntityDescription): installed_version: Callable[[dict], str | None] = lambda api: None latest_version: Callable[[dict], str | None] = lambda api: None + has_update: Callable[[dict], bool | None] = lambda api: None release_base_url: str | None = None title: str | None = None @@ -34,6 +35,7 @@ UPDATE_ENTITY_TYPES: tuple[PiHoleUpdateEntityDescription, ...] = ( entity_category=EntityCategory.DIAGNOSTIC, installed_version=lambda versions: versions.get("core_current"), latest_version=lambda versions: versions.get("core_latest"), + has_update=lambda versions: versions.get("core_update"), release_base_url="https://github.com/pi-hole/pi-hole/releases/tag", ), PiHoleUpdateEntityDescription( @@ -43,6 +45,7 @@ UPDATE_ENTITY_TYPES: tuple[PiHoleUpdateEntityDescription, ...] = ( entity_category=EntityCategory.DIAGNOSTIC, installed_version=lambda versions: versions.get("web_current"), latest_version=lambda versions: versions.get("web_latest"), + has_update=lambda versions: versions.get("web_update"), release_base_url="https://github.com/pi-hole/AdminLTE/releases/tag", ), PiHoleUpdateEntityDescription( @@ -52,6 +55,7 @@ UPDATE_ENTITY_TYPES: tuple[PiHoleUpdateEntityDescription, ...] = ( entity_category=EntityCategory.DIAGNOSTIC, installed_version=lambda versions: versions.get("FTL_current"), latest_version=lambda versions: versions.get("FTL_latest"), + has_update=lambda versions: versions.get("FTL_update"), release_base_url="https://github.com/pi-hole/FTL/releases/tag", ), ) @@ -110,7 +114,9 @@ class PiHoleUpdateEntity(PiHoleEntity, UpdateEntity): def latest_version(self) -> str | None: """Latest version available for install.""" if isinstance(self.api.versions, dict): - return self.entity_description.latest_version(self.api.versions) + if self.entity_description.has_update(self.api.versions): + return self.entity_description.latest_version(self.api.versions) + return self.installed_version return None @property diff --git a/tests/components/pi_hole/__init__.py b/tests/components/pi_hole/__init__.py index 38231778624..993f6a2571c 100644 --- a/tests/components/pi_hole/__init__.py +++ b/tests/components/pi_hole/__init__.py @@ -33,7 +33,7 @@ ZERO_DATA = { "unique_domains": 0, } -SAMPLE_VERSIONS = { +SAMPLE_VERSIONS_WITH_UPDATES = { "core_current": "v5.5", "core_latest": "v5.6", "core_update": True, @@ -45,6 +45,18 @@ SAMPLE_VERSIONS = { "FTL_update": True, } +SAMPLE_VERSIONS_NO_UPDATES = { + "core_current": "v5.5", + "core_latest": "v5.5", + "core_update": False, + "web_current": "v5.7", + "web_latest": "v5.7", + "web_update": False, + "FTL_current": "v5.10", + "FTL_latest": "v5.10", + "FTL_update": False, +} + HOST = "1.2.3.4" PORT = 80 LOCATION = "location" @@ -103,7 +115,9 @@ CONFIG_ENTRY_WITHOUT_API_KEY = { SWITCH_ENTITY_ID = "switch.pi_hole" -def _create_mocked_hole(raise_exception=False, has_versions=True, has_data=True): +def _create_mocked_hole( + raise_exception=False, has_versions=True, has_update=True, has_data=True +): mocked_hole = MagicMock() type(mocked_hole).get_data = AsyncMock( side_effect=HoleError("") if raise_exception else None @@ -118,7 +132,10 @@ def _create_mocked_hole(raise_exception=False, has_versions=True, has_data=True) else: mocked_hole.data = [] if has_versions: - mocked_hole.versions = SAMPLE_VERSIONS + if has_update: + mocked_hole.versions = SAMPLE_VERSIONS_WITH_UPDATES + else: + mocked_hole.versions = SAMPLE_VERSIONS_NO_UPDATES else: mocked_hole.versions = None return mocked_hole diff --git a/tests/components/pi_hole/test_config_flow.py b/tests/components/pi_hole/test_config_flow.py index 326b01b9a7a..d13712d6f76 100644 --- a/tests/components/pi_hole/test_config_flow.py +++ b/tests/components/pi_hole/test_config_flow.py @@ -96,7 +96,7 @@ async def test_flow_user_without_api_key(hass: HomeAssistant) -> None: async def test_flow_user_invalid(hass: HomeAssistant) -> None: """Test user initialized flow with invalid server.""" - mocked_hole = _create_mocked_hole(True) + mocked_hole = _create_mocked_hole(raise_exception=True) with _patch_config_flow_hole(mocked_hole): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER}, data=CONFIG_FLOW_USER diff --git a/tests/components/pi_hole/test_update.py b/tests/components/pi_hole/test_update.py index 091b553c475..705e9f9c08d 100644 --- a/tests/components/pi_hole/test_update.py +++ b/tests/components/pi_hole/test_update.py @@ -1,7 +1,7 @@ """Test pi_hole component.""" from homeassistant.components import pi_hole -from homeassistant.const import STATE_ON, STATE_UNKNOWN +from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNKNOWN from homeassistant.core import HomeAssistant from . import CONFIG_DATA_DEFAULTS, _create_mocked_hole, _patch_init_hole @@ -80,3 +80,44 @@ async def test_update_no_versions(hass: HomeAssistant) -> None: assert state.attributes["installed_version"] is None assert state.attributes["latest_version"] is None assert state.attributes["release_url"] is None + + +async def test_update_no_updates(hass: HomeAssistant) -> None: + """Tests update entity when no latest data available.""" + mocked_hole = _create_mocked_hole(has_versions=True, has_update=False) + entry = MockConfigEntry(domain=pi_hole.DOMAIN, data=CONFIG_DATA_DEFAULTS) + entry.add_to_hass(hass) + with _patch_init_hole(mocked_hole): + assert await hass.config_entries.async_setup(entry.entry_id) + + await hass.async_block_till_done() + + state = hass.states.get("update.pi_hole_core_update_available") + assert state.name == "Pi-Hole Core update available" + assert state.state == STATE_OFF + assert state.attributes["installed_version"] == "v5.5" + assert state.attributes["latest_version"] == "v5.5" + assert ( + state.attributes["release_url"] + == "https://github.com/pi-hole/pi-hole/releases/tag/v5.5" + ) + + state = hass.states.get("update.pi_hole_ftl_update_available") + assert state.name == "Pi-Hole FTL update available" + assert state.state == STATE_OFF + assert state.attributes["installed_version"] == "v5.10" + assert state.attributes["latest_version"] == "v5.10" + assert ( + state.attributes["release_url"] + == "https://github.com/pi-hole/FTL/releases/tag/v5.10" + ) + + state = hass.states.get("update.pi_hole_web_update_available") + assert state.name == "Pi-Hole Web update available" + assert state.state == STATE_OFF + assert state.attributes["installed_version"] == "v5.7" + assert state.attributes["latest_version"] == "v5.7" + assert ( + state.attributes["release_url"] + == "https://github.com/pi-hole/AdminLTE/releases/tag/v5.7" + )