git/intake/main
internal/artist/artist_test.go
140 lines4 KB last change raw · history
package artist

import (
	"os"
	"path/filepath"
	"reflect"
	"testing"
)

func TestSplit(t *testing.T) {
	cases := []struct {
		in     string
		want   []string
		collab bool
	}{
		{"Porter Robinson & Madeon", []string{"Porter Robinson", "Madeon"}, true},
		{"Porter Robinson and Madeon", []string{"Porter Robinson", "Madeon"}, true},
		{"Boards of Canada", []string{"Boards of Canada"}, false},
		{"Björk", []string{"Björk"}, false},
		{"A feat. B", []string{"A", "B"}, true},
		{"A, B & C", []string{"A", "B", "C"}, true},
		{"", []string{""}, false},
	}
	for _, c := range cases {
		got, collab := Split(c.in)
		if !reflect.DeepEqual(got, c.want) || collab != c.collab {
			t.Errorf("Split(%q) = %v,%v want %v,%v", c.in, got, collab, c.want, c.collab)
		}
	}
}

func TestRomanize(t *testing.T) {
	cases := []struct{ in, want string }{
		{"きのこ帝国", "kinoko"},
		{"プライマル", "puraimaru"},
		{"きのこ 帝国", "kinoko"},
		{"Привет", "privet"},
		{"Ελλάδα", "ellada"},
		{"Boards of Canada", ""},
		{"椎名林檎", ""},
	}
	for _, c := range cases {
		if got := Romanize(c.in); got != c.want {
			t.Errorf("Romanize(%q) = %q, want %q", c.in, got, c.want)
		}
	}
}

func TestSimilarity(t *testing.T) {
	cases := []struct {
		a, b string
		min  float64
	}{
		{"deadmau5", "deadmou5", 0.85},
		{"porter-robinson-madeon", "porter-robinson", 0.9},
		{"c418", "c418", 1.0},
		{"boards-of-canada", "aphex-twin", 0.0},
	}
	for _, c := range cases {
		got := Similarity(c.a, c.b)
		if got < c.min {
			t.Errorf("Similarity(%q,%q) = %.2f, want >= %.2f", c.a, c.b, got, c.min)
		}
	}
}

func TestResolveExactAndAlias(t *testing.T) {
	ix := NewIndex()
	ix.AddDir("c418")
	ix.AddDir("boards-of-canada")

	for _, credit := range []string{"C418", "c418", "C418 "} {
		m := ix.Resolve(credit)
		if len(m.Dirs) == 0 || m.Dirs[0].Dir != "c418" || !m.Dirs[0].ExactDir {
			t.Errorf("Resolve(%q): got %+v, want exact c418", credit, m.Dirs)
		}
	}

	ix.SetAlias("Various Artists", "various-artists")
	ix.AddDir("various-artists")
	m := ix.Resolve("Various Artists")
	if len(m.Dirs) == 0 || m.Dirs[0].Dir != "various-artists" {
		t.Fatalf("alias resolution failed: %+v", m.Dirs)
	}
}

func TestResolveFuzzyAndNew(t *testing.T) {
	ix := NewIndex()
	ix.AddDir("deadmau5")

	m := ix.Resolve("deadmou5")
	if len(m.Dirs) == 0 || m.Dirs[0].Dir != "deadmau5" || !m.Dirs[0].Fuzzy {
		t.Errorf("expected fuzzy match to deadmau5, got %+v", m.Dirs)
	}

	m = ix.Resolve("Aphex Twin")
	last := m.Dirs[len(m.Dirs)-1]
	if last.Dir != "aphex-twin" || last.Score != 0 {
		t.Errorf("expected new folder aphex-twin, got %+v", m.Dirs)
	}
}

func TestAliasRoundTrip(t *testing.T) {
	dir := t.TempDir()
	path := filepath.Join(dir, "artists.toml")

	ix := NewIndex()
	ix.SetAlias("椎名林檎", "shiina-ringo")
	ix.SetAlias("C418", "c418")
	ix.SetAlias("Porter Robinson & Madeon", "porter-robinson")
	if err := ix.SaveAliases(path); err != nil {
		t.Fatal(err)
	}

	data, err := os.ReadFile(path)
	if err != nil {
		t.Fatal(err)
	}
	if len(data) == 0 || data[0] != '#' {
		t.Errorf("alias file should start with an explanatory comment, got %q", string(data[:min(len(data), 40)]))
	}

	back := NewIndex()
	if err := back.LoadAliases(path); err != nil {
		t.Fatal(err)
	}
	for k, want := range ix.Alias {
		if got := back.Alias[k]; got != want {
			t.Errorf("alias %q round-tripped as %q, want %q", k, got, want)
		}
	}
}

func TestLoadAliasesMissingFile(t *testing.T) {
	ix := NewIndex()
	if err := ix.LoadAliases(filepath.Join(t.TempDir(), "nope.toml")); err != nil {
		t.Errorf("missing alias file should not be an error, got %v", err)
	}
}