Files
NaviWatcher/internal/musicbrainz/model_test.go
Vladimir Zagainov 674daed93b feat: create MusicBrainz client and data models
Add internal/musicbrainz/ package with:
- client.go: MusicBrainzClient struct wrapping net/http.Client with
  channel-based rate limiter (1 req/sec), doGet method with proper
  User-Agent header, and Close for cleanup
- model.go: ReleaseGroup, Artist, ExternalRelease, and Parsed* structs
- XML parsing functions for release-group list and artist responses
- Comprehensive tests: XML parsing (success, empty, malformed),
  client constructor, doGet (success, non-200, unreachable server),
  rate limiter behavior
2026-05-26 11:52:17 +03:00

202 lines
5.5 KiB
Go

package musicbrainz
import (
"testing"
)
func TestParseReleaseGroups_Success(t *testing.T) {
data := []byte(`<?xml version="1.0" encoding="UTF-8"?>
<metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#">
<release-group-list count="2">
<release-group id="rg-uuid-1" type="Album">
<title>Dark Side of the Moon</title>
<first-release-date>1973-03-01</first-release-date>
<artist-credit>
<name-credit>
<artist id="artist-uuid-1">
<name>Pink Floyd</name>
</artist>
</name-credit>
</artist-credit>
</release-group>
<release-group id="rg-uuid-2" type="Single">
<title>Another Brick in the Wall</title>
<first-release-date>1979-11-30</first-release-date>
<artist-credit>
<name-credit>
<artist id="artist-uuid-1">
<name>Pink Floyd</name>
</artist>
</name-credit>
</artist-credit>
</release-group>
</release-group-list>
</metadata>`)
result, err := ParseReleaseGroups(data)
if err != nil {
t.Fatalf("ParseReleaseGroups() error = %v", err)
}
if result.Count != 2 {
t.Errorf("ParseReleaseGroups().Count = %d, want 2", result.Count)
}
if len(result.ReleaseGroups) != 2 {
t.Fatalf("ParseReleaseGroups() returned %d groups, want 2", len(result.ReleaseGroups))
}
expected := []ReleaseGroup{
{
ID: "rg-uuid-1",
Title: "Dark Side of the Moon",
Type: "Album",
ArtistID: "artist-uuid-1",
ArtistName: "Pink Floyd",
ReleaseDate: "1973-03-01",
},
{
ID: "rg-uuid-2",
Title: "Another Brick in the Wall",
Type: "Single",
ArtistID: "artist-uuid-1",
ArtistName: "Pink Floyd",
ReleaseDate: "1979-11-30",
},
}
for i, rg := range result.ReleaseGroups {
if rg.ID != expected[i].ID {
t.Errorf("ReleaseGroups[%d].ID = %q, want %q", i, rg.ID, expected[i].ID)
}
if rg.Title != expected[i].Title {
t.Errorf("ReleaseGroups[%d].Title = %q, want %q", i, rg.Title, expected[i].Title)
}
if rg.Type != expected[i].Type {
t.Errorf("ReleaseGroups[%d].Type = %q, want %q", i, rg.Type, expected[i].Type)
}
if rg.ArtistID != expected[i].ArtistID {
t.Errorf("ReleaseGroups[%d].ArtistID = %q, want %q", i, rg.ArtistID, expected[i].ArtistID)
}
if rg.ArtistName != expected[i].ArtistName {
t.Errorf("ReleaseGroups[%d].ArtistName = %q, want %q", i, rg.ArtistName, expected[i].ArtistName)
}
if rg.ReleaseDate != expected[i].ReleaseDate {
t.Errorf("ReleaseGroups[%d].ReleaseDate = %q, want %q", i, rg.ReleaseDate, expected[i].ReleaseDate)
}
}
}
func TestParseReleaseGroups_Empty(t *testing.T) {
data := []byte(`<?xml version="1.0" encoding="UTF-8"?>
<metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#">
<release-group-list count="0">
</release-group-list>
</metadata>`)
result, err := ParseReleaseGroups(data)
if err != nil {
t.Fatalf("ParseReleaseGroups() error = %v", err)
}
if result.Count != 0 {
t.Errorf("ParseReleaseGroups().Count = %d, want 0", result.Count)
}
if len(result.ReleaseGroups) != 0 {
t.Errorf("ParseReleaseGroups() returned %d groups, want 0", len(result.ReleaseGroups))
}
}
func TestParseReleaseGroups_MalformedXML(t *testing.T) {
tests := []struct {
name string
data []byte
}{
{
name: "truncated XML",
data: []byte(`<?xml version="1.0"?><metadata><release-group-list>`),
},
{
name: "not XML at all",
data: []byte(`this is not xml`),
},
{
name: "wrong root element",
data: []byte(`<?xml version="1.0"?><wrongRoot><item>test</item></wrongRoot>`),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := ParseReleaseGroups(tt.data)
if err == nil {
t.Fatal("ParseReleaseGroups() expected error for malformed XML, got nil")
}
})
}
}
func TestParseReleaseGroups_WithStatus(t *testing.T) {
data := []byte(`<?xml version="1.0" encoding="UTF-8"?>
<metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#">
<release-group-list count="1">
<release-group id="rg-bootleg" type="Album" status="Bootleg">
<title>Unofficial Live Recording</title>
<first-release-date>2020-01-01</first-release-date>
<artist-credit>
<name-credit>
<artist id="artist-uuid-2">
<name>Test Artist</name>
</artist>
</name-credit>
</artist-credit>
</release-group>
</release-group-list>
</metadata>`)
result, err := ParseReleaseGroups(data)
if err != nil {
t.Fatalf("ParseReleaseGroups() error = %v", err)
}
if len(result.ReleaseGroups) != 1 {
t.Fatalf("ParseReleaseGroups() returned %d groups, want 1", len(result.ReleaseGroups))
}
if result.ReleaseGroups[0].Status != "Bootleg" {
t.Errorf("ReleaseGroups[0].Status = %q, want %q", result.ReleaseGroups[0].Status, "Bootleg")
}
}
func TestParseArtist_Success(t *testing.T) {
data := []byte(`<?xml version="1.0" encoding="UTF-8"?>
<metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#">
<artist id="artist-uuid-1" type="Group">
<name>Pink Floyd</name>
</artist>
</metadata>`)
result, err := ParseArtist(data)
if err != nil {
t.Fatalf("ParseArtist() error = %v", err)
}
if result.ID != "artist-uuid-1" {
t.Errorf("ParseArtist().ID = %q, want %q", result.ID, "artist-uuid-1")
}
if result.Name != "Pink Floyd" {
t.Errorf("ParseArtist().Name = %q, want %q", result.Name, "Pink Floyd")
}
}
func TestParseArtist_MalformedXML(t *testing.T) {
data := []byte(`this is not xml`)
_, err := ParseArtist(data)
if err == nil {
t.Fatal("ParseArtist() expected error for malformed XML, got nil")
}
}