test(subsonic): envelope JSON/XML/JSONP + WriteFail

This commit is contained in:
2026-04-19 17:39:03 +00:00
parent da2bb672f0
commit 1885d197d6
+101
View File
@@ -0,0 +1,101 @@
package subsonic
import (
"encoding/json"
"encoding/xml"
"io"
"net/http/httptest"
"strings"
"testing"
)
func TestWriteJSONEnvelope(t *testing.T) {
rec := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/rest/ping.view", nil)
Write(rec, req, PingResponse{Envelope: NewEnvelope("ok")})
if ct := rec.Header().Get("Content-Type"); !strings.HasPrefix(ct, "application/json") {
t.Errorf("content-type = %q", ct)
}
var payload map[string]map[string]any
if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
t.Fatalf("unmarshal: %v — body=%s", err, rec.Body)
}
inner, ok := payload["subsonic-response"]
if !ok {
t.Fatalf("missing subsonic-response key: %s", rec.Body)
}
if inner["status"] != "ok" || inner["version"] != APIVersion || inner["type"] != ServerType {
t.Errorf("envelope fields = %+v", inner)
}
if inner["openSubsonic"] != true {
t.Errorf("openSubsonic flag missing: %+v", inner)
}
}
func TestWriteXMLEnvelope(t *testing.T) {
rec := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/rest/getLicense.view?f=xml", nil)
Write(rec, req, LicenseResponse{
Envelope: NewEnvelope("ok"),
License: License{Valid: true},
})
if ct := rec.Header().Get("Content-Type"); !strings.HasPrefix(ct, "application/xml") {
t.Errorf("content-type = %q", ct)
}
body, _ := io.ReadAll(rec.Body)
var decoded struct {
XMLName xml.Name `xml:"subsonic-response"`
Status string `xml:"status,attr"`
Version string `xml:"version,attr"`
License struct {
Valid bool `xml:"valid,attr"`
} `xml:"license"`
}
if err := xml.Unmarshal(body, &decoded); err != nil {
t.Fatalf("xml decode: %v — body=%s", err, body)
}
if decoded.Status != "ok" || decoded.Version != APIVersion {
t.Errorf("envelope attrs = %+v", decoded)
}
if !decoded.License.Valid {
t.Errorf("license.valid attr not parsed: %+v", decoded)
}
}
func TestWriteFailEnvelopeJSON(t *testing.T) {
rec := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/rest/ping.view", nil)
WriteFail(rec, req, ErrWrongCredentials, "nope")
var payload map[string]map[string]any
if err := json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
t.Fatalf("unmarshal: %v", err)
}
inner := payload["subsonic-response"]
if inner["status"] != "failed" {
t.Errorf("status = %v, want failed", inner["status"])
}
errMap, ok := inner["error"].(map[string]any)
if !ok {
t.Fatalf("error field missing/not object: %+v", inner)
}
if int(errMap["code"].(float64)) != ErrWrongCredentials {
t.Errorf("error.code = %v, want %d", errMap["code"], ErrWrongCredentials)
}
if errMap["message"] != "nope" {
t.Errorf("error.message = %v", errMap["message"])
}
}
func TestWriteJSONPWrapsCallback(t *testing.T) {
rec := httptest.NewRecorder()
req := httptest.NewRequest("GET", "/rest/ping.view?f=jsonp&callback=cb", nil)
Write(rec, req, PingResponse{Envelope: NewEnvelope("ok")})
body := rec.Body.String()
if !strings.HasPrefix(body, "cb(") || !strings.HasSuffix(strings.TrimSpace(body), ")") {
t.Errorf("jsonp wrapper missing: %q", body)
}
}