diff --git a/homeassistant/components/vizio/__init__.py b/homeassistant/components/vizio/__init__.py index bec6b803023..d51b6a4fbca 100644 --- a/homeassistant/components/vizio/__init__.py +++ b/homeassistant/components/vizio/__init__.py @@ -15,7 +15,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers import config_validation as cv from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.typing import ConfigType -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from .const import CONF_APPS, CONF_DEVICE_CLASS, DOMAIN, VIZIO_SCHEMA @@ -106,10 +106,26 @@ class VizioAppsDataUpdateCoordinator(DataUpdateCoordinator): update_method=self._async_update_data, ) self.data = APPS + self.fail_count = 0 + self.fail_threshold = 10 async def _async_update_data(self) -> list[dict[str, Any]]: """Update data via library.""" data = await gen_apps_list_from_url(session=async_get_clientsession(self.hass)) if not data: - raise UpdateFailed + if self.fail_count == self.fail_threshold: + _LOGGER.warning( + ( + "Unable to retrieve the apps list from the external server " + "for the last %s days" + ), + self.fail_threshold, + ) + self.fail_count = 0 + self.fail_threshold += 10 + else: + self.fail_count += 1 + return self.data + self.fail_count = 0 + self.fail_threshold = 10 return sorted(data, key=lambda app: app["name"]) diff --git a/tests/components/vizio/conftest.py b/tests/components/vizio/conftest.py index 8124827dbf0..2c32b07cc1a 100644 --- a/tests/components/vizio/conftest.py +++ b/tests/components/vizio/conftest.py @@ -68,6 +68,16 @@ def vizio_data_coordinator_update_fixture(): yield +@pytest.fixture(name="vizio_data_coordinator_update_failure") +def vizio_data_coordinator_update_failure_fixture(): + """Mock get data coordinator update failure.""" + with patch( + "homeassistant.components.vizio.gen_apps_list_from_url", + return_value=None, + ): + yield + + @pytest.fixture(name="vizio_no_unique_id") def vizio_no_unique_id_fixture(): """Mock no vizio unique ID returrned.""" diff --git a/tests/components/vizio/test_init.py b/tests/components/vizio/test_init.py index 16e2a5bb769..c3e8afe49e6 100644 --- a/tests/components/vizio/test_init.py +++ b/tests/components/vizio/test_init.py @@ -1,4 +1,6 @@ """Tests for Vizio init.""" +from datetime import timedelta + import pytest from homeassistant.components.media_player.const import DOMAIN as MP_DOMAIN @@ -6,10 +8,11 @@ from homeassistant.components.vizio.const import DOMAIN from homeassistant.const import STATE_UNAVAILABLE from homeassistant.core import HomeAssistant from homeassistant.setup import async_setup_component +import homeassistant.util.dt as dt_util from .const import MOCK_SPEAKER_CONFIG, MOCK_USER_VALID_TV_CONFIG, UNIQUE_ID -from tests.common import MockConfigEntry +from tests.common import MockConfigEntry, async_fire_time_changed async def test_setup_component( @@ -71,3 +74,34 @@ async def test_speaker_load_and_unload( for entity in entities: assert hass.states.get(entity).state == STATE_UNAVAILABLE assert DOMAIN not in hass.data + + +async def test_coordinator_update_failure( + hass: HomeAssistant, + vizio_connect: pytest.fixture, + vizio_bypass_update: pytest.fixture, + vizio_data_coordinator_update_failure: pytest.fixture, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test coordinator update failure after 10 days.""" + now = dt_util.now() + config_entry = MockConfigEntry( + domain=DOMAIN, data=MOCK_USER_VALID_TV_CONFIG, unique_id=UNIQUE_ID + ) + config_entry.add_to_hass(hass) + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + assert len(hass.states.async_entity_ids(MP_DOMAIN)) == 1 + assert DOMAIN in hass.data + + for days in range(1, 10): + async_fire_time_changed(hass, now + timedelta(days=days)) + await hass.async_block_till_done() + assert ( + "Unable to retrieve the apps list from the external server" + not in caplog.text + ) + + async_fire_time_changed(hass, now + timedelta(days=10)) + await hass.async_block_till_done() + assert "Unable to retrieve the apps list from the external server" in caplog.text