core/tests/components/squeezebox/conftest.py

290 lines
9.4 KiB
Python

"""Setup the squeezebox tests."""
from collections.abc import Generator
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from homeassistant.components.media_player import MediaType
from homeassistant.components.squeezebox import const
from homeassistant.components.squeezebox.browse_media import (
MEDIA_TYPE_TO_SQUEEZEBOX,
SQUEEZEBOX_ID_BY_TYPE,
)
from homeassistant.components.squeezebox.const import (
STATUS_QUERY_LIBRARYNAME,
STATUS_QUERY_MAC,
STATUS_QUERY_UUID,
STATUS_QUERY_VERSION,
STATUS_SENSOR_INFO_TOTAL_ALBUMS,
STATUS_SENSOR_INFO_TOTAL_ARTISTS,
STATUS_SENSOR_INFO_TOTAL_DURATION,
STATUS_SENSOR_INFO_TOTAL_GENRES,
STATUS_SENSOR_INFO_TOTAL_SONGS,
STATUS_SENSOR_LASTSCAN,
STATUS_SENSOR_OTHER_PLAYER_COUNT,
STATUS_SENSOR_PLAYER_COUNT,
STATUS_SENSOR_RESCAN,
)
from homeassistant.const import CONF_HOST, CONF_PORT, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import format_mac
# from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry
TEST_HOST = "1.2.3.4"
TEST_PORT = "9000"
TEST_USE_HTTPS = False
SERVER_UUIDS = [
"12345678-1234-1234-1234-123456789012",
"87654321-4321-4321-4321-210987654321",
]
TEST_MAC = ["aa:bb:cc:dd:ee:ff", "ff:ee:dd:cc:bb:aa"]
TEST_PLAYER_NAME = "Test Player"
TEST_SERVER_NAME = "Test Server"
FAKE_VALID_ITEM_ID = "1234"
FAKE_INVALID_ITEM_ID = "4321"
FAKE_IP = "42.42.42.42"
FAKE_MAC = "deadbeefdead"
FAKE_UUID = "deadbeefdeadbeefbeefdeafbeef42"
FAKE_PORT = 9000
FAKE_VERSION = "42.0"
FAKE_QUERY_RESPONSE = {
STATUS_QUERY_UUID: FAKE_UUID,
STATUS_QUERY_MAC: FAKE_MAC,
STATUS_QUERY_VERSION: FAKE_VERSION,
STATUS_SENSOR_RESCAN: 1,
STATUS_SENSOR_LASTSCAN: 0,
STATUS_QUERY_LIBRARYNAME: "FakeLib",
STATUS_SENSOR_INFO_TOTAL_ALBUMS: 4,
STATUS_SENSOR_INFO_TOTAL_ARTISTS: 2,
STATUS_SENSOR_INFO_TOTAL_DURATION: 500,
STATUS_SENSOR_INFO_TOTAL_GENRES: 1,
STATUS_SENSOR_INFO_TOTAL_SONGS: 42,
STATUS_SENSOR_PLAYER_COUNT: 10,
STATUS_SENSOR_OTHER_PLAYER_COUNT: 0,
"players_loop": [
{
"isplaying": 0,
"name": "SqueezeLite-HA-Addon",
"seq_no": 0,
"modelname": "SqueezeLite-HA-Addon",
"playerindex": "status",
"model": "squeezelite",
"uuid": FAKE_UUID,
"canpoweroff": 1,
"ip": "192.168.78.86:57700",
"displaytype": "none",
"playerid": "f9:23:cd:37:c5:ff",
"power": 0,
"isplayer": 1,
"connected": 1,
"firmware": "v2.0.0-1488",
}
],
"count": 1,
}
@pytest.fixture
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.squeezebox.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry
@pytest.fixture
def config_entry(hass: HomeAssistant) -> MockConfigEntry:
"""Add the squeezebox mock config entry to hass."""
config_entry = MockConfigEntry(
domain=const.DOMAIN,
unique_id=SERVER_UUIDS[0],
data={
CONF_HOST: TEST_HOST,
CONF_PORT: TEST_PORT,
const.CONF_HTTPS: TEST_USE_HTTPS,
},
)
config_entry.add_to_hass(hass)
return config_entry
async def mock_async_browse(
media_type: MediaType, limit: int, browse_id: tuple | None = None
) -> dict | None:
"""Mock the async_browse method of pysqueezebox.Player."""
child_types = {
"favorites": "favorites",
"new music": "album",
"albums": "album",
"album": "track",
"genres": "genre",
"genre": "album",
"artists": "artist",
"artist": "album",
"titles": "title",
"title": "title",
"playlists": "playlist",
"playlist": "title",
}
fake_items = [
{
"title": "Fake Item 1",
"id": FAKE_VALID_ITEM_ID,
"hasitems": False,
"item_type": child_types[media_type],
"artwork_track_id": "b35bb9e9",
"url": "file:///var/lib/squeezeboxserver/music/track_1.mp3",
},
{
"title": "Fake Item 2",
"id": FAKE_VALID_ITEM_ID + "_2",
"hasitems": media_type == "favorites",
"item_type": child_types[media_type],
"image_url": "http://lms.internal:9000/html/images/favorites.png",
"url": "file:///var/lib/squeezeboxserver/music/track_2.mp3",
},
{
"title": "Fake Item 3",
"id": FAKE_VALID_ITEM_ID + "_3",
"hasitems": media_type == "favorites",
"album_id": FAKE_VALID_ITEM_ID if media_type == "favorites" else None,
"url": "file:///var/lib/squeezeboxserver/music/track_3.mp3",
},
]
if browse_id:
search_type, search_id = browse_id
if search_id:
if search_type == "playlist_id":
return (
{
"title": "Fake Item 1",
"items": fake_items,
}
if search_id == FAKE_VALID_ITEM_ID
else None
)
if search_type in SQUEEZEBOX_ID_BY_TYPE.values():
for item in fake_items:
if item["id"] == search_id:
return {
"title": item["title"],
"items": [item],
}
return None
if search_type in SQUEEZEBOX_ID_BY_TYPE.values():
return {
"title": search_type,
"items": fake_items,
}
return None
if media_type in MEDIA_TYPE_TO_SQUEEZEBOX.values():
return {
"title": media_type,
"items": fake_items,
}
return None
@pytest.fixture
def player() -> MagicMock:
"""Return a mock player."""
return mock_pysqueezebox_player()
@pytest.fixture
def player_factory() -> MagicMock:
"""Return a factory for creating mock players."""
return mock_pysqueezebox_player
def mock_pysqueezebox_player(uuid: str) -> MagicMock:
"""Mock a Lyrion Media Server player."""
with patch(
"homeassistant.components.squeezebox.Player", autospec=True
) as mock_player:
mock_player.async_browse = AsyncMock(side_effect=mock_async_browse)
mock_player.generate_image_url_from_track_id = MagicMock(
return_value="http://lms.internal:9000/html/images/favorites.png"
)
mock_player.name = TEST_PLAYER_NAME
mock_player.player_id = uuid
mock_player.mode = "stop"
mock_player.playlist = None
mock_player.album = None
mock_player.artist = None
mock_player.remote_title = None
mock_player.title = None
mock_player.image_url = None
mock_player.model = "SqueezeLite"
return mock_player
@pytest.fixture
def lms_factory(player_factory: MagicMock) -> MagicMock:
"""Return a factory for creating mock Lyrion Media Servers with arbitrary number of players."""
return lambda player_count, uuid: mock_pysqueezebox_server(
player_factory, player_count, uuid
)
@pytest.fixture
def lms(player_factory: MagicMock) -> MagicMock:
"""Mock a Lyrion Media Server with one mock player attached."""
return mock_pysqueezebox_server(player_factory, 1, uuid=TEST_MAC[0])
def mock_pysqueezebox_server(
player_factory: MagicMock, player_count: int, uuid: str
) -> MagicMock:
"""Create a mock Lyrion Media Server with the given number of mock players attached."""
with patch("homeassistant.components.squeezebox.Server", autospec=True) as mock_lms:
players = [player_factory(TEST_MAC[index]) for index in range(player_count)]
mock_lms.async_get_players = AsyncMock(return_value=players)
mock_lms.uuid = uuid
mock_lms.name = TEST_SERVER_NAME
mock_lms.async_query = AsyncMock(return_value={"uuid": format_mac(uuid)})
mock_lms.async_status = AsyncMock(return_value={"uuid": format_mac(uuid)})
return mock_lms
async def configure_squeezebox_media_player_platform(
hass: HomeAssistant,
config_entry: MockConfigEntry,
lms: MagicMock,
) -> None:
"""Configure a squeezebox config entry with appropriate mocks for media_player."""
with (
patch("homeassistant.components.squeezebox.PLATFORMS", [Platform.MEDIA_PLAYER]),
patch("homeassistant.components.squeezebox.Server", return_value=lms),
):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done(wait_background_tasks=True)
@pytest.fixture
async def configured_player(
hass: HomeAssistant, config_entry: MockConfigEntry, lms: MagicMock
) -> MagicMock:
"""Fixture mocking calls to pysqueezebox Player from a configured squeezebox."""
await configure_squeezebox_media_player_platform(hass, config_entry, lms)
return (await lms.async_get_players())[0]
@pytest.fixture
async def configured_players(
hass: HomeAssistant, config_entry: MockConfigEntry, lms_factory: MagicMock
) -> list[MagicMock]:
"""Fixture mocking calls to two pysqueezebox Players from a configured squeezebox."""
lms = lms_factory(2, uuid=SERVER_UUIDS[0])
await configure_squeezebox_media_player_platform(hass, config_entry, lms)
return await lms.async_get_players()