"""Tests for Plex server.""" from unittest.mock import patch from plexapi.exceptions import BadRequest, NotFound import pytest from homeassistant.components.media_player.const import ( ATTR_MEDIA_CONTENT_ID, ATTR_MEDIA_CONTENT_TYPE, DOMAIN as MEDIA_PLAYER_DOMAIN, MEDIA_TYPE_EPISODE, MEDIA_TYPE_MOVIE, MEDIA_TYPE_MUSIC, MEDIA_TYPE_PLAYLIST, MEDIA_TYPE_VIDEO, SERVICE_PLAY_MEDIA, ) from homeassistant.components.plex.const import DOMAIN from homeassistant.components.plex.errors import MediaNotFound from homeassistant.const import ATTR_ENTITY_ID async def test_media_lookups(hass, mock_plex_server, requests_mock, playqueue_created): """Test media lookups to Plex server.""" # Plex Key searches media_player_id = hass.states.async_entity_ids("media_player")[0] requests_mock.post("/playqueues", text=playqueue_created) requests_mock.get("/player/playback/playMedia", status_code=200) assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: DOMAIN, ATTR_MEDIA_CONTENT_ID: 1, }, True, ) with pytest.raises(MediaNotFound) as excinfo: with patch("plexapi.server.PlexServer.fetchItem", side_effect=NotFound): assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: DOMAIN, ATTR_MEDIA_CONTENT_ID: 123, }, True, ) assert "Media for key 123 not found" in str(excinfo.value) # TV show searches with pytest.raises(MediaNotFound) as excinfo: payload = '{"library_name": "Not a Library", "show_name": "TV Show"}' assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_EPISODE, ATTR_MEDIA_CONTENT_ID: payload, }, True, ) assert "Library 'Not a Library' not found in" in str(excinfo.value) with patch("plexapi.library.LibrarySection.search") as search: assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_EPISODE, ATTR_MEDIA_CONTENT_ID: '{"library_name": "TV Shows", "show_name": "TV Show"}', }, True, ) search.assert_called_with(**{"show.title": "TV Show", "libtype": "show"}) assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_EPISODE, ATTR_MEDIA_CONTENT_ID: '{"library_name": "TV Shows", "episode_name": "An Episode"}', }, True, ) search.assert_called_with( **{"episode.title": "An Episode", "libtype": "episode"} ) assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_EPISODE, ATTR_MEDIA_CONTENT_ID: '{"library_name": "TV Shows", "show_name": "TV Show", "season_number": 1}', }, True, ) search.assert_called_with( **{"show.title": "TV Show", "season.index": 1, "libtype": "season"} ) assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_EPISODE, ATTR_MEDIA_CONTENT_ID: '{"library_name": "TV Shows", "show_name": "TV Show", "season_number": 1, "episode_number": 3}', }, True, ) search.assert_called_with( **{ "show.title": "TV Show", "season.index": 1, "episode.index": 3, "libtype": "episode", } ) assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC, ATTR_MEDIA_CONTENT_ID: '{"library_name": "Music", "artist_name": "Artist"}', }, True, ) search.assert_called_with(**{"artist.title": "Artist", "libtype": "artist"}) assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC, ATTR_MEDIA_CONTENT_ID: '{"library_name": "Music", "album_name": "Album"}', }, True, ) search.assert_called_with(**{"album.title": "Album", "libtype": "album"}) assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC, ATTR_MEDIA_CONTENT_ID: '{"library_name": "Music", "artist_name": "Artist", "track_name": "Track 3"}', }, True, ) search.assert_called_with( **{"artist.title": "Artist", "track.title": "Track 3", "libtype": "track"} ) assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC, ATTR_MEDIA_CONTENT_ID: '{"library_name": "Music", "artist_name": "Artist", "album_name": "Album"}', }, True, ) search.assert_called_with( **{"artist.title": "Artist", "album.title": "Album", "libtype": "album"} ) assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC, ATTR_MEDIA_CONTENT_ID: '{"library_name": "Music", "artist_name": "Artist", "album_name": "Album", "track_number": 3}', }, True, ) search.assert_called_with( **{ "artist.title": "Artist", "album.title": "Album", "track.index": 3, "libtype": "track", } ) assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC, ATTR_MEDIA_CONTENT_ID: '{"library_name": "Music", "artist_name": "Artist", "album_name": "Album", "track_name": "Track 3"}', }, True, ) search.assert_called_with( **{ "artist.title": "Artist", "album.title": "Album", "track.title": "Track 3", "libtype": "track", } ) # Movie searches assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_VIDEO, ATTR_MEDIA_CONTENT_ID: '{"library_name": "Movies", "video_name": "Movie 1"}', }, True, ) search.assert_called_with(**{"movie.title": "Movie 1", "libtype": None}) assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MOVIE, ATTR_MEDIA_CONTENT_ID: '{"library_name": "Movies", "title": "Movie 1"}', }, True, ) search.assert_called_with(**{"title": "Movie 1", "libtype": None}) with pytest.raises(MediaNotFound) as excinfo: payload = '{"title": "Movie 1"}' assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_VIDEO, ATTR_MEDIA_CONTENT_ID: payload, }, True, ) assert "Must specify 'library_name' for this search" in str(excinfo.value) with pytest.raises(MediaNotFound) as excinfo: payload = '{"library_name": "Movies", "title": "Not a Movie"}' with patch("plexapi.library.LibrarySection.search", side_effect=BadRequest): assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_VIDEO, ATTR_MEDIA_CONTENT_ID: payload, }, True, ) assert "Problem in query" in str(excinfo.value) # Playlist searches assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_PLAYLIST, ATTR_MEDIA_CONTENT_ID: '{"playlist_name": "Playlist 1"}', }, True, ) with pytest.raises(MediaNotFound) as excinfo: payload = '{"playlist_name": "Not a Playlist"}' assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_PLAYLIST, ATTR_MEDIA_CONTENT_ID: payload, }, True, ) assert "Playlist 'Not a Playlist' not found" in str(excinfo.value) with pytest.raises(MediaNotFound) as excinfo: payload = "{}" assert await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, { ATTR_ENTITY_ID: media_player_id, ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_PLAYLIST, ATTR_MEDIA_CONTENT_ID: payload, }, True, ) assert "Must specify 'playlist_name' for this search" in str(excinfo.value)