139 lines
4.4 KiB
Go
139 lines
4.4 KiB
Go
package spotify
|
|
|
|
import "testing"
|
|
|
|
// TestSpotifyTrackPageSizeRespectsAPILimit asserts spotifyTrackPageSize stays
|
|
// within the Spotify Web API's silent 50-item cap; see the constant's comment
|
|
// in provider.go for why exceeding it silently drops tracks.
|
|
func TestSpotifyTrackPageSizeRespectsAPILimit(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
got int
|
|
max int
|
|
}{
|
|
{"spotifyTrackPageSize within /v1/playlists/{id}/items cap", spotifyTrackPageSize, 50},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.got > tt.max {
|
|
t.Fatalf("page size = %d, want <= %d (Spotify Web API cap)", tt.got, tt.max)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestTrackFromItem verifies the playlist-item to Track mapping, especially
|
|
// that podcast episodes keep their spotify:episode: URI (regression for the
|
|
// 404 when episodes were forced to spotify:track:). See issue #228.
|
|
func TestTrackFromItem(t *testing.T) {
|
|
playable := true
|
|
unplayable := false
|
|
|
|
t.Run("music track", func(t *testing.T) {
|
|
item := &spotifyItem{
|
|
ID: "abc", Name: "Aerodynamic", Type: "track",
|
|
URI: "spotify:track:abc", DurationMs: 212000, TrackNumber: 3,
|
|
IsPlayable: &playable,
|
|
Artists: []spotifyArtist{{Name: "Daft Punk"}},
|
|
}
|
|
item.Album.Name = "Discovery"
|
|
item.Album.ReleaseDate = "2001-03-12"
|
|
|
|
got := trackFromItem(item)
|
|
if got.Path != "spotify:track:abc" {
|
|
t.Errorf("Path = %q, want spotify:track:abc", got.Path)
|
|
}
|
|
if got.Artist != "Daft Punk" || got.Album != "Discovery" || got.Year != 2001 {
|
|
t.Errorf("got %q / %q / %d, want Daft Punk / Discovery / 2001", got.Artist, got.Album, got.Year)
|
|
}
|
|
if got.DurationSecs != 212 {
|
|
t.Errorf("DurationSecs = %d, want 212", got.DurationSecs)
|
|
}
|
|
})
|
|
|
|
t.Run("podcast episode keeps episode uri", func(t *testing.T) {
|
|
item := &spotifyItem{
|
|
ID: "ep1", Name: "Episode 42", Type: "episode",
|
|
URI: "spotify:episode:ep1", DurationMs: 3600000, ReleaseDate: "2024-06-01",
|
|
}
|
|
item.Show.Name = "The Show"
|
|
|
|
got := trackFromItem(item)
|
|
if got.Path != "spotify:episode:ep1" {
|
|
t.Errorf("Path = %q, want spotify:episode:ep1 (not spotify:track:)", got.Path)
|
|
}
|
|
if got.Artist != "The Show" || got.Album != "The Show" {
|
|
t.Errorf("episode artist/album = %q / %q, want show name", got.Artist, got.Album)
|
|
}
|
|
if got.Year != 2024 {
|
|
t.Errorf("Year = %d, want 2024 (from top-level release_date)", got.Year)
|
|
}
|
|
})
|
|
|
|
t.Run("search episode without show name", func(t *testing.T) {
|
|
// /v1/search returns simplified episode objects with no show field.
|
|
item := &spotifyItem{
|
|
ID: "ep2", Name: "JRE #2000", Type: "episode",
|
|
URI: "spotify:episode:ep2", DurationMs: 10800000, ReleaseDate: "2023-08-01",
|
|
}
|
|
got := trackFromItem(item)
|
|
if got.Path != "spotify:episode:ep2" {
|
|
t.Errorf("Path = %q, want spotify:episode:ep2", got.Path)
|
|
}
|
|
if got.Title != "JRE #2000" {
|
|
t.Errorf("Title = %q, want JRE #2000", got.Title)
|
|
}
|
|
})
|
|
|
|
t.Run("missing uri falls back to track id", func(t *testing.T) {
|
|
got := trackFromItem(&spotifyItem{ID: "xyz", Name: "No URI"})
|
|
if got.Path != "spotify:track:xyz" {
|
|
t.Errorf("Path = %q, want spotify:track:xyz fallback", got.Path)
|
|
}
|
|
})
|
|
|
|
t.Run("unplayable track flagged", func(t *testing.T) {
|
|
got := trackFromItem(&spotifyItem{ID: "u", URI: "spotify:track:u", IsPlayable: &unplayable})
|
|
if !got.Unplayable {
|
|
t.Error("Unplayable = false, want true")
|
|
}
|
|
})
|
|
}
|
|
|
|
// TestPlaylistAccessible verifies the visibility filter that hides playlists
|
|
// the current Spotify user can't list tracks for (would otherwise return 403).
|
|
func TestPlaylistAccessible(t *testing.T) {
|
|
const me = "user123"
|
|
|
|
tests := []struct {
|
|
name string
|
|
ownerID string
|
|
collaborative bool
|
|
userID string
|
|
want bool
|
|
}{
|
|
{"own playlist", me, false, me, true},
|
|
{"own collaborative", me, true, me, true},
|
|
{"other user's playlist", "otheruser", false, me, false},
|
|
{"other user's collaborative", "otheruser", true, me, true},
|
|
{"no userID fallback", "otheruser", false, "", true},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
item := spotifyPlaylistItem{
|
|
ID: "pl1",
|
|
Name: "Test",
|
|
Collaborative: tt.collaborative,
|
|
}
|
|
item.Owner.ID = tt.ownerID
|
|
|
|
got := playlistAccessible(item, tt.userID)
|
|
if got != tt.want {
|
|
t.Errorf("playlistAccessible(owner=%q, collaborative=%v, userID=%q) = %v, want %v",
|
|
tt.ownerID, tt.collaborative, tt.userID, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|