From 194a97ce34e12d404901168f5920ff401f1c0f2c Mon Sep 17 00:00:00 2001 From: James Mackay Date: Fri, 9 Oct 2026 07:17:14 +0100 Subject: [PATCH] feat(button,media_player): Pair ADB carries entity_category CONFIG (t30 G11) + BrowseMediaSource domain parameter at root and children (t30 G18, 2026-05-20 blog contract); stubs/tests pin both --- custom_components/nvidia_shield/button.py | 3 ++- custom_components/nvidia_shield/media_player.py | 4 ++++ tests/entity_stublib.py | 5 +++++ tests/test_command_routing.py | 4 ++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/custom_components/nvidia_shield/button.py b/custom_components/nvidia_shield/button.py index 620bba0..08889ab 100644 --- a/custom_components/nvidia_shield/button.py +++ b/custom_components/nvidia_shield/button.py @@ -5,7 +5,7 @@ import logging from homeassistant.components.button import ButtonEntity from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant -from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.entity import DeviceInfo, EntityCategory from homeassistant.helpers.entity_platform import AddEntitiesCallback from .adb_session import AdbMediaSessionPoller, ensure_adb_key @@ -36,6 +36,7 @@ class NvidiaShieldPairAdbButton(ButtonEntity): _attr_has_entity_name = True _attr_name = "Pair ADB" + _attr_entity_category = EntityCategory.CONFIG _attr_icon = "mdi:link-variant" def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None: diff --git a/custom_components/nvidia_shield/media_player.py b/custom_components/nvidia_shield/media_player.py index 10d0bab..2bbadea 100644 --- a/custom_components/nvidia_shield/media_player.py +++ b/custom_components/nvidia_shield/media_player.py @@ -941,6 +941,8 @@ class NvidiaShieldMediaPlayer(MediaPlayerEntity): ) app_map = self._entry.options.get(CONF_APP_NAME_MAP) or DEFAULT_APP_DIRECTORY + # G18 (2026-05-20 blog): BrowseMediaSource must carry the domain + # parameter so the frontend can attribute the media tree. children = [ BrowseMediaSource( title=name, @@ -949,6 +951,7 @@ class NvidiaShieldMediaPlayer(MediaPlayerEntity): media_content_id=pkg, can_play=True, can_expand=False, + domain=DOMAIN, ) for pkg, name in app_map.items() ] @@ -960,6 +963,7 @@ class NvidiaShieldMediaPlayer(MediaPlayerEntity): can_play=False, can_expand=True, children=children, + domain=DOMAIN, ) # ── play_media (§7): channel digits, app/url launch ── diff --git a/tests/entity_stublib.py b/tests/entity_stublib.py index 714b7b4..d24aa1c 100644 --- a/tests/entity_stublib.py +++ b/tests/entity_stublib.py @@ -78,6 +78,7 @@ class BrowseMediaSource: media_content_id, can_play, can_expand, + domain=None, # t30 G18 (2026-05-20 blog contract) children=None, thumbnail=None, ): @@ -87,6 +88,7 @@ class BrowseMediaSource: self.media_content_id = media_content_id self.can_play = can_play self.can_expand = can_expand + self.domain = domain self.children = children or [] self.thumbnail = thumbnail @@ -287,6 +289,9 @@ def install() -> None: ) entity = types.ModuleType("homeassistant.helpers.entity") entity.DeviceInfo = dict + entity.EntityCategory = types.SimpleNamespace( + CONFIG="config", DIAGNOSTIC="diagnostic" + ) helpers.entity = entity entity_platform = types.ModuleType("homeassistant.helpers.entity_platform") entity_platform.AddEntitiesCallback = object diff --git a/tests/test_command_routing.py b/tests/test_command_routing.py index 7a45890..202a442 100644 --- a/tests/test_command_routing.py +++ b/tests/test_command_routing.py @@ -971,6 +971,10 @@ class TestBrowseMediaDirectory: ("com.netflix.ninja", "Netflix"), ] assert all(c.media_content_type == "app" for c in root.children) + # t30 G18 (2026-05-20 blog): the domain parameter is present at + # every level of the tree + assert root.domain == "nvidia_shield" + assert all(c.domain == "nvidia_shield" for c in root.children) async def test_root_falls_back_to_the_curated_default(self, modules): player, _s, _i = make_player(modules) # no apps map configured