core/tests/components/sonos/test_media_player.py

173 lines
5.1 KiB
Python
Raw Normal View History

"""Tests for the Sonos Media Player platform."""
import logging
import pytest
from homeassistant.components.media_player import (
DOMAIN as MP_DOMAIN,
SERVICE_PLAY_MEDIA,
)
from homeassistant.const import STATE_IDLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import (
CONNECTION_NETWORK_MAC,
CONNECTION_UPNP,
DeviceRegistry,
)
from .conftest import SoCoMockFactory
async def test_device_registry(
hass: HomeAssistant, device_registry: DeviceRegistry, async_autosetup_sonos, soco
) -> None:
"""Test sonos device registered in the device registry."""
reg_device = device_registry.async_get_device(
identifiers={("sonos", "RINCON_test")}
)
assert reg_device is not None
assert reg_device.model == "Model Name"
assert reg_device.sw_version == "13.1"
assert reg_device.connections == {
(CONNECTION_NETWORK_MAC, "00:11:22:33:44:55"),
(CONNECTION_UPNP, "uuid:RINCON_test"),
}
assert reg_device.manufacturer == "Sonos"
assert reg_device.name == "Zone A"
# Default device provides battery info, area should not be suggested
assert reg_device.suggested_area is None
async def test_device_registry_not_portable(
hass: HomeAssistant, device_registry: DeviceRegistry, async_setup_sonos, soco
) -> None:
"""Test non-portable sonos device registered in the device registry to ensure area suggested."""
soco.get_battery_info.return_value = {}
await async_setup_sonos()
reg_device = device_registry.async_get_device(
identifiers={("sonos", "RINCON_test")}
)
assert reg_device is not None
assert reg_device.suggested_area == "Zone A"
async def test_entity_basic(
hass: HomeAssistant, async_autosetup_sonos, discover
) -> None:
"""Test basic state and attributes."""
state = hass.states.get("media_player.zone_a")
assert state.state == STATE_IDLE
attributes = state.attributes
assert attributes["friendly_name"] == "Zone A"
assert attributes["is_volume_muted"] is False
assert attributes["volume_level"] == 0.19
class _MockMusicServiceItem:
"""Mocks a Soco MusicServiceItem."""
def __init__(
self,
title: str,
item_id: str,
parent_id: str,
item_class: str,
) -> None:
"""Initialize the mock item."""
self.title = title
self.item_id = item_id
self.item_class = item_class
self.parent_id = parent_id
def get_uri(self) -> str:
"""Return URI."""
return self.item_id.replace("S://", "x-file-cifs://")
_mock_playlists = [
_MockMusicServiceItem(
"playlist1",
"S://192.168.1.68/music/iTunes/iTunes%20Music%20Library.xml#GUID_1",
"A:PLAYLISTS",
"object.container.playlistContainer",
),
_MockMusicServiceItem(
"playlist2",
"S://192.168.1.68/music/iTunes/iTunes%20Music%20Library.xml#GUID_2",
"A:PLAYLISTS",
"object.container.playlistContainer",
),
]
@pytest.mark.parametrize(
("media_content_id", "expected_item_id"),
[
(
_mock_playlists[0].item_id,
_mock_playlists[0].item_id,
),
(
f"S:{_mock_playlists[1].title}",
_mock_playlists[1].item_id,
),
],
)
async def test_play_media_music_library_playlist(
hass: HomeAssistant,
soco_factory: SoCoMockFactory,
async_autosetup_sonos,
discover,
media_content_id,
expected_item_id,
) -> None:
"""Test that playlists can be found by id or title."""
soco_mock = soco_factory.mock_list.get("192.168.42.2")
soco_mock.music_library.get_playlists.return_value = _mock_playlists
await hass.services.async_call(
MP_DOMAIN,
SERVICE_PLAY_MEDIA,
{
"entity_id": "media_player.zone_a",
"media_content_type": "playlist",
"media_content_id": media_content_id,
},
blocking=True,
)
assert soco_mock.clear_queue.call_count == 1
assert soco_mock.add_to_queue.call_count == 1
assert soco_mock.add_to_queue.call_args_list[0].args[0].item_id == expected_item_id
assert soco_mock.play_from_queue.call_count == 1
async def test_play_media_music_library_playlist_dne(
hass: HomeAssistant,
soco_factory: SoCoMockFactory,
async_autosetup_sonos,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test error handling when attempting to play a non-existent playlist ."""
media_content_id = "S:nonexistent"
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()
await hass.services.async_call(
MP_DOMAIN,
SERVICE_PLAY_MEDIA,
{
"entity_id": "media_player.zone_a",
"media_content_type": "playlist",
"media_content_id": media_content_id,
},
blocking=True,
)
assert soco_mock.play_uri.call_count == 0
assert media_content_id in caplog.text
assert "playlist" in caplog.text