Started movinf client tests into Pytest framework

This commit is contained in:
Michael Shepanski 2017-05-12 23:25:57 -04:00
parent ef8eb94bc5
commit 650a88d638
7 changed files with 75 additions and 27 deletions

View file

@ -70,6 +70,10 @@ class PlexClient(PlexObject):
if connect and self._baseurl:
self.connect(timeout=timeout)
def _nextCommandId(self):
self._commandId += 0
return self._commandId
def connect(self, timeout=None):
""" Alias of reload as any subsequent requests to this client will be
made directly to the device even if the object attributes were initially
@ -113,7 +117,7 @@ class PlexClient(PlexObject):
headers.update(kwargs)
return headers
def proxyThroughServer(self, value=True):
def proxyThroughServer(self, value=True, server=None):
""" Tells this PlexClient instance to proxy all future commands through the PlexServer.
Useful if you do not wish to connect directly to the Client device itself.
@ -123,6 +127,8 @@ class PlexClient(PlexObject):
Raises:
:class:`~plexapi.exceptions.Unsupported`: Cannot use client proxy with unknown server.
"""
if server:
self._server = server
if value is True and not self._server:
raise Unsupported('Cannot use client proxy with unknown server.')
self._proxyThroughServer = value
@ -165,8 +171,7 @@ class PlexClient(PlexObject):
raise Unsupported('Client %s doesnt support %s controller.' % (self.title, controller))
key = '/player/%s%s' % (command, utils.joinArgs(params))
headers = {'X-Plex-Target-Client-Identifier': self.machineIdentifier}
self._commandId += 1
params['commandID'] = self._commandId
params['commandID'] = self._nextCommandId()
proxy = self._proxyThroughServer if proxy is None else proxy
if proxy:
return self._server.query(key, headers=headers)
@ -428,6 +433,8 @@ class PlexClient(PlexObject):
'port': server_url[-1],
'offset': offset,
'key': media.key,
'token': self._server._token,
'commandID': self._nextCommandId(),
'containerKey': '/playQueues/%s?window=100&own=1' % playqueue.playQueueID,
}, **params))

View file

@ -93,20 +93,17 @@ class MediaPart(PlexObject):
streams.append(cls(self._server, elem, self._initpath))
return streams
@property
def videoStreams(self):
""" Returns a list of :class:`~plexapi.media.VideoStream` objects in this MediaPart. """
return [s for s in self.streams if s.streamType == VideoStream.STREAMTYPE]
return [stream for stream in self.streams if stream.streamType == VideoStream.STREAMTYPE]
@property
def audioStreams(self):
""" Returns a list of :class:`~plexapi.media.AudioStream` objects in this MediaPart. """
return [s for s in self.streams if s.streamType == AudioStream.STREAMTYPE]
return [stream for stream in self.streams if stream.streamType == AudioStream.STREAMTYPE]
@property
def subtitleStreams(self):
""" Returns a list of :class:`~plexapi.media.SubtitleStream` objects in this MediaPart. """
return [s for s in self.streams if s.streamType == SubtitleStream.STREAMTYPE]
return [stream for stream in self.streams if stream.streamType == SubtitleStream.STREAMTYPE]
class MediaPartStream(PlexObject):

View file

@ -144,7 +144,15 @@ class Movie(Video, Playable):
""" This does not exist in plex xml response but is added to have a common
interface to get the location of the Movie/Show/Episode
"""
return [p.file for p in self.iterParts() if p]
return [part.file for part in self.iterParts() if part]
def subtitleStreams(self):
""" Returns a list of :class:`~plexapi.media.SubtitleStream` objects for all MediaParts. """
streams = []
for elem in self.media:
for part in elem.parts:
streams += part.subtitleStreams()
return streams
def _prettyfilename(self):
# This is just for compat.

View file

@ -30,7 +30,7 @@ MYPLEX_PASSWORD = plexapi.CONFIG.get('auth.myplex_password')
CLIENT_BASEURL = plexapi.CONFIG.get('auth.client_baseurl')
CLIENT_TOKEN = plexapi.CONFIG.get('auth.client_token')
MIN_DATETIME = datetime(2008, 1, 1)
MIN_DATETIME = datetime(1999, 1, 1)
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}$'
@ -79,7 +79,7 @@ def plex2():
@pytest.fixture()
def client(request):
return PlexClient(baseurl=CLIENT_BASEURL, token=CLIENT_TOKEN)
return PlexClient(plex(), baseurl=CLIENT_BASEURL, token=CLIENT_TOKEN)
@pytest.fixture()

View file

@ -2,6 +2,18 @@
import pytest, time
def _check_capabilities(client, capabilities):
supported = client.protocolCapabilities
for capability in capabilities:
if capability not in supported:
pytest.skip('Client doesnt support %s capability.', capability)
def _check_proxy(plex, client, proxy):
if proxy:
client.proxyThroughServer(server=plex)
@pytest.mark.client
def test_list_clients(account, plex):
assert account.resources(), 'MyPlex is not listing any devlices.'
@ -10,17 +22,10 @@ def test_list_clients(account, plex):
@pytest.mark.client
def test_client_navigation_direct(plex, client, episode, artist):
_navigate(plex, client, episode, artist)
@pytest.mark.client
def test_client_navigation_via_proxy(plex, client, episode, artist):
client.proxyThroughServer()
_navigate(plex, client, episode, artist)
def _navigate(plex, client, episode, artist):
@pytest.mark.parametrize('proxy', [False, True])
def test_client_navigation(plex, client, episode, artist, proxy):
_check_capabilities(client, ['navigation'])
_check_proxy(plex, client, proxy)
# Browse around a bit..
client.moveDown(); time.sleep(0.5)
client.moveDown(); time.sleep(0.5)
@ -44,6 +49,36 @@ def _navigate(plex, client, episode, artist):
client.goBack(); time.sleep(5)
@pytest.mark.client
@pytest.mark.parametrize('proxy', [False, True])
def test_video_playback(plex, client, movie, proxy):
_check_capabilities(client, ['playback'])
_check_proxy(plex, client, proxy)
try:
# Need a movie with subtitles
movie = plex.library.section('Movies').get('Moana').reload()
mtype = 'video'
subs = [stream for stream in movie.subtitleStreams() if stream.language == 'English']
# Basic play ability
print('Basic play ability')
client.playMedia(movie); time.sleep(5)
client.pause(mtype); time.sleep(2)
# Step forward, back, seek in time
print('Step forward, back, seek in time')
client.stepForward(mtype); time.sleep(5)
client.play(mtype); time.sleep(3)
client.stepBack(mtype); time.sleep(5)
client.play(mtype); time.sleep(3)
client.seekTo(10*60*1000); time.sleep(5)
# Enable subtitles
print('Enable subtitles')
client.setSubtitleStream(0, mtype); time.sleep(10)
client.setSubtitleStream(subs[0].id, mtype); time.sleep(10)
client.stop(mtype); time.sleep(1)
finally:
movie.markWatched()
@pytest.mark.client
def _test_client_PlexClient__loadData(pms):
pass

View file

@ -20,7 +20,7 @@ def test_server_attr(plex):
assert plex.platform in ('Linux', 'Windows')
assert len(plex.platformVersion) >= 5
assert plex._token == utils.SERVER_TOKEN
assert plex.transcoderActiveVideoSessions == 0
assert utils.is_int(plex.transcoderActiveVideoSessions, gte=0)
assert utils.is_datetime(plex.updatedAt)
assert len(plex.version) >= 5
@ -168,7 +168,7 @@ def test_server_client_not_found(plex):
def test_server_Server_sessions(plex):
assert len(plex.sessions()) == 0
assert len(plex.sessions()) >= 0
@pytest.mark.client

View file

@ -81,7 +81,8 @@ def test_video_Movie_attrs(movies):
assert movie.originallyAvailableAt.strftime('%Y-%m-%d') in ('2008-01-11', '2008-02-11')
assert movie.player is None
assert movie.playlistItemID is None
assert movie.primaryExtraKey is None
if movie.primaryExtraKey:
assert utils.is_metadata(movie.primaryExtraKey)
assert [i.tag for i in movie.producers] == []
assert float(movie.rating) >= 6.4
assert movie.ratingImage == 'rottentomatoes://image.rating.ripe'
@ -460,7 +461,7 @@ def test_video_Episode_attrs(episode):
def test_video_Season(show):
seasons = show.seasons()
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[:2]]
assert show.season('Season 1') == seasons[0]