173 lines
5.1 KiB
Python
173 lines
5.1 KiB
Python
"""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
|