167 lines
5.2 KiB
Go
167 lines
5.2 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestParsePrimaryArtist(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
wantPrimary string
|
|
wantFeat string
|
|
}{
|
|
{"Radiohead", "Radiohead", ""},
|
|
{"Wretch 32 Feat. Badness & Ghetts", "Wretch 32", "Feat. Badness & Ghetts"},
|
|
{"Artist Ft. Guest", "Artist", "Ft. Guest"},
|
|
{"Artist Featuring Someone", "Artist", "Featuring Someone"},
|
|
{"PinkPantheress & Ice Spice", "PinkPantheress", ""},
|
|
{"Artist A / Artist B", "Artist A", ""},
|
|
{"", "", ""},
|
|
}
|
|
for _, tt := range tests {
|
|
gotPrimary, gotFeat := parsePrimaryArtist(tt.input)
|
|
if gotPrimary != tt.wantPrimary {
|
|
t.Errorf("parsePrimaryArtist(%q) primary = %q, want %q", tt.input, gotPrimary, tt.wantPrimary)
|
|
}
|
|
if gotFeat != tt.wantFeat {
|
|
t.Errorf("parsePrimaryArtist(%q) feat = %q, want %q", tt.input, gotFeat, tt.wantFeat)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBuildSpotifySearchURL(t *testing.T) {
|
|
tests := []struct {
|
|
title, artist string
|
|
wantPrefix string
|
|
wantContains string
|
|
}{
|
|
{"Never Gonna Give You Up", "Rick Astley", "https://open.spotify.com/search/", "Rick%20Astley"},
|
|
{"Karma Police", "Radiohead", "https://open.spotify.com/search/", "Radiohead"},
|
|
{"", "Solo Artist", "https://open.spotify.com/search/", "Solo%20Artist"},
|
|
{"Only Title", "", "https://open.spotify.com/search/", "Only%20Title"},
|
|
{"", "", "https://open.spotify.com/search/", ""},
|
|
}
|
|
for _, tt := range tests {
|
|
got := buildSpotifySearchURL(tt.title, tt.artist)
|
|
if !strings.HasPrefix(got, tt.wantPrefix) {
|
|
t.Errorf("buildSpotifySearchURL(%q, %q) = %q, want prefix %q", tt.title, tt.artist, got, tt.wantPrefix)
|
|
}
|
|
if tt.wantContains != "" && !strings.Contains(got, tt.wantContains) {
|
|
t.Errorf("buildSpotifySearchURL(%q, %q) = %q, want to contain %q", tt.title, tt.artist, got, tt.wantContains)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSpotifyCacheKey(t *testing.T) {
|
|
key1 := spotifyCacheKey("Radiohead", "Karma Police", "OK Computer")
|
|
key2 := spotifyCacheKey("Radiohead", "Karma Police", "OK Computer")
|
|
key3 := spotifyCacheKey("Radiohead", "Karma Police", "The Bends")
|
|
|
|
if key1 != key2 {
|
|
t.Error("identical inputs should produce identical cache keys")
|
|
}
|
|
if key1 == key3 {
|
|
t.Error("different albums should produce different cache keys")
|
|
}
|
|
if !strings.HasPrefix(key1, "spotify.url.") {
|
|
t.Errorf("cache key %q should start with 'spotify.url.'", key1)
|
|
}
|
|
|
|
// Case-insensitive: "Radiohead" == "radiohead"
|
|
keyUpper := spotifyCacheKey("Radiohead", "Karma Police", "OK Computer")
|
|
keyLower := spotifyCacheKey("radiohead", "karma police", "ok computer")
|
|
if keyUpper != keyLower {
|
|
t.Error("cache key should be case-insensitive")
|
|
}
|
|
}
|
|
|
|
func TestParseSpotifyID(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
body string
|
|
want string
|
|
}{
|
|
{
|
|
name: "valid single result",
|
|
body: `[{"spotify_track_ids":["4tIGK5G9hNDA50ZdGioZRG"]}]`,
|
|
want: "4tIGK5G9hNDA50ZdGioZRG",
|
|
},
|
|
{
|
|
name: "multiple IDs picks first",
|
|
body: `[{"artist_name":"Lil Baby & Drake","track_name":"Yes Indeed","spotify_track_ids":["6vN77lE9LK6HP2DewaN6HZ","4wlLbLeDWbA6TzwZFp1UaK"]}]`,
|
|
want: "6vN77lE9LK6HP2DewaN6HZ",
|
|
},
|
|
{
|
|
name: "valid result with extra fields",
|
|
body: `[{"artist_name":"Radiohead","track_name":"Karma Police","spotify_track_ids":["63OQupATfueTdZMWIV7nzz"],"release_name":"OK Computer"}]`,
|
|
want: "63OQupATfueTdZMWIV7nzz",
|
|
},
|
|
{
|
|
name: "empty spotify_track_ids array",
|
|
body: `[{"spotify_track_ids":[]}]`,
|
|
want: "",
|
|
},
|
|
{
|
|
name: "no spotify_track_ids field",
|
|
body: `[{"artist_name":"Unknown"}]`,
|
|
want: "",
|
|
},
|
|
{
|
|
name: "empty array",
|
|
body: `[]`,
|
|
want: "",
|
|
},
|
|
{
|
|
name: "invalid JSON",
|
|
body: `not json`,
|
|
want: "",
|
|
},
|
|
{
|
|
name: "null spotify_track_ids with next result valid",
|
|
body: `[{"spotify_track_ids":[]},{"spotify_track_ids":["abc123"]}]`,
|
|
want: "abc123",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := parseSpotifyID([]byte(tt.body))
|
|
if got != tt.want {
|
|
t.Errorf("parseSpotifyID(%s) = %q, want %q", tt.body, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListenBrainzRequestPayloads(t *testing.T) {
|
|
// Verify MBID request body is valid JSON
|
|
mbid := "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
|
mbidBody := []byte(`[{"recording_mbid":"` + mbid + `"}]`)
|
|
var mbidParsed []map[string]string
|
|
if err := json.Unmarshal(mbidBody, &mbidParsed); err != nil {
|
|
t.Fatalf("MBID request body is not valid JSON: %v", err)
|
|
}
|
|
if mbidParsed[0]["recording_mbid"] != mbid {
|
|
t.Errorf("MBID body recording_mbid = %q, want %q", mbidParsed[0]["recording_mbid"], mbid)
|
|
}
|
|
|
|
// Verify metadata request body handles special characters via %q formatting
|
|
artist := `Guns N' Roses`
|
|
title := `Sweet Child O' Mine`
|
|
album := `Appetite for Destruction`
|
|
metaBody := []byte(`[{"artist_name":` + jsonQuote(artist) + `,"track_name":` + jsonQuote(title) + `,"release_name":` + jsonQuote(album) + `}]`)
|
|
var metaParsed []map[string]string
|
|
if err := json.Unmarshal(metaBody, &metaParsed); err != nil {
|
|
t.Fatalf("Metadata request body is not valid JSON: %v", err)
|
|
}
|
|
if metaParsed[0]["artist_name"] != artist {
|
|
t.Errorf("artist_name = %q, want %q", metaParsed[0]["artist_name"], artist)
|
|
}
|
|
}
|
|
|
|
func jsonQuote(s string) string {
|
|
b, _ := json.Marshal(s)
|
|
return string(b)
|
|
}
|