python-plexapi/tests/test_playlist.py

339 lines
12 KiB
Python
Raw Normal View History

2017-01-09 14:21:54 +00:00
# -*- coding: utf-8 -*-
2017-10-25 19:53:52 +00:00
import time
2021-08-04 21:02:01 +00:00
from urllib.parse import quote_plus
2020-04-29 21:23:22 +00:00
2017-10-25 19:53:52 +00:00
import pytest
2021-05-27 07:16:01 +00:00
from plexapi.exceptions import BadRequest, NotFound, Unsupported
2017-01-09 14:21:54 +00:00
2021-05-30 02:00:59 +00:00
from . import conftest as utils
2021-07-28 21:50:24 +00:00
from . import test_mixins
2021-05-30 02:00:59 +00:00
def test_Playlist_attrs(playlist):
assert utils.is_datetime(playlist.addedAt)
assert playlist.allowSync is True
assert utils.is_composite(playlist.composite, prefix="/playlists")
assert playlist.content is None
assert utils.is_int(playlist.duration)
assert playlist.durationInSeconds is None
assert playlist.icon is None
assert playlist.guid.startswith("com.plexapp.agents.none://")
assert playlist.key.startswith("/playlists/")
assert playlist.leafCount == 3
assert playlist.playlistType == "video"
assert utils.is_int(playlist.ratingKey)
assert playlist.smart is False
assert playlist.summary == ""
assert playlist.title == "Test Playlist"
assert playlist.type == "playlist"
assert utils.is_datetime(playlist.updatedAt)
assert playlist.thumb == playlist.composite
assert playlist.metadataType == "movie"
assert playlist.isVideo is True
assert playlist.isAudio is False
assert playlist.isPhoto is False
def test_Playlist_create(plex, show):
2017-01-09 14:21:54 +00:00
# create the playlist
2017-04-16 15:58:21 +00:00
title = 'test_create_playlist_show'
episodes = show.episodes()
2021-05-30 01:05:42 +00:00
playlist = plex.createPlaylist(title, items=episodes[:3])
2017-01-09 14:21:54 +00:00
try:
items = playlist.items()
2017-04-16 15:58:21 +00:00
# Test create playlist
2017-01-09 14:21:54 +00:00
assert playlist.title == title, 'Playlist not created successfully.'
assert len(items) == 3, 'Playlist does not contain 3 items.'
assert items[0].ratingKey == episodes[0].ratingKey, 'Items not in proper order [0a].'
assert items[1].ratingKey == episodes[1].ratingKey, 'Items not in proper order [1a].'
assert items[2].ratingKey == episodes[2].ratingKey, 'Items not in proper order [2a].'
2017-04-16 15:58:21 +00:00
# Test move items around (b)
2017-01-09 14:21:54 +00:00
playlist.moveItem(items[1])
2021-05-27 07:16:01 +00:00
items = playlist.reload().items()
2017-01-09 14:21:54 +00:00
assert items[0].ratingKey == episodes[1].ratingKey, 'Items not in proper order [0b].'
assert items[1].ratingKey == episodes[0].ratingKey, 'Items not in proper order [1b].'
assert items[2].ratingKey == episodes[2].ratingKey, 'Items not in proper order [2b].'
2017-04-16 15:58:21 +00:00
# Test move items around (c)
2017-01-09 14:21:54 +00:00
playlist.moveItem(items[0], items[1])
2021-05-27 07:16:01 +00:00
items = playlist.reload().items()
2017-01-09 14:21:54 +00:00
assert items[0].ratingKey == episodes[0].ratingKey, 'Items not in proper order [0c].'
assert items[1].ratingKey == episodes[1].ratingKey, 'Items not in proper order [1c].'
assert items[2].ratingKey == episodes[2].ratingKey, 'Items not in proper order [2c].'
2017-04-16 15:58:21 +00:00
# Test add item
2017-01-09 14:21:54 +00:00
playlist.addItems(episodes[3])
2021-05-27 07:16:01 +00:00
items = playlist.reload().items()
assert items[3].ratingKey == episodes[3].ratingKey, f'Missing added item: {episodes[3]}'
2017-04-16 15:58:21 +00:00
# Test add two items
2017-01-09 14:21:54 +00:00
playlist.addItems(episodes[4:6])
2021-05-27 07:16:01 +00:00
items = playlist.reload().items()
assert items[4].ratingKey == episodes[4].ratingKey, f'Missing added item: {episodes[4]}'
assert items[5].ratingKey == episodes[5].ratingKey, f'Missing added item: {episodes[5]}'
assert len(items) == 6, f'Playlist should have 6 items, {len(items)} found'
2017-04-16 15:58:21 +00:00
# Test remove item
2021-05-27 07:16:01 +00:00
toremove = items[5]
playlist.removeItems(toremove)
items = playlist.reload().items()
assert toremove not in items, f'Removed item still in playlist: {items[5]}'
assert len(items) == 5, f'Playlist should have 5 items, {len(items)} found'
2021-05-27 07:16:01 +00:00
# Test remove two item
toremove = items[3:5]
playlist.removeItems(toremove)
items = playlist.reload().items()
assert toremove[0] not in items, f'Removed item still in playlist: {items[3]}'
assert toremove[1] not in items, f'Removed item still in playlist: {items[4]}'
assert len(items) == 3, f'Playlist should have 5 items, {len(items)} found'
2021-05-27 07:16:01 +00:00
finally:
playlist.delete()
2021-05-30 02:00:59 +00:00
def test_Playlist_edit(plex, movie):
2021-05-27 07:16:01 +00:00
title = 'test_playlist_edit'
new_title = 'test_playlist_edit_new_title'
new_summary = 'test_playlist_edit_summary'
try:
2021-05-30 01:05:42 +00:00
playlist = plex.createPlaylist(title, items=movie)
2021-05-27 07:16:01 +00:00
assert playlist.title == title
assert playlist.summary == ''
playlist.editTitle(new_title).editSummary(new_summary)
2021-05-27 07:16:01 +00:00
playlist.reload()
assert playlist.title == new_title
assert playlist.summary == new_summary
2017-01-09 14:21:54 +00:00
finally:
playlist.delete()
2021-05-30 02:00:59 +00:00
def test_Playlist_item(plex, show):
2020-12-24 17:21:29 +00:00
title = 'test_playlist_item'
2020-12-24 07:03:08 +00:00
episodes = show.episodes()
try:
2021-05-30 01:05:42 +00:00
playlist = plex.createPlaylist(title, items=episodes[:3])
2020-12-24 07:03:08 +00:00
item1 = playlist.item("Winter Is Coming")
assert item1 in playlist.items()
item2 = playlist.get("Winter Is Coming")
assert item2 in playlist.items()
assert item1 == item2
2020-12-24 17:21:29 +00:00
with pytest.raises(NotFound):
playlist.item("Does not exist")
2020-12-24 07:03:08 +00:00
finally:
playlist.delete()
2017-04-29 05:47:21 +00:00
@pytest.mark.client
2021-05-30 02:00:59 +00:00
def test_Playlist_play(plex, client, artist, album):
2017-01-09 14:21:54 +00:00
try:
2017-04-16 15:58:21 +00:00
playlist_name = 'test_play_playlist'
2021-05-30 01:05:42 +00:00
playlist = plex.createPlaylist(playlist_name, items=album)
2017-01-09 14:21:54 +00:00
client.playMedia(playlist); time.sleep(5)
client.stop('music'); time.sleep(1)
finally:
playlist.delete()
2017-04-16 15:58:21 +00:00
assert playlist_name not in [i.title for i in plex.playlists()]
2017-01-09 14:21:54 +00:00
2021-05-30 02:00:59 +00:00
def test_Playlist_photos(plex, photoalbum):
2017-04-16 15:58:21 +00:00
album = photoalbum
2017-01-09 14:21:54 +00:00
photos = album.photos()
try:
2017-04-16 15:58:21 +00:00
playlist_name = 'test_playlist_photos'
2021-05-30 01:05:42 +00:00
playlist = plex.createPlaylist(playlist_name, items=photos)
2017-04-16 15:58:21 +00:00
assert len(playlist.items()) >= 1
2017-01-09 14:21:54 +00:00
finally:
playlist.delete()
2017-04-16 15:58:21 +00:00
assert playlist_name not in [i.title for i in plex.playlists()]
2017-01-09 14:21:54 +00:00
2017-04-29 05:47:21 +00:00
@pytest.mark.client
2021-05-30 02:00:59 +00:00
def test_Play_photos(plex, client, photoalbum):
2017-04-29 05:47:21 +00:00
photos = photoalbum.photos()
2017-01-09 14:21:54 +00:00
for photo in photos[:4]:
client.playMedia(photo)
time.sleep(2)
2021-05-30 02:00:59 +00:00
def test_Playlist_copyToUser(plex, show, fresh_plex, shared_username):
2017-07-17 14:11:03 +00:00
episodes = show.episodes()
2021-05-30 01:05:42 +00:00
playlist = plex.createPlaylist('shared_from_test_plexapi', items=episodes)
2017-07-17 14:11:03 +00:00
try:
Improvements in tests process (#297) * lets begin * skip plexpass tests if there is not plexpass on account * test new myplex attrubutes * bootstrap: proper photos organisation * fix rest of photos tests * fix myplex new attributes test * fix music bootstrap by setting agent to lastfm * fix sync tests * increase bootstrap timeout * remove timeout from .travis.yml * do not create playlist-style photoalbums in plex-bootstraptest.py * allow negative filtering in LibrarySection.search() * fix sync tests once again * use sendCrashReports in test_settings * fix test_settings * fix test_video * do not accept eula in bootstrap * fix PlexServer.isLatest() * add test against old version of PlexServer * fix MyPlexAccount.OutOut * add flag for one-time testing in Travis * fix test_library onDeck tests * fix more tests * use tqdm in plex-bootstraptest for media scanning progress * create sections one-by-one * update docs on AlertListener for timeline entries * fix plex-bootstraptest for server version 1.3.2 * display skip/xpass/xfail reasons * fix tests on 1.3 * wait for music to be fully processed in plex-bootstraptest * fix misplaced TEST_ACCOUNT_ONCE * fix test_myplex_users, not sure if in proper-way * add pytest-rerunfailures; mark test_myplex_optout as flaky * fix comment * Revert "add pytest-rerunfailures; mark test_myplex_optout as flaky" This reverts commit 580e4c95a758c92329d757eb2f3fc3bf44b26f09. * restart plex container on failure * add conftest.wait_until() and used where some retries are required * add more wait_until() usage in test_sync * fix managed user search * fix updating managed users in myplex * allow to add new servers to existent users * add new server to a shared user while bootstrapping * add some docs on testing process * perform few attemps when unable to get the claim token * unlock websocket-client in requirements_dev * fix docblock in tools/plex-teardowntest * do not hardcode mediapart size in test_video * remove cache:pip from travis * Revert "unlock websocket-client in requirements_dev" This reverts commit 0d536bd06dbdc4a4b869a1686f8cd008898859fe. * remove debug from server.py * improve webhook tests * fix type() check to isinstance() * remove excessive `else` branch due to Hellowlol advice * add `unknown` as allowed `myPlexMappingState` in test_server
2018-09-14 18:03:23 +00:00
playlist.copyToUser(shared_username)
user = plex.myPlexAccount().user(shared_username)
2017-07-17 14:11:03 +00:00
user_plex = fresh_plex(plex._baseurl, user.get_token(plex.machineIdentifier))
assert playlist.title in [p.title for p in user_plex.playlists()]
finally:
playlist.delete()
2018-11-16 23:20:21 +00:00
2021-05-30 02:00:59 +00:00
def test_Playlist_createSmart(plex, movies, movie):
2021-05-27 07:16:01 +00:00
try:
playlist = plex.createPlaylist(
title='smart_playlist',
smart=True,
limit=2,
section=movies,
sort='titleSort:desc',
**{'year>>': 2007}
)
items = playlist.items()
assert playlist.smart
assert len(items) == 2
assert items == sorted(items, key=lambda i: i.titleSort, reverse=True)
playlist.updateFilters(limit=1, year=movie.year)
playlist.reload()
assert len(playlist.items()) == 1
assert movie in playlist
finally:
playlist.delete()
@pytest.mark.parametrize(
"smartFilter",
[
{"or": [{"show.title": "game"}, {"show.title": "100"}]},
{
"and": [
{
"or": [
{
"and": [
{"show.title": "game"},
{"show.title": "thrones"},
{
"or": [
{"show.year>>": "1999"},
{"show.viewCount<<": "3"},
]
},
]
},
{"show.title": "100"},
]
},
{"or": [{"show.contentRating": "TV-14"}, {"show.addedAt>>": "-10y"}]},
{"episode.hdr!": "1"},
]
},
],
)
def test_Playlist_smartFilters(smartFilter, plex, tvshows):
try:
playlist = plex.createPlaylist(
title="smart_playlist_filters",
smart=True,
section=tvshows,
limit=5,
libtype="show",
sort=[
"season.index:nullsLast",
"episode.index:nullsLast",
"show.titleSort",
],
filters=smartFilter,
)
filters = playlist.filters()
filters["libtype"] = (
tvshows.METADATA_TYPE
) # Override libtype to check playlist items
assert filters["filters"] == smartFilter
assert tvshows.search(**filters) == playlist.items()
finally:
playlist.delete()
2021-05-30 02:00:59 +00:00
def test_Playlist_section(plex, movies, movie):
2021-05-27 07:16:01 +00:00
title = 'test_playlist_section'
try:
2021-05-30 01:05:42 +00:00
playlist = plex.createPlaylist(title, items=movie)
2021-05-27 07:16:01 +00:00
with pytest.raises(BadRequest):
playlist.section()
finally:
2021-05-27 07:16:01 +00:00
playlist.delete()
try:
playlist = plex.createPlaylist(title, smart=True, section=movies, **{'year>>': 2000})
assert playlist.section() == movies
playlist.content = ''
assert playlist.section() == movies
playlist.updateFilters(year=1990)
playlist.reload()
playlist.content = ''
with pytest.raises(Unsupported):
playlist.section()
finally:
playlist.delete()
2021-05-30 02:00:59 +00:00
def test_Playlist_exceptions(plex, movies, movie, artist):
2021-05-27 07:16:01 +00:00
title = 'test_playlist_exceptions'
try:
2021-05-30 01:05:42 +00:00
playlist = plex.createPlaylist(title, items=movie)
2021-05-27 07:16:01 +00:00
with pytest.raises(BadRequest):
playlist.updateFilters()
with pytest.raises(BadRequest):
playlist.addItems(artist)
with pytest.raises(NotFound):
playlist.removeItems(artist)
with pytest.raises(NotFound):
playlist.moveItem(artist)
with pytest.raises(NotFound):
playlist.moveItem(item=movie, after=artist)
2021-05-27 07:16:01 +00:00
finally:
playlist.delete()
with pytest.raises(BadRequest):
plex.createPlaylist(title, items=[])
with pytest.raises(BadRequest):
plex.createPlaylist(title, items=[movie, artist])
try:
2021-05-30 02:26:12 +00:00
playlist = plex.createPlaylist(title, smart=True, section=movies.title, **{'year>>': 2000})
2021-05-27 07:16:01 +00:00
with pytest.raises(BadRequest):
playlist.addItems(movie)
with pytest.raises(BadRequest):
playlist.removeItems(movie)
with pytest.raises(BadRequest):
playlist.moveItem(movie)
finally:
playlist.delete()
2021-07-28 21:50:24 +00:00
def test_Playlist_m3ufile(plex, tvshows, music, m3ufile):
title = 'test_playlist_m3ufile'
try:
playlist = plex.createPlaylist(title, section=music.title, m3ufilepath=m3ufile)
assert playlist.title == title
finally:
playlist.delete()
with pytest.raises(BadRequest):
plex.createPlaylist(title, section=tvshows, m3ufilepath='does_not_exist.m3u')
with pytest.raises(BadRequest):
plex.createPlaylist(title, section=music, m3ufilepath='does_not_exist.m3u')
2021-08-04 21:02:01 +00:00
def test_Playlist_PlexWebURL(plex, show):
title = 'test_playlist_plexweburl'
episodes = show.episodes()
playlist = plex.createPlaylist(title, items=episodes[:3])
try:
url = playlist.getWebURL()
assert url.startswith('https://app.plex.tv/desktop')
assert plex.machineIdentifier in url
assert 'playlist' in url
assert quote_plus(playlist.key) in url
finally:
playlist.delete()
@pytest.mark.xfail(reason="Changing images fails randomly")
2021-07-28 21:50:24 +00:00
def test_Playlist_mixins_images(playlist):
test_mixins.lock_art(playlist)
test_mixins.lock_poster(playlist)
test_mixins.edit_art(playlist)
2021-07-28 21:50:24 +00:00
test_mixins.edit_poster(playlist)
def test_Playlist_mixins_fields(playlist):
test_mixins.edit_sort_title(playlist)
test_mixins.edit_summary(playlist)
test_mixins.edit_title(playlist)