mirror of https://github.com/home-assistant/core
353 lines
11 KiB
Python
353 lines
11 KiB
Python
"""Tests for the Jellyfin media_player platform."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
from syrupy.assertion import SnapshotAssertion
|
|
|
|
from homeassistant.components.jellyfin.const import DOMAIN
|
|
from homeassistant.components.media_player import BrowseError
|
|
from homeassistant.components.media_source import (
|
|
DOMAIN as MEDIA_SOURCE_DOMAIN,
|
|
URI_SCHEME,
|
|
async_browse_media,
|
|
async_resolve_media,
|
|
)
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.setup import async_setup_component
|
|
|
|
from . import load_json_fixture
|
|
|
|
from tests.common import MockConfigEntry
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
async def setup_component(hass: HomeAssistant) -> None:
|
|
"""Set up component."""
|
|
assert await async_setup_component(hass, MEDIA_SOURCE_DOMAIN, {})
|
|
|
|
|
|
async def test_resolve(
|
|
hass: HomeAssistant,
|
|
mock_client: MagicMock,
|
|
init_integration: MockConfigEntry,
|
|
mock_jellyfin: MagicMock,
|
|
mock_api: MagicMock,
|
|
snapshot: SnapshotAssertion,
|
|
) -> None:
|
|
"""Test resolving Jellyfin media items."""
|
|
|
|
# Test resolving a track
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("track.json")
|
|
|
|
play_media = await async_resolve_media(
|
|
hass, f"{URI_SCHEME}{DOMAIN}/TRACK-UUID", "media_player.jellyfin_device"
|
|
)
|
|
|
|
assert play_media.mime_type == "audio/flac"
|
|
assert play_media.url == snapshot
|
|
|
|
mock_api.audio_url.assert_called_with("TRACK-UUID")
|
|
assert mock_api.audio_url.call_count == 1
|
|
mock_api.audio_url.reset_mock()
|
|
|
|
# Test resolving a movie
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("movie.json")
|
|
|
|
play_media = await async_resolve_media(
|
|
hass, f"{URI_SCHEME}{DOMAIN}/MOVIE-UUID", "media_player.jellyfin_device"
|
|
)
|
|
|
|
assert play_media.mime_type == "video/mp4"
|
|
assert play_media.url == snapshot
|
|
|
|
# Test resolving an unsupported item
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("unsupported-item.json")
|
|
|
|
with pytest.raises(BrowseError):
|
|
await async_resolve_media(
|
|
hass,
|
|
f"{URI_SCHEME}{DOMAIN}/UNSUPPORTED-ITEM-UUID",
|
|
"media_player.jellyfin_device",
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"audio_codec",
|
|
[("aac"), ("wma"), ("vorbis"), ("mp3")],
|
|
)
|
|
async def test_audio_codec_resolve(
|
|
hass: HomeAssistant,
|
|
mock_client: MagicMock,
|
|
init_integration: MockConfigEntry,
|
|
mock_jellyfin: MagicMock,
|
|
mock_api: MagicMock,
|
|
snapshot: SnapshotAssertion,
|
|
audio_codec: str,
|
|
) -> None:
|
|
"""Test resolving Jellyfin media items with audio codec."""
|
|
|
|
# Test resolving a track
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("track.json")
|
|
|
|
result = await hass.config_entries.options.async_init(init_integration.entry_id)
|
|
await hass.config_entries.options.async_configure(
|
|
result["flow_id"], user_input={"audio_codec": audio_codec}
|
|
)
|
|
assert init_integration.options["audio_codec"] == audio_codec
|
|
|
|
play_media = await async_resolve_media(
|
|
hass, f"{URI_SCHEME}{DOMAIN}/TRACK-UUID", "media_player.jellyfin_device"
|
|
)
|
|
|
|
assert play_media.mime_type == "audio/flac"
|
|
assert play_media.url == snapshot
|
|
|
|
mock_api.audio_url.assert_called_with("TRACK-UUID", audio_codec=audio_codec)
|
|
assert mock_api.audio_url.call_count == 1
|
|
|
|
|
|
async def test_root(
|
|
hass: HomeAssistant,
|
|
mock_client: MagicMock,
|
|
init_integration: MockConfigEntry,
|
|
mock_jellyfin: MagicMock,
|
|
mock_api: MagicMock,
|
|
snapshot: SnapshotAssertion,
|
|
) -> None:
|
|
"""Test browsing the Jellyfin root."""
|
|
|
|
browse = await async_browse_media(hass, f"{URI_SCHEME}{DOMAIN}")
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier is None
|
|
assert browse.title == "Jellyfin"
|
|
assert vars(browse.children[0]) == snapshot
|
|
|
|
|
|
async def test_tv_library(
|
|
hass: HomeAssistant,
|
|
mock_client: MagicMock,
|
|
init_integration: MockConfigEntry,
|
|
mock_jellyfin: MagicMock,
|
|
mock_api: MagicMock,
|
|
snapshot: SnapshotAssertion,
|
|
) -> None:
|
|
"""Test browsing a Jellyfin TV Library."""
|
|
|
|
# Test browsing an empty tv library
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("tv-collection.json")
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = {"Items": []}
|
|
|
|
browse = await async_browse_media(
|
|
hass, f"{URI_SCHEME}{DOMAIN}/TV-COLLECTION-FOLDER-UUID"
|
|
)
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "TV-COLLECTION-FOLDER-UUID"
|
|
assert browse.title == "TVShows"
|
|
assert browse.children == []
|
|
|
|
# Test browsing a tv library containing series
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = load_json_fixture("series-list.json")
|
|
|
|
browse = await async_browse_media(
|
|
hass, f"{URI_SCHEME}{DOMAIN}/TV-COLLECTION-FOLDER-UUID"
|
|
)
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "TV-COLLECTION-FOLDER-UUID"
|
|
assert browse.title == "TVShows"
|
|
assert vars(browse.children[0]) == snapshot
|
|
|
|
# Test browsing a series
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("series.json")
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = load_json_fixture("seasons.json")
|
|
|
|
browse = await async_browse_media(hass, f"{URI_SCHEME}{DOMAIN}/SERIES-UUID")
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "SERIES-UUID"
|
|
assert browse.title == "SERIES"
|
|
assert vars(browse.children[0]) == snapshot
|
|
|
|
# Test browsing a season
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("season.json")
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = load_json_fixture("episodes.json")
|
|
|
|
browse = await async_browse_media(hass, f"{URI_SCHEME}{DOMAIN}/SEASON-UUID")
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "SEASON-UUID"
|
|
assert browse.title == "SEASON"
|
|
assert vars(browse.children[0]) == snapshot
|
|
|
|
|
|
async def test_movie_library(
|
|
hass: HomeAssistant,
|
|
mock_client: MagicMock,
|
|
init_integration: MockConfigEntry,
|
|
mock_jellyfin: MagicMock,
|
|
mock_api: MagicMock,
|
|
snapshot: SnapshotAssertion,
|
|
) -> None:
|
|
"""Test browsing a Jellyfin Movie Library."""
|
|
|
|
# Test empty movie library
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("movie-collection.json")
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = {"Items": []}
|
|
|
|
browse = await async_browse_media(
|
|
hass, f"{URI_SCHEME}{DOMAIN}/MOVIE-COLLECTION-FOLDER-UUID"
|
|
)
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "MOVIE-COLLECTION-FOLDER-UUID"
|
|
assert browse.title == "Movies"
|
|
assert browse.children == []
|
|
|
|
# Test browsing a movie library containing movies
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = load_json_fixture("movies.json")
|
|
|
|
browse = await async_browse_media(
|
|
hass, f"{URI_SCHEME}{DOMAIN}/MOVIE-COLLECTION-FOLDER-UUID"
|
|
)
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "MOVIE-COLLECTION-FOLDER-UUID"
|
|
assert browse.title == "Movies"
|
|
assert vars(browse.children[0]) == snapshot
|
|
|
|
|
|
async def test_music_library(
|
|
hass: HomeAssistant,
|
|
mock_client: MagicMock,
|
|
init_integration: MockConfigEntry,
|
|
mock_jellyfin: MagicMock,
|
|
mock_api: MagicMock,
|
|
snapshot: SnapshotAssertion,
|
|
) -> None:
|
|
"""Test browsing a Jellyfin Music Library."""
|
|
|
|
# Test browsinng an empty music library
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("music-collection.json")
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = {"Items": []}
|
|
|
|
browse = await async_browse_media(
|
|
hass, f"{URI_SCHEME}{DOMAIN}/MUSIC-COLLECTION-FOLDER-UUID"
|
|
)
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "MUSIC-COLLECTION-FOLDER-UUID"
|
|
assert browse.title == "Music"
|
|
assert browse.children == []
|
|
|
|
# Test browsing a music library containing albums
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = load_json_fixture("albums.json")
|
|
|
|
browse = await async_browse_media(
|
|
hass, f"{URI_SCHEME}{DOMAIN}/MUSIC-COLLECTION-FOLDER-UUID"
|
|
)
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "MUSIC-COLLECTION-FOLDER-UUID"
|
|
assert browse.title == "Music"
|
|
assert vars(browse.children[0]) == snapshot
|
|
|
|
# Test browsing an artist
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("artist.json")
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = load_json_fixture("albums.json")
|
|
|
|
browse = await async_browse_media(hass, f"{URI_SCHEME}{DOMAIN}/ARTIST-UUID")
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "ARTIST-UUID"
|
|
assert browse.title == "ARTIST"
|
|
assert vars(browse.children[0]) == snapshot
|
|
|
|
# Test browsing an album
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("album.json")
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = load_json_fixture("tracks.json")
|
|
|
|
browse = await async_browse_media(hass, f"{URI_SCHEME}{DOMAIN}/ALBUM-UUID")
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "ALBUM-UUID"
|
|
assert browse.title == "ALBUM"
|
|
assert vars(browse.children[0]) == snapshot
|
|
|
|
# Test browsing an album with a track with no source
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = load_json_fixture("tracks-nosource.json")
|
|
|
|
browse = await async_browse_media(hass, f"{URI_SCHEME}{DOMAIN}/ALBUM-UUID")
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "ALBUM-UUID"
|
|
assert browse.title == "ALBUM"
|
|
|
|
assert browse.children == []
|
|
|
|
# Test browsing an album with a track with no path
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = load_json_fixture("tracks-nopath.json")
|
|
|
|
browse = await async_browse_media(hass, f"{URI_SCHEME}{DOMAIN}/ALBUM-UUID")
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "ALBUM-UUID"
|
|
assert browse.title == "ALBUM"
|
|
|
|
assert browse.children == []
|
|
|
|
# Test browsing an album with a track with an unknown file extension
|
|
mock_api.user_items.side_effect = None
|
|
mock_api.user_items.return_value = load_json_fixture(
|
|
"tracks-unknown-extension.json"
|
|
)
|
|
|
|
browse = await async_browse_media(hass, f"{URI_SCHEME}{DOMAIN}/ALBUM-UUID")
|
|
|
|
assert browse.domain == DOMAIN
|
|
assert browse.identifier == "ALBUM-UUID"
|
|
assert browse.title == "ALBUM"
|
|
|
|
assert browse.children == []
|
|
|
|
|
|
async def test_browse_unsupported(
|
|
hass: HomeAssistant,
|
|
mock_client: MagicMock,
|
|
init_integration: MockConfigEntry,
|
|
mock_jellyfin: MagicMock,
|
|
mock_api: MagicMock,
|
|
) -> None:
|
|
"""Test browsing an unsupported item."""
|
|
|
|
mock_api.get_item.side_effect = None
|
|
mock_api.get_item.return_value = load_json_fixture("unsupported-item.json")
|
|
|
|
with pytest.raises(BrowseError):
|
|
await async_browse_media(hass, f"{URI_SCHEME}{DOMAIN}/UNSUPPORTED-ITEM-UUID")
|