core/tests/components/plex/test_services.py

234 lines
7.9 KiB
Python
Raw Normal View History

"""Tests for various Plex services."""
from http import HTTPStatus
from unittest.mock import patch
import plexapi.audio
from plexapi.exceptions import NotFound
import plexapi.playqueue
import pytest
from homeassistant.components.media_player.const import MEDIA_TYPE_MUSIC
from homeassistant.components.plex.const import (
CONF_SERVER,
CONF_SERVER_IDENTIFIER,
DOMAIN,
PLEX_SERVER_CONFIG,
PLEX_URI_SCHEME,
SERVICE_REFRESH_LIBRARY,
SERVICE_SCAN_CLIENTS,
)
from homeassistant.components.plex.services import process_plex_payload
from homeassistant.const import CONF_URL
from homeassistant.exceptions import HomeAssistantError
from .const import DEFAULT_DATA, DEFAULT_OPTIONS, SECONDARY_DATA
from tests.common import MockConfigEntry
async def test_refresh_library(
hass,
mock_plex_server,
setup_plex_server,
requests_mock,
empty_payload,
plex_server_accounts,
plex_server_base,
):
"""Test refresh_library service call."""
url = mock_plex_server.url_in_use
refresh = requests_mock.get(
f"{url}/library/sections/1/refresh", status_code=HTTPStatus.OK
)
# Test with non-existent server
with pytest.raises(HomeAssistantError):
assert await hass.services.async_call(
DOMAIN,
SERVICE_REFRESH_LIBRARY,
{"server_name": "Not a Server", "library_name": "Movies"},
True,
)
assert not refresh.called
# Test with non-existent library
assert await hass.services.async_call(
DOMAIN,
SERVICE_REFRESH_LIBRARY,
{"library_name": "Not a Library"},
True,
)
assert not refresh.called
# Test with valid library
assert await hass.services.async_call(
DOMAIN,
SERVICE_REFRESH_LIBRARY,
{"library_name": "Movies"},
True,
)
assert refresh.call_count == 1
# Add a second configured server
secondary_url = SECONDARY_DATA[PLEX_SERVER_CONFIG][CONF_URL]
secondary_name = SECONDARY_DATA[CONF_SERVER]
secondary_id = SECONDARY_DATA[CONF_SERVER_IDENTIFIER]
requests_mock.get(
secondary_url,
text=plex_server_base.format(
name=secondary_name, machine_identifier=secondary_id
),
)
requests_mock.get(f"{secondary_url}/accounts", text=plex_server_accounts)
requests_mock.get(f"{secondary_url}/clients", text=empty_payload)
requests_mock.get(f"{secondary_url}/status/sessions", text=empty_payload)
entry_2 = MockConfigEntry(
domain=DOMAIN,
data=SECONDARY_DATA,
options=DEFAULT_OPTIONS,
unique_id=SECONDARY_DATA["server_id"],
)
await setup_plex_server(config_entry=entry_2)
# Test multiple servers available but none specified
with pytest.raises(HomeAssistantError) as excinfo:
assert await hass.services.async_call(
DOMAIN,
SERVICE_REFRESH_LIBRARY,
{"library_name": "Movies"},
True,
)
assert "Multiple Plex servers configured" in str(excinfo.value)
assert refresh.call_count == 1
async def test_scan_clients(hass, mock_plex_server):
"""Test scan_for_clients service call."""
assert await hass.services.async_call(
DOMAIN,
SERVICE_SCAN_CLIENTS,
blocking=True,
)
async def test_lookup_media_for_other_integrations(
hass,
entry,
setup_plex_server,
requests_mock,
playqueue_1234,
playqueue_created,
):
"""Test media lookup for media_player.play_media calls from cast/sonos."""
CONTENT_ID = PLEX_URI_SCHEME + '{"library_name": "Music", "artist_name": "Artist"}'
CONTENT_ID_KEY = PLEX_URI_SCHEME + "100"
CONTENT_ID_BAD_MEDIA = (
PLEX_URI_SCHEME + '{"library_name": "Music", "artist_name": "Not an Artist"}'
)
CONTENT_ID_PLAYQUEUE = PLEX_URI_SCHEME + '{"playqueue_id": 1234}'
CONTENT_ID_BAD_PLAYQUEUE = PLEX_URI_SCHEME + '{"playqueue_id": 1235}'
CONTENT_ID_SERVER = (
PLEX_URI_SCHEME
+ '{"plex_server": "Plex Server 1", "library_name": "Music", "artist_name": "Artist"}'
)
CONTENT_ID_SHUFFLE = (
PLEX_URI_SCHEME
+ '{"library_name": "Music", "artist_name": "Artist", "shuffle": 1}'
)
# Test with no Plex integration available
with pytest.raises(HomeAssistantError) as excinfo:
process_plex_payload(hass, MEDIA_TYPE_MUSIC, CONTENT_ID)
assert "Plex integration not configured" in str(excinfo.value)
with patch(
"homeassistant.components.plex.PlexServer.connect", side_effect=NotFound
):
# Initialize Plex integration without setting up a server
with pytest.raises(AssertionError):
await setup_plex_server()
# Test with no Plex servers available
with pytest.raises(HomeAssistantError) as excinfo:
process_plex_payload(hass, MEDIA_TYPE_MUSIC, CONTENT_ID)
assert "No Plex servers available" in str(excinfo.value)
# Complete setup of a Plex server
await hass.config_entries.async_unload(entry.entry_id)
await setup_plex_server()
# Test lookup success without playqueue
result = process_plex_payload(
hass, MEDIA_TYPE_MUSIC, CONTENT_ID, supports_playqueues=False
)
assert isinstance(result.media, plexapi.audio.Artist)
assert not result.shuffle
# Test media key payload without playqueue
result = process_plex_payload(
hass, MEDIA_TYPE_MUSIC, CONTENT_ID_KEY, supports_playqueues=False
)
assert isinstance(result.media, plexapi.audio.Track)
assert not result.shuffle
# Test with specified server without playqueue
result = process_plex_payload(
hass, MEDIA_TYPE_MUSIC, CONTENT_ID_SERVER, supports_playqueues=False
)
assert isinstance(result.media, plexapi.audio.Artist)
assert not result.shuffle
# Test shuffle without playqueue
result = process_plex_payload(
hass, MEDIA_TYPE_MUSIC, CONTENT_ID_SHUFFLE, supports_playqueues=False
)
assert isinstance(result.media, plexapi.audio.Artist)
assert result.shuffle
# Test with media not found
with patch("plexapi.library.LibrarySection.search", return_value=None):
with pytest.raises(HomeAssistantError) as excinfo:
process_plex_payload(hass, MEDIA_TYPE_MUSIC, CONTENT_ID_BAD_MEDIA)
assert f"No {MEDIA_TYPE_MUSIC} results in 'Music' for" in str(excinfo.value)
# Test with playqueue
requests_mock.get("https://1.2.3.4:32400/playQueues/1234", text=playqueue_1234)
result = process_plex_payload(hass, MEDIA_TYPE_MUSIC, CONTENT_ID_PLAYQUEUE)
assert isinstance(result.media, plexapi.playqueue.PlayQueue)
# Test with invalid playqueue
requests_mock.get(
"https://1.2.3.4:32400/playQueues/1235", status_code=HTTPStatus.NOT_FOUND
)
with pytest.raises(HomeAssistantError) as excinfo:
process_plex_payload(hass, MEDIA_TYPE_MUSIC, CONTENT_ID_BAD_PLAYQUEUE)
assert "PlayQueue '1235' could not be found" in str(excinfo.value)
# Test playqueue is created with shuffle
requests_mock.post("/playqueues", text=playqueue_created)
result = process_plex_payload(hass, MEDIA_TYPE_MUSIC, CONTENT_ID_SHUFFLE)
assert isinstance(result.media, plexapi.playqueue.PlayQueue)
async def test_lookup_media_with_urls(hass, mock_plex_server):
"""Test media lookup for media_player.play_media calls from cast/sonos."""
CONTENT_ID_URL = f"{PLEX_URI_SCHEME}{DEFAULT_DATA[CONF_SERVER_IDENTIFIER]}/100"
# Test URL format
result = process_plex_payload(
hass, MEDIA_TYPE_MUSIC, CONTENT_ID_URL, supports_playqueues=False
)
assert isinstance(result.media, plexapi.audio.Track)
assert result.shuffle is False
# Test URL format with shuffle
CONTENT_ID_URL_WITH_SHUFFLE = CONTENT_ID_URL + "?shuffle=1"
result = process_plex_payload(
hass, MEDIA_TYPE_MUSIC, CONTENT_ID_URL_WITH_SHUFFLE, supports_playqueues=False
)
assert isinstance(result.media, plexapi.audio.Track)
assert result.shuffle is True
assert result.offset == 0