Fix missing media player for a new console added at runtime (#182883)

This commit is contained in:
Sean Cardus
2026-09-30 11:45:32 +01:00
committed by GitHub
parent 1dc254789b
commit 98e2663822
3 changed files with 68 additions and 2 deletions
+6
View File
@@ -155,6 +155,12 @@ class XboxConsoleBaseEntity(CoordinatorEntity[XboxConsoleStatusCoordinator]):
"""Return if entity is available."""
return self.coordinator.data.get(self._console.id) is not None
@property
@override
def entity_picture(self) -> str | None:
"""Return the entity picture."""
return super().entity_picture if self.available else None
def to_https(image_url: str) -> str:
"""Convert image URLs to secure URLs."""
@@ -127,6 +127,7 @@ class XboxMediaPlayer(XboxConsoleBaseEntity, MediaPlayerEntity):
@override
def state(self) -> MediaPlayerState | None:
"""State of the player."""
status = self.data.status
if status.playback_state in XBOX_STATE_MAP:
return XBOX_STATE_MAP[status.playback_state]
@@ -136,7 +137,10 @@ class XboxMediaPlayer(XboxConsoleBaseEntity, MediaPlayerEntity):
@override
def supported_features(self) -> MediaPlayerEntityFeature:
"""Flag media player features that are supported."""
if self.state not in [MediaPlayerState.PLAYING, MediaPlayerState.PAUSED]:
if not self.available or self.state not in [
MediaPlayerState.PLAYING,
MediaPlayerState.PAUSED,
]:
return (
SUPPORT_XBOX
& ~MediaPlayerEntityFeature.NEXT_TRACK
@@ -181,7 +185,8 @@ class XboxMediaPlayer(XboxConsoleBaseEntity, MediaPlayerEntity):
return (
to_https(image.uri)
if (app_details := self.data.app_details)
if self.available
and (app_details := self.data.app_details)
and (image := _find_media_image(app_details.localized_properties[0].images))
else None
)
@@ -1,14 +1,17 @@
"""Test the Xbox media_player platform."""
from collections.abc import Generator
from datetime import timedelta
from typing import Any
from unittest.mock import patch
from freezegun.api import FrozenDateTimeFactory
from httpx import HTTPStatusError, RequestError, TimeoutException
import pytest
from pythonxbox.api.provider.catalog.models import CatalogResponse
from pythonxbox.api.provider.smartglass.models import (
CommandResponse,
SmartglassConsoleList,
SmartglassConsoleStatus,
VolumeDirection,
)
@@ -35,6 +38,7 @@ from homeassistant.const import (
SERVICE_VOLUME_DOWN,
SERVICE_VOLUME_MUTE,
SERVICE_VOLUME_UP,
STATE_UNAVAILABLE,
Platform,
)
from homeassistant.core import HomeAssistant
@@ -45,6 +49,7 @@ from tests.common import (
AsyncMock,
Mock,
MockConfigEntry,
async_fire_time_changed,
async_load_json_object_fixture,
snapshot_platform,
)
@@ -110,6 +115,56 @@ async def test_media_players(
await snapshot_platform(hass, entity_registry, snapshot, config_entry.entry_id)
async def test_media_player_added_before_console_status(
hass: HomeAssistant,
config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
xbox_live_client: AsyncMock,
freezer: FrozenDateTimeFactory,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test a console that appears before it has been polled for status.
The status coordinator only polls consoles an entity has registered for, so
a console added at runtime has no status data when its entity is created.
"""
xbox_live_client.smartglass.get_console_list.return_value = SmartglassConsoleList(
**await async_load_json_object_fixture(
hass, "smartglass_console_list_empty.json", DOMAIN
) # pyright: ignore[reportArgumentType]
)
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED
assert not config_entry.runtime_data.status.data
xbox_live_client.smartglass.get_console_list.return_value = SmartglassConsoleList(
**await async_load_json_object_fixture(
hass, "smartglass_console_list.json", DOMAIN
) # pyright: ignore[reportArgumentType]
)
freezer.tick(timedelta(minutes=10))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert "Error adding entity" not in caplog.text
assert entity_registry.async_get("media_player.xonex") is not None
assert (state := hass.states.get("media_player.xonex")) is not None
assert state.state == STATE_UNAVAILABLE
freezer.tick(timedelta(seconds=15))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert (state := hass.states.get("media_player.xonex")) is not None
assert state.state != STATE_UNAVAILABLE
@pytest.mark.usefixtures("xbox_live_client")
async def test_browse_media(
hass: HomeAssistant,