Files
wehub-resource-sync ead81af521
Deploy to GitHub Pages / deploy (push) Failing after 0s
CI / go (push) Has been cancelled
CI / build (darwin, macos-14) (push) Has been cancelled
CI / build (windows, windows-2025) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:31:13 +08:00

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)
}
})
}
}