1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-09-20 03:11:04 +00:00
supysonic/tests/api/test_playlist.py

342 lines
12 KiB
Python

# This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API.
#
# Copyright (C) 2017-2018 Alban 'spl0k' Féron
#
# Distributed under terms of the GNU AGPLv3 license.
import uuid
from pony.orm import db_session
from supysonic.db import Folder, Artist, Album, Track, Playlist, User
from .apitestbase import ApiTestBase
class PlaylistTestCase(ApiTestBase):
def setUp(self):
super().setUp()
with db_session:
root = Folder(root=True, name="Root folder", path="tests/assets")
artist = Artist(name="Artist")
album = Album(name="Album", artist=artist)
songs = {}
for num, song in enumerate(["One", "Two", "Three", "Four"]):
track = Track(
disc=1,
number=num,
title=song,
duration=2,
album=album,
artist=artist,
bitrate=320,
path="tests/assets/" + song,
last_modification=0,
root_folder=root,
folder=root,
)
songs[song] = track
users = {u.name: u for u in User.select()}
playlist = Playlist(user=users["alice"], name="Alice's")
playlist.add(songs["One"])
playlist.add(songs["Three"])
playlist = Playlist(user=users["alice"], public=True, name="Alice's public")
playlist.add(songs["One"])
playlist.add(songs["Two"])
playlist = Playlist(user=users["bob"], name="Bob's")
playlist.add(songs["Two"])
playlist.add(songs["Four"])
def test_get_playlists(self):
# get own playlists
rv, child = self._make_request("getPlaylists", tag="playlists")
self.assertEqual(len(child), 2)
self.assertEqual(child[0].get("owner"), "alice")
self.assertEqual(child[1].get("owner"), "alice")
# get own and public
rv, child = self._make_request(
"getPlaylists", {"u": "bob", "p": "B0b"}, tag="playlists"
)
self.assertEqual(len(child), 2)
self.assertTrue(
child[0].get("owner") == "alice" or child[1].get("owner") == "alice"
)
self.assertTrue(
child[0].get("owner") == "bob" or child[1].get("owner") == "bob"
)
self.assertIsNotNone(
self._find(child, "./playlist[@owner='alice'][@public='true']")
)
# get other
rv, child = self._make_request(
"getPlaylists", {"username": "bob"}, tag="playlists"
)
self.assertEqual(len(child), 1)
self.assertEqual(child[0].get("owner"), "bob")
# get other when not admin
self._make_request(
"getPlaylists", {"u": "bob", "p": "B0b", "username": "alice"}, error=50
)
# get from unknown user
self._make_request("getPlaylists", {"username": "johndoe"}, error=70)
def test_get_playlist(self):
# missing param
self._make_request("getPlaylist", error=10)
# invalid id
self._make_request("getPlaylist", {"id": 1234}, error=0)
# unknown
self._make_request("getPlaylist", {"id": str(uuid.uuid4())}, error=70)
# other's private from non admin
with db_session:
playlist = Playlist.get(lambda p: not p.public and p.user.name == "alice")
self._make_request(
"getPlaylist", {"u": "bob", "p": "B0b", "id": str(playlist.id)}, error=50
)
# standard
rv, child = self._make_request("getPlaylists", tag="playlists")
self._make_request("getPlaylist", {"id": child[0].get("id")}, tag="playlist")
rv, child = self._make_request(
"getPlaylist", {"id": child[1].get("id")}, tag="playlist"
)
self.assertEqual(child.get("songCount"), "2")
self.assertEqual(
self._xpath(child, "count(./entry)"), 2
) # don't count children, there may be 'allowedUser's (even though not supported by supysonic)
self.assertEqual(child.get("duration"), "4")
self.assertEqual(child[0].get("title"), "One")
self.assertTrue(
child[1].get("title") == "Two" or child[1].get("title") == "Three"
) # depending on 'getPlaylists' result ordering
def test_create_playlist(self):
self._make_request("createPlaylist", error=10)
self._make_request(
"createPlaylist", {"name": "wrongId", "songId": "abc"}, error=0
)
self._make_request(
"createPlaylist",
{"name": "unknownId", "songId": str(uuid.uuid4())},
error=70,
)
self._make_request("createPlaylist", {"playlistId": "abc"}, error=0)
self._make_request(
"createPlaylist", {"playlistId": str(uuid.uuid4())}, error=70
)
# create
self._make_request("createPlaylist", {"name": "new playlist"}, skip_post=True)
rv, child = self._make_request("getPlaylists", tag="playlists")
self.assertEqual(len(child), 3)
playlist = self._find(child, "./playlist[@name='new playlist']")
self.assertEqual(len(playlist), 0)
# "update" newly created
self._make_request("createPlaylist", {"playlistId": playlist.get("id")})
rv, child = self._make_request("getPlaylists", tag="playlists")
self.assertEqual(len(child), 3)
# renaming
self._make_request(
"createPlaylist", {"playlistId": playlist.get("id"), "name": "renamed"}
)
rv, child = self._make_request("getPlaylists", tag="playlists")
self.assertEqual(len(child), 3)
self.assertIsNone(self._find(child, "./playlist[@name='new playlist']"))
playlist = self._find(child, "./playlist[@name='renamed']")
self.assertIsNotNone(playlist)
# update from other user
self._make_request(
"createPlaylist",
{"u": "bob", "p": "B0b", "playlistId": playlist.get("id")},
error=50,
)
# create more useful playlist
with db_session:
songs = {s.title: str(s.id) for s in Track.select()}
self._make_request(
"createPlaylist",
{
"name": "songs",
"songId": list(map(lambda s: songs[s], ["Three", "One", "Two"])),
},
skip_post=True,
)
with db_session:
playlist = Playlist.get(name="songs")
self.assertIsNotNone(playlist)
rv, child = self._make_request(
"getPlaylist", {"id": str(playlist.id)}, tag="playlist"
)
self.assertEqual(child.get("songCount"), "3")
self.assertEqual(self._xpath(child, "count(./entry)"), 3)
self.assertEqual(child[0].get("title"), "Three")
self.assertEqual(child[1].get("title"), "One")
self.assertEqual(child[2].get("title"), "Two")
# update
self._make_request(
"createPlaylist",
{"playlistId": str(playlist.id), "songId": songs["Two"]},
skip_post=True,
)
rv, child = self._make_request(
"getPlaylist", {"id": str(playlist.id)}, tag="playlist"
)
self.assertEqual(child.get("songCount"), "1")
self.assertEqual(self._xpath(child, "count(./entry)"), 1)
self.assertEqual(child[0].get("title"), "Two")
@db_session
def assertPlaylistCountEqual(self, count):
self.assertEqual(Playlist.select().count(), count)
def test_delete_playlist(self):
# check params
self._make_request("deletePlaylist", error=10)
self._make_request("deletePlaylist", {"id": "string"}, error=0)
self._make_request("deletePlaylist", {"id": str(uuid.uuid4())}, error=70)
# delete unowned when not admin
with db_session:
playlist = Playlist.select(lambda p: p.user.name == "alice").first()
self._make_request(
"deletePlaylist", {"u": "bob", "p": "B0b", "id": str(playlist.id)}, error=50
)
self.assertPlaylistCountEqual(3)
# delete owned
self._make_request("deletePlaylist", {"id": str(playlist.id)}, skip_post=True)
self.assertPlaylistCountEqual(2)
self._make_request("deletePlaylist", {"id": str(playlist.id)}, error=70)
self.assertPlaylistCountEqual(2)
# delete unowned when admin
with db_session:
playlist = Playlist.get(lambda p: p.user.name == "bob")
self._make_request("deletePlaylist", {"id": str(playlist.id)}, skip_post=True)
self.assertPlaylistCountEqual(1)
def test_update_playlist(self):
self._make_request("updatePlaylist", error=10)
self._make_request("updatePlaylist", {"playlistId": 1234}, error=0)
self._make_request(
"updatePlaylist", {"playlistId": str(uuid.uuid4())}, error=70
)
with db_session:
playlist = (
Playlist.select(lambda p: p.user.name == "alice")
.order_by(Playlist.created)
.first()
)
pid = str(playlist.id)
self._make_request(
"updatePlaylist", {"playlistId": pid, "songIdToAdd": "string"}, error=0
)
self._make_request(
"updatePlaylist",
{"playlistId": pid, "songIndexToRemove": "string"},
error=0,
)
name = str(playlist.name)
self._make_request(
"updatePlaylist",
{"u": "bob", "p": "B0b", "playlistId": pid, "name": "new name"},
error=50,
)
rv, child = self._make_request("getPlaylist", {"id": pid}, tag="playlist")
self.assertEqual(child.get("name"), name)
self.assertEqual(self._xpath(child, "count(./entry)"), 2)
self._make_request(
"updatePlaylist", {"playlistId": pid, "name": "new name"}, skip_post=True
)
rv, child = self._make_request("getPlaylist", {"id": pid}, tag="playlist")
self.assertEqual(child.get("name"), "new name")
self.assertEqual(self._xpath(child, "count(./entry)"), 2)
self._make_request(
"updatePlaylist",
{"playlistId": pid, "songIndexToRemove": [-1, 2]},
skip_post=True,
)
rv, child = self._make_request("getPlaylist", {"id": pid}, tag="playlist")
self.assertEqual(self._xpath(child, "count(./entry)"), 2)
self._make_request(
"updatePlaylist",
{"playlistId": pid, "songIndexToRemove": [0, 2]},
skip_post=True,
)
rv, child = self._make_request("getPlaylist", {"id": pid}, tag="playlist")
self.assertEqual(self._xpath(child, "count(./entry)"), 1)
self.assertEqual(self._find(child, "./entry").get("title"), "Three")
with db_session:
songs = {s.title: str(s.id) for s in Track.select()}
self._make_request(
"updatePlaylist",
{
"playlistId": pid,
"songIdToAdd": [songs["One"], songs["Two"], songs["Two"]],
},
skip_post=True,
)
rv, child = self._make_request("getPlaylist", {"id": pid}, tag="playlist")
self.assertSequenceEqual(
self._xpath(child, "./entry/@title"), ["Three", "One", "Two", "Two"]
)
self._make_request(
"updatePlaylist",
{"playlistId": pid, "songIndexToRemove": [2, 1]},
skip_post=True,
)
rv, child = self._make_request("getPlaylist", {"id": pid}, tag="playlist")
self.assertSequenceEqual(self._xpath(child, "./entry/@title"), ["Three", "Two"])
self._make_request(
"updatePlaylist",
{"playlistId": pid, "songIdToAdd": songs["One"]},
skip_post=True,
)
self._make_request(
"updatePlaylist",
{"playlistId": pid, "songIndexToRemove": [1, 1]},
skip_post=True,
)
rv, child = self._make_request("getPlaylist", {"id": pid}, tag="playlist")
self.assertSequenceEqual(self._xpath(child, "./entry/@title"), ["Three", "One"])
self._make_request(
"updatePlaylist",
{"playlistId": pid, "songIdToAdd": str(uuid.uuid4())},
error=70,
)
rv, child = self._make_request("getPlaylist", {"id": pid}, tag="playlist")
self.assertEqual(self._xpath(child, "count(./entry)"), 2)
if __name__ == "__main__":
unittest.main()