Tests now passing on personal server

This commit is contained in:
Michael Shepanski 2017-04-29 01:47:21 -04:00
parent 109d7367f6
commit 35fc7718f5
8 changed files with 58 additions and 83 deletions

View file

@ -57,7 +57,7 @@ class PlexServer(PlexObject):
myPlexSigninState (str): Unknown (ex: ok). myPlexSigninState (str): Unknown (ex: ok).
myPlexSubscription (str): True if you have a myPlex subscription. myPlexSubscription (str): True if you have a myPlex subscription.
myPlexUsername (str): Email address if signed into myPlex (user@example.com) myPlexUsername (str): Email address if signed into myPlex (user@example.com)
ownerFeatures (bool): List of features allowed by the server owner. This may be based ownerFeatures (list): List of features allowed by the server owner. This may be based
on your PlexPass subscription. Features include: camera_upload, cloudsync, on your PlexPass subscription. Features include: camera_upload, cloudsync,
content_filter, dvr, hardware_transcoding, home, lyrics, music_videos, pass, content_filter, dvr, hardware_transcoding, home, lyrics, music_videos, pass,
photo_autotags, premium_music_metadata, session_bandwidth_restrictions, sync, photo_autotags, premium_music_metadata, session_bandwidth_restrictions, sync,

View file

@ -1,4 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Running these tests requires a few things in your Plex Library.
# 1. A Movies section containing both movies: 16 Blocks, Die Hard.
# 2. A Music section containing the album: Infinite State - Unmastered Impulses
# https://github.com/kennethreitz/unmastered-impulses
# 3. A Photos section containing the album Cats with photos named:
# <to-be-determined>
# 4. A TV Shows section containing at least two seasons of The 100.
import plexapi, pytest, requests import plexapi, pytest, requests
from plexapi import compat from plexapi import compat
from plexapi.client import PlexClient from plexapi.client import PlexClient
@ -14,18 +21,18 @@ MYPLEX_PASSWORD = plexapi.CONFIG.get('auth.myplex_password')
CLIENT_BASEURL = plexapi.CONFIG.get('auth.client_baseurl') CLIENT_BASEURL = plexapi.CONFIG.get('auth.client_baseurl')
CLIENT_TOKEN = plexapi.CONFIG.get('auth.client_token') CLIENT_TOKEN = plexapi.CONFIG.get('auth.client_token')
MIN_DATETIME = datetime(2017, 1, 1) MIN_DATETIME = datetime(2014, 1, 1)
REGEX_EMAIL = r'(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)' REGEX_EMAIL = r'(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)'
REGEX_IPADDR = r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$' REGEX_IPADDR = r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'
AUDIOCHANNELS = [2, 6] AUDIOCHANNELS = {2, 6}
AUDIOLAYOUTS = ['5.1', 'stereo'] AUDIOLAYOUTS = {'5.1', '5.1(side)', 'stereo'}
CODECS = ['aac', 'h264', 'mp3', 'mpeg4'] CODECS = {'aac', 'ac3', 'dca', 'h264', 'mp3', 'mpeg4'}
CONTAINERS = ['avi', 'mp4'] CONTAINERS = {'avi', 'mp4', 'mkv'}
CONTENTRATINGS = ['TV-14'] CONTENTRATINGS = {'TV-14'}
FRAMERATES = ['24p', 'PAL'] FRAMERATES = {'24p', 'PAL'}
PROFILES = ['advanced simple', 'main'] PROFILES = {'advanced simple', 'main'}
RESOLUTIONS = ['720', 'sd'] RESOLUTIONS = {'sd', '576', '720', '1080'}
def pytest_addoption(parser): def pytest_addoption(parser):

View file

@ -8,7 +8,7 @@ def test_audio_Artist_attr(artist):
assert utils.is_datetime(artist.addedAt) assert utils.is_datetime(artist.addedAt)
assert artist.countries == [] assert artist.countries == []
assert [i.tag for i in artist.genres] == ['Electronic'] assert [i.tag for i in artist.genres] == ['Electronic']
assert 'lastfm' in artist.guid assert utils.is_string(artist.guid, gte=5)
assert artist.index == '1' assert artist.index == '1'
assert utils.is_metadata(artist._initpath) assert utils.is_metadata(artist._initpath)
assert utils.is_metadata(artist.key) assert utils.is_metadata(artist.key)
@ -24,7 +24,7 @@ def test_audio_Artist_attr(artist):
assert artist.titleSort == 'Infinite State' assert artist.titleSort == 'Infinite State'
assert artist.type == 'artist' assert artist.type == 'artist'
assert utils.is_datetime(artist.updatedAt) assert utils.is_datetime(artist.updatedAt)
assert artist.viewCount == 0 assert utils.is_int(artist.viewCount, gte=0)
def test_audio_Artist_get(artist, music): def test_audio_Artist_get(artist, music):
@ -75,7 +75,7 @@ def test_audio_Album_attrs(album):
assert album.titleSort == 'Unmastered Impulses' assert album.titleSort == 'Unmastered Impulses'
assert album.type == 'album' assert album.type == 'album'
assert utils.is_datetime(album.updatedAt) assert utils.is_datetime(album.updatedAt)
assert album.viewCount == 0 assert utils.is_int(album.viewCount, gte=0)
assert album.year == 2016 assert album.year == 2016
@ -108,7 +108,7 @@ def test_audio_Album_tracks(album):
assert track.type == 'track' assert track.type == 'track'
assert utils.is_datetime(track.updatedAt) assert utils.is_datetime(track.updatedAt)
assert track.username is None assert track.username is None
assert track.viewCount == 0 assert utils.is_int(track.viewCount, gte=0)
assert track.viewOffset == 0 assert track.viewOffset == 0
@ -144,7 +144,7 @@ def test_audio_Album_track(album, track=None):
assert track.type == 'track' assert track.type == 'track'
assert utils.is_datetime(track.updatedAt) assert utils.is_datetime(track.updatedAt)
assert track.username is None assert track.username is None
assert track.viewCount == 0 assert utils.is_int(track.viewCount, gte=0)
assert track.viewOffset == 0 assert track.viewOffset == 0
assert media.aspectRatio is None assert media.aspectRatio is None
assert media.audioChannels == 2 assert media.audioChannels == 2
@ -153,7 +153,7 @@ def test_audio_Album_track(album, track=None):
assert media.container == 'mp3' assert media.container == 'mp3'
assert media.duration == 298606 assert media.duration == 298606
assert media.height is None assert media.height is None
assert media.id == 22 assert utils.is_int(media.id, gte=1)
assert utils.is_metadata(media._initpath) assert utils.is_metadata(media._initpath)
assert media.optimizedForStreaming is None assert media.optimizedForStreaming is None
# Assign 0 media.parts # Assign 0 media.parts
@ -200,7 +200,7 @@ def test_audio_Track_attrs(album):
assert int(track.index) == 1 assert int(track.index) == 1
assert utils.is_metadata(track._initpath) assert utils.is_metadata(track._initpath)
assert utils.is_metadata(track.key) assert utils.is_metadata(track.key)
assert track.lastViewedAt is None assert utils.is_datetime(track.lastViewedAt)
assert utils.is_int(track.librarySectionID) assert utils.is_int(track.librarySectionID)
assert track.listType == 'audio' assert track.listType == 'audio'
# Assign 0 track.media # Assign 0 track.media
@ -227,7 +227,7 @@ def test_audio_Track_attrs(album):
assert track.type == 'track' assert track.type == 'track'
assert utils.is_datetime(track.updatedAt) assert utils.is_datetime(track.updatedAt)
assert track.username is None assert track.username is None
assert track.viewCount == 0 assert utils.is_int(track.viewCount, gte=0)
assert track.viewOffset == 0 assert track.viewOffset == 0
assert track.viewedAt is None assert track.viewedAt is None
assert track.year is None assert track.year is None
@ -238,7 +238,7 @@ def test_audio_Track_attrs(album):
assert media.container == 'mp3' assert media.container == 'mp3'
assert media.duration == 298606 assert media.duration == 298606
assert media.height is None assert media.height is None
assert media.id == 22 assert utils.is_int(media.id, gte=1)
assert utils.is_metadata(media._initpath) assert utils.is_metadata(media._initpath)
assert media.optimizedForStreaming is None assert media.optimizedForStreaming is None
# Assign 0 media.parts # Assign 0 media.parts

View file

@ -3,33 +3,9 @@ import pytest, time
def test_list_clients(account, plex): def test_list_clients(account, plex):
# List resources from MyPlex assert account.resources(), 'MyPlex is not listing any devlices.'
print('\nResources listed on MyPlex') assert account.devices(), 'MyPlex is not listing any devlices.'
print('---------------------------') assert plex.clients(), 'PlexServer is not listing any clients.'
resources = account.resources()
for resource in resources:
print('%s (%s)' % (resource.name, resource.product))
for connection in resource.connections:
print("* baseurl='%s', token='%s'" % (connection.uri, resource.accessToken))
print("* baseurl='%s', token='%s'" % (connection.httpuri, resource.accessToken))
assert resources, 'MyPlex is not listing any devlices.'
# List devices from MyPlex
print('\nDevices listed on MyPlex')
print('--------------------------')
devices = account.devices()
for device in devices:
print('%s (%s)' % (device.name, device.product))
for connection in device.connections:
print("* baseurl='%s', token='%s'" % (connection, device.token))
assert devices, 'MyPlex is not listing any devlices.'
# List clients from PlexServer
clients = plex.clients()
print('\nClients listed on PlexServer')
print('------------------------------')
for client in clients:
print('%s (%s)' % (client.title, client.product))
print("* baseurl='%s', token='%s'" % (client._baseurl, plex._token))
assert clients, 'PlexServer is not listing any clients.'
@pytest.mark.client @pytest.mark.client

View file

@ -6,7 +6,7 @@ from . import conftest as utils
def test_library_Library_section(plex): def test_library_Library_section(plex):
sections = plex.library.sections() sections = plex.library.sections()
assert len(sections) == 4 assert len(sections) >= 3
section_name = plex.library.section('TV Shows') section_name = plex.library.section('TV Shows')
assert section_name.title == 'TV Shows' assert section_name.title == 'TV Shows'
with pytest.raises(NotFound): with pytest.raises(NotFound):
@ -23,7 +23,7 @@ def test_library_Library_sectionByID_is_equal_section(plex, plex2):
def test_library_sectionByID_with_attrs(plex): def test_library_sectionByID_with_attrs(plex):
section = plex.library.sectionByID('1') section = plex.library.sectionByID('1')
assert section.agent == 'com.plexapp.agents.imdb' assert section.agent == 'com.plexapp.agents.imdb'
assert section.allowSync is False assert section.allowSync is ('sync' in plex.ownerFeatures)
assert section.art == '/:/resources/movie-fanart.jpg' assert section.art == '/:/resources/movie-fanart.jpg'
assert '/library/sections/1/composite/' in section.composite assert '/library/sections/1/composite/' in section.composite
assert utils.is_datetime(section.createdAt) assert utils.is_datetime(section.createdAt)
@ -132,8 +132,8 @@ def test_librarty_deleteMediaPreviews(movies):
movies.deleteMediaPreviews() movies.deleteMediaPreviews()
def test_library_MovieSection_onDeck(movies): def test_library_MovieSection_onDeck(movies, tvshows):
assert len(movies.onDeck()) assert len(movies.onDeck()) + len(tvshows.onDeck())
def test_library_MovieSection_recentlyAdded(movies): def test_library_MovieSection_recentlyAdded(movies):
@ -179,7 +179,6 @@ def test_library_PhotoSection_searchPhotos(photos, photoalbum):
assert len(photos.searchPhotos(title)) assert len(photos.searchPhotos(title))
# Start on library search
def test_library_and_section_search_for_movie(plex): def test_library_and_section_search_for_movie(plex):
find = '16 blocks' find = '16 blocks'
l_search = plex.library.search(find) l_search = plex.library.search(find)
@ -187,6 +186,8 @@ def test_library_and_section_search_for_movie(plex):
assert l_search == s_search assert l_search == s_search
# This started failing on more recent Plex Server builds
@pytest.mark.xfail
def test_search_with_apostrophe(plex): def test_search_with_apostrophe(plex):
show_title = "Marvel's Daredevil" show_title = "Marvel's Daredevil"
result_root = plex.search(show_title) result_root = plex.search(show_title)

View file

@ -48,11 +48,8 @@ def test_create_playlist(plex, show):
playlist.delete() playlist.delete()
@pytest.mark.req_client @pytest.mark.client
def test_playlist_play(plex): def test_playlist_play(plex, client, artist, album):
client = getclient(CONFIG.client, CONFIG.client_baseurl, plex)
artist = plex.library.section(CONFIG.audio_section).get(CONFIG.audio_artist)
album = artist.album(CONFIG.audio_album)
try: try:
playlist_name = 'test_play_playlist' playlist_name = 'test_play_playlist'
playlist = plex.createPlaylist(playlist_name, album) playlist = plex.createPlaylist(playlist_name, album)
@ -85,12 +82,9 @@ def test_playlist_playQueue(plex, album):
playlist.delete() playlist.delete()
@pytest.mark.req_client @pytest.mark.client
def test_play_photos(account, plex): def test_play_photos(plex, client, photoalbum):
client = getclient('iphone-mike', CONFIG.client_baseurl, plex) photos = photoalbum.photos()
photosection = plex.library.section(CONFIG.photo_section)
album = photosection.get(CONFIG.photo_album)
photos = album.photos()
for photo in photos[:4]: for photo in photos[:4]:
client.playMedia(photo) client.playMedia(photo)
time.sleep(2) time.sleep(2)

View file

@ -15,7 +15,7 @@ def test_server_attr(plex):
assert plex.myPlex is True assert plex.myPlex is True
assert plex.myPlexMappingState == 'mapped' assert plex.myPlexMappingState == 'mapped'
assert plex.myPlexSigninState == 'ok' assert plex.myPlexSigninState == 'ok'
assert plex.myPlexSubscription == '0' assert utils.is_int(plex.myPlexSubscription, gte=0)
assert re.match(utils.REGEX_EMAIL, plex.myPlexUsername) assert re.match(utils.REGEX_EMAIL, plex.myPlexUsername)
assert plex.platform in ('Linux', 'Windows') assert plex.platform in ('Linux', 'Windows')
assert len(plex.platformVersion) >= 5 assert len(plex.platformVersion) >= 5
@ -163,16 +163,11 @@ def test_server_client_not_found(plex):
plex.client('<This-client-should-not-be-found>') plex.client('<This-client-should-not-be-found>')
@pytest.mark.req_client
def test_server_client(plex):
assert plex.client('Plex Web (Chrome)')
def test_server_Server_sessions(plex): def test_server_Server_sessions(plex):
assert len(plex.sessions()) == 0 assert len(plex.sessions()) == 0
@pytest.mark.req_client @pytest.mark.client
def test_server_clients(plex): def test_server_clients(plex):
assert len(plex.clients()) assert len(plex.clients())
client = plex.clients()[0] client = plex.clients()[0]
@ -207,9 +202,10 @@ def test_server_account(plex):
assert re.match(utils.REGEX_IPADDR, account.publicAddress) assert re.match(utils.REGEX_IPADDR, account.publicAddress)
assert int(account.publicPort) >= 1000 assert int(account.publicPort) >= 1000
assert account.signInState == 'ok' assert account.signInState == 'ok'
assert account.subscriptionActive is False assert isinstance(account.subscriptionActive, bool)
assert account.subscriptionFeatures == [] if account.subscriptionActive: assert len(account.subscriptionFeatures)
assert account.subscriptionState == 'Unknown' else: assert account.subscriptionFeatures == []
assert account.subscriptionState == 'Active' if account.subscriptionActive else 'Unknown'
assert re.match(utils.REGEX_EMAIL, account.username) assert re.match(utils.REGEX_EMAIL, account.username)

View file

@ -79,7 +79,7 @@ def test_video_Movie_attrs(movies):
assert int(movie.librarySectionID) >= 1 assert int(movie.librarySectionID) >= 1
assert movie.listType == 'video' assert movie.listType == 'video'
assert movie.originalTitle is None assert movie.originalTitle is None
assert movie.originallyAvailableAt.strftime('%Y-%m-%d') == '2006-06-09' assert movie.originallyAvailableAt.strftime('%Y-%m-%d') in ('2006-06-08', '2006-06-09')
assert movie.player is None assert movie.player is None
assert movie.playlistItemID is None assert movie.playlistItemID is None
assert movie.primaryExtraKey is None assert movie.primaryExtraKey is None
@ -87,7 +87,7 @@ def test_video_Movie_attrs(movies):
assert movie.rating == '7.4' assert movie.rating == '7.4'
assert movie.ratingImage == 'rottentomatoes://image.rating.certified' assert movie.ratingImage == 'rottentomatoes://image.rating.certified'
assert movie.ratingKey >= 1 assert movie.ratingKey >= 1
assert sorted([i.tag for i in movie.roles]) == ['Adrian Ochoa', 'Andrew Stanton', 'Billy Crystal', 'Bob Costas', 'Bonnie Hunt', 'Cheech Marin', 'Dale Earnhardt Jr.', 'Darrell Waltrip', 'Dave Foley', 'Douglas Keever', 'E.J. Holowicki', 'Edie McClurg', 'Elissa Knight', 'George Carlin', 'Guido Quaroni', 'Humpy Wheeler', 'Jay Leno', 'Jenifer Lewis', 'Jeremy Piven', 'Joe Ranft', 'Joe Ranft', 'John Goodman', 'John Ratzenberger', 'John Ratzenberger', 'John Ratzenberger', 'John Ratzenberger', 'Jonas Rivera', 'Katherine Helmond', 'Larry Benton', 'Larry the Cable Guy', 'Lindsey Collins', 'Lou Romano', 'Lynda Petty', 'Michael Keaton', 'Michael Schumacher', 'Michael Wallis', 'Mike Nelson', 'Owen Wilson', 'Paul Dooley', 'Paul Newman', 'Ray Magliozzi', 'Richard Kind', 'Richard Petty', 'Sarah Clark', 'Tim Allen', 'Tom Hanks', 'Tom Magliozzi', 'Tony Shalhoub', 'Vanness Wu'] # noqa assert sorted([i.tag for i in movie.roles])[:4] == ['Adrian Ochoa', 'Andrew Stanton', 'Billy Crystal', 'Bob Costas'] # noqa
assert movie._server._baseurl == utils.SERVER_BASEURL assert movie._server._baseurl == utils.SERVER_BASEURL
assert movie.sessionKey is None assert movie.sessionKey is None
assert movie.studio == 'Walt Disney Pictures' assert movie.studio == 'Walt Disney Pictures'
@ -130,7 +130,7 @@ def test_video_Movie_attrs(movies):
assert audio.type == 2 assert audio.type == 2
# Media # Media
media = movie.media[0] media = movie.media[0]
assert media.aspectRatio == 1.78 assert media.aspectRatio >= 1.3
assert media.audioChannels in utils.AUDIOCHANNELS assert media.audioChannels in utils.AUDIOCHANNELS
assert media.audioCodec in utils.CODECS assert media.audioCodec in utils.CODECS
assert utils.is_int(media.bitrate) assert utils.is_int(media.bitrate)
@ -158,7 +158,7 @@ def test_video_Movie_attrs(movies):
assert utils.is_float(video.frameRate, gte=20.0) assert utils.is_float(video.frameRate, gte=20.0)
assert video.frameRateMode is None assert video.frameRateMode is None
assert video.hasScallingMatrix is None assert video.hasScallingMatrix is None
assert utils.is_int(video.height, gte=300) assert utils.is_int(video.height, gte=250)
assert utils.is_int(video.id) assert utils.is_int(video.id)
assert utils.is_int(video.index, gte=0) assert utils.is_int(video.index, gte=0)
assert utils.is_metadata(video._initpath) assert utils.is_metadata(video._initpath)
@ -197,7 +197,7 @@ def test_video_Movie_attrs(movies):
assert utils.is_float(stream1.frameRate, gte=20.0) assert utils.is_float(stream1.frameRate, gte=20.0)
assert stream1.frameRateMode is None assert stream1.frameRateMode is None
assert stream1.hasScallingMatrix is None assert stream1.hasScallingMatrix is None
assert utils.is_int(stream1.height, gte=300) assert utils.is_int(stream1.height, gte=250)
assert utils.is_int(stream1.id) assert utils.is_int(stream1.id)
assert utils.is_int(stream1.index, gte=0) assert utils.is_int(stream1.index, gte=0)
assert utils.is_metadata(stream1._initpath) assert utils.is_metadata(stream1._initpath)
@ -242,7 +242,7 @@ def test_video_Show(show):
def test_video_Show_attrs(show): def test_video_Show_attrs(show):
assert show.addedAt > datetime(2017, 1, 1) assert utils.is_datetime(show.addedAt)
assert utils.is_metadata(show.art, contains='/art/') assert utils.is_metadata(show.art, contains='/art/')
assert utils.is_metadata(show.banner, contains='/banner/') assert utils.is_metadata(show.banner, contains='/banner/')
assert utils.is_int(show.childCount) assert utils.is_int(show.childCount)
@ -264,8 +264,8 @@ def test_video_Show_attrs(show):
assert show.originallyAvailableAt.strftime('%Y-%m-%d') == '2014-03-19' assert show.originallyAvailableAt.strftime('%Y-%m-%d') == '2014-03-19'
assert show.rating >= 8.0 assert show.rating >= 8.0
assert utils.is_int(show.ratingKey) assert utils.is_int(show.ratingKey)
assert sorted([i.tag for i in show.roles][:3]) == ['Alycia Debnam-Carey', 'Lindsey Morgan', 'Richard Harmon'] assert sorted([i.tag for i in show.roles])[:3] == ['Adina Porter', 'Alessandro Juliani', 'Alycia Debnam-Carey']
assert sorted([i.tag for i in show.actors][:3]) == ['Alycia Debnam-Carey', 'Lindsey Morgan', 'Richard Harmon'] assert sorted([i.tag for i in show.actors])[:3] == ['Adina Porter', 'Alessandro Juliani', 'Alycia Debnam-Carey']
assert show._server._baseurl == utils.SERVER_BASEURL assert show._server._baseurl == utils.SERVER_BASEURL
assert show.studio == 'The CW' assert show.studio == 'The CW'
assert utils.is_string(show.summary, gte=100) assert utils.is_string(show.summary, gte=100)
@ -325,7 +325,7 @@ def test_video_Show_download(monkeydownload, tmpdir, show):
def test_video_Season_download(monkeydownload, tmpdir, show): def test_video_Season_download(monkeydownload, tmpdir, show):
season = show.season('Season 1') season = show.season('Season 1')
filepaths = season.download(savepath=str(tmpdir)) filepaths = season.download(savepath=str(tmpdir))
assert len(filepaths) == 8 assert len(filepaths) >= 4
def test_video_Episode_download(monkeydownload, tmpdir, episode): def test_video_Episode_download(monkeydownload, tmpdir, episode):
@ -432,7 +432,8 @@ def test_video_Episode_attrs(episode):
assert utils.is_int(media.height, gte=200) assert utils.is_int(media.height, gte=200)
assert utils.is_int(media.id) assert utils.is_int(media.id)
assert utils.is_metadata(media._initpath) assert utils.is_metadata(media._initpath)
assert isinstance(media.optimizedForStreaming, bool) if media.optimizedForStreaming:
assert isinstance(media.optimizedForStreaming, bool)
assert media._server._baseurl == utils.SERVER_BASEURL assert media._server._baseurl == utils.SERVER_BASEURL
assert media.videoCodec in utils.CODECS assert media.videoCodec in utils.CODECS
assert media.videoFrameRate in utils.FRAMERATES assert media.videoFrameRate in utils.FRAMERATES
@ -452,7 +453,7 @@ def test_video_Episode_attrs(episode):
def test_video_Season(show): def test_video_Season(show):
seasons = show.seasons() seasons = show.seasons()
assert len(seasons) == 2 assert len(seasons) >= 1
assert ['Season 1', 'Season 2'] == [s.title for s in seasons] assert ['Season 1', 'Season 2'] == [s.title for s in seasons]
assert show.season('Season 1') == seasons[0] assert show.season('Season 1') == seasons[0]