mirror of
https://github.com/spl0k/supysonic.git
synced 2024-12-22 17:06:17 +00:00
Listing endpoints tests
This commit is contained in:
parent
c709fa7e29
commit
5084c745dc
@ -17,6 +17,8 @@ from .test_user import UserTestCase
|
|||||||
from .test_chat import ChatTestCase
|
from .test_chat import ChatTestCase
|
||||||
from .test_search import SearchTestCase
|
from .test_search import SearchTestCase
|
||||||
from .test_playlist import PlaylistTestCase
|
from .test_playlist import PlaylistTestCase
|
||||||
|
from .test_browse import BrowseTestCase
|
||||||
|
from .test_album_songs import AlbumSongsTestCase
|
||||||
|
|
||||||
def suite():
|
def suite():
|
||||||
suite = unittest.TestSuite()
|
suite = unittest.TestSuite()
|
||||||
@ -28,6 +30,8 @@ def suite():
|
|||||||
suite.addTest(unittest.makeSuite(ChatTestCase))
|
suite.addTest(unittest.makeSuite(ChatTestCase))
|
||||||
suite.addTest(unittest.makeSuite(SearchTestCase))
|
suite.addTest(unittest.makeSuite(SearchTestCase))
|
||||||
suite.addTest(unittest.makeSuite(PlaylistTestCase))
|
suite.addTest(unittest.makeSuite(PlaylistTestCase))
|
||||||
|
suite.addTest(unittest.makeSuite(BrowseTestCase))
|
||||||
|
suite.addTest(unittest.makeSuite(AlbumSongsTestCase))
|
||||||
|
|
||||||
return suite
|
return suite
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ class ApiTestBase(unittest.TestCase):
|
|||||||
xml = etree.fromstring(rg.data)
|
xml = etree.fromstring(rg.data)
|
||||||
self.schema.assert_(xml)
|
self.schema.assert_(xml)
|
||||||
|
|
||||||
if 'status="ok"' in rg.data:
|
if xml.get('status') == 'ok':
|
||||||
self.assertIsNone(error)
|
self.assertIsNone(error)
|
||||||
if tag:
|
if tag:
|
||||||
self.assertEqual(xml[0].tag, '{{{}}}{}'.format(NS, tag))
|
self.assertEqual(xml[0].tag, '{{{}}}{}'.format(NS, tag))
|
||||||
|
120
tests/api/test_album_songs.py
Normal file
120
tests/api/test_album_songs.py
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim:fenc=utf-8
|
||||||
|
#
|
||||||
|
# This file is part of Supysonic.
|
||||||
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2017 Alban 'spl0k' Féron
|
||||||
|
#
|
||||||
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from supysonic.db import Folder, Artist, Album, Track
|
||||||
|
|
||||||
|
from .apitestbase import ApiTestBase
|
||||||
|
|
||||||
|
class AlbumSongsTestCase(ApiTestBase):
|
||||||
|
# I'm too lazy to write proper tests concerning the data on those endpoints
|
||||||
|
# Let's just check paramter validation and ensure coverage
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(AlbumSongsTestCase, self).setUp()
|
||||||
|
|
||||||
|
folder = Folder()
|
||||||
|
folder.name = 'Root'
|
||||||
|
folder.root = True
|
||||||
|
folder.path = 'tests/assets'
|
||||||
|
|
||||||
|
artist = Artist()
|
||||||
|
artist.name = 'Artist'
|
||||||
|
|
||||||
|
album = Album()
|
||||||
|
album.name = 'Album'
|
||||||
|
album.artist = artist
|
||||||
|
|
||||||
|
track = Track()
|
||||||
|
track.title = 'Track'
|
||||||
|
track.album = album
|
||||||
|
track.artist = artist
|
||||||
|
track.disc = 1
|
||||||
|
track.number = 1
|
||||||
|
track.path = 'tests/assets/empty'
|
||||||
|
track.folder = folder
|
||||||
|
track.root_folder = folder
|
||||||
|
track.duration = 2
|
||||||
|
track.bitrate = 320
|
||||||
|
track.content_type = 'audio/mpeg'
|
||||||
|
track.last_modification = 0
|
||||||
|
|
||||||
|
self.store.add(track)
|
||||||
|
self.store.commit()
|
||||||
|
|
||||||
|
def test_get_album_list(self):
|
||||||
|
self._make_request('getAlbumList', error = 10)
|
||||||
|
self._make_request('getAlbumList', { 'type': 'kraken' }, error = 0)
|
||||||
|
self._make_request('getAlbumList', { 'type': 'random', 'size': 'huge' }, error = 0)
|
||||||
|
self._make_request('getAlbumList', { 'type': 'newest', 'offset': 'minus one' }, error = 0)
|
||||||
|
|
||||||
|
types = [ 'random', 'newest', 'highest', 'frequent', 'recent', 'alphabeticalByName',
|
||||||
|
'alphabeticalByArtist', 'starred' ]
|
||||||
|
for t in types:
|
||||||
|
self._make_request('getAlbumList', { 'type': t }, tag = 'albumList', skip_post = True)
|
||||||
|
|
||||||
|
rv, child = self._make_request('getAlbumList', { 'type': 'random' }, tag = 'albumList', skip_post = True)
|
||||||
|
self.assertEqual(len(child), 10)
|
||||||
|
rv, child = self._make_request('getAlbumList', { 'type': 'random', 'size': 3 }, tag = 'albumList', skip_post = True)
|
||||||
|
self.assertEqual(len(child), 3)
|
||||||
|
|
||||||
|
self.store.remove(self.store.find(Folder).one())
|
||||||
|
rv, child = self._make_request('getAlbumList', { 'type': 'random' }, tag = 'albumList')
|
||||||
|
self.assertEqual(len(child), 0)
|
||||||
|
|
||||||
|
def test_get_album_list2(self):
|
||||||
|
self._make_request('getAlbumList2', error = 10)
|
||||||
|
self._make_request('getAlbumList2', { 'type': 'void' }, error = 0)
|
||||||
|
self._make_request('getAlbumList2', { 'type': 'random', 'size': 'size_t' }, error = 0)
|
||||||
|
self._make_request('getAlbumList2', { 'type': 'newest', 'offset': '&v + 2' }, error = 0)
|
||||||
|
|
||||||
|
types = [ 'random', 'newest', 'frequent', 'recent', 'starred', 'alphabeticalByName', 'alphabeticalByArtist' ]
|
||||||
|
for t in types:
|
||||||
|
self._make_request('getAlbumList2', { 'type': t }, tag = 'albumList2', skip_post = True)
|
||||||
|
|
||||||
|
rv, child = self._make_request('getAlbumList2', { 'type': 'random' }, tag = 'albumList2', skip_post = True)
|
||||||
|
self.assertEqual(len(child), 10)
|
||||||
|
rv, child = self._make_request('getAlbumList2', { 'type': 'random', 'size': 3 }, tag = 'albumList2', skip_post = True)
|
||||||
|
self.assertEqual(len(child), 3)
|
||||||
|
|
||||||
|
self.store.remove(self.store.find(Track).one())
|
||||||
|
self.store.remove(self.store.find(Album).one())
|
||||||
|
rv, child = self._make_request('getAlbumList2', { 'type': 'random' }, tag = 'albumList2')
|
||||||
|
self.assertEqual(len(child), 0)
|
||||||
|
|
||||||
|
def test_get_random_songs(self):
|
||||||
|
self._make_request('getRandomSongs', { 'size': '8 floors' }, error = 0)
|
||||||
|
self._make_request('getRandomSongs', { 'fromYear': 'year' }, error = 0)
|
||||||
|
self._make_request('getRandomSongs', { 'toYear': 'year' }, error = 0)
|
||||||
|
self._make_request('getRandomSongs', { 'musicFolderId': 'idid' }, error = 0)
|
||||||
|
self._make_request('getRandomSongs', { 'musicFolderId': uuid.uuid4() }, error = 70)
|
||||||
|
|
||||||
|
rv, child = self._make_request('getRandomSongs', tag = 'randomSongs')
|
||||||
|
self.assertEqual(len(child), 10)
|
||||||
|
rv, child = self._make_request('getRandomSongs', { 'size': 3 }, tag = 'randomSongs')
|
||||||
|
self.assertEqual(len(child), 3)
|
||||||
|
|
||||||
|
fid = self.store.find(Folder).one().id
|
||||||
|
self._make_request('getRandomSongs', { 'fromYear': -52, 'toYear': '1984', 'genre': 'some cryptic subgenre youve never heard of', 'musicFolderId': fid }, tag = 'randomSongs')
|
||||||
|
|
||||||
|
def test_now_playing(self):
|
||||||
|
self._make_request('getNowPlaying', tag = 'nowPlaying')
|
||||||
|
|
||||||
|
def test_get_starred(self):
|
||||||
|
self._make_request('getStarred', tag = 'starred')
|
||||||
|
|
||||||
|
def test_get_starred2(self):
|
||||||
|
self._make_request('getStarred2', tag = 'starred2')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
188
tests/api/test_browse.py
Normal file
188
tests/api/test_browse.py
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# vim:fenc=utf-8
|
||||||
|
#
|
||||||
|
# This file is part of Supysonic.
|
||||||
|
# Supysonic is a Python implementation of the Subsonic server API.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2017 Alban 'spl0k' Féron
|
||||||
|
#
|
||||||
|
# Distributed under terms of the GNU AGPLv3 license.
|
||||||
|
|
||||||
|
from lxml import etree
|
||||||
|
import time
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
from supysonic.db import Folder, Artist, Album, Track
|
||||||
|
|
||||||
|
from .apitestbase import ApiTestBase
|
||||||
|
|
||||||
|
class BrowseTestCase(ApiTestBase):
|
||||||
|
def setUp(self):
|
||||||
|
super(BrowseTestCase, self).setUp()
|
||||||
|
|
||||||
|
empty = Folder()
|
||||||
|
empty.root = True
|
||||||
|
empty.name = 'Empty root'
|
||||||
|
empty.path = '/tmp'
|
||||||
|
self.store.add(empty)
|
||||||
|
|
||||||
|
root = Folder()
|
||||||
|
root.root = True
|
||||||
|
root.name = 'Root folder'
|
||||||
|
root.path = 'tests/assets'
|
||||||
|
self.store.add(root)
|
||||||
|
|
||||||
|
for letter in 'ABC':
|
||||||
|
folder = Folder()
|
||||||
|
folder.name = letter + 'rtist'
|
||||||
|
folder.path = 'tests/assets/{}rtist'.format(letter)
|
||||||
|
folder.parent = root
|
||||||
|
|
||||||
|
artist = Artist()
|
||||||
|
artist.name = letter + 'rtist'
|
||||||
|
|
||||||
|
for lether in 'AB':
|
||||||
|
afolder = Folder()
|
||||||
|
afolder.name = letter + lether + 'lbum'
|
||||||
|
afolder.path = 'tests/assets/{0}rtist/{0}{1}lbum'.format(letter, lether)
|
||||||
|
afolder.parent = folder
|
||||||
|
|
||||||
|
album = Album()
|
||||||
|
album.name = letter + lether + 'lbum'
|
||||||
|
album.artist = artist
|
||||||
|
|
||||||
|
for num, song in enumerate([ 'One', 'Two', 'Three' ]):
|
||||||
|
track = Track()
|
||||||
|
track.disc = 1
|
||||||
|
track.number = num
|
||||||
|
track.title = song
|
||||||
|
track.duration = 2
|
||||||
|
track.album = album
|
||||||
|
track.artist = artist
|
||||||
|
track.bitrate = 320
|
||||||
|
track.path = 'tests/assets/{0}rtist/{0}{1}lbum/{2}'.format(letter, lether, song)
|
||||||
|
track.content_type = 'audio/mpeg'
|
||||||
|
track.last_modification = 0
|
||||||
|
track.root_folder = root
|
||||||
|
track.folder = afolder
|
||||||
|
self.store.add(track)
|
||||||
|
|
||||||
|
self.store.commit()
|
||||||
|
|
||||||
|
self.assertEqual(self.store.find(Folder).count(), 11)
|
||||||
|
self.assertEqual(self.store.find(Folder, Folder.root == True).count(), 2)
|
||||||
|
self.assertEqual(self.store.find(Artist).count(), 3)
|
||||||
|
self.assertEqual(self.store.find(Album).count(), 6)
|
||||||
|
self.assertEqual(self.store.find(Track).count(), 18)
|
||||||
|
|
||||||
|
def test_get_music_folders(self):
|
||||||
|
# Do not validate against the XSD here, this is the only place where the API should return ids as ints
|
||||||
|
# all our ids are uuids :/
|
||||||
|
rv = self.client.get('/rest/getMusicFolders.view', query_string = { 'u': 'alice', 'p': 'Alic3', 'c': 'tests' })
|
||||||
|
self.assertEqual(rv.status_code, 200)
|
||||||
|
xml = etree.fromstring(rv.data)
|
||||||
|
|
||||||
|
NS = '{http://subsonic.org/restapi}'
|
||||||
|
self.assertEqual(xml.tag, NS + 'subsonic-response')
|
||||||
|
self.assertEqual(xml.get('status'), 'ok')
|
||||||
|
self.assertEqual(len(xml), 1)
|
||||||
|
self.assertEqual(xml[0].tag, NS + 'musicFolders')
|
||||||
|
self.assertEqual(len(xml[0]), 2)
|
||||||
|
self.assertSequenceEqual(sorted(self._xpath(xml, './musicFolders/musicFolder/@name')), [ 'Empty root', 'Root folder' ])
|
||||||
|
|
||||||
|
def test_get_indexes(self):
|
||||||
|
self._make_request('getIndexes', { 'musicFolderId': 'abcdef' }, error = 0)
|
||||||
|
self._make_request('getIndexes', { 'musicFolderId': str(uuid.uuid4()) }, error = 70)
|
||||||
|
self._make_request('getIndexes', { 'ifModifiedSince': 'quoi' }, error = 0)
|
||||||
|
|
||||||
|
rv, child = self._make_request('getIndexes', { 'ifModifiedSince': int(time.time() * 1000 + 1000) }, tag = 'indexes')
|
||||||
|
self.assertEqual(len(child), 0)
|
||||||
|
|
||||||
|
fid = self.store.find(Folder, Folder.name == 'Empty root').one().id
|
||||||
|
rv, child = self._make_request('getIndexes', { 'musicFolderId': str(fid) }, tag = 'indexes')
|
||||||
|
self.assertEqual(len(child), 0)
|
||||||
|
|
||||||
|
rv, child = self._make_request('getIndexes', tag = 'indexes')
|
||||||
|
self.assertEqual(len(child), 3)
|
||||||
|
for i, letter in enumerate([ 'A', 'B', 'C' ]):
|
||||||
|
self.assertEqual(child[i].get('name'), letter)
|
||||||
|
self.assertEqual(len(child[i]), 1)
|
||||||
|
self.assertEqual(child[i][0].get('name'), letter + 'rtist')
|
||||||
|
|
||||||
|
def test_get_music_directory(self):
|
||||||
|
self._make_request('getMusicDirectory', error = 10)
|
||||||
|
self._make_request('getMusicDirectory', { 'id': 'id' }, error = 0)
|
||||||
|
self._make_request('getMusicDirectory', { 'id': str(uuid.uuid4()) }, error = 70)
|
||||||
|
|
||||||
|
# should test with folders with both children folders and tracks. this code would break in that case
|
||||||
|
for f in self.store.find(Folder):
|
||||||
|
rv, child = self._make_request('getMusicDirectory', { 'id': str(f.id) }, tag = 'directory')
|
||||||
|
self.assertEqual(child.get('id'), str(f.id))
|
||||||
|
self.assertEqual(child.get('name'), f.name)
|
||||||
|
self.assertEqual(len(child), f.children.count() + f.tracks.count())
|
||||||
|
for dbc, xmlc in zip(sorted(f.children, key = lambda c: c.name), sorted(child, key = lambda c: c.get('title'))):
|
||||||
|
self.assertEqual(dbc.name, xmlc.get('title'))
|
||||||
|
self.assertEqual(xmlc.get('artist'), f.name)
|
||||||
|
self.assertEqual(xmlc.get('parent'), str(f.id))
|
||||||
|
for t, xmlc in zip(sorted(f.tracks, key = lambda t: t.title), sorted(child, key = lambda c: c.get('title'))):
|
||||||
|
self.assertEqual(t.title, xmlc.get('title'))
|
||||||
|
self.assertEqual(xmlc.get('parent'), str(f.id))
|
||||||
|
|
||||||
|
def test_get_artists(self):
|
||||||
|
# same as getIndexes standard case
|
||||||
|
# dataset should be improved to have a different directory structure than /root/Artist/Album/Track
|
||||||
|
|
||||||
|
rv, child = self._make_request('getArtists', tag = 'artists')
|
||||||
|
self.assertEqual(len(child), 3)
|
||||||
|
for i, letter in enumerate([ 'A', 'B', 'C' ]):
|
||||||
|
self.assertEqual(child[i].get('name'), letter)
|
||||||
|
self.assertEqual(len(child[i]), 1)
|
||||||
|
self.assertEqual(child[i][0].get('name'), letter + 'rtist')
|
||||||
|
|
||||||
|
def test_get_artist(self):
|
||||||
|
# dataset should be improved to have tracks by a different artist than the album's artist
|
||||||
|
self._make_request('getArtist', error = 10)
|
||||||
|
self._make_request('getArtist', { 'id': 'artist' }, error = 0)
|
||||||
|
self._make_request('getArtist', { 'id': str(uuid.uuid4()) }, error = 70)
|
||||||
|
|
||||||
|
for ar in self.store.find(Artist):
|
||||||
|
rv, child = self._make_request('getArtist', { 'id': str(ar.id) }, tag = 'artist')
|
||||||
|
self.assertEqual(child.get('id'), str(ar.id))
|
||||||
|
self.assertEqual(child.get('albumCount'), str(len(child)))
|
||||||
|
self.assertEqual(len(child), ar.albums.count())
|
||||||
|
for dal, xal in zip(sorted(ar.albums, key = lambda a: a.name), sorted(child, key = lambda c: c.get('name'))):
|
||||||
|
self.assertEqual(dal.name, xal.get('name'))
|
||||||
|
self.assertEqual(xal.get('artist'), ar.name) # could break with a better dataset
|
||||||
|
self.assertEqual(xal.get('artistId'), str(ar.id)) # see above
|
||||||
|
|
||||||
|
def test_get_album(self):
|
||||||
|
self._make_request('getAlbum', error = 10)
|
||||||
|
self._make_request('getAlbum', { 'id': 'nastynasty' }, error = 0)
|
||||||
|
self._make_request('getAlbum', { 'id': str(uuid.uuid4()) }, error = 70)
|
||||||
|
|
||||||
|
a = self.store.find(Album)[0]
|
||||||
|
rv, child = self._make_request('getAlbum', { 'id': str(a.id) }, tag = 'album')
|
||||||
|
self.assertEqual(child.get('id'), str(a.id))
|
||||||
|
self.assertEqual(child.get('songCount'), str(len(child)))
|
||||||
|
|
||||||
|
self.assertEqual(len(child), a.tracks.count())
|
||||||
|
for dal, xal in zip(sorted(a.tracks, key = lambda t: t.title), sorted(child, key = lambda c: c.get('title'))):
|
||||||
|
self.assertEqual(dal.title, xal.get('title'))
|
||||||
|
self.assertEqual(xal.get('album'), a.name)
|
||||||
|
self.assertEqual(xal.get('albumId'), str(a.id))
|
||||||
|
|
||||||
|
def test_get_song(self):
|
||||||
|
self._make_request('getSong', error = 10)
|
||||||
|
self._make_request('getSong', { 'id': 'nastynasty' }, error = 0)
|
||||||
|
self._make_request('getSong', { 'id': str(uuid.uuid4()) }, error = 70)
|
||||||
|
|
||||||
|
s = self.store.find(Track)[0]
|
||||||
|
self._make_request('getSong', { 'id': str(s.id) }, tag = 'song')
|
||||||
|
|
||||||
|
def test_get_videos(self):
|
||||||
|
self._make_request('getVideos', error = 0)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user