From: Chris Fulljames Date: Sun, 16 Feb 2025 17:38:40 +0000 (-0500) Subject: Add playlist tests - incomplete X-Git-Url: https://littlesong.place/gitweb/?a=commitdiff_plain;h=dbdce9c8d572226729f7f9bfcddfac04697b0d95;p=littlesongplace.git Add playlist tests - incomplete --- diff --git a/main.py b/main.py index 488fd02..ed075b6 100644 --- a/main.py +++ b/main.py @@ -157,9 +157,9 @@ def users_profile(profile_username): userid = session.get("userid", None) show_private = userid == profile_userid if show_private: - plist_data = query_db("select * from playlists where userid = ? order by created desc", [profile_userid]) + plist_data = query_db("select * from playlists where userid = ? order by updated desc", [profile_userid]) else: - plist_data = query_db("select * from playlists where userid = ? and private = 0 order by created desc", [profile_userid]) + plist_data = query_db("select * from playlists where userid = ? and private = 0 order by updated desc", [profile_userid]) # Get songs for current profile songs = Song.get_all_for_userid(profile_userid) @@ -744,7 +744,7 @@ def delete_playlist(playlistid): # Cannot delete other user's playlist if session["userid"] != plist_data["userid"]: - abort(401) + abort(403) # Delete playlist query_db("delete from playlists where playlistid = ?", args=[playlistid]) @@ -770,7 +770,7 @@ def append_to_playlist(): # Cannot edit other user's playlist if session["userid"] != plist_data["userid"]: - abort(401) + abort(403) songid = request.form["songid"] @@ -809,18 +809,26 @@ def edit_playlist_post(playlistid): if session["userid"] != plist_data["userid"]: abort(401) - # Make sure all songs are valid - try: - songids = [int(s) for s in request.form["songids"].split(",")] - except ValueError: - # Invalid songid(s) - abort(400) + # Make sure name is valid + name = request.form["name"] + if not name or len(name) > 200: + flash_and_log("Playlist must have a name", "error") + return redirect(request.referrer) - for songid in songids: - song_data = query_db("select * from songs where songid = ?", args=[songid]) - if not song_data: + # Make sure all songs are valid + songids = [] + if request.form["songids"]: + try: + songids = [int(s) for s in request.form["songids"].split(",")] + except ValueError: + # Invalid songid(s) abort(400) + for songid in songids: + song_data = query_db("select * from songs where songid = ?", args=[songid]) + if not song_data: + abort(400) + # All songs valid - delete old songs query_db("delete from playlist_songs where playlistid = ?", args=[playlistid]) @@ -831,7 +839,6 @@ def edit_playlist_post(playlistid): # Update private, name private = int(request.form["type"] == "private") - name = request.form["name"] query_db("update playlists set private = ?, name = ? where playlistid = ?", [private, name, playlistid]) get_db().commit() @@ -849,10 +856,8 @@ def playlists(playlistid): # Protect private playlists if plist_data["private"]: - if "userid" not in session: - return redirect("/login") - elif session["userid"] != plist_data["userid"]: - abort(401) # Cannot view other user's private playlist + if ("userid" not in session) or (session["userid"] != plist_data["userid"]): + abort(404) # Cannot view other user's private playlist - pretend it doesn't even exist # Get songs songs = Song.get_for_playlist(playlistid) diff --git a/test/test_offline.py b/test/test_offline.py index 539f124..29755a2 100644 --- a/test/test_offline.py +++ b/test/test_offline.py @@ -966,3 +966,189 @@ def test_no_new_activity_after_checking(client): assert response.status_code == 200 assert not response.json["new_activity"] +################################################################################ +# Playlists +################################################################################ + +# Create Playlist ############################################################## + +def test_create_playlist(client): + _create_user(client, "user", login=True) + response = client.post("/create-playlist", data={"name": "my playlist", "type": "private"}) + assert response.status_code == 302 + + response = client.get("/users/user") + assert b"my playlist" in response.data + assert b"[Private]" in response.data + +def test_create_playlist_invalid_name(client): + _create_user(client, "user", login=True) + response = client.post("/create-playlist", data={"name": "a"*201, "type": "private"}) + assert response.status_code == 302 + response = client.get("/users/user") + assert b"must have a name" in response.data + + response = client.post("/create-playlist", data={"name": "", "type": "private"}) + assert response.status_code == 302 + response = client.get("/users/user") + assert b"must have a name" in response.data + +def test_create_playlist_not_logged_in(client): + response = client.post("/create-playlist", data={"name": "my playlist", "type": "private"}) + assert response.status_code == 302 + assert response.headers["Location"] == "/login" + +# Delete Playlist ############################################################## + +def _create_user_and_playlist(client): + _create_user(client, "user", login=True) + client.post("/create-playlist", data={"name": "my playlist", "type": "private"}) + +def test_delete_playlist(client): + _create_user_and_playlist(client) + response = client.get("/delete-playlist/1", follow_redirects=True) + assert b"Deleted playlist my playlist" in response.data + + response = client.get("/users/user") + assert not b"my playlist" in response.data + +def test_delete_playlist_invalid_playlistid(client): + _create_user_and_playlist(client) + response = client.get("/delete-playlist/2") + assert response.status_code == 404 + +def test_delete_playlist_not_logged_in(client): + _create_user_and_playlist(client) + client.get("/logout") + + response = client.get("/delete-playlist/2") + assert response.status_code == 401 + +def test_delete_playlist_other_users_playlist(client): + _create_user_and_playlist(client) + _create_user(client, "user2", login=True) + + response = client.get("/delete-playlist/1") + assert response.status_code == 403 + +# Append to Playlist ########################################################### + +def _create_user_song_and_playlist(client, playlist_type="private"): + _create_user_and_song(client) + client.post("/create-playlist", data={"name": "my playlist", "type": playlist_type}) + +def test_append_to_playlist(client): + _create_user_song_and_playlist(client) + client.post("/append-to-playlist", data={"playlistid": "1", "songid": "1"}) + response = client.get("/") + assert b"Added 'song title' to my playlist" in response.data + +def test_append_to_playlist_not_logged_in(client): + _create_user_song_and_playlist(client) + client.get("/logout") + response = client.post("/append-to-playlist", data={"playlistid": "1", "songid": "1"}) + assert response.status_code == 401 + +def test_append_to_other_users_playlist(client): + _create_user_song_and_playlist(client) + _create_user(client, "user2", login=True) + response = client.post("/append-to-playlist", data={"playlistid": "1", "songid": "1"}) + assert response.status_code == 403 + +def test_append_playlist_invalid_songid(client): + _create_user_song_and_playlist(client) + response = client.post("/append-to-playlist", data={"playlistid": "1", "songid": "2"}) + assert response.status_code == 404 + +def test_append_playlist_invalid_playlistid(client): + _create_user_song_and_playlist(client) + response = client.post("/append-to-playlist", data={"playlistid": "2", "songid": "1"}) + assert response.status_code == 404 + +# Playlist on Profile ########################################################## + +def test_playlists_on_own_profile(client): + _create_user_song_and_playlist(client) # Private playlist + client.post("/create-playlist", data={"name": "my public playlist", "type": "public"}, follow_redirects=True) + client.get("/users/user") # Clear flashes + + # Shows public and private playlists + response = client.get("/users/user") + assert b"my playlist" in response.data + assert b"my public playlist" in response.data + +def test_playlists_on_other_users_profile(client): + _create_user_song_and_playlist(client) # Private playlist + client.post("/create-playlist", data={"name": "my public playlist", "type": "public"}) + client.get("/users/user") # Clear flashes + + # Shows only public playlists + _create_user(client, "user2", login=True) + response = client.get("/users/user") + assert b"my playlist" not in response.data + assert b"my public playlist" in response.data + +# View Playlist ################################################################ + +def test_view_own_public_playlist(client): + _create_user_song_and_playlist(client, playlist_type="public") + response = client.get("/playlists/1") + assert response.status_code == 200 + assert b"[Public]" in response.data + +def test_view_own_private_playlist(client): + _create_user_song_and_playlist(client, playlist_type="private") + response = client.get("/playlists/1") + assert response.status_code == 200 + assert b"[Private]" in response.data + +def test_view_other_users_public_playlist(client): + _create_user_song_and_playlist(client, playlist_type="public") + _create_user(client, "user2", login=True) + response = client.get("/playlists/1") + assert response.status_code == 200 + assert b"[Public]" not in response.data # Type not shown + +def test_view_other_users_private_playlist(client): + _create_user_song_and_playlist(client, playlist_type="private") + _create_user(client, "user2", login=True) + response = client.get("/playlists/1") + assert response.status_code == 404 + +def test_view_invalid_playlist(client): + response = client.get("/playlists/0") + assert response.status_code == 404 + +# Edit Playlist ################################################################ + +def test_edit_playlist_change_type(client): + _create_user_song_and_playlist(client, playlist_type="private") + response = client.post("/edit-playlist/1", data={"name": "my playlist", "type": "public", "songids": ""}) + assert response.status_code == 302 + + response = client.get("/playlists/1") + assert b"[Public]" in response.data + +def test_edit_playlist_change_name(client): + _create_user_song_and_playlist(client, playlist_type="private") + response = client.post("/edit-playlist/1", data={"name": "cool new playlist name", "type": "private", "songids": ""}) + assert response.status_code == 302 + + response = client.get("/playlists/1") + assert b"cool new playlist name" in response.data + +def test_edit_playlist_change_name_invalid(client): + _create_user_song_and_playlist(client, playlist_type="private") + client.get("/playlists/1") # Clear flashes + response = client.post("/edit-playlist/1", data={"name": "", "type": "private", "songids": ""}) + assert response.status_code == 302 + + response = client.get("/playlists/1") + assert b"my playlist" in response.data + assert b"must have a name" in response.data + +# Edit playlist - change song order +# Edit playlist - remove song(s) +# Edit playlist - not logged in +# Edit playlist - other user's playlist +# Edit playlist - invalid songid diff --git a/todo.txt b/todo.txt index 40a601e..2dcc9df 100644 --- a/todo.txt +++ b/todo.txt @@ -2,10 +2,11 @@ NOW - Test playlist API SOON -- Break up main.py +- Break up main.py, test_offline.py - AJAX pages so songs can play during navigation - Pinned profile playlists +- Image support in comments, descriptions, bios, etc. - Player minimize button - Shuffle all page - Shuffle song list toggle