App v0.2.27 and gateway 0.1.23
Skip Intro from Emby's own chapter markers, trickplay seek previews from BIF files, a server-composed home hero ranked on Radarr/Sonarr dates and review scores, and My Alerts as its own page behind the user picker. Related titles now degrade at every step instead of returning empty, and the "+" is back on Manage users so a second viewer can be added from the launcher. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4a4df7a73c
commit
80c304d86b
@@ -0,0 +1,78 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/ponzischeme89/memby/server/internal/store"
|
||||
)
|
||||
|
||||
// The television decodes this into GatewayTrickplay; the matching Kotlin test is
|
||||
// `decodes a seek preview layout` in GatewayPayloadTest. Rename a field on either side and
|
||||
// one of them fails before a TV ever sees it.
|
||||
func TestTrickplayManifestShape(t *testing.T) {
|
||||
raw, err := json.Marshal(trickplayManifest{
|
||||
Available: true, IntervalMs: 10_000, Count: 817, Width: 320, Height: 172,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
want := `{"available":true,"intervalMs":10000,"count":817,"width":320,"height":172}`
|
||||
if string(raw) != want {
|
||||
t.Fatalf("manifest = %s, want %s", raw, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrickplayManifestOmitsTheRestWhenUnavailable(t *testing.T) {
|
||||
// A title with no thumbnails, an operator who has turned the feature off and a gateway
|
||||
// with no Emby all mean the same thing to a television, so they must all look the same
|
||||
// on the wire — and none of them may carry a count it would try to draw from.
|
||||
raw, err := json.Marshal(trickplayManifest{})
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
if string(raw) != `{"available":false}` {
|
||||
t.Fatalf("manifest = %s", raw)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrickplayAnswersUnavailableRatherThanFailing(t *testing.T) {
|
||||
// A gateway with no Emby configured still answers, with 200 and "no previews". The
|
||||
// seek indicator is a complete answer without a thumbnail, and an error here would be
|
||||
// one nobody could act on, logged once per press of Right.
|
||||
s := &Server{}
|
||||
req := httptest.NewRequest(http.MethodGet, "/v1/items/42/trickplay", nil)
|
||||
req.SetPathValue("id", "42")
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
s.handleTrickplay(rec, req, store.Session{EmbyUserID: "user-1"})
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200", rec.Code)
|
||||
}
|
||||
var manifest trickplayManifest
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &manifest); err != nil {
|
||||
t.Fatalf("unmarshal: %v", err)
|
||||
}
|
||||
if manifest.Available {
|
||||
t.Fatal("a gateway with no Emby offered seek previews")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrickplayFrameRejectsAnUnreadableIndex(t *testing.T) {
|
||||
s := &Server{}
|
||||
for _, frame := range []string{"", "-1", "twelve", "12.png.jpg"} {
|
||||
req := httptest.NewRequest(http.MethodGet, "/v1/items/42/trickplay/"+frame, nil)
|
||||
req.SetPathValue("id", "42")
|
||||
req.SetPathValue("frame", frame)
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
s.handleTrickplayFrame(rec, req, store.Session{EmbyUserID: "user-1"})
|
||||
|
||||
if rec.Code != http.StatusNotFound {
|
||||
t.Fatalf("frame %q: status = %d, want 404", frame, rec.Code)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user