mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Add Sonos tests for media_player play Sonos Playlist and improve error handling (#124126)
* initial commit * initial commit * initial commit * updates * add json fixture * use match on pytest.raises
This commit is contained in:
parent
b74aced6f3
commit
d327ec904c
@ -643,11 +643,16 @@ class SonosMediaPlayerEntity(SonosEntity, MediaPlayerEntity):
|
||||
playlists = soco.get_sonos_playlists(complete_result=True)
|
||||
playlist = next((p for p in playlists if p.title == media_id), None)
|
||||
if not playlist:
|
||||
_LOGGER.error('Could not find a Sonos playlist named "%s"', media_id)
|
||||
else:
|
||||
soco.clear_queue()
|
||||
soco.add_to_queue(playlist, timeout=LONG_SERVICE_TIMEOUT)
|
||||
soco.play_from_queue(0)
|
||||
raise ServiceValidationError(
|
||||
translation_domain=SONOS_DOMAIN,
|
||||
translation_key="invalid_sonos_playlist",
|
||||
translation_placeholders={
|
||||
"name": media_id,
|
||||
},
|
||||
)
|
||||
soco.clear_queue()
|
||||
soco.add_to_queue(playlist, timeout=LONG_SERVICE_TIMEOUT)
|
||||
soco.play_from_queue(0)
|
||||
elif media_type in PLAYABLE_MEDIA_TYPES:
|
||||
item = media_browser.get_media(self.media.library, media_id, media_type)
|
||||
|
||||
|
@ -177,6 +177,9 @@
|
||||
"exceptions": {
|
||||
"invalid_favorite": {
|
||||
"message": "Could not find a Sonos favorite: {name}"
|
||||
},
|
||||
"invalid_sonos_playlist": {
|
||||
"message": "Could not find Sonos playlist: {name}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, MagicMock, Mock, patch
|
||||
import pytest
|
||||
from soco import SoCo
|
||||
from soco.alarms import Alarms
|
||||
from soco.data_structures import DidlFavorite, SearchResult
|
||||
from soco.data_structures import DidlFavorite, DidlPlaylistContainer, SearchResult
|
||||
from soco.events_base import Event as SonosEvent
|
||||
|
||||
from homeassistant.components import ssdp, zeroconf
|
||||
@ -184,6 +184,7 @@ class SoCoMockFactory:
|
||||
current_track_info_empty,
|
||||
battery_info,
|
||||
alarm_clock,
|
||||
sonos_playlists: SearchResult,
|
||||
) -> None:
|
||||
"""Initialize the mock factory."""
|
||||
self.mock_list: dict[str, MockSoCo] = {}
|
||||
@ -192,6 +193,7 @@ class SoCoMockFactory:
|
||||
self.current_track_info = current_track_info_empty
|
||||
self.battery_info = battery_info
|
||||
self.alarm_clock = alarm_clock
|
||||
self.sonos_playlists = sonos_playlists
|
||||
|
||||
def cache_mock(
|
||||
self, mock_soco: MockSoCo, ip_address: str, name: str = "Zone A"
|
||||
@ -204,6 +206,7 @@ class SoCoMockFactory:
|
||||
mock_soco.music_library = self.music_library
|
||||
mock_soco.get_current_track_info.return_value = self.current_track_info
|
||||
mock_soco.music_source_from_uri = SoCo.music_source_from_uri
|
||||
mock_soco.get_sonos_playlists.return_value = self.sonos_playlists
|
||||
my_speaker_info = self.speaker_info.copy()
|
||||
my_speaker_info["zone_name"] = name
|
||||
my_speaker_info["uid"] = mock_soco.uid
|
||||
@ -254,11 +257,21 @@ def soco_sharelink():
|
||||
|
||||
@pytest.fixture(name="soco_factory")
|
||||
def soco_factory(
|
||||
music_library, speaker_info, current_track_info_empty, battery_info, alarm_clock
|
||||
music_library,
|
||||
speaker_info,
|
||||
current_track_info_empty,
|
||||
battery_info,
|
||||
alarm_clock,
|
||||
sonos_playlists: SearchResult,
|
||||
):
|
||||
"""Create factory for instantiating SoCo mocks."""
|
||||
factory = SoCoMockFactory(
|
||||
music_library, speaker_info, current_track_info_empty, battery_info, alarm_clock
|
||||
music_library,
|
||||
speaker_info,
|
||||
current_track_info_empty,
|
||||
battery_info,
|
||||
alarm_clock,
|
||||
sonos_playlists,
|
||||
)
|
||||
with (
|
||||
patch("homeassistant.components.sonos.SoCo", new=factory.get_mock),
|
||||
@ -335,6 +348,14 @@ def sonos_favorites_fixture() -> SearchResult:
|
||||
return SearchResult(favorite_list, "favorites", 3, 3, 1)
|
||||
|
||||
|
||||
@pytest.fixture(name="sonos_playlists")
|
||||
def sonos_playlists_fixture() -> SearchResult:
|
||||
"""Create sonos playlist fixture."""
|
||||
playlists = load_json_value_fixture("sonos_playlists.json", "sonos")
|
||||
playlists_list = [DidlPlaylistContainer.from_dict(pl) for pl in playlists]
|
||||
return SearchResult(playlists_list, "sonos_playlists", 1, 1, 0)
|
||||
|
||||
|
||||
class MockMusicServiceItem:
|
||||
"""Mocks a Soco MusicServiceItem."""
|
||||
|
||||
|
13
tests/components/sonos/fixtures/sonos_playlists.json
Normal file
13
tests/components/sonos/fixtures/sonos_playlists.json
Normal file
@ -0,0 +1,13 @@
|
||||
[
|
||||
{
|
||||
"title": "sample playlist",
|
||||
"parent_id": "SQ:",
|
||||
"item_id": "SQ:0",
|
||||
"resources": [
|
||||
{
|
||||
"uri": "file:///jffs/settings/savedqueues.rsq#0",
|
||||
"protocol_info": "file:*:audio/mpegurl:*"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -1,10 +1,10 @@
|
||||
"""Tests for the Sonos Media Player platform."""
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from soco.data_structures import SearchResult
|
||||
from syrupy import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.media_player import (
|
||||
@ -535,8 +535,10 @@ async def test_play_media_music_library_playlist_dne(
|
||||
soco_mock = soco_factory.mock_list.get("192.168.42.2")
|
||||
soco_mock.music_library.get_playlists.return_value = _mock_playlists
|
||||
|
||||
with caplog.at_level(logging.ERROR):
|
||||
caplog.clear()
|
||||
with pytest.raises(
|
||||
ServiceValidationError,
|
||||
match=f"Could not find Sonos playlist: {media_content_id}",
|
||||
):
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
@ -548,8 +550,53 @@ async def test_play_media_music_library_playlist_dne(
|
||||
blocking=True,
|
||||
)
|
||||
assert soco_mock.play_uri.call_count == 0
|
||||
assert media_content_id in caplog.text
|
||||
assert "playlist" in caplog.text
|
||||
|
||||
|
||||
async def test_play_sonos_playlist(
|
||||
hass: HomeAssistant,
|
||||
async_autosetup_sonos,
|
||||
soco: MockSoCo,
|
||||
sonos_playlists: SearchResult,
|
||||
) -> None:
|
||||
"""Test that sonos playlists can be played."""
|
||||
|
||||
# Test a successful call
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
{
|
||||
ATTR_ENTITY_ID: "media_player.zone_a",
|
||||
ATTR_MEDIA_CONTENT_TYPE: "playlist",
|
||||
ATTR_MEDIA_CONTENT_ID: "sample playlist",
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert soco.clear_queue.call_count == 1
|
||||
assert soco.add_to_queue.call_count == 1
|
||||
soco.add_to_queue.asset_called_with(
|
||||
sonos_playlists[0], timeout=LONG_SERVICE_TIMEOUT
|
||||
)
|
||||
|
||||
# Test playing a non-existent playlist
|
||||
soco.clear_queue.reset_mock()
|
||||
soco.add_to_queue.reset_mock()
|
||||
media_content_id: str = "bad playlist"
|
||||
with pytest.raises(
|
||||
ServiceValidationError,
|
||||
match=f"Could not find Sonos playlist: {media_content_id}",
|
||||
):
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
{
|
||||
ATTR_ENTITY_ID: "media_player.zone_a",
|
||||
ATTR_MEDIA_CONTENT_TYPE: "playlist",
|
||||
ATTR_MEDIA_CONTENT_ID: media_content_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert soco.clear_queue.call_count == 0
|
||||
assert soco.add_to_queue.call_count == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
Loading…
x
Reference in New Issue
Block a user