diff --git a/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .JSON b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .JSON new file mode 100644 index 000000000..7ab8e7d5b --- /dev/null +++ b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .JSON @@ -0,0 +1,55 @@ +{ + "status": "ok", + "version": "1.8.0", + "type": "navidrome", + "serverVersion": "v0.0.0", + "openSubsonic": true, + "album": { + "id": "1", + "name": "album", + "artist": "artist", + "userRating": 0, + "genre": "rock", + "genres": [ + { + "name": "rock" + }, + { + "name": "progressive" + } + ], + "musicBrainzId": "1234", + "song": [ + { + "id": "1", + "isDir": true, + "title": "title", + "album": "album", + "artist": "artist", + "track": 1, + "year": 1985, + "genre": "Rock", + "genres": [ + { + "name": "rock" + }, + { + "name": "progressive" + } + ], + "coverArt": "1", + "size": 8421341, + "contentType": "audio/flac", + "suffix": "flac", + "starred": "2016-03-02T20:30:00Z", + "transcodedContentType": "audio/mpeg", + "transcodedSuffix": "mp3", + "duration": 146, + "bitRate": 320, + "isVideo": false, + "bpm": 127, + "comment": "a comment" + } + ] + } +} diff --git a/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .XML b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .XML new file mode 100644 index 000000000..9ca452e7c --- /dev/null +++ b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 with data should match .XML @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 without data should match .JSON b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 without data should match .JSON new file mode 100644 index 000000000..6c2024a08 --- /dev/null +++ b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 without data should match .JSON @@ -0,0 +1,14 @@ +{ + "status": "ok", + "version": "1.8.0", + "type": "navidrome", + "serverVersion": "v0.0.0", + "openSubsonic": true, + "album": { + "id": "", + "name": "", + "userRating": 0, + "genres": [], + "musicBrainzId": "" + } +} diff --git a/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 without data should match .XML b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 without data should match .XML new file mode 100644 index 000000000..affb6490b --- /dev/null +++ b/server/subsonic/responses/.snapshots/Responses AlbumWithSongsID3 without data should match .XML @@ -0,0 +1,3 @@ + + + diff --git a/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON b/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON index 2321f3a0b..0c7330801 100644 --- a/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON +++ b/server/subsonic/responses/.snapshots/Responses Child with data should match .JSON @@ -15,7 +15,14 @@ "track": 1, "year": 1985, "genre": "Rock", - "genres": [], + "genres": [ + { + "name": "rock" + }, + { + "name": "progressive" + } + ], "coverArt": "1", "size": 8421341, "contentType": "audio/flac", @@ -26,8 +33,8 @@ "duration": 146, "bitRate": 320, "isVideo": false, - "bpm": 0, - "comment": "" + "bpm": 127, + "comment": "a comment" } ], "id": "1", diff --git a/server/subsonic/responses/.snapshots/Responses Child with data should match .XML b/server/subsonic/responses/.snapshots/Responses Child with data should match .XML index 32d8fdc8a..22ab7893b 100644 --- a/server/subsonic/responses/.snapshots/Responses Child with data should match .XML +++ b/server/subsonic/responses/.snapshots/Responses Child with data should match .XML @@ -1,5 +1,8 @@ - + + + + diff --git a/server/subsonic/responses/.snapshots/Responses Child without data should match .JSON b/server/subsonic/responses/.snapshots/Responses Child without data should match .JSON new file mode 100644 index 000000000..b239d6476 --- /dev/null +++ b/server/subsonic/responses/.snapshots/Responses Child without data should match .JSON @@ -0,0 +1,21 @@ +{ + "status": "ok", + "version": "1.8.0", + "type": "navidrome", + "serverVersion": "v0.0.0", + "openSubsonic": true, + "directory": { + "child": [ + { + "id": "1", + "isDir": false, + "genres": [], + "isVideo": false, + "bpm": 0, + "comment": "" + } + ], + "id": "", + "name": "" + } +} diff --git a/server/subsonic/responses/.snapshots/Responses Child without data should match .XML b/server/subsonic/responses/.snapshots/Responses Child without data should match .XML new file mode 100644 index 000000000..2b736b573 --- /dev/null +++ b/server/subsonic/responses/.snapshots/Responses Child without data should match .XML @@ -0,0 +1,5 @@ + + + + + diff --git a/server/subsonic/responses/responses.go b/server/subsonic/responses/responses.go index 8b48add8d..87f9fa508 100644 --- a/server/subsonic/responses/responses.go +++ b/server/subsonic/responses/responses.go @@ -107,59 +107,45 @@ type Indexes struct { } type Child struct { - Id string `xml:"id,attr" json:"id"` - Parent string `xml:"parent,attr,omitempty" json:"parent,omitempty"` - IsDir bool `xml:"isDir,attr" json:"isDir"` - Title string `xml:"title,attr,omitempty" json:"title,omitempty"` - Name string `xml:"name,attr,omitempty" json:"name,omitempty"` - Album string `xml:"album,attr,omitempty" json:"album,omitempty"` - Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"` - Track int32 `xml:"track,attr,omitempty" json:"track,omitempty"` - Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"` - Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"` - Genres []ItemGenre `xml:"genres" json:"genres"` - CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"` - Size int64 `xml:"size,attr,omitempty" json:"size,omitempty"` - ContentType string `xml:"contentType,attr,omitempty" json:"contentType,omitempty"` - Suffix string `xml:"suffix,attr,omitempty" json:"suffix,omitempty"` - Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"` - TranscodedContentType string `xml:"transcodedContentType,attr,omitempty" json:"transcodedContentType,omitempty"` - TranscodedSuffix string `xml:"transcodedSuffix,attr,omitempty" json:"transcodedSuffix,omitempty"` - Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"` - BitRate int32 `xml:"bitRate,attr,omitempty" json:"bitRate,omitempty"` - Path string `xml:"path,attr,omitempty" json:"path,omitempty"` - PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"` - Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"` - DiscNumber int32 `xml:"discNumber,attr,omitempty" json:"discNumber,omitempty"` - Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"` - AlbumId string `xml:"albumId,attr,omitempty" json:"albumId,omitempty"` - ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"` - Type string `xml:"type,attr,omitempty" json:"type,omitempty"` - UserRating int32 `xml:"userRating,attr,omitempty" json:"userRating,omitempty"` - SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"` - IsVideo bool `xml:"isVideo,attr" json:"isVideo"` - BookmarkPosition int64 `xml:"bookmarkPosition,attr,omitempty" json:"bookmarkPosition,omitempty"` - Bpm int32 `xml:"bpm,attr" json:"bpm"` - Comment string `xml:"comment,attr" json:"comment"` + Id string `xml:"id,attr" json:"id"` + Parent string `xml:"parent,attr,omitempty" json:"parent,omitempty"` + IsDir bool `xml:"isDir,attr" json:"isDir"` + Title string `xml:"title,attr,omitempty" json:"title,omitempty"` + Name string `xml:"name,attr,omitempty" json:"name,omitempty"` + Album string `xml:"album,attr,omitempty" json:"album,omitempty"` + Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"` + Track int32 `xml:"track,attr,omitempty" json:"track,omitempty"` + Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"` + Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"` + Genres ItemGenres `xml:"genres" json:"genres"` + CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"` + Size int64 `xml:"size,attr,omitempty" json:"size,omitempty"` + ContentType string `xml:"contentType,attr,omitempty" json:"contentType,omitempty"` + Suffix string `xml:"suffix,attr,omitempty" json:"suffix,omitempty"` + Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"` + TranscodedContentType string `xml:"transcodedContentType,attr,omitempty" json:"transcodedContentType,omitempty"` + TranscodedSuffix string `xml:"transcodedSuffix,attr,omitempty" json:"transcodedSuffix,omitempty"` + Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"` + BitRate int32 `xml:"bitRate,attr,omitempty" json:"bitRate,omitempty"` + Path string `xml:"path,attr,omitempty" json:"path,omitempty"` + PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"` + Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"` + DiscNumber int32 `xml:"discNumber,attr,omitempty" json:"discNumber,omitempty"` + Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"` + AlbumId string `xml:"albumId,attr,omitempty" json:"albumId,omitempty"` + ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"` + Type string `xml:"type,attr,omitempty" json:"type,omitempty"` + UserRating int32 `xml:"userRating,attr,omitempty" json:"userRating,omitempty"` + SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"` + IsVideo bool `xml:"isVideo,attr" json:"isVideo"` + BookmarkPosition int64 `xml:"bookmarkPosition,attr,omitempty" json:"bookmarkPosition,omitempty"` + Bpm int32 `xml:"bpm,attr" json:"bpm"` + Comment string `xml:"comment,attr" json:"comment"` /* */ } -func (c Child) MarshalJSON() ([]byte, error) { - // ensure fields that need custom default values are set properly - type Alias Child - a := struct { - Alias - }{ - Alias: (Alias)(c), - } - if a.Genres == nil { - a.Genres = make([]ItemGenre, 0) - } - return json.Marshal(a) -} - type Songs struct { Songs []Child `xml:"song" json:"song,omitempty"` } @@ -202,36 +188,22 @@ type ArtistID3 struct { } type AlbumID3 struct { - Id string `xml:"id,attr" json:"id"` - Name string `xml:"name,attr" json:"name"` - Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"` - ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"` - CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"` - SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"` - Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"` - PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"` - Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"` - Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"` - Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"` - UserRating int32 `xml:"userRating,attr" json:"userRating"` - Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"` - Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"` - Genres []ItemGenre `xml:"genres" json:"genres"` - MusicBrainzId string `xml:"musicBrainzId,attr" json:"musicBrainzId"` -} - -func (a AlbumID3) MarshalJSON() ([]byte, error) { - // ensure fields that need custom default values are set properly - type Alias AlbumID3 - x := struct { - Alias - }{ - Alias: (Alias)(a), - } - if x.Genres == nil { - x.Genres = make([]ItemGenre, 0) - } - return json.Marshal(x) + Id string `xml:"id,attr" json:"id"` + Name string `xml:"name,attr" json:"name"` + Artist string `xml:"artist,attr,omitempty" json:"artist,omitempty"` + ArtistId string `xml:"artistId,attr,omitempty" json:"artistId,omitempty"` + CoverArt string `xml:"coverArt,attr,omitempty" json:"coverArt,omitempty"` + SongCount int32 `xml:"songCount,attr,omitempty" json:"songCount,omitempty"` + Duration int32 `xml:"duration,attr,omitempty" json:"duration,omitempty"` + PlayCount int64 `xml:"playCount,attr,omitempty" json:"playCount,omitempty"` + Played *time.Time `xml:"played,attr,omitempty" json:"played,omitempty"` + Created *time.Time `xml:"created,attr,omitempty" json:"created,omitempty"` + Starred *time.Time `xml:"starred,attr,omitempty" json:"starred,omitempty"` + UserRating int32 `xml:"userRating,attr" json:"userRating"` + Year int32 `xml:"year,attr,omitempty" json:"year,omitempty"` + Genre string `xml:"genre,attr,omitempty" json:"genre,omitempty"` + Genres ItemGenres `xml:"genres" json:"genres"` + MusicBrainzId string `xml:"musicBrainzId,attr" json:"musicBrainzId"` } type ArtistWithAlbumsID3 struct { @@ -458,3 +430,14 @@ type OpenSubsonicExtensions struct{} type ItemGenre struct { Name string `xml:"name,attr" json:"name"` } + +type ItemGenres []ItemGenre + +func (i ItemGenres) MarshalJSON() ([]byte, error) { + if len(i) == 0 { + return json.Marshal([]ItemGenre{}) + } + type Alias []ItemGenre + a := (Alias)(i) + return json.Marshal(a) +} diff --git a/server/subsonic/responses/responses_test.go b/server/subsonic/responses/responses_test.go index c2bc4c2bf..6fc95270c 100644 --- a/server/subsonic/responses/responses_test.go +++ b/server/subsonic/responses/responses_test.go @@ -121,6 +121,17 @@ var _ = Describe("Responses", func() { }) Describe("Child", func() { + Context("without data", func() { + BeforeEach(func() { + response.Directory = &Directory{Child: []Child{{Id: "1"}}} + }) + It("should match .XML", func() { + Expect(xml.MarshalIndent(response, "", " ")).To(MatchSnapshot()) + }) + It("should match .JSON", func() { + Expect(json.MarshalIndent(response, "", " ")).To(MatchSnapshot()) + }) + }) Context("with data", func() { BeforeEach(func() { response.Directory = &Directory{Id: "1", Name: "N"} @@ -130,7 +141,8 @@ var _ = Describe("Responses", func() { Id: "1", IsDir: true, Title: "title", Album: "album", Artist: "artist", Track: 1, Year: 1985, Genre: "Rock", CoverArt: "1", Size: 8421341, ContentType: "audio/flac", Suffix: "flac", TranscodedContentType: "audio/mpeg", TranscodedSuffix: "mp3", - Duration: 146, BitRate: 320, Starred: &t, + Duration: 146, BitRate: 320, Starred: &t, Genres: []ItemGenre{{Name: "rock"}, {Name: "progressive"}}, + Comment: "a comment", Bpm: 127, } response.Directory.Child = child }) @@ -144,6 +156,43 @@ var _ = Describe("Responses", func() { }) }) + Describe("AlbumWithSongsID3", func() { + BeforeEach(func() { + response.AlbumWithSongsID3 = &AlbumWithSongsID3{} + }) + Context("without data", func() { + It("should match .XML", func() { + Expect(xml.MarshalIndent(response, "", " ")).To(MatchSnapshot()) + }) + It("should match .JSON", func() { + Expect(json.MarshalIndent(response, "", " ")).To(MatchSnapshot()) + }) + }) + + Context("with data", func() { + BeforeEach(func() { + album := AlbumID3{Id: "1", Name: "album", Artist: "artist", Genre: "rock", + Genres: []ItemGenre{{Name: "rock"}, {Name: "progressive"}}, MusicBrainzId: "1234"} + t := time.Date(2016, 03, 2, 20, 30, 0, 0, time.UTC) + songs := []Child{{ + Id: "1", IsDir: true, Title: "title", Album: "album", Artist: "artist", Track: 1, + Year: 1985, Genre: "Rock", CoverArt: "1", Size: 8421341, ContentType: "audio/flac", + Suffix: "flac", TranscodedContentType: "audio/mpeg", TranscodedSuffix: "mp3", + Duration: 146, BitRate: 320, Starred: &t, Genres: []ItemGenre{{Name: "rock"}, {Name: "progressive"}}, + Comment: "a comment", Bpm: 127, + }} + response.AlbumWithSongsID3.AlbumID3 = album + response.AlbumWithSongsID3.Song = songs + }) + It("should match .XML", func() { + Expect(xml.MarshalIndent(response, "", " ")).To(MatchSnapshot()) + }) + It("should match .JSON", func() { + Expect(json.MarshalIndent(response, "", " ")).To(MatchSnapshot()) + }) + }) + }) + Describe("Directory", func() { BeforeEach(func() { response.Directory = &Directory{Id: "1", Name: "N"}