package subsonic import ( "database/sql" "net/http/httptest" "testing" "git.noroutes.net/NoRoutes/vibetunes/internal/database" ) func mustUserID(t *testing.T, db *sql.DB, username string) string { t.Helper() u, err := database.GetUserByUsername(db, username) if err != nil { t.Fatal(err) } return u.ID } func TestStarUnstarSong(t *testing.T) { s, db := newTestServer(t) createTestUser(t, s, "alice", "password123", false) seedLibrary(t, s) song := firstSong(t, s) srv := httptest.NewServer(s.Router()) defer srv.Close() q := baseParams("alice", "password123") q.Set("id", song.ID) resp := getPath(t, srv.URL, "/rest/star.view", q) x := decodeXML(t, resp) if x.Status != "ok" { t.Fatalf("star failed: %+v", x) } starred, err := database.IsStarred(db, mustUserID(t, db, "alice"), "song", song.ID) if err != nil || !starred { t.Fatalf("IsStarred = %v, %v, want true", starred, err) } resp = getPath(t, srv.URL, "/rest/unstar.view", q) x = decodeXML(t, resp) if x.Status != "ok" { t.Fatalf("unstar failed: %+v", x) } starred, err = database.IsStarred(db, mustUserID(t, db, "alice"), "song", song.ID) if err != nil || starred { t.Fatalf("IsStarred after unstar = %v, %v, want false", starred, err) } } func TestStarMissingParams(t *testing.T) { s, srv := newTestRecorderServer(t) createTestUser(t, s, "alice", "password123", false) resp := getPath(t, srv.URL, "/rest/star.view", baseParams("alice", "password123")) x := decodeXML(t, resp) if x.Status != "failed" || x.Error == nil || x.Error.Code != ErrMissingParameter { t.Fatalf("expected error 10, got %+v", x) } } func TestSetRating(t *testing.T) { s, srv := newTestRecorderServer(t) createTestUser(t, s, "alice", "password123", false) seedLibrary(t, s) song := firstSong(t, s) q := baseParams("alice", "password123") q.Set("id", song.ID) q.Set("rating", "4") resp := getPath(t, srv.URL, "/rest/setRating.view", q) x := decodeXML(t, resp) if x.Status != "ok" { t.Fatalf("setRating failed: %+v", x) } } func TestSetRatingInvalidValue(t *testing.T) { s, srv := newTestRecorderServer(t) createTestUser(t, s, "alice", "password123", false) seedLibrary(t, s) song := firstSong(t, s) q := baseParams("alice", "password123") q.Set("id", song.ID) q.Set("rating", "9") resp := getPath(t, srv.URL, "/rest/setRating.view", q) x := decodeXML(t, resp) if x.Status != "failed" { t.Fatalf("expected failure for out-of-range rating, got %+v", x) } } func TestScrobbleRecordsPlayback(t *testing.T) { s, db := newTestServer(t) createTestUser(t, s, "alice", "password123", false) seedLibrary(t, s) song := firstSong(t, s) srv := httptest.NewServer(s.Router()) defer srv.Close() q := baseParams("alice", "password123") q.Set("id", song.ID) resp := getPath(t, srv.URL, "/rest/scrobble.view", q) x := decodeXML(t, resp) if x.Status != "ok" { t.Fatalf("scrobble failed: %+v", x) } history, err := database.ListRecentlyPlayed(db, mustUserID(t, db, "alice"), 10) if err != nil || len(history) != 1 { t.Fatalf("ListRecentlyPlayed = %v, %v, want 1 entry", history, err) } }