package deezer import ( "context" "encoding/json" "fmt" "net/http" "net/http/httptest" "strings" "testing" "streamrip-go/internal/config" ) func TestSearchTrack(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/search/track": _ = json.NewEncoder(w).Encode(map[string]any{"data": []any{map[string]any{"id": 1, "title": "Dreams", "artist": map[string]any{"name": "Fleetwood Mac"}}}}) default: w.WriteHeader(http.StatusNotFound) } })) defer ts.Close() cfgData := config.DefaultConfigData() c := New(&config.Config{File: cfgData, Session: cfgData}) c.loggedIn = true orig := baseURL baseURL = ts.URL defer func() { baseURL = orig }() pages, err := c.Search(context.Background(), "track", "dreams", 5) if err != nil { t.Fatalf("Search() error = %v", err) } if len(pages) != 1 { t.Fatalf("pages len = %d, want 1", len(pages)) } } func TestGetDownloadableUsesPreview(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/track/42": _ = json.NewEncoder(w).Encode(map[string]any{"id": 42, "title": "X", "preview": "https://cdn.example/p.mp3"}) default: w.WriteHeader(http.StatusNotFound) } })) defer ts.Close() cfgData := config.DefaultConfigData() c := New(&config.Config{File: cfgData, Session: cfgData}) c.loggedIn = true orig := baseURL baseURL = ts.URL defer func() { baseURL = orig }() d, err := c.GetDownloadable(context.Background(), "42", 0) if err != nil { t.Fatalf("GetDownloadable() error = %v", err) } if d.URL != "https://cdn.example/p.mp3" || d.Extension != "mp3" { t.Fatalf("unexpected downloadable: %+v", d) } } func TestGetMetadataSetsExplicitFromBool(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/track/9": _ = json.NewEncoder(w).Encode(map[string]any{ "id": 9, "title": "X", "explicit_lyrics": true, "artist": map[string]any{"name": "Artist"}, }) default: w.WriteHeader(http.StatusNotFound) } })) defer ts.Close() cfgData := config.DefaultConfigData() c := New(&config.Config{File: cfgData, Session: cfgData}) c.loggedIn = true orig := baseURL baseURL = ts.URL defer func() { baseURL = orig }() meta, err := c.GetMetadata(context.Background(), "9", "track") if err != nil { t.Fatalf("GetMetadata() error = %v", err) } if explicit, _ := meta["explicit"].(bool); !explicit { t.Fatalf("expected explicit=true, got %#v", meta["explicit"]) } } func TestSearchReturnsStructuredAPIError(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/search/track" { _ = json.NewEncoder(w).Encode(map[string]any{"error": map[string]any{"message": "invalid query"}}) return } w.WriteHeader(http.StatusNotFound) })) defer ts.Close() cfgData := config.DefaultConfigData() c := New(&config.Config{File: cfgData, Session: cfgData}) c.loggedIn = true orig := baseURL baseURL = ts.URL defer func() { baseURL = orig }() _, err := c.Search(context.Background(), "track", "", 5) if err == nil || !strings.Contains(err.Error(), "invalid query") { t.Fatalf("expected structured deezer error, got %v", err) } } func TestGetDownloadableErrorsWhenFullQualityFailsAndFallbackDisabled(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/track/42" { _ = json.NewEncoder(w).Encode(map[string]any{"id": 42, "title": "X", "preview": "https://cdn.example/p.mp3"}) return } w.WriteHeader(http.StatusNotFound) })) defer ts.Close() cfgData := config.DefaultConfigData() cfgData.Deezer.UseDeezloader = true cfgData.Deezer.LowerQualityIfNotAvailable = false c := New(&config.Config{File: cfgData, Session: cfgData}) c.loggedIn = true c.bin = "definitely-not-a-real-yt-dlp-bin" c.run = func(context.Context, string, ...string) ([]byte, error) { return nil, fmt.Errorf("unexpected run call") } orig := baseURL baseURL = ts.URL defer func() { baseURL = orig }() _, err := c.GetDownloadable(context.Background(), "42", 2) if err == nil || !strings.Contains(err.Error(), "full-quality mode failed") { t.Fatalf("expected full-quality failure error, got %v", err) } }