1
0
mirror of https://github.com/home-assistant/core.git synced 2026-05-14 20:41:24 +01:00
Files
core/tests/components/vizio/test_init.py
T
Raman Gupta f94a075641 Decouple Vizio apps coordinator from config entry (#163923)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Joostlek <joostlek@outlook.com>
2026-03-03 11:22:41 +01:00

155 lines
5.5 KiB
Python

"""Tests for Vizio init."""
from datetime import timedelta
from unittest.mock import patch
from freezegun.api import FrozenDateTimeFactory
import pytest
from homeassistant.components.media_player import MediaPlayerDeviceClass
from homeassistant.components.vizio.const import DOMAIN
from homeassistant.const import (
CONF_ACCESS_TOKEN,
CONF_DEVICE_CLASS,
CONF_HOST,
CONF_NAME,
STATE_UNAVAILABLE,
Platform,
)
from homeassistant.core import HomeAssistant
from .const import (
APP_LIST,
HOST2,
MOCK_SPEAKER_CONFIG,
MOCK_USER_VALID_TV_CONFIG,
NAME2,
UNIQUE_ID,
)
from tests.common import MockConfigEntry, async_fire_time_changed
@pytest.mark.usefixtures("vizio_connect", "vizio_update")
async def test_tv_load_and_unload(hass: HomeAssistant) -> None:
"""Test loading and unloading TV entry."""
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(Platform.MEDIA_PLAYER)) == 1
assert DOMAIN in hass.data
assert await hass.config_entries.async_unload(config_entry.entry_id)
await hass.async_block_till_done()
entities = hass.states.async_entity_ids(Platform.MEDIA_PLAYER)
assert len(entities) == 1
for entity in entities:
assert hass.states.get(entity).state == STATE_UNAVAILABLE
assert DOMAIN not in hass.data
@pytest.mark.usefixtures("vizio_connect", "vizio_update")
async def test_speaker_load_and_unload(hass: HomeAssistant) -> None:
"""Test loading and unloading speaker entry."""
config_entry = MockConfigEntry(
domain=DOMAIN, data=MOCK_SPEAKER_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(Platform.MEDIA_PLAYER)) == 1
assert DOMAIN in hass.data
assert await hass.config_entries.async_unload(config_entry.entry_id)
await hass.async_block_till_done()
entities = hass.states.async_entity_ids(Platform.MEDIA_PLAYER)
assert len(entities) == 1
for entity in entities:
assert hass.states.get(entity).state == STATE_UNAVAILABLE
assert DOMAIN not in hass.data
@pytest.mark.usefixtures(
"vizio_connect", "vizio_bypass_update", "vizio_data_coordinator_update_failure"
)
async def test_coordinator_update_failure(
hass: HomeAssistant,
freezer: FrozenDateTimeFactory,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test coordinator update failure after 10 days."""
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(Platform.MEDIA_PLAYER)) == 1
# Failing 25 days in a row should result in a single log message
# (first one after 10 days, next one would be at 30 days)
for days in range(1, 25):
freezer.tick(timedelta(days=days))
async_fire_time_changed(hass)
await hass.async_block_till_done()
err_msg = "Unable to retrieve the apps list from the external server"
assert len([record for record in caplog.records if err_msg in record.msg]) == 1
@pytest.mark.usefixtures("vizio_connect", "vizio_bypass_update")
async def test_apps_coordinator_persists_until_last_tv_unloads(
hass: HomeAssistant, freezer: FrozenDateTimeFactory
) -> None:
"""Test shared apps coordinator is not shut down until the last TV entry unloads."""
config_entry_1 = MockConfigEntry(
domain=DOMAIN, data=MOCK_USER_VALID_TV_CONFIG, unique_id=UNIQUE_ID
)
config_entry_2 = MockConfigEntry(
domain=DOMAIN,
data={
CONF_NAME: NAME2,
CONF_HOST: HOST2,
CONF_DEVICE_CLASS: MediaPlayerDeviceClass.TV,
CONF_ACCESS_TOKEN: "deadbeef2",
},
unique_id="testid2",
)
config_entry_1.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry_1.entry_id)
await hass.async_block_till_done()
config_entry_2.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry_2.entry_id)
await hass.async_block_till_done()
assert len(hass.states.async_entity_ids(Platform.MEDIA_PLAYER)) == 2
# Unload first TV — coordinator should still be fetching apps
assert await hass.config_entries.async_unload(config_entry_1.entry_id)
await hass.async_block_till_done()
with patch(
"homeassistant.components.vizio.coordinator.gen_apps_list_from_url",
return_value=APP_LIST,
) as mock_fetch:
freezer.tick(timedelta(days=1))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert mock_fetch.call_count == 1
# Unload second (last) TV — coordinator should stop fetching apps
assert await hass.config_entries.async_unload(config_entry_2.entry_id)
await hass.async_block_till_done()
with patch(
"homeassistant.components.vizio.coordinator.gen_apps_list_from_url",
return_value=APP_LIST,
) as mock_fetch:
freezer.tick(timedelta(days=2))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert mock_fetch.call_count == 0