Cleanup LG webOS TV name (#135028)

This commit is contained in:
Shay Levy 2025-01-08 13:06:02 +02:00 committed by GitHub
parent 7a2a6cf7d8
commit 43ec63eabc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 67 additions and 41 deletions

View File

@ -16,7 +16,7 @@ from homeassistant.config_entries import (
ConfigFlowResult,
OptionsFlow,
)
from homeassistant.const import CONF_CLIENT_SECRET, CONF_HOST, CONF_NAME
from homeassistant.const import CONF_CLIENT_SECRET, CONF_HOST
from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv
@ -27,7 +27,6 @@ from .helpers import async_get_sources
DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
},
extra=vol.ALLOW_EXTRA,
)
@ -57,7 +56,6 @@ class FlowHandler(ConfigFlow, domain=DOMAIN):
errors: dict[str, str] = {}
if user_input is not None:
self._host = user_input[CONF_HOST]
self._name = user_input[CONF_NAME]
return await self.async_step_pairing()
return self.async_show_form(
@ -86,6 +84,9 @@ class FlowHandler(ConfigFlow, domain=DOMAIN):
)
self._abort_if_unique_id_configured({CONF_HOST: self._host})
data = {CONF_HOST: self._host, CONF_CLIENT_SECRET: client.client_key}
if not self._name:
self._name = f"{DEFAULT_NAME} {client.system_info["modelName"]}"
return self.async_create_entry(title=self._name, data=data)
return self.async_show_form(step_id="pairing", errors=errors)
@ -98,7 +99,9 @@ class FlowHandler(ConfigFlow, domain=DOMAIN):
host = urlparse(discovery_info.ssdp_location).hostname
assert host
self._host = host
self._name = discovery_info.upnp.get(ssdp.ATTR_UPNP_FRIENDLY_NAME, DEFAULT_NAME)
self._name = discovery_info.upnp.get(
ssdp.ATTR_UPNP_FRIENDLY_NAME, DEFAULT_NAME
).replace("[LG]", "LG")
uuid = discovery_info.upnp[ssdp.ATTR_UPNP_UDN]
assert uuid

View File

@ -11,7 +11,7 @@ DOMAIN = "webostv"
PLATFORMS = [Platform.MEDIA_PLAYER]
DATA_CONFIG_ENTRY = "config_entry"
DATA_HASS_CONFIG = "hass_config"
DEFAULT_NAME = "LG webOS Smart TV"
DEFAULT_NAME = "LG webOS TV"
ATTR_BUTTON = "button"
ATTR_CONFIG_ENTRY_ID = "entry_id"

View File

@ -8,10 +8,12 @@ rules:
common-modules:
status: exempt
comment: The integration does not use common patterns.
config-flow-test-coverage: todo
config-flow-test-coverage:
status: todo
comment: remove duplicated config flow start in tests, make sure tests ends with CREATE_ENTRY or ABORT, use hass.config_entries.async_setup instead of async_setup_component, snapshot in diagnostics (and other tests when possible), test_client_disconnected validate no error in log
config-flow:
status: todo
comment: remove duplicated config flow start in tests, make sure tests ends with CREATE_ENTRY or ABORT, remove name parameter, use hass.config_entries.async_setup instead of async_setup_component, snapshot in diagnostics (and other tests when possible), test_client_disconnected validate no error in log, make reauth flow more graceful
comment: make reauth flow more graceful
dependency-transparency: done
docs-actions:
status: todo

View File

@ -1,12 +1,11 @@
{
"config": {
"flow_title": "LG webOS Smart TV",
"flow_title": "{name}",
"step": {
"user": {
"description": "Turn on TV, fill the following fields and select **Submit**",
"description": "Turn on the TV, fill the host field and select **Submit**",
"data": {
"host": "[%key:common::config_flow::data::host%]",
"name": "[%key:common::config_flow::data::name%]"
"host": "[%key:common::config_flow::data::host%]"
},
"data_description": {
"host": "Hostname or IP address of your webOS TV."

View File

@ -7,7 +7,15 @@ import pytest
from homeassistant.components.webostv.const import LIVE_TV_APP_ID
from .const import CHANNEL_1, CHANNEL_2, CLIENT_KEY, FAKE_UUID, MOCK_APPS, MOCK_INPUTS
from .const import (
CHANNEL_1,
CHANNEL_2,
CLIENT_KEY,
FAKE_UUID,
MOCK_APPS,
MOCK_INPUTS,
TV_MODEL,
)
@pytest.fixture
@ -28,7 +36,7 @@ def client_fixture():
client = mock_client_class.return_value
client.hello_info = {"deviceUUID": FAKE_UUID}
client.software_info = {"major_ver": "major", "minor_ver": "minor"}
client.system_info = {"modelName": "TVFAKE"}
client.system_info = {"modelName": TV_MODEL}
client.client_key = CLIENT_KEY
client.apps = MOCK_APPS
client.inputs = MOCK_INPUTS

View File

@ -2,10 +2,12 @@
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
from homeassistant.components.webostv.const import LIVE_TV_APP_ID
from homeassistant.util import slugify
FAKE_UUID = "some-fake-uuid"
TV_NAME = "fake_webos"
ENTITY_ID = f"{MP_DOMAIN}.{TV_NAME}"
TV_MODEL = "MODEL"
TV_NAME = f"LG webOS TV {TV_MODEL}"
ENTITY_ID = f"{MP_DOMAIN}.{slugify(TV_NAME)}"
HOST = "1.2.3.4"
CLIENT_KEY = "some-secret"

View File

@ -10,26 +10,31 @@ from homeassistant import config_entries
from homeassistant.components import ssdp
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, CONF_HOST, CONF_NAME, CONF_SOURCE
from homeassistant.const import CONF_CLIENT_SECRET, CONF_HOST, CONF_SOURCE
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from . import setup_webostv
from .const import CLIENT_KEY, FAKE_UUID, HOST, MOCK_APPS, MOCK_INPUTS, TV_NAME
from .const import (
CLIENT_KEY,
FAKE_UUID,
HOST,
MOCK_APPS,
MOCK_INPUTS,
TV_MODEL,
TV_NAME,
)
pytestmark = pytest.mark.usefixtures("mock_setup_entry")
MOCK_USER_CONFIG = {
CONF_HOST: HOST,
CONF_NAME: TV_NAME,
}
MOCK_USER_CONFIG = {CONF_HOST: HOST}
MOCK_DISCOVERY_INFO = ssdp.SsdpServiceInfo(
ssdp_usn="mock_usn",
ssdp_st="mock_st",
ssdp_location=f"http://{HOST}",
upnp={
ssdp.ATTR_UPNP_FRIENDLY_NAME: "LG Webostv",
ssdp.ATTR_UPNP_FRIENDLY_NAME: f"[LG] webOS TV {TV_MODEL}",
ssdp.ATTR_UPNP_UDN: f"uuid:{FAKE_UUID}",
},
)
@ -194,6 +199,14 @@ async def test_form_ssdp(hass: HomeAssistant, client) -> None:
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "pairing"
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], user_input={}
)
await hass.async_block_till_done()
assert result2["type"] is FlowResultType.CREATE_ENTRY
assert result2["title"] == TV_NAME
async def test_ssdp_in_progress(hass: HomeAssistant, client) -> None:
"""Test abort if ssdp paring is already in progress."""
@ -253,10 +266,7 @@ async def test_form_abort_uuid_configured(hass: HomeAssistant, client) -> None:
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "user"
user_config = {
CONF_HOST: "new_host",
CONF_NAME: TV_NAME,
}
user_config = {CONF_HOST: "new_host"}
result = await hass.config_entries.flow.async_init(
DOMAIN,

View File

@ -36,7 +36,7 @@ async def test_diagnostics(
"in1": {"appId": "app0", "id": "in1", "label": "Input01"},
"in2": {"appId": "app1", "id": "in2", "label": "Input02"},
},
"system_info": {"modelName": "TVFAKE"},
"system_info": {"modelName": "MODEL"},
"software_info": {"major_ver": "major", "minor_ver": "minor"},
"hello_info": {"deviceUUID": "**REDACTED**"},
"sound_output": "speaker",
@ -47,7 +47,7 @@ async def test_diagnostics(
"version": 1,
"minor_version": 1,
"domain": "webostv",
"title": "fake_webos",
"title": "LG webOS TV MODEL",
"data": {
"client_secret": "**REDACTED**",
"host": "**REDACTED**",

View File

@ -67,7 +67,7 @@ from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from . import setup_webostv
from .const import CHANNEL_2, ENTITY_ID, TV_NAME
from .const import CHANNEL_2, ENTITY_ID, TV_MODEL, TV_NAME
from tests.common import async_fire_time_changed, mock_restore_cache
from tests.test_util.aiohttp import AiohttpClientMocker
@ -340,7 +340,7 @@ async def test_entity_attributes(
assert device.manufacturer == "LG"
assert device.name == TV_NAME
assert device.sw_version == "major.minor"
assert device.model == "TVFAKE"
assert device.model == TV_MODEL
# Sound output when off
monkeypatch.setattr(client, "sound_output", None)

View File

@ -14,22 +14,24 @@ from homeassistant.components.webostv import DOMAIN
from homeassistant.const import ATTR_ICON
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from homeassistant.util import slugify
from . import setup_webostv
from .const import TV_NAME
ICON_PATH = "/some/path"
MESSAGE = "one, two, testing, testing"
SERVICE_NAME = slugify(TV_NAME)
async def test_notify(hass: HomeAssistant, client) -> None:
"""Test sending a message."""
await setup_webostv(hass)
assert hass.services.has_service(NOTIFY_DOMAIN, TV_NAME)
assert hass.services.has_service(NOTIFY_DOMAIN, SERVICE_NAME)
await hass.services.async_call(
NOTIFY_DOMAIN,
TV_NAME,
SERVICE_NAME,
{
ATTR_MESSAGE: MESSAGE,
ATTR_DATA: {
@ -44,7 +46,7 @@ async def test_notify(hass: HomeAssistant, client) -> None:
await hass.services.async_call(
NOTIFY_DOMAIN,
TV_NAME,
SERVICE_NAME,
{
ATTR_MESSAGE: MESSAGE,
ATTR_DATA: {
@ -59,7 +61,7 @@ async def test_notify(hass: HomeAssistant, client) -> None:
await hass.services.async_call(
NOTIFY_DOMAIN,
TV_NAME,
SERVICE_NAME,
{
ATTR_MESSAGE: "only message, no data",
},
@ -77,12 +79,12 @@ async def test_notify_not_connected(
) -> None:
"""Test sending a message when client is not connected."""
await setup_webostv(hass)
assert hass.services.has_service(NOTIFY_DOMAIN, TV_NAME)
assert hass.services.has_service(NOTIFY_DOMAIN, SERVICE_NAME)
monkeypatch.setattr(client, "is_connected", Mock(return_value=False))
await hass.services.async_call(
NOTIFY_DOMAIN,
TV_NAME,
SERVICE_NAME,
{
ATTR_MESSAGE: MESSAGE,
ATTR_DATA: {
@ -104,12 +106,12 @@ async def test_icon_not_found(
) -> None:
"""Test notify icon not found error."""
await setup_webostv(hass)
assert hass.services.has_service(NOTIFY_DOMAIN, TV_NAME)
assert hass.services.has_service(NOTIFY_DOMAIN, SERVICE_NAME)
monkeypatch.setattr(client, "send_message", Mock(side_effect=FileNotFoundError))
await hass.services.async_call(
NOTIFY_DOMAIN,
TV_NAME,
SERVICE_NAME,
{
ATTR_MESSAGE: MESSAGE,
ATTR_DATA: {
@ -141,13 +143,13 @@ async def test_connection_errors(
) -> None:
"""Test connection errors scenarios."""
await setup_webostv(hass)
assert hass.services.has_service("notify", TV_NAME)
assert hass.services.has_service("notify", SERVICE_NAME)
monkeypatch.setattr(client, "is_connected", Mock(return_value=False))
monkeypatch.setattr(client, "connect", Mock(side_effect=side_effect))
await hass.services.async_call(
NOTIFY_DOMAIN,
TV_NAME,
SERVICE_NAME,
{
ATTR_MESSAGE: MESSAGE,
ATTR_DATA: {
@ -175,4 +177,4 @@ async def test_no_discovery_info(
await hass.async_block_till_done()
assert NOTIFY_DOMAIN in hass.config.components
assert f"Failed to initialize notification service {DOMAIN}" in caplog.text
assert not hass.services.has_service("notify", TV_NAME)
assert not hass.services.has_service("notify", SERVICE_NAME)