1
mirror of https://github.com/home-assistant/core synced 2024-07-24 16:42:06 +02:00

Separate Plex/Sonos cross-integration tests (#45370)

This commit is contained in:
jjlawren 2021-01-21 05:22:19 -05:00 committed by GitHub
parent 16843d9ec7
commit 1f66457a34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 117 additions and 103 deletions

View File

@ -70,8 +70,9 @@ def refresh_library(hass, service_call):
def get_plex_server(hass, plex_server_name=None):
"""Retrieve a configured Plex server by name."""
if DOMAIN not in hass.data:
raise HomeAssistantError("Plex integration not configured")
plex_servers = hass.data[DOMAIN][SERVERS].values()
if not plex_servers:
raise HomeAssistantError("No Plex servers available")
@ -106,7 +107,7 @@ def lookup_plex_media(hass, content_type, content_id):
plex_server_name = content.pop("plex_server", None)
shuffle = content.pop("shuffle", 0)
plex_server = get_plex_server(hass, plex_server_name=plex_server_name)
plex_server = get_plex_server(hass, plex_server_name)
media = plex_server.lookup_media(content_type, **content)
if media is None:

View File

@ -254,6 +254,12 @@ def show_seasons_fixture():
return load_fixture("plex/show_seasons.xml")
@pytest.fixture(name="sonos_resources", scope="session")
def sonos_resources_fixture():
"""Load Sonos resources payload and return it."""
return load_fixture("plex/sonos_resources.xml")
@pytest.fixture(name="entry")
def mock_config_entry():
"""Return the default mocked config entry."""

View File

@ -1,6 +1,10 @@
"""Tests for various Plex services."""
from unittest.mock import patch
from plexapi.exceptions import NotFound
import pytest
from homeassistant.components.media_player.const import MEDIA_TYPE_MUSIC
from homeassistant.components.plex.const import (
CONF_SERVER,
CONF_SERVER_IDENTIFIER,
@ -9,6 +13,7 @@ from homeassistant.components.plex.const import (
SERVICE_REFRESH_LIBRARY,
SERVICE_SCAN_CLIENTS,
)
from homeassistant.components.plex.services import play_on_sonos
from homeassistant.const import CONF_URL
from homeassistant.exceptions import HomeAssistantError
@ -100,3 +105,76 @@ async def test_scan_clients(hass, mock_plex_server):
SERVICE_SCAN_CLIENTS,
blocking=True,
)
async def test_sonos_play_media(
hass,
entry,
setup_plex_server,
requests_mock,
empty_payload,
playqueue_created,
plextv_account,
sonos_resources,
):
"""Test playback from a Sonos media_player.play_media call."""
media_content_id = (
'{"library_name": "Music", "artist_name": "Artist", "album_name": "Album"}'
)
sonos_speaker_name = "Zone A"
requests_mock.get("https://plex.tv/users/account", text=plextv_account)
requests_mock.post("/playqueues", text=playqueue_created)
playback_mock = requests_mock.get("/player/playback/playMedia", status_code=200)
# Test with no Plex integration available
with pytest.raises(HomeAssistantError) as excinfo:
play_on_sonos(hass, MEDIA_TYPE_MUSIC, media_content_id, sonos_speaker_name)
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:
play_on_sonos(hass, MEDIA_TYPE_MUSIC, media_content_id, sonos_speaker_name)
assert "No Plex servers available" in str(excinfo.value)
# Complete setup of a Plex server
await hass.config_entries.async_unload(entry.entry_id)
mock_plex_server = await setup_plex_server()
# Test with no speakers available
requests_mock.get("https://sonos.plex.tv/resources", text=empty_payload)
with pytest.raises(HomeAssistantError) as excinfo:
play_on_sonos(hass, MEDIA_TYPE_MUSIC, media_content_id, sonos_speaker_name)
assert f"Sonos speaker '{sonos_speaker_name}' is not associated with" in str(
excinfo.value
)
assert playback_mock.call_count == 0
# Test with speakers available
requests_mock.get("https://sonos.plex.tv/resources", text=sonos_resources)
with patch.object(mock_plex_server.account, "_sonos_cache_timestamp", 0):
play_on_sonos(hass, MEDIA_TYPE_MUSIC, media_content_id, sonos_speaker_name)
assert playback_mock.call_count == 1
# Test with speakers available and media key payload
play_on_sonos(hass, MEDIA_TYPE_MUSIC, "100", sonos_speaker_name)
assert playback_mock.call_count == 2
# Test with speakers available and Plex server specified
content_id_with_server = '{"plex_server": "Plex Server 1", "library_name": "Music", "artist_name": "Artist", "album_name": "Album"}'
play_on_sonos(hass, MEDIA_TYPE_MUSIC, content_id_with_server, sonos_speaker_name)
assert playback_mock.call_count == 3
# Test with speakers available but media not found
content_id_bad_media = '{"library_name": "Music", "artist_name": "Not an Artist"}'
with pytest.raises(HomeAssistantError) as excinfo:
play_on_sonos(hass, MEDIA_TYPE_MUSIC, content_id_bad_media, sonos_speaker_name)
assert "Plex media not found" in str(excinfo.value)
assert playback_mock.call_count == 3

View File

@ -7,7 +7,7 @@ from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
from homeassistant.components.sonos import DOMAIN
from homeassistant.const import CONF_HOSTS
from tests.common import MockConfigEntry, load_fixture
from tests.common import MockConfigEntry
@pytest.fixture(name="config_entry")
@ -77,21 +77,3 @@ def speaker_info_fixture():
"software_version": "49.2-64250",
"mac_address": "00-11-22-33-44-55",
}
@pytest.fixture(name="plex_empty_payload", scope="session")
def plex_empty_payload_fixture():
"""Load an empty payload and return it."""
return load_fixture("plex/empty_payload.xml")
@pytest.fixture(name="plextv_account", scope="session")
def plextv_account_fixture():
"""Load account info from plex.tv and return it."""
return load_fixture("plex/plextv_account.xml")
@pytest.fixture(name="plex_sonos_resources", scope="session")
def plex_sonos_resources_fixture():
"""Load Sonos resources payload and return it."""
return load_fixture("plex/sonos_resources.xml")

View File

@ -1,7 +1,6 @@
"""Tests for the Sonos Media Player platform."""
from unittest.mock import patch
from plexapi.myplex import MyPlexAccount
import pytest
from homeassistant.components.media_player.const import (
@ -11,7 +10,7 @@ from homeassistant.components.media_player.const import (
MEDIA_TYPE_MUSIC,
SERVICE_PLAY_MEDIA,
)
from homeassistant.components.plex.const import DOMAIN as PLEX_DOMAIN, SERVERS
from homeassistant.components.plex.const import PLEX_URI_SCHEME
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.exceptions import HomeAssistantError
@ -22,99 +21,47 @@ async def test_plex_play_media(
hass,
config_entry,
config,
requests_mock,
plextv_account,
plex_empty_payload,
plex_sonos_resources,
):
"""Test playing media via the Plex integration."""
requests_mock.get("https://plex.tv/users/account", text=plextv_account)
requests_mock.get("https://sonos.plex.tv/resources", text=plex_empty_payload)
class MockPlexServer:
"""Mock a PlexServer instance."""
def __init__(self, has_media=False):
self.account = MyPlexAccount(token="token")
self.friendly_name = "plex"
if has_media:
self.media = "media"
else:
self.media = None
def create_playqueue(self, media, **kwargs):
pass
def lookup_media(self, content_type, **kwargs):
return self.media
await setup_platform(hass, config_entry, config)
hass.data[PLEX_DOMAIN] = {SERVERS: {}}
media_player = "media_player.zone_a"
media_content_id = (
'{"library_name": "Music", "artist_name": "Artist", "album_name": "Album"}'
)
# Test Plex service call with media key
with pytest.raises(HomeAssistantError) as excinfo:
with patch(
"homeassistant.components.sonos.media_player.play_on_sonos"
) as mock_play:
# Test successful Plex service call
assert await hass.services.async_call(
MP_DOMAIN,
SERVICE_PLAY_MEDIA,
{
ATTR_ENTITY_ID: media_player,
ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC,
ATTR_MEDIA_CONTENT_ID: "plex://5",
ATTR_MEDIA_CONTENT_ID: f"{PLEX_URI_SCHEME}{media_content_id}",
},
True,
blocking=True,
)
assert "No Plex servers available" in str(excinfo.value)
# Add a mocked Plex server with no media
hass.data[PLEX_DOMAIN][SERVERS] = {"plex": MockPlexServer()}
assert len(mock_play.mock_calls) == 1
assert mock_play.mock_calls[0][1][1] == MEDIA_TYPE_MUSIC
assert mock_play.mock_calls[0][1][2] == media_content_id
assert mock_play.mock_calls[0][1][3] == "Zone A"
# Test Plex service call with dict
with pytest.raises(HomeAssistantError) as excinfo:
assert await hass.services.async_call(
MP_DOMAIN,
SERVICE_PLAY_MEDIA,
{
ATTR_ENTITY_ID: media_player,
ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC,
ATTR_MEDIA_CONTENT_ID: 'plex://{"library_name": "Music", "artist_name": "Artist"}',
},
True,
)
assert "Plex media not found" in str(excinfo.value)
# Test failed Plex service call
mock_play.reset_mock()
mock_play.side_effect = HomeAssistantError
# Add a mocked Plex server
hass.data[PLEX_DOMAIN][SERVERS] = {"plex": MockPlexServer(has_media=True)}
# Test Plex service call with no Sonos speakers
requests_mock.get("https://sonos.plex.tv/resources", text=plex_empty_payload)
with pytest.raises(HomeAssistantError) as excinfo:
assert await hass.services.async_call(
MP_DOMAIN,
SERVICE_PLAY_MEDIA,
{
ATTR_ENTITY_ID: media_player,
ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC,
ATTR_MEDIA_CONTENT_ID: 'plex://{"library_name": "Music", "artist_name": "Artist"}',
},
True,
)
assert "Sonos speaker 'Zone A' is not associated with" in str(excinfo.value)
# Test successful Plex service call
account = hass.data[PLEX_DOMAIN][SERVERS]["plex"].account
requests_mock.get("https://sonos.plex.tv/resources", text=plex_sonos_resources)
with patch.object(account, "_sonos_cache_timestamp", 0), patch(
"plexapi.sonos.PlexSonosClient.playMedia"
):
assert await hass.services.async_call(
MP_DOMAIN,
SERVICE_PLAY_MEDIA,
{
ATTR_ENTITY_ID: media_player,
ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC,
ATTR_MEDIA_CONTENT_ID: 'plex://{"plex_server": "plex", "library_name": "Music", "artist_name": "Artist", "album_name": "Album"}',
},
True,
)
with pytest.raises(HomeAssistantError):
await hass.services.async_call(
MP_DOMAIN,
SERVICE_PLAY_MEDIA,
{
ATTR_ENTITY_ID: media_player,
ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC,
ATTR_MEDIA_CONTENT_ID: f"{PLEX_URI_SCHEME}{media_content_id}",
},
blocking=True,
)
assert mock_play.called