Subsonic: sharing (getShares, createShare, updateShare, deleteShare) plus real public share web pages and stream route
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
package subsonic
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestShareLifecycle(t *testing.T) {
|
||||
s, srv := newTestRecorderServer(t)
|
||||
createTestUser(t, s, "alice", "password123", false)
|
||||
seedLibrary(t, s)
|
||||
song := firstSong(t, s)
|
||||
|
||||
q := baseParams("alice", "password123")
|
||||
q.Add("id", song.ID)
|
||||
q.Set("description", "Check this out")
|
||||
q.Set("f", "json")
|
||||
resp := getPath(t, srv.URL, "/rest/createShare.view", q)
|
||||
j := decodeJSON(t, resp)
|
||||
shares := j["shares"].(map[string]any)["share"].([]any)
|
||||
if len(shares) != 1 {
|
||||
t.Fatalf("createShare shares = %v, want 1", shares)
|
||||
}
|
||||
share := shares[0].(map[string]any)
|
||||
if share["url"] == nil || share["url"] == "" {
|
||||
t.Fatalf("share missing url: %v", share)
|
||||
}
|
||||
shareID := share["id"].(string)
|
||||
entries, ok := share["entry"].([]any)
|
||||
if !ok || len(entries) != 1 {
|
||||
t.Fatalf("share entries = %v, want 1", share["entry"])
|
||||
}
|
||||
|
||||
q2 := baseParams("alice", "password123")
|
||||
q2.Set("f", "json")
|
||||
resp = getPath(t, srv.URL, "/rest/getShares.view", q2)
|
||||
j = decodeJSON(t, resp)
|
||||
shares = j["shares"].(map[string]any)["share"].([]any)
|
||||
if len(shares) != 1 {
|
||||
t.Fatalf("getShares = %v, want 1", shares)
|
||||
}
|
||||
|
||||
q3 := baseParams("alice", "password123")
|
||||
q3.Set("id", shareID)
|
||||
q3.Set("description", "Updated description")
|
||||
resp = getPath(t, srv.URL, "/rest/updateShare.view", q3)
|
||||
x := decodeXML(t, resp)
|
||||
if x.Status != "ok" {
|
||||
t.Fatalf("updateShare failed: %+v", x)
|
||||
}
|
||||
|
||||
q4 := baseParams("alice", "password123")
|
||||
q4.Set("id", shareID)
|
||||
resp = getPath(t, srv.URL, "/rest/deleteShare.view", q4)
|
||||
x = decodeXML(t, resp)
|
||||
if x.Status != "ok" {
|
||||
t.Fatalf("deleteShare failed: %+v", x)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShareOtherUserCannotModify(t *testing.T) {
|
||||
s, _ := newTestServer(t)
|
||||
createTestUser(t, s, "owner", "password123", false)
|
||||
createTestUser(t, s, "other", "password123", false)
|
||||
seedLibrary(t, s)
|
||||
srv := httptest.NewServer(s.Router())
|
||||
defer srv.Close()
|
||||
|
||||
q := baseParams("owner", "password123")
|
||||
q.Add("id", firstSong(t, s).ID)
|
||||
q.Set("f", "json")
|
||||
resp := getPath(t, srv.URL, "/rest/createShare.view", q)
|
||||
j := decodeJSON(t, resp)
|
||||
shares := j["shares"].(map[string]any)["share"].([]any)
|
||||
shareID := shares[0].(map[string]any)["id"].(string)
|
||||
|
||||
q2 := baseParams("other", "password123")
|
||||
q2.Set("id", shareID)
|
||||
resp = getPath(t, srv.URL, "/rest/deleteShare.view", q2)
|
||||
x := decodeXML(t, resp)
|
||||
if x.Status != "failed" || x.Error == nil || x.Error.Code != ErrUnauthorized {
|
||||
t.Fatalf("expected error 50 deleting another user's share, got %+v", x)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateShareMissingID(t *testing.T) {
|
||||
s, srv := newTestRecorderServer(t)
|
||||
createTestUser(t, s, "alice", "password123", false)
|
||||
|
||||
resp := getPath(t, srv.URL, "/rest/createShare.view", baseParams("alice", "password123"))
|
||||
x := decodeXML(t, resp)
|
||||
if x.Status != "failed" || x.Error == nil || x.Error.Code != ErrMissingParameter {
|
||||
t.Fatalf("expected error 10, got %+v", x)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user