147 lines
4.1 KiB
Go
147 lines
4.1 KiB
Go
package soundcloud
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/bjarneo/cliamp/resolve"
|
|
)
|
|
|
|
func TestNewFromConfig(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
cfg Config
|
|
want bool // want non-nil
|
|
}{
|
|
{"default (not enabled)", Config{}, false},
|
|
{"explicitly enabled", Config{Enabled: true}, true},
|
|
{"enabled with user", Config{Enabled: true, User: "alice"}, true},
|
|
{"enabled trims user", Config{Enabled: true, User: " bob "}, true},
|
|
{"user without enabled stays nil", Config{User: "alice"}, false},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := NewFromConfig(tt.cfg)
|
|
if (got != nil) != tt.want {
|
|
t.Fatalf("NewFromConfig(%+v) non-nil = %v, want %v", tt.cfg, got != nil, tt.want)
|
|
}
|
|
if got != nil && tt.cfg.User != "" && got.user != "bob" && got.user != "alice" {
|
|
if got.user == "" {
|
|
t.Errorf("user not propagated, got empty")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestProviderName(t *testing.T) {
|
|
p := NewFromConfig(Config{Enabled: true})
|
|
if got := p.Name(); got != "SoundCloud" {
|
|
t.Errorf("Name() = %q, want SoundCloud", got)
|
|
}
|
|
}
|
|
|
|
func TestPlaylistsWithoutUserShowsBrowse(t *testing.T) {
|
|
p := NewFromConfig(Config{Enabled: true})
|
|
pls, err := p.Playlists()
|
|
if err != nil {
|
|
t.Fatalf("Playlists() error = %v", err)
|
|
}
|
|
if len(pls) == 0 {
|
|
t.Fatal("Playlists() returned 0 entries, want curated browse list")
|
|
}
|
|
for _, pl := range pls {
|
|
if pl.Section != "Browse" {
|
|
t.Errorf("playlist %q has Section %q, want Browse", pl.Name, pl.Section)
|
|
}
|
|
if !strings.HasPrefix(pl.ID, "scsearch") {
|
|
t.Errorf("browse playlist %q ID = %q, want scsearch prefix", pl.Name, pl.ID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPlaylistsWithUserShowsOnlyUserEntries(t *testing.T) {
|
|
p := NewFromConfig(Config{Enabled: true, User: "alice"})
|
|
pls, err := p.Playlists()
|
|
if err != nil {
|
|
t.Fatalf("Playlists() error = %v", err)
|
|
}
|
|
if len(pls) != 3 {
|
|
t.Fatalf("Playlists() = %d entries, want 3 (user-only when User is set)", len(pls))
|
|
}
|
|
|
|
wantNames := map[string]string{
|
|
"https://soundcloud.com/alice/tracks": "Tracks",
|
|
"https://soundcloud.com/alice/likes": "Likes",
|
|
"https://soundcloud.com/alice/reposts": "Reposts",
|
|
}
|
|
for _, pl := range pls {
|
|
want, ok := wantNames[pl.ID]
|
|
if !ok {
|
|
t.Errorf("unexpected playlist ID %q", pl.ID)
|
|
continue
|
|
}
|
|
if pl.Name != want {
|
|
t.Errorf("Playlist %q Name = %q, want %q", pl.ID, pl.Name, want)
|
|
}
|
|
if pl.Section != "alice" {
|
|
t.Errorf("Playlist %q Section = %q, want alice", pl.ID, pl.Section)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPlaylistsEscapesUsername(t *testing.T) {
|
|
p := NewFromConfig(Config{Enabled: true, User: "weird name"})
|
|
pls, _ := p.Playlists()
|
|
if len(pls) == 0 {
|
|
t.Fatal("expected non-empty playlists")
|
|
}
|
|
for _, pl := range pls {
|
|
if got, want := pl.ID, "https://soundcloud.com/weird%20name/"; len(got) < len(want) || got[:len(want)] != want {
|
|
t.Errorf("playlist ID %q not URL-escaped", pl.ID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSearchTracksEmptyQuery(t *testing.T) {
|
|
p := NewFromConfig(Config{Enabled: true})
|
|
tracks, err := p.SearchTracks(context.Background(), " ", 10)
|
|
if err != nil {
|
|
t.Fatalf("SearchTracks(empty) error = %v", err)
|
|
}
|
|
if len(tracks) != 0 {
|
|
t.Errorf("SearchTracks(empty) returned %d tracks, want 0", len(tracks))
|
|
}
|
|
}
|
|
|
|
func TestTracksRejectsEmptyID(t *testing.T) {
|
|
p := NewFromConfig(Config{Enabled: true})
|
|
_, err := p.Tracks("")
|
|
if err == nil {
|
|
t.Fatal("Tracks(\"\") expected error, got nil")
|
|
}
|
|
}
|
|
|
|
func TestConfigIsSet(t *testing.T) {
|
|
if (Config{}).IsSet() {
|
|
t.Error("Config{} should not be set (opt-in)")
|
|
}
|
|
if !(Config{Enabled: true}).IsSet() {
|
|
t.Error("Config{Enabled:true} should report set")
|
|
}
|
|
}
|
|
|
|
func TestNewFromConfigPropagatesCookies(t *testing.T) {
|
|
t.Cleanup(func() { resolve.SetYTDLCookiesFrom("") })
|
|
|
|
resolve.SetYTDLCookiesFrom("") // baseline
|
|
|
|
NewFromConfig(Config{Enabled: true, CookiesFrom: "firefox"})
|
|
// The exported getter is internal; we verify by side effect: a subsequent
|
|
// resolve call would emit --cookies-from-browser firefox. We can't easily
|
|
// invoke yt-dlp from a unit test, so the smoke test is that the setter
|
|
// accepts our value without panic and the constructor succeeds.
|
|
// (Full plumbing is exercised manually; resolve.ytdlCookiesFrom is private.)
|
|
}
|