Files
silo-server/internal/sections/resolver_test.go

229 lines
7.2 KiB
Go

package sections
import (
"encoding/json"
"testing"
)
func TestResolve_NoOverrides(t *testing.T) {
admin := []*PageSection{
{ID: "1", Position: 0, SectionType: SectionRecentlyAdded, Title: "Recently Added", ItemLimit: 20, Config: json.RawMessage(`{}`)},
{ID: "2", Position: 1, SectionType: SectionFavorites, Title: "Favorites", ItemLimit: 10, Config: json.RawMessage(`{}`)},
}
result := Resolve(admin, nil)
if len(result) != 2 {
t.Fatalf("expected 2 sections, got %d", len(result))
}
if result[0].Title != "Recently Added" {
t.Errorf("first section title = %q", result[0].Title)
}
}
func TestResolve_HiddenOverride(t *testing.T) {
admin := []*PageSection{
{ID: "1", Position: 0, SectionType: SectionRecentlyAdded, Title: "Recently Added", ItemLimit: 20, Config: json.RawMessage(`{}`)},
{ID: "2", Position: 1, SectionType: SectionFavorites, Title: "Favorites", ItemLimit: 10, Config: json.RawMessage(`{}`)},
}
overrides := []ProfileSectionOverride{
{SectionID: "1", Hidden: true},
}
result := Resolve(admin, overrides)
if len(result) != 1 {
t.Fatalf("expected 1 section (1 hidden), got %d", len(result))
}
if result[0].ID != "2" {
t.Errorf("remaining section ID = %q, want %q", result[0].ID, "2")
}
}
func TestResolve_RemovedOverrideSkipsAdminSection(t *testing.T) {
admin := []*PageSection{
{ID: "1", Position: 0, SectionType: SectionRecentlyAdded, Title: "Recently Added", ItemLimit: 20, Config: json.RawMessage(`{}`)},
{ID: "2", Position: 1, SectionType: SectionFavorites, Title: "Favorites", ItemLimit: 10, Config: json.RawMessage(`{}`)},
}
overrides := []ProfileSectionOverride{
{SectionID: "1", Removed: true},
}
result := Resolve(admin, overrides)
if len(result) != 1 || result[0].ID != "2" {
t.Fatalf("resolved IDs = %#v, want only section 2", result)
}
}
func TestResolve_PositionOverride(t *testing.T) {
admin := []*PageSection{
{ID: "1", Position: 0, SectionType: SectionRecentlyAdded, Title: "A", ItemLimit: 20, Config: json.RawMessage(`{}`)},
{ID: "2", Position: 1, SectionType: SectionFavorites, Title: "B", ItemLimit: 10, Config: json.RawMessage(`{}`)},
}
posB := 0
posA := 1
overrides := []ProfileSectionOverride{
{SectionID: "2", Position: &posB}, // Move B to position 0
{SectionID: "1", Position: &posA}, // Move A to position 1
}
result := Resolve(admin, overrides)
if result[0].ID != "2" {
t.Errorf("first section should be B (id=2), got id=%s", result[0].ID)
}
if result[1].ID != "1" {
t.Errorf("second section should be A (id=1), got id=%s", result[1].ID)
}
}
func TestResolve_UserAddedSection(t *testing.T) {
admin := []*PageSection{
{ID: "1", Position: 0, SectionType: SectionRecentlyAdded, Title: "A", ItemLimit: 20, Config: json.RawMessage(`{}`)},
}
pos := 1
overrides := []ProfileSectionOverride{
{ID: "custom-1", SectionID: "", SectionType: "genre", Title: "My Action", Position: &pos, ItemLimit: new(15), Config: json.RawMessage(`{"genres":["Action"]}`)},
}
result := Resolve(admin, overrides)
if len(result) != 2 {
t.Fatalf("expected 2 sections, got %d", len(result))
}
if result[1].Title != "My Action" {
t.Errorf("second section title = %q, want %q", result[1].Title, "My Action")
}
if !result[1].IsCustom {
t.Error("user-added section should be marked IsCustom")
}
}
func TestResolve_RemovedCustomSection(t *testing.T) {
admin := []*PageSection{
{ID: "1", Position: 0, SectionType: SectionRecentlyAdded, Title: "A", ItemLimit: 20, Config: json.RawMessage(`{}`)},
}
overrides := []ProfileSectionOverride{
{ID: "custom-1", SectionType: "genre", Title: "My Action", Removed: true},
}
result := Resolve(admin, overrides)
if len(result) != 1 {
t.Fatalf("expected removed custom section to be skipped, got %d sections", len(result))
}
if result[0].ID != "1" {
t.Fatalf("remaining section ID = %q, want %q", result[0].ID, "1")
}
}
func TestResolveForSettings_IncludesHidden(t *testing.T) {
admin := []*PageSection{
{ID: "1", Position: 0, SectionType: SectionRecentlyAdded, Title: "Recently Added", ItemLimit: 20, Config: json.RawMessage(`{}`)},
{ID: "2", Position: 1, SectionType: SectionFavorites, Title: "Favorites", ItemLimit: 10, Config: json.RawMessage(`{}`)},
}
overrides := []ProfileSectionOverride{
{SectionID: "1", Hidden: true},
}
result := ResolveForSettings(admin, overrides)
if len(result) != 2 {
t.Fatalf("expected 2 sections (including hidden), got %d", len(result))
}
if !result[0].Hidden {
t.Error("section 1 should be marked Hidden")
}
if result[0].Customized != true {
t.Error("hidden section should be marked Customized")
}
if result[1].Hidden {
t.Error("section 2 should not be hidden")
}
}
func TestResolveForSettings_SkipsRemovedSection(t *testing.T) {
admin := []*PageSection{
{ID: "1", Position: 0, SectionType: SectionRecentlyAdded, Title: "Recently Added", ItemLimit: 20, Config: json.RawMessage(`{}`)},
}
overrides := []ProfileSectionOverride{
{SectionID: "1", Removed: true},
}
result := ResolveForSettings(admin, overrides)
if len(result) != 0 {
t.Fatalf("expected removed section to be omitted from settings, got %d entries", len(result))
}
}
func TestResolveForSettings_SkipsRemovedCustomSection(t *testing.T) {
admin := []*PageSection{
{ID: "1", Position: 0, SectionType: SectionRecentlyAdded, Title: "Recently Added", ItemLimit: 20, Config: json.RawMessage(`{}`)},
}
overrides := []ProfileSectionOverride{
{ID: "custom-1", SectionType: "genre", Title: "My Action", Removed: true},
}
result := ResolveForSettings(admin, overrides)
if len(result) != 1 {
t.Fatalf("expected removed custom section to be omitted from settings, got %d entries", len(result))
}
if result[0].ID != "1" {
t.Fatalf("remaining section ID = %q, want %q", result[0].ID, "1")
}
}
func TestResolveIncludesUserAddedRecipeFromOverride(t *testing.T) {
admin := []*PageSection{}
overrides := []ProfileSectionOverride{
{
ID: "u1",
ProfileID: "p1",
Scope: "home",
SectionID: "",
IsUserAdded: true,
UserSectionType: "hidden_gems",
UserConfig: json.RawMessage(`{"min_rating":7.5}`),
UserTitle: "Hidden Gems",
},
}
resolved := Resolve(admin, overrides)
if len(resolved) != 1 {
t.Fatalf("got %d sections", len(resolved))
}
if resolved[0].SectionType != "hidden_gems" {
t.Errorf("section_type = %s want hidden_gems", resolved[0].SectionType)
}
if resolved[0].Title != "Hidden Gems" {
t.Errorf("title = %s want Hidden Gems", resolved[0].Title)
}
if string(resolved[0].Config) != `{"min_rating":7.5}` {
t.Errorf("config = %s want {\"min_rating\":7.5}", resolved[0].Config)
}
if !resolved[0].IsCustom {
t.Error("expected IsCustom true")
}
}
func TestResolveBackwardCompatLegacyUserAdded(t *testing.T) {
// An override with the OLD shape (no IsUserAdded flag, but SectionID empty)
// should still resolve correctly using the legacy fields.
admin := []*PageSection{}
overrides := []ProfileSectionOverride{
{
ID: "u2",
ProfileID: "p1",
Scope: "home",
SectionID: "",
SectionType: "recently_added",
Title: "My recents",
},
}
resolved := Resolve(admin, overrides)
if len(resolved) != 1 || resolved[0].SectionType != "recently_added" || resolved[0].Title != "My recents" {
t.Fatalf("legacy user-added not resolved correctly: %+v", resolved)
}
}