Files

133 lines
4.8 KiB
Go
Raw Permalink Normal View History

package handlers
import (
"context"
"fmt"
"testing"
"github.com/Silo-Server/silo-server/internal/models"
)
type fakeItemLookup struct {
items map[string]*models.MediaItem
}
func (f *fakeItemLookup) GetByID(_ context.Context, contentID string) (*models.MediaItem, error) {
if item, ok := f.items[contentID]; ok {
return item, nil
}
return nil, fmt.Errorf("item %s not found", contentID)
}
func splitTestHandler(items map[string]*models.MediaItem) *AdminSplitHandler {
return &AdminSplitHandler{items: &fakeItemLookup{items: items}}
}
func TestResolveSplitTarget_ProviderIDsDeriveDeterministicID(t *testing.T) {
t.Parallel()
source := &models.MediaItem{ContentID: "movie-tmdb-100", Type: "movie", Title: "The Grudge", Year: 2004}
h := splitTestHandler(map[string]*models.MediaItem{source.ContentID: source})
moved := []splitFile{{ID: 1, MediaFolderID: 3, FilePath: "/m/a.mkv", ObservedRootPath: "/m"}}
target, err := h.resolveSplitTarget(context.Background(), source, moved, splitTargetRequest{
ProviderIDs: map[string]string{"TMDB": " 11838 "},
})
if err != nil {
t.Fatalf("resolveSplitTarget: %v", err)
}
if target.contentID != "movie-tmdb-11838" {
t.Fatalf("contentID = %q, want movie-tmdb-11838", target.contentID)
}
if !target.created {
t.Fatal("expected target.created for unknown derived id")
}
if target.providerIDs["tmdb"] != "11838" {
t.Fatalf("providerIDs = %v, want normalized tmdb 11838", target.providerIDs)
}
// Falls back to the source title for the skeleton row.
if target.title != source.Title {
t.Fatalf("title = %q, want %q", target.title, source.Title)
}
}
func TestResolveSplitTarget_ExistingContentIDAdoptsProviderIDs(t *testing.T) {
t.Parallel()
source := &models.MediaItem{ContentID: "movie-tmdb-100", Type: "movie", Title: "Crash"}
existing := &models.MediaItem{ContentID: "movie-tmdb-10723", Type: "movie", Title: "Crash (1996)", TmdbID: "10723"}
h := splitTestHandler(map[string]*models.MediaItem{
source.ContentID: source,
existing.ContentID: existing,
})
moved := []splitFile{{ID: 1, MediaFolderID: 3, FilePath: "/m/a.mkv", ObservedRootPath: "/m"}}
target, err := h.resolveSplitTarget(context.Background(), source, moved, splitTargetRequest{
ContentID: existing.ContentID,
})
if err != nil {
t.Fatalf("resolveSplitTarget: %v", err)
}
if target.created {
t.Fatal("existing target must not be flagged created")
}
if target.providerIDs["tmdb"] != "10723" {
t.Fatalf("providerIDs = %v, want target's tmdb id for override persistence", target.providerIDs)
}
}
func TestResolveSplitTarget_Rejections(t *testing.T) {
t.Parallel()
source := &models.MediaItem{ContentID: "movie-tmdb-100", Type: "movie", Title: "A"}
series := &models.MediaItem{ContentID: "series-tvdb-5", Type: "series", Title: "B"}
h := splitTestHandler(map[string]*models.MediaItem{
source.ContentID: source,
series.ContentID: series,
})
moved := []splitFile{{ID: 1, MediaFolderID: 3, FilePath: "/m/a.mkv", ObservedRootPath: "/m"}}
cases := []struct {
name string
req splitTargetRequest
}{
{"no target", splitTargetRequest{}},
{"type mismatch", splitTargetRequest{ContentID: series.ContentID}},
{"unknown content id", splitTargetRequest{ContentID: "movie-tmdb-404"}},
{"target equals source", splitTargetRequest{ContentID: source.ContentID}},
{"unusable provider ids", splitTargetRequest{ProviderIDs: map[string]string{"anidb": "1"}}},
}
for _, tc := range cases {
if _, err := h.resolveSplitTarget(context.Background(), source, moved, tc.req); err == nil {
t.Errorf("%s: expected error", tc.name)
}
}
}
func TestDeriveEpisodePairs(t *testing.T) {
t.Parallel()
series := &models.MediaItem{ContentID: "series-tvdb-100", Type: "series"}
moved := []splitFile{
{ID: 1, EpisodeID: "episode-tvdb-100-1-1", SeasonNumber: 1, EpisodeNumber: 1},
{ID: 2, EpisodeID: "episode-tvdb-100-1-2", SeasonNumber: 1, EpisodeNumber: 2},
{ID: 3, EpisodeID: "episode-tvdb-100-1-2", SeasonNumber: 1, EpisodeNumber: 2}, // dup version
{ID: 4, EpisodeID: "", SeasonNumber: 1, EpisodeNumber: 3}, // never linked
{ID: 5, EpisodeID: "episode-tvdb-100-0-0", SeasonNumber: 0, EpisodeNumber: 0}, // unparsed
}
pairs := deriveEpisodePairs(series, moved, "series-tvdb-200")
if len(pairs) != 2 {
t.Fatalf("pairs = %v, want 2", pairs)
}
if pairs[0].To != "episode-tvdb-200-1-1" || pairs[1].To != "episode-tvdb-200-1-2" {
t.Fatalf("pair targets = %v, want re-anchored deterministic ids", pairs)
}
// Local target: no deterministic anchor, no pairs.
if got := deriveEpisodePairs(series, moved, "local-abcdef"); got != nil {
t.Fatalf("local target pairs = %v, want nil", got)
}
// Movies never pair.
movie := &models.MediaItem{ContentID: "movie-tmdb-1", Type: "movie"}
if got := deriveEpisodePairs(movie, moved, "movie-tmdb-2"); got != nil {
t.Fatalf("movie pairs = %v, want nil", got)
}
}