301 lines
6.8 KiB
Go
301 lines
6.8 KiB
Go
package main
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
// TestNormalizePath validates the GProTab path normalization logic
|
|
func TestNormalizePath(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "Full https GProTab URL",
|
|
input: "https://gprotab.net/en/tabs/metallica/one",
|
|
expected: "/en/tabs/metallica/one",
|
|
},
|
|
{
|
|
name: "Full http GProTab URL",
|
|
input: "http://gprotab.net/en/tabs/slayer/raining-blood",
|
|
expected: "/en/tabs/slayer/raining-blood",
|
|
},
|
|
{
|
|
name: "Clean relative path",
|
|
input: "/en/tabs/pantera/walk",
|
|
expected: "/en/tabs/pantera/walk",
|
|
},
|
|
{
|
|
name: "Partial slash slug",
|
|
input: "megadeth/holy-wars",
|
|
expected: "/en/tabs/megadeth/holy-wars",
|
|
},
|
|
{
|
|
name: "Simple text input",
|
|
input: "metallica",
|
|
expected: "metallica",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := normalizePath(tt.input)
|
|
if result != tt.expected {
|
|
t.Errorf("normalizePath(%q) = %q; expected %q", tt.input, result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestCleanSongsterrName validates slug generation formatting
|
|
func TestCleanSongsterrName(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "Simple lowercase conversion",
|
|
input: "Metallica",
|
|
expected: "metallica",
|
|
},
|
|
{
|
|
name: "Spaces to hyphens",
|
|
input: "The Eagles",
|
|
expected: "the-eagles",
|
|
},
|
|
{
|
|
name: "Special characters removal",
|
|
input: "Guns N' Roses & Friends!",
|
|
expected: "guns-n-roses-friends",
|
|
},
|
|
{
|
|
name: "Collapsing multiple hyphens",
|
|
input: "rock---and---roll",
|
|
expected: "rock-and-roll",
|
|
},
|
|
{
|
|
name: "Trailing and leading hyphens removal",
|
|
input: "---led zeppelin---",
|
|
expected: "led-zeppelin",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := cleanSongsterrName(tt.input)
|
|
if result != tt.expected {
|
|
t.Errorf("cleanSongsterrName(%q) = %q; expected %q", tt.input, result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestSanitizeDirName validates OS-safe folder name formatting
|
|
func TestSanitizeDirName(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "Preserve capitalization and spaces",
|
|
input: "As I Lay Dying",
|
|
expected: "As I Lay Dying",
|
|
},
|
|
{
|
|
name: "Filter standard Windows slash characters",
|
|
input: "AC/DC",
|
|
expected: "ACDC",
|
|
},
|
|
{
|
|
name: "Remove illegal OS characters but keep capitalization and symbols",
|
|
input: "Guns N' Roses: Live & Loud *Special?",
|
|
expected: "Guns N' Roses Live & Loud Special",
|
|
},
|
|
{
|
|
name: "Collapse adjacent spaces",
|
|
input: " Slayer Metal ",
|
|
expected: "Slayer Metal",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := sanitizeDirName(tt.input)
|
|
if result != tt.expected {
|
|
t.Errorf("sanitizeDirName(%q) = %q; expected %q", tt.input, result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestIsTargetArtist validates the robust sub-artist matching logic
|
|
func TestIsTargetArtist(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
songArtist string
|
|
targetArtist string
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "Direct matching exact",
|
|
songArtist: "August Burns Red",
|
|
targetArtist: "August Burns Red",
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "Direct matching case insensitive",
|
|
songArtist: "august burns red",
|
|
targetArtist: "August Burns Red",
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "Squished name matching",
|
|
songArtist: "augustburnsred",
|
|
targetArtist: "August Burns Red",
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "Trailing punctuation/comma matching",
|
|
songArtist: "August Burns Red,",
|
|
targetArtist: "August Burns Red",
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "Collaboration split by comma matching",
|
|
songArtist: "August Burns Red, Jeremy McKinnon",
|
|
targetArtist: "August Burns Red",
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "Collaboration split by ft matching",
|
|
songArtist: "August Burns Red ft. Jeremy McKinnon",
|
|
targetArtist: "August Burns Red",
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "Collaborator second in split",
|
|
songArtist: "Jeremy McKinnon & August Burns Red",
|
|
targetArtist: "August Burns Red",
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "Not matching similar name parody",
|
|
songArtist: "August Burns All The Tabs",
|
|
targetArtist: "August Burns Red",
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "Not matching misspelling",
|
|
songArtist: "August Burn Red",
|
|
targetArtist: "August Burns Red",
|
|
expected: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := isTargetArtist(tt.songArtist, tt.targetArtist)
|
|
if result != tt.expected {
|
|
t.Errorf("isTargetArtist(%q, %q) = %v; expected %v", tt.songArtist, tt.targetArtist, result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestParseSelection validates parsing selections
|
|
func TestParseSelection(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
maxVal int
|
|
expected []int
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "Single number",
|
|
input: "3",
|
|
maxVal: 10,
|
|
expected: []int{2},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Comma separated",
|
|
input: "1,3,5",
|
|
maxVal: 10,
|
|
expected: []int{0, 2, 4},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Range",
|
|
input: "2-5",
|
|
maxVal: 10,
|
|
expected: []int{1, 2, 3, 4},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Mixed comma and range",
|
|
input: "1,3-5,8",
|
|
maxVal: 10,
|
|
expected: []int{0, 2, 3, 4, 7},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "De-duplicate and sort",
|
|
input: "5,1-3,2",
|
|
maxVal: 10,
|
|
expected: []int{0, 1, 2, 4},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Out of bounds single",
|
|
input: "11",
|
|
maxVal: 10,
|
|
expected: nil,
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Out of bounds range",
|
|
input: "8-12",
|
|
maxVal: 10,
|
|
expected: nil,
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Empty input",
|
|
input: "",
|
|
maxVal: 10,
|
|
expected: nil,
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
res, err := parseSelection(tt.input, tt.maxVal)
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Errorf("expected error for input %q, but got none", tt.input)
|
|
}
|
|
} else {
|
|
if err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
if len(res) != len(tt.expected) {
|
|
t.Errorf("expected length %d, got %d", len(tt.expected), len(res))
|
|
} else {
|
|
for i := range res {
|
|
if res[i] != tt.expected[i] {
|
|
t.Errorf("at index %d: expected %d, got %d", i, tt.expected[i], res[i])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
|