build spotify-to-navidrome migrator with recovery flow

This commit is contained in:
2026-04-09 03:10:58 +02:00
parent 650a0c6a87
commit c1360a6423
23 changed files with 3383 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
package match
import (
"context"
"strings"
"testing"
"navimigrate/internal/model"
"navimigrate/internal/navidrome"
)
type fakeSearcher struct {
tracks []navidrome.Track
}
func (f fakeSearcher) SearchTracks(context.Context, string, int) ([]navidrome.Track, error) {
return f.tracks, nil
}
func TestNormalizeTransliteratesCyrillic(t *testing.T) {
got := normalize("детство")
if got != "detstvo" {
t.Fatalf("expected detstvo, got %q", got)
}
}
func TestBuildQueriesIncludesLatinVariant(t *testing.T) {
m := NewMatcher(fakeSearcher{}, 45)
q := m.buildQueries(model.Track{
Title: "детство",
Artists: []string{"Rauf & Faik"},
})
joined := strings.Join(q, "\n")
if !strings.Contains(strings.ToLower(joined), "detstvo") {
t.Fatalf("expected transliterated query to include detstvo, got %v", q)
}
}
func TestMatchThresholdIsConfigurable(t *testing.T) {
src := model.Track{
Title: "One More Time",
Artists: []string{"Daft Punk"},
DurationMS: 317000,
}
candidate := navidrome.Track{
ID: "track-1",
Title: "One More Time",
Artist: "Daft Punk",
Duration: 317,
}
m := NewMatcher(fakeSearcher{tracks: []navidrome.Track{candidate}}, 100)
res := m.MatchTrack(context.Background(), src)
if res.Matched {
t.Fatalf("expected no match with high threshold, score=%.1f", res.Score)
}
m = NewMatcher(fakeSearcher{tracks: []navidrome.Track{candidate}}, 0)
res = m.MatchTrack(context.Background(), src)
if !res.Matched {
t.Fatalf("expected match with low threshold, score=%.1f", res.Score)
}
}