mirror of
https://github.com/navidrome/navidrome.git
synced 2025-05-31 23:59:35 +03:00
Started the implementation of getMusicDirectory. Probably will need to introduce a new 'service' layer...
This commit is contained in:
parent
68786d4b39
commit
9577d9ae87
@ -3,7 +3,6 @@ package api_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"encoding/xml"
|
||||
"github.com/deluan/gosonic/api/responses"
|
||||
"github.com/deluan/gosonic/consts"
|
||||
"github.com/deluan/gosonic/domain"
|
||||
@ -39,17 +38,13 @@ func TestGetIndexes(t *testing.T) {
|
||||
mockRepo.SetError(true)
|
||||
_, w := Get(AddParams("/rest/getIndexes.view", "ifModifiedSince=0"), "TestGetIndexes")
|
||||
|
||||
v := responses.Subsonic{}
|
||||
xml.Unmarshal(w.Body.Bytes(), &v)
|
||||
So(v.Status, ShouldEqual, "fail")
|
||||
So(w.Body, ShouldReceiveError, responses.ERROR_GENERIC)
|
||||
})
|
||||
Convey("Return fail on Property Table error", func() {
|
||||
propRepo.SetError(true)
|
||||
_, w := Get(AddParams("/rest/getIndexes.view"), "TestGetIndexes")
|
||||
|
||||
v := responses.Subsonic{}
|
||||
xml.Unmarshal(w.Body.Bytes(), &v)
|
||||
So(v.Status, ShouldEqual, "fail")
|
||||
So(w.Body, ShouldReceiveError, responses.ERROR_GENERIC)
|
||||
})
|
||||
Convey("When the index is empty", func() {
|
||||
_, w := Get(AddParams("/rest/getIndexes.view"), "TestGetIndexes")
|
||||
|
44
api/get_music_directory.go
Normal file
44
api/get_music_directory.go
Normal file
@ -0,0 +1,44 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/deluan/gosonic/api/responses"
|
||||
"github.com/deluan/gosonic/domain"
|
||||
"github.com/deluan/gosonic/utils"
|
||||
"github.com/karlkfi/inject"
|
||||
"github.com/astaxie/beego"
|
||||
)
|
||||
|
||||
type GetMusicDirectoryController struct {
|
||||
BaseAPIController
|
||||
artistRepo domain.ArtistRepository
|
||||
}
|
||||
|
||||
func (c *GetMusicDirectoryController) Prepare() {
|
||||
inject.ExtractAssignable(utils.Graph, &c.artistRepo)
|
||||
}
|
||||
|
||||
func (c *GetMusicDirectoryController) Get() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
if id == "" {
|
||||
c.SendError(responses.ERROR_MISSING_PARAMETER, "id parameter required")
|
||||
}
|
||||
|
||||
found, err := c.artistRepo.Exists(id)
|
||||
if err != nil {
|
||||
beego.Error("Error searching for Artist:", err)
|
||||
c.SendError(responses.ERROR_GENERIC, "Internal Error")
|
||||
}
|
||||
|
||||
if found {
|
||||
_, err := c.artistRepo.Get(id)
|
||||
if err != nil {
|
||||
beego.Error("Error reading Artist from DB", err)
|
||||
c.SendError(responses.ERROR_GENERIC, "Internal Error")
|
||||
}
|
||||
}
|
||||
|
||||
response := c.NewEmpty()
|
||||
response.Directory = &responses.Directory{}
|
||||
c.SendResponse(response)
|
||||
}
|
40
api/get_music_directory_test.go
Normal file
40
api/get_music_directory_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
package api_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/deluan/gosonic/domain"
|
||||
"github.com/deluan/gosonic/tests/mocks"
|
||||
"github.com/deluan/gosonic/utils"
|
||||
. "github.com/deluan/gosonic/tests"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"github.com/deluan/gosonic/api/responses"
|
||||
)
|
||||
|
||||
func TestGetMusicDirectory(t *testing.T) {
|
||||
Init(t, false)
|
||||
|
||||
mockRepo := mocks.CreateMockArtistRepo()
|
||||
utils.DefineSingleton(new(domain.ArtistRepository), func() domain.ArtistRepository {
|
||||
return mockRepo
|
||||
})
|
||||
|
||||
mockRepo.SetData("[]")
|
||||
mockRepo.SetError(false)
|
||||
|
||||
Convey("Subject: GetMusicDirectory Endpoint", t, func() {
|
||||
Convey("Should fail if missing Id parameter", func() {
|
||||
_, w := Get(AddParams("/rest/getMusicDirectory.view"), "TestGetMusicDirectory")
|
||||
|
||||
So(w.Body, ShouldReceiveError, responses.ERROR_MISSING_PARAMETER)
|
||||
})
|
||||
Convey("Id is for an artist", func() {
|
||||
Convey("Return fail on Artist Table error", func() {
|
||||
mockRepo.SetError(true)
|
||||
_, w := Get(AddParams("/rest/getMusicDirectory.view", "id=1"), "TestGetMusicDirectory")
|
||||
|
||||
So(w.Body, ShouldReceiveError, responses.ERROR_GENERIC)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
@ -6,7 +6,7 @@ type Subsonic struct {
|
||||
XMLName xml.Name `xml:"http://subsonic.org/restapi subsonic-response" json:"-"`
|
||||
Status string `xml:"status,attr" json:"status"`
|
||||
Version string `xml:"version,attr" json:"version"`
|
||||
Error *Error `xml:",omitempty" json:"error,omitempty"`
|
||||
Error *Error `xml:"error,omitempty" json:"error,omitempty"`
|
||||
License *License `xml:"license,omitempty" json:"license,omitempty"`
|
||||
MusicFolders *MusicFolders `xml:"musicFolders,omitempty" json:"musicFolders,omitempty"`
|
||||
Indexes *Indexes `xml:"indexes,omitempty" json:"indexes,omitempty"`
|
||||
@ -18,8 +18,8 @@ type JsonWrapper struct {
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
Code int `xml:"code,attr"`
|
||||
Message string `xml:"message,attr"`
|
||||
Code int `xml:"code,attr" json:"code"`
|
||||
Message string `xml:"message,attr" json:"message"`
|
||||
}
|
||||
|
||||
type License struct {
|
||||
|
@ -1,9 +1,10 @@
|
||||
package responses
|
||||
package responses_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
. "github.com/deluan/gosonic/tests"
|
||||
. "github.com/deluan/gosonic/api/responses"
|
||||
)
|
||||
|
||||
func TestSubsonicResponses(t *testing.T) {
|
||||
|
@ -10,4 +10,5 @@ func init() {
|
||||
utils.DefineSingleton(new(domain.ArtistIndexRepository), persistence.NewArtistIndexRepository)
|
||||
utils.DefineSingleton(new(domain.PropertyRepository), persistence.NewPropertyRepository)
|
||||
utils.DefineSingleton(new(domain.MediaFolderRepository), persistence.NewMediaFolderRepository)
|
||||
utils.DefineSingleton(new(domain.ArtistRepository), persistence.NewArtistRepository)
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ func mapEndpoints() {
|
||||
beego.NSRouter("/getLicense.view", &api.GetLicenseController{}, "*:Get"),
|
||||
beego.NSRouter("/getMusicFolders.view", &api.GetMusicFoldersController{}, "*:Get"),
|
||||
beego.NSRouter("/getIndexes.view", &api.GetIndexesController{}, "*:Get"),
|
||||
beego.NSRouter("/getMusicDirectory.view", &api.GetMusicDirectoryController{}, "*:Get"),
|
||||
)
|
||||
beego.AddNamespace(ns)
|
||||
|
||||
|
@ -3,4 +3,5 @@ package domain
|
||||
type BaseRepository interface {
|
||||
NewId(fields ...string) string
|
||||
CountAll() (int, error)
|
||||
Exists(id string) (bool, error)
|
||||
}
|
||||
|
@ -39,6 +39,11 @@ func (r *baseRepository) CountAll() (int, error) {
|
||||
return len(ids), err
|
||||
}
|
||||
|
||||
func (r *baseRepository) Exists(id string) (bool, error) {
|
||||
res, err := db().SIsMember([]byte(r.table + "s:all"), []byte(id))
|
||||
return res != 0, err
|
||||
}
|
||||
|
||||
func (r *baseRepository) saveOrUpdate(id string, entity interface{}) error {
|
||||
recordPrefix := fmt.Sprintf("%s:%s:", r.table, id)
|
||||
allKey := r.table + "s:all"
|
||||
|
@ -7,17 +7,17 @@ import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
type artistIndex struct {
|
||||
type artistIndexRepository struct {
|
||||
baseRepository
|
||||
}
|
||||
|
||||
func NewArtistIndexRepository() domain.ArtistIndexRepository {
|
||||
r := &artistIndex{}
|
||||
r := &artistIndexRepository{}
|
||||
r.init("index", &domain.ArtistIndex{})
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *artistIndex) Put(m *domain.ArtistIndex) error {
|
||||
func (r *artistIndexRepository) Put(m *domain.ArtistIndex) error {
|
||||
if m.Id == "" {
|
||||
return errors.New("Id is not set")
|
||||
}
|
||||
@ -25,13 +25,13 @@ func (r *artistIndex) Put(m *domain.ArtistIndex) error {
|
||||
return r.saveOrUpdate(m.Id, m)
|
||||
}
|
||||
|
||||
func (r *artistIndex) Get(id string) (*domain.ArtistIndex, error) {
|
||||
func (r *artistIndexRepository) Get(id string) (*domain.ArtistIndex, error) {
|
||||
var rec interface{}
|
||||
rec, err := r.readEntity(id)
|
||||
return rec.(*domain.ArtistIndex), err
|
||||
}
|
||||
|
||||
func (r *artistIndex) GetAll() ([]domain.ArtistIndex, error) {
|
||||
func (r *artistIndexRepository) GetAll() ([]domain.ArtistIndex, error) {
|
||||
var indices = make([]domain.ArtistIndex, 0)
|
||||
err := r.loadAll(&indices, "")
|
||||
return indices, err
|
||||
|
@ -23,6 +23,17 @@ func TestIndexRepository(t *testing.T) {
|
||||
|
||||
So(s, shouldBeEqual, i)
|
||||
})
|
||||
Convey("It should be able to check for existance of an Id", func() {
|
||||
i := &domain.ArtistIndex{Id: "123"}
|
||||
|
||||
repo.Put(i)
|
||||
|
||||
s, _ := repo.Exists("123")
|
||||
So(s, ShouldBeTrue)
|
||||
|
||||
s, _ = repo.Exists("NOT_FOUND")
|
||||
So(s, ShouldBeFalse)
|
||||
})
|
||||
Convey("Method Put() should return error if Id is not set", func() {
|
||||
i := &domain.ArtistIndex{}
|
||||
|
||||
|
@ -5,6 +5,8 @@ import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"github.com/deluan/gosonic/api/responses"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
func ShouldMatchXML(actual interface{}, expected ...interface{}) string {
|
||||
@ -25,6 +27,17 @@ func ShouldMatchJSON(actual interface{}, expected ...interface{}) string {
|
||||
return ShouldEqual(s, expected[0].(string))
|
||||
}
|
||||
|
||||
func ShouldReceiveError(actual interface{}, expected ...interface{}) string {
|
||||
v := responses.Subsonic{}
|
||||
err := xml.Unmarshal(actual.(*bytes.Buffer).Bytes(), &v)
|
||||
if err != nil {
|
||||
return fmt.Sprintf("Malformed XML: %v", err)
|
||||
}
|
||||
|
||||
return ShouldEqual(v.Error.Code, expected[0].(int))
|
||||
|
||||
}
|
||||
|
||||
func UnindentJSON(j []byte) string {
|
||||
var m = make(map[string]interface{})
|
||||
json.Unmarshal(j, &m)
|
38
tests/mocks/mock_artist_repo.go
Normal file
38
tests/mocks/mock_artist_repo.go
Normal file
@ -0,0 +1,38 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/deluan/gosonic/domain"
|
||||
"errors"
|
||||
)
|
||||
|
||||
func CreateMockArtistRepo() *MockArtist {
|
||||
return &MockArtist{}
|
||||
}
|
||||
|
||||
type MockArtist struct {
|
||||
domain.ArtistRepository
|
||||
data map[string]domain.Artist
|
||||
err bool
|
||||
}
|
||||
|
||||
func (m *MockArtist) SetError(err bool) {
|
||||
m.err = err
|
||||
}
|
||||
|
||||
func (m *MockArtist) SetData(j string) {
|
||||
m.data = make(map[string]domain.Artist)
|
||||
err := json.Unmarshal([]byte(j), &m.data)
|
||||
if err != nil {
|
||||
fmt.Println("ERROR: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MockArtist) Exists(id string) (bool, error) {
|
||||
if m.err {
|
||||
return false, errors.New("Error!")
|
||||
}
|
||||
_, found := m.data[id];
|
||||
return found, nil
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user