diff --git a/homeassistant/components/webostv/config_flow.py b/homeassistant/components/webostv/config_flow.py index 3bf4f7c6aeb..4c8ff6e5fd3 100644 --- a/homeassistant/components/webostv/config_flow.py +++ b/homeassistant/components/webostv/config_flow.py @@ -24,6 +24,7 @@ from homeassistant.helpers.typing import ConfigType from . import async_control_connect from .const import CONF_SOURCES, DEFAULT_NAME, DOMAIN, WEBOSTV_EXCEPTIONS +from .helpers import async_get_sources DATA_SCHEMA = vol.Schema( { @@ -198,20 +199,3 @@ class OptionsFlowHandler(config_entries.OptionsFlow): return self.async_show_form( step_id="init", data_schema=options_schema, errors=errors ) - - -async def async_get_sources(host: str, key: str) -> list[str]: - """Construct sources list.""" - try: - client = await async_control_connect(host, key) - except WEBOSTV_EXCEPTIONS: - return [] - - return list( - dict.fromkeys( # Preserve order when filtering duplicates - [ - *(app["title"] for app in client.apps.values()), - *(app["label"] for app in client.inputs.values()), - ] - ) - ) diff --git a/homeassistant/components/webostv/helpers.py b/homeassistant/components/webostv/helpers.py index d3f5fec6826..70a253d5ceb 100644 --- a/homeassistant/components/webostv/helpers.py +++ b/homeassistant/components/webostv/helpers.py @@ -6,8 +6,8 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers.device_registry import DeviceEntry -from . import WebOsClientWrapper -from .const import DATA_CONFIG_ENTRY, DOMAIN +from . import WebOsClientWrapper, async_control_connect +from .const import DATA_CONFIG_ENTRY, DOMAIN, LIVE_TV_APP_ID, WEBOSTV_EXCEPTIONS @callback @@ -81,3 +81,29 @@ def async_get_client_wrapper_by_device_entry( ) return wrapper + + +async def async_get_sources(host: str, key: str) -> list[str]: + """Construct sources list.""" + try: + client = await async_control_connect(host, key) + except WEBOSTV_EXCEPTIONS: + return [] + + sources = [] + found_live_tv = False + for app in client.apps.values(): + sources.append(app["title"]) + if app["id"] == LIVE_TV_APP_ID: + found_live_tv = True + + for source in client.inputs.values(): + sources.append(source["label"]) + if source["appId"] == LIVE_TV_APP_ID: + found_live_tv = True + + if not found_live_tv: + sources.append("Live TV") + + # Preserve order when filtering duplicates + return list(dict.fromkeys(sources)) diff --git a/tests/components/webostv/__init__.py b/tests/components/webostv/__init__.py index d6e2505b96c..1cbc72b43fc 100644 --- a/tests/components/webostv/__init__.py +++ b/tests/components/webostv/__init__.py @@ -11,27 +11,10 @@ from homeassistant.const import CONF_CLIENT_SECRET, CONF_HOST from homeassistant.helpers import entity_registry from homeassistant.setup import async_setup_component +from .const import CLIENT_KEY, FAKE_UUID, HOST, MOCK_CLIENT_KEYS, TV_NAME + from tests.common import MockConfigEntry -FAKE_UUID = "some-fake-uuid" -TV_NAME = "fake_webos" -ENTITY_ID = f"{MP_DOMAIN}.{TV_NAME}" -HOST = "1.2.3.4" -CLIENT_KEY = "some-secret" -MOCK_CLIENT_KEYS = {HOST: CLIENT_KEY} -MOCK_JSON = '{"1.2.3.4": "some-secret"}' - -CHANNEL_1 = { - "channelNumber": "1", - "channelName": "Channel 1", - "channelId": "ch1id", -} -CHANNEL_2 = { - "channelNumber": "20", - "channelName": "Channel Name 2", - "channelId": "ch2id", -} - async def setup_webostv(hass, unique_id=FAKE_UUID): """Initialize webostv and media_player for tests.""" diff --git a/tests/components/webostv/conftest.py b/tests/components/webostv/conftest.py index 23c8687018c..05f1be66d00 100644 --- a/tests/components/webostv/conftest.py +++ b/tests/components/webostv/conftest.py @@ -6,7 +6,7 @@ import pytest from homeassistant.components.webostv.const import LIVE_TV_APP_ID from homeassistant.helpers import entity_registry -from . import CHANNEL_1, CHANNEL_2, CLIENT_KEY, FAKE_UUID +from .const import CHANNEL_1, CHANNEL_2, CLIENT_KEY, FAKE_UUID, MOCK_APPS, MOCK_INPUTS from tests.common import async_mock_service @@ -28,18 +28,8 @@ def client_fixture(): client.software_info = {"major_ver": "major", "minor_ver": "minor"} client.system_info = {"modelName": "TVFAKE"} client.client_key = CLIENT_KEY - client.apps = { - LIVE_TV_APP_ID: { - "title": "Live TV", - "id": LIVE_TV_APP_ID, - "largeIcon": "large-icon", - "icon": "icon", - }, - } - client.inputs = { - "in1": {"label": "Input01", "id": "in1", "appId": "app0"}, - "in2": {"label": "Input02", "id": "in2", "appId": "app1"}, - } + client.apps = MOCK_APPS + client.inputs = MOCK_INPUTS client.current_app_id = LIVE_TV_APP_ID client.channels = [CHANNEL_1, CHANNEL_2] diff --git a/tests/components/webostv/const.py b/tests/components/webostv/const.py new file mode 100644 index 00000000000..eca38837d8e --- /dev/null +++ b/tests/components/webostv/const.py @@ -0,0 +1,36 @@ +"""Constants for LG webOS Smart TV tests.""" +from homeassistant.components.media_player import DOMAIN as MP_DOMAIN +from homeassistant.components.webostv.const import LIVE_TV_APP_ID + +FAKE_UUID = "some-fake-uuid" +TV_NAME = "fake_webos" +ENTITY_ID = f"{MP_DOMAIN}.{TV_NAME}" +HOST = "1.2.3.4" +CLIENT_KEY = "some-secret" +MOCK_CLIENT_KEYS = {HOST: CLIENT_KEY} +MOCK_JSON = '{"1.2.3.4": "some-secret"}' + +CHANNEL_1 = { + "channelNumber": "1", + "channelName": "Channel 1", + "channelId": "ch1id", +} +CHANNEL_2 = { + "channelNumber": "20", + "channelName": "Channel Name 2", + "channelId": "ch2id", +} + +MOCK_APPS = { + LIVE_TV_APP_ID: { + "title": "Live TV", + "id": LIVE_TV_APP_ID, + "largeIcon": "large-icon", + "icon": "icon", + }, +} + +MOCK_INPUTS = { + "in1": {"label": "Input01", "id": "in1", "appId": "app0"}, + "in2": {"label": "Input02", "id": "in2", "appId": "app1"}, +} diff --git a/tests/components/webostv/test_config_flow.py b/tests/components/webostv/test_config_flow.py index 34e6d96bfdd..b2b20677513 100644 --- a/tests/components/webostv/test_config_flow.py +++ b/tests/components/webostv/test_config_flow.py @@ -7,7 +7,7 @@ import pytest from homeassistant import config_entries from homeassistant.components import ssdp -from homeassistant.components.webostv.const import CONF_SOURCES, DOMAIN +from homeassistant.components.webostv.const import CONF_SOURCES, DOMAIN, LIVE_TV_APP_ID from homeassistant.config_entries import SOURCE_SSDP from homeassistant.const import ( CONF_CLIENT_SECRET, @@ -24,7 +24,8 @@ from homeassistant.data_entry_flow import ( RESULT_TYPE_FORM, ) -from . import CLIENT_KEY, FAKE_UUID, HOST, TV_NAME, setup_webostv +from . import setup_webostv +from .const import CLIENT_KEY, FAKE_UUID, HOST, MOCK_APPS, MOCK_INPUTS, TV_NAME MOCK_YAML_CONFIG = { CONF_HOST: HOST, @@ -149,8 +150,27 @@ async def test_form(hass, client): assert result["title"] == TV_NAME -async def test_options_flow(hass, client): - """Test options config flow.""" +@pytest.mark.parametrize( + "apps, inputs", + [ + # Live TV in apps (default) + (MOCK_APPS, MOCK_INPUTS), + # Live TV in inputs + ( + {}, + { + **MOCK_INPUTS, + "livetv": {"label": "Live TV", "id": "livetv", "appId": LIVE_TV_APP_ID}, + }, + ), + # Live TV not found + ({}, MOCK_INPUTS), + ], +) +async def test_options_flow_live_tv_in_apps(hass, client, apps, inputs): + """Test options config flow Live TV found in apps.""" + client.apps = apps + client.inputs = inputs entry = await setup_webostv(hass) result = await hass.config_entries.options.async_init(entry.entry_id) @@ -161,20 +181,24 @@ async def test_options_flow(hass, client): result2 = await hass.config_entries.options.async_configure( result["flow_id"], - user_input={CONF_SOURCES: ["Input01", "Input02"]}, + user_input={CONF_SOURCES: ["Live TV", "Input01", "Input02"]}, ) await hass.async_block_till_done() assert result2["type"] == RESULT_TYPE_CREATE_ENTRY - assert result2["data"][CONF_SOURCES] == ["Input01", "Input02"] + assert result2["data"][CONF_SOURCES] == ["Live TV", "Input01", "Input02"] + + +async def test_options_flow_cannot_retrieve(hass, client): + """Test options config flow cannot retrieve sources.""" + entry = await setup_webostv(hass) client.connect = Mock(side_effect=ConnectionRefusedError()) - result3 = await hass.config_entries.options.async_init(entry.entry_id) - + result = await hass.config_entries.options.async_init(entry.entry_id) await hass.async_block_till_done() - assert result3["type"] == RESULT_TYPE_FORM - assert result3["errors"] == {"base": "cannot_retrieve"} + assert result["type"] == RESULT_TYPE_FORM + assert result["errors"] == {"base": "cannot_retrieve"} async def test_form_cannot_connect(hass, client): diff --git a/tests/components/webostv/test_device_trigger.py b/tests/components/webostv/test_device_trigger.py index ef7c86327a8..fb8512d56f1 100644 --- a/tests/components/webostv/test_device_trigger.py +++ b/tests/components/webostv/test_device_trigger.py @@ -11,7 +11,8 @@ from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.device_registry import async_get as get_dev_reg from homeassistant.setup import async_setup_component -from . import ENTITY_ID, FAKE_UUID, setup_webostv +from . import setup_webostv +from .const import ENTITY_ID, FAKE_UUID from tests.common import MockConfigEntry, async_get_device_automations diff --git a/tests/components/webostv/test_init.py b/tests/components/webostv/test_init.py index eeb1e2fa0ee..8729576d869 100644 --- a/tests/components/webostv/test_init.py +++ b/tests/components/webostv/test_init.py @@ -8,11 +8,11 @@ from homeassistant.components.media_player import DOMAIN as MP_DOMAIN from homeassistant.components.webostv import DOMAIN from . import ( - MOCK_JSON, create_memory_sqlite_engine, is_entity_unique_id_updated, setup_legacy_component, ) +from .const import MOCK_JSON async def test_missing_keys_file_abort(hass, client, caplog): diff --git a/tests/components/webostv/test_media_player.py b/tests/components/webostv/test_media_player.py index a4071c741e5..c249b491d9a 100644 --- a/tests/components/webostv/test_media_player.py +++ b/tests/components/webostv/test_media_player.py @@ -64,7 +64,8 @@ from homeassistant.helpers import device_registry from homeassistant.setup import async_setup_component from homeassistant.util import dt -from . import CHANNEL_2, ENTITY_ID, TV_NAME, setup_webostv +from . import setup_webostv +from .const import CHANNEL_2, ENTITY_ID, TV_NAME from tests.common import async_fire_time_changed diff --git a/tests/components/webostv/test_notify.py b/tests/components/webostv/test_notify.py index 315ae6ac919..a5188545737 100644 --- a/tests/components/webostv/test_notify.py +++ b/tests/components/webostv/test_notify.py @@ -9,7 +9,8 @@ from homeassistant.components.webostv import DOMAIN from homeassistant.const import CONF_ICON, CONF_SERVICE_DATA from homeassistant.setup import async_setup_component -from . import TV_NAME, setup_webostv +from . import setup_webostv +from .const import TV_NAME ICON_PATH = "/some/path" MESSAGE = "one, two, testing, testing" diff --git a/tests/components/webostv/test_trigger.py b/tests/components/webostv/test_trigger.py index f2fabe58ede..cbc72638ad9 100644 --- a/tests/components/webostv/test_trigger.py +++ b/tests/components/webostv/test_trigger.py @@ -7,7 +7,8 @@ from homeassistant.const import SERVICE_RELOAD from homeassistant.helpers.device_registry import async_get as get_dev_reg from homeassistant.setup import async_setup_component -from . import ENTITY_ID, FAKE_UUID, setup_webostv +from . import setup_webostv +from .const import ENTITY_ID, FAKE_UUID from tests.common import MockEntity, MockEntityPlatform