improve CLI error semantics and soundcloud canonicalization

Auto-upgrade outdated configs on startup, add actionable SSL verification hints in rip error paths, and harden SoundCloud search/metadata with canonical URL handling and richer source IDs.
This commit is contained in:
2026-04-20 15:16:59 +02:00
parent 0748d5a325
commit 0ba8faa943
9 changed files with 502 additions and 106 deletions

View File

@@ -1,6 +1,9 @@
package main
import "testing"
import (
"errors"
"testing"
)
func TestParseFileInputJSONItems(t *testing.T) {
content := []byte(`[
@@ -167,26 +170,6 @@ func TestNormalizeCodecRejectsUnknown(t *testing.T) {
}
}
func TestGroupLastFMResolvedTracksBySourcePreservesOrderAndDuplicates(t *testing.T) {
resolved := []resolvedLastFMTrack{
{Source: "tidal", ID: "1"},
{Source: "tidal", ID: "1"},
{Source: "qobuz", ID: "2"},
{Source: "tidal", ID: "3"},
{Source: "", ID: "4"},
}
groups := groupLastFMResolvedTracksBySource(resolved)
if len(groups["tidal"]) != 3 {
t.Fatalf("tidal ids len = %d, want 3", len(groups["tidal"]))
}
if len(groups["qobuz"]) != 1 {
t.Fatalf("qobuz ids len = %d, want 1", len(groups["qobuz"]))
}
if groups["tidal"][0] != "1" || groups["tidal"][1] != "1" || groups["tidal"][2] != "3" {
t.Fatalf("unexpected tidal ordering: %+v", groups["tidal"])
}
}
func TestExtractLastFMTracksFromMirrorMarkdown(t *testing.T) {
md := `Title: My Playlist | user playlists | Last.fm
| Play | Image | Loved | Name | Artist name | Buy | Options | Duration |
@@ -204,3 +187,29 @@ func TestExtractLastFMTracksFromMirrorMarkdown(t *testing.T) {
t.Fatalf("unexpected first track: %+v", tracks[0])
}
}
func TestParseSearchArgsAllowsFirstAndOutputFileButCallerCanReject(t *testing.T) {
opts, err := parseSearchArgs([]string{"q", "--first", "--output-file", "/tmp/out.json"}, 20)
if err != nil {
t.Fatalf("parseSearchArgs() error = %v", err)
}
if !opts.first || opts.outputFile == "" {
t.Fatalf("expected first=true and output file set, got %+v", opts)
}
}
func TestErrorWithActionableHintForSSL(t *testing.T) {
err := errors.New("x509: certificate signed by unknown authority")
msg := errorWithActionableHint(err, globalOptions{})
if msg == err.Error() {
t.Fatalf("expected ssl hint in message")
}
}
func TestErrorWithActionableHintNoHintWhenDisabled(t *testing.T) {
err := errors.New("tls handshake failure")
msg := errorWithActionableHint(err, globalOptions{noSSLVerify: true})
if msg != err.Error() {
t.Fatalf("unexpected hint when noSSLVerify set")
}
}