package speaker import ( "os" "path/filepath" "strings" "testing" ) func TestSpeakerForSourceMatchesBasenameCaseInsensitive(t *testing.T) { dir := t.TempDir() path := writeSpeakerMap(t, dir, `match: - speaker: "Eric Rakestraw" match: - "eric_rakestraw" `) speakers, err := LoadMap(path) if err != nil { t.Fatalf("load speaker map: %v", err) } got, err := speakers.SpeakerForSource(filepath.Join(dir, "2026-04-19-Eric_Rakestraw.json")) if err != nil { t.Fatalf("resolve speaker: %v", err) } if got != "Eric Rakestraw" { t.Fatalf("speaker = %q, want %q", got, "Eric Rakestraw") } } func TestSpeakerForSourceUsesBasenameOnly(t *testing.T) { dir := t.TempDir() path := writeSpeakerMap(t, dir, `match: - speaker: "Directory Match" match: - "speaker-dir" `) speakers, err := LoadMap(path) if err != nil { t.Fatalf("load speaker map: %v", err) } _, err = speakers.SpeakerForSource(filepath.Join(dir, "speaker-dir", "input.json")) if err == nil { t.Fatal("expected no match") } if !strings.Contains(err.Error(), `input.json`) { t.Fatalf("expected basename in error, got %v", err) } } func TestSpeakerForSourceUsesFirstMatchingRule(t *testing.T) { dir := t.TempDir() path := writeSpeakerMap(t, dir, `match: - speaker: "First" match: - "adam" - speaker: "Second" match: - "adam_rakestraw" `) speakers, err := LoadMap(path) if err != nil { t.Fatalf("load speaker map: %v", err) } got, err := speakers.SpeakerForSource("2026-04-19-Adam_Rakestraw.json") if err != nil { t.Fatalf("resolve speaker: %v", err) } if got != "First" { t.Fatalf("speaker = %q, want %q", got, "First") } } func TestLoadMapValidation(t *testing.T) { tests := []struct { name string content string want string }{ { name: "missing top-level match", content: `inputs: {}`, want: "must contain at least one match rule", }, { name: "empty match list", content: `match: []`, want: "must contain at least one match rule", }, { name: "empty speaker", content: `match: - speaker: "" match: ["eric"] `, want: "must include speaker", }, { name: "empty rule match list", content: `match: - speaker: "Eric" match: [] `, want: "must include at least one match string", }, { name: "empty match string", content: `match: - speaker: "Eric" match: [" "] `, want: "contains empty match string", }, { name: "duplicate speaker", content: `match: - speaker: "Eric" match: ["eric"] - speaker: "Eric" match: ["rakestraw"] `, want: `duplicate speaker "Eric"`, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { dir := t.TempDir() path := writeSpeakerMap(t, dir, test.content) _, err := LoadMap(path) if err == nil { t.Fatal("expected error") } if !strings.Contains(err.Error(), test.want) { t.Fatalf("expected error to contain %q, got %v", test.want, err) } }) } } func writeSpeakerMap(t *testing.T, dir string, content string) string { t.Helper() path := filepath.Join(dir, "speakers.yml") if err := os.WriteFile(path, []byte(content), 0o600); err != nil { t.Fatalf("write speaker map: %v", err) } return path }