arnaucube
arnaucube/jellyfin-toolsPublic Self-hosted repository
jellyfin-tools/jellyfin-year-review/internal/generate/platforms_test.go
jellyfin-year-review/internal/generate/platforms_test.goRaw
 1package generate
 2
 3import (
 4	"reflect"
 5	"testing"
 6
 7	"reelreview/internal/model"
 8)
 9
10func TestPlatformsCountDistinctEligibleTitles(t *testing.T) {
11	s := fixture()
12	s.Users = append(s.Users, model.User{ID: bob, Name: "Bob"})
13	s.Items[0].Studios = []string{"Netflix", "NETFLIX", "Unrelated studio"}
14	s.Items = append(s.Items,
15		model.Item{ID: "series", Title: "Show", Type: "Series", Studios: []string{"HBO Max", "HBO"}},
16		model.Item{ID: "e1", Type: "Episode", SeriesID: "series"},
17		model.Item{ID: "e2", Type: "Episode", SeriesID: "series"},
18		model.Item{ID: "apple", Type: "Movie", Studios: []string{"Apple Original Films"}},
19		model.Item{ID: "unknown", Type: "Movie", Studios: []string{"Warner Bros. Pictures"}},
20		model.Item{ID: "shared", Type: "Movie", Platforms: []string{" Netflix ", "netflix", "AppleTV", "Apple TV+"}},
21		model.Item{ID: "excluded", Type: "Movie", Platforms: []string{"Hulu"}},
22	)
23	for i, item := range []string{"film", "film", "e1", "e2", "e1", "apple", "unknown", "shared", "excluded"} {
24		p := play(item+string(rune('a'+i)), "2025-03-01T12:00:00Z", "2025-03-01T13:00:00Z")
25		p.ItemID = item
26		if item == "excluded" {
27			p.UserID = bob
28		}
29		s.Playback = append(s.Playback, p)
30	}
31	outside := play("outside", "2024-03-01T12:00:00Z", "2024-03-01T13:00:00Z")
32	outside.ItemID = "excluded"
33	short := play("short", "2025-03-01T12:00:00Z", "2025-03-01T12:00:30Z")
34	short.ItemID = "excluded"
35	s.Playback = append(s.Playback, outside, short)
36	want := []model.Platform{{Name: "Apple TV+", Movies: 2}, {Name: "Netflix", Movies: 2}, {Name: "HBO", Shows: 1}, {Name: "Other", Movies: 1}}
37	if got := compute(t, s, DefaultConfig(2025))[0].Platforms; !reflect.DeepEqual(got, want) {
38		t.Fatalf("platforms = %+v, want %+v", got, want)
39	}
40}
41
42func TestPlatformMetadataAndEmptyHistory(t *testing.T) {
43	for _, tc := range []struct {
44		name string
45		item model.Item
46		want []string
47	}{
48		{"explicit overrides studios", model.Item{Platforms: []string{" Custom Service ", "custom service"}, Studios: []string{"Netflix"}}, []string{"Custom Service"}},
49		{"blank explicit uses studios", model.Item{Platforms: []string{" "}, Studios: []string{"amazon prime video"}}, []string{"Prime Video"}},
50		{"missing metadata", model.Item{}, []string{}},
51		{"no guessed Disney availability", model.Item{Studios: []string{"Walt Disney Pictures"}}, []string{}},
52	} {
53		t.Run(tc.name, func(t *testing.T) {
54			if got := itemPlatforms(tc.item); !reflect.DeepEqual(got, tc.want) {
55				t.Fatalf("platforms = %v, want %v", got, tc.want)
56			}
57		})
58	}
59	if got := compute(t, fixture(), DefaultConfig(2025))[0].Platforms; len(got) != 0 {
60		t.Fatalf("empty history produced counts: %+v", got)
61	}
62}
63
64// Other stays last even when most watched titles lack platform metadata.
65func TestPlatformsKeepOtherLast(t *testing.T) {
66	movies := []model.Content{{ID: "a"}, {ID: "b"}, {ID: "c"}, {ID: "netflix"}}
67	items := map[string]model.Item{"netflix": {Studios: []string{"Netflix"}}}
68	want := []model.Platform{{Name: "Netflix", Movies: 1}, {Name: "Other", Movies: 3}}
69	if got := platforms(movies, nil, items); !reflect.DeepEqual(got, want) {
70		t.Fatalf("platforms = %+v, want %+v", got, want)
71	}
72}