Add Sonos tests for announce and update error handling (#124539)

* initial commit

* update error message

* use match for error message
This commit is contained in:
Pete Sage 2024-08-25 15:25:20 -04:00 committed by GitHub
parent 18212052a4
commit 8bc9fd23bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 95 additions and 2 deletions

View File

@ -542,8 +542,13 @@ class SonosMediaPlayerEntity(SonosEntity, MediaPlayerEntity):
raise HomeAssistantError(
f"Error when calling Sonos websocket: {exc}"
) from exc
if response["success"]:
if response.get("success"):
return
raise HomeAssistantError(
translation_domain=SONOS_DOMAIN,
translation_key="announce_media_error",
translation_placeholders={"media_id": media_id, "response": response},
)
if spotify.is_spotify_media_type(media_type):
media_type = spotify.resolve_spotify_media_type(media_type)

View File

@ -180,6 +180,9 @@
},
"invalid_sonos_playlist": {
"message": "Could not find Sonos playlist: {name}"
},
"announce_media_error": {
"message": "Announcing clip {media_id} failed {response}"
}
}
}

View File

@ -255,6 +255,19 @@ def soco_sharelink():
yield mock_instance
@pytest.fixture(name="sonos_websocket")
def sonos_websocket():
"""Fixture to mock SonosWebSocket."""
with patch(
"homeassistant.components.sonos.speaker.SonosWebsocket"
) as mock_sonos_ws:
mock_instance = AsyncMock()
mock_instance.play_clip = AsyncMock()
mock_instance.play_clip.return_value = [{"success": 1}, {}]
mock_sonos_ws.return_value = mock_instance
yield mock_instance
@pytest.fixture(name="soco_factory")
def soco_factory(
music_library,
@ -263,6 +276,7 @@ def soco_factory(
battery_info,
alarm_clock,
sonos_playlists: SearchResult,
sonos_websocket,
):
"""Create factory for instantiating SoCo mocks."""
factory = SoCoMockFactory(

View File

@ -5,13 +5,16 @@ from unittest.mock import patch
import pytest
from soco.data_structures import SearchResult
from sonos_websocket.exception import SonosWebsocketError
from syrupy import SnapshotAssertion
from homeassistant.components.media_player import (
ATTR_INPUT_SOURCE,
ATTR_MEDIA_ANNOUNCE,
ATTR_MEDIA_CONTENT_ID,
ATTR_MEDIA_CONTENT_TYPE,
ATTR_MEDIA_ENQUEUE,
ATTR_MEDIA_EXTRA,
ATTR_MEDIA_REPEAT,
ATTR_MEDIA_SHUFFLE,
ATTR_MEDIA_VOLUME_LEVEL,
@ -47,7 +50,7 @@ from homeassistant.const import (
SERVICE_VOLUME_UP,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.device_registry import (
CONNECTION_NETWORK_MAC,
@ -1050,3 +1053,71 @@ async def test_media_transport(
blocking=True,
)
assert getattr(soco, client_call).call_count == 1
async def test_play_media_announce(
hass: HomeAssistant,
soco: MockSoCo,
async_autosetup_sonos,
sonos_websocket,
) -> None:
"""Test playing media with the announce."""
content_id: str = "http://10.0.0.1:8123/local/sounds/doorbell.mp3"
volume: float = 0.30
# Test the success path
await hass.services.async_call(
MP_DOMAIN,
SERVICE_PLAY_MEDIA,
{
ATTR_ENTITY_ID: "media_player.zone_a",
ATTR_MEDIA_CONTENT_TYPE: "music",
ATTR_MEDIA_CONTENT_ID: content_id,
ATTR_MEDIA_ANNOUNCE: True,
ATTR_MEDIA_EXTRA: {"volume": volume},
},
blocking=True,
)
assert sonos_websocket.play_clip.call_count == 1
sonos_websocket.play_clip.assert_called_with(content_id, volume=volume)
# Test receiving a websocket exception
sonos_websocket.play_clip.reset_mock()
sonos_websocket.play_clip.side_effect = SonosWebsocketError("Error Message")
with pytest.raises(
HomeAssistantError, match="Error when calling Sonos websocket: Error Message"
):
await hass.services.async_call(
MP_DOMAIN,
SERVICE_PLAY_MEDIA,
{
ATTR_ENTITY_ID: "media_player.zone_a",
ATTR_MEDIA_CONTENT_TYPE: "music",
ATTR_MEDIA_CONTENT_ID: content_id,
ATTR_MEDIA_ANNOUNCE: True,
},
blocking=True,
)
assert sonos_websocket.play_clip.call_count == 1
sonos_websocket.play_clip.assert_called_with(content_id, volume=None)
# Test receiving a non success result
sonos_websocket.play_clip.reset_mock()
sonos_websocket.play_clip.side_effect = None
retval = {"success": 0}
sonos_websocket.play_clip.return_value = [retval, {}]
with pytest.raises(
HomeAssistantError, match=f"Announcing clip {content_id} failed {retval}"
):
await hass.services.async_call(
MP_DOMAIN,
SERVICE_PLAY_MEDIA,
{
ATTR_ENTITY_ID: "media_player.zone_a",
ATTR_MEDIA_CONTENT_TYPE: "music",
ATTR_MEDIA_CONTENT_ID: content_id,
ATTR_MEDIA_ANNOUNCE: True,
},
blocking=True,
)
assert sonos_websocket.play_clip.call_count == 1