From eb6bb3bbd4076197c4d8985c8afab6b33655c3f2 Mon Sep 17 00:00:00 2001 From: mkelvers Date: Sun, 17 May 2026 21:16:39 +0200 Subject: [PATCH] feat: add episode service merge and broadcast tests --- internal/episodes/service/service_test.go | 69 +++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 internal/episodes/service/service_test.go diff --git a/internal/episodes/service/service_test.go b/internal/episodes/service/service_test.go new file mode 100644 index 0000000..986ccf4 --- /dev/null +++ b/internal/episodes/service/service_test.go @@ -0,0 +1,69 @@ +package service + +import ( + "mal/integrations/jikan" + "mal/internal/domain" + "testing" + "time" +) + +func TestMergeEpisodesUsesUnionAndSynthesizesProviderOnlyEntries(t *testing.T) { + episodes := mergeEpisodes([]jikan.Episode{ + {MalID: 1, Title: "Start"}, + {MalID: 2, Title: "Second", Filler: true}, + {MalID: 5, Title: "Future", Recap: true}, + }, domain.EpisodeAvailability{ + Sub: []int{1, 2, 3, 6}, + Dub: []int{1, 2, 3}, + }) + + if len(episodes) != 5 { + t.Fatalf("len(episodes) = %d, want 5", len(episodes)) + } + + assertEpisode(t, episodes[0], 1, "Start", true, true, false, false, false) + assertEpisode(t, episodes[1], 2, "Second", true, true, false, true, false) + assertEpisode(t, episodes[2], 3, "Episode 3", true, true, false, false, false) + assertEpisode(t, episodes[3], 5, "Future", false, false, false, false, true) + assertEpisode(t, episodes[4], 6, "Episode 6", true, false, true, false, false) +} + +func TestNextBroadcastAfterUsesJikanTimezone(t *testing.T) { + anime := domain.Anime{MalID: 1} + anime.Broadcast.Day = "Saturdays" + anime.Broadcast.Time = "23:00" + anime.Broadcast.Timezone = "Asia/Tokyo" + + after := time.Date(2026, 5, 15, 12, 0, 0, 0, time.UTC) + got := nextBroadcastAfter(anime, after) + want := time.Date(2026, 5, 16, 14, 0, 0, 0, time.UTC) + + if !got.Equal(want) { + t.Fatalf("nextBroadcastAfter() = %s, want %s", got, want) + } +} + +func TestNextRetryTimeWithinAndAfterRetryWindow(t *testing.T) { + anime := domain.Anime{MalID: 1} + anime.Broadcast.Day = "Saturdays" + anime.Broadcast.Time = "12:00" + anime.Broadcast.Timezone = "UTC" + + within := time.Date(2026, 5, 16, 13, 0, 0, 0, time.UTC) + if got := nextRetryTime(anime, within); !got.Equal(within.Add(retryInterval)) { + t.Fatalf("nextRetryTime(within) = %s, want %s", got, within.Add(retryInterval)) + } + + after := time.Date(2026, 5, 16, 16, 1, 0, 0, time.UTC) + want := time.Date(2026, 5, 23, 12, 0, 0, 0, time.UTC) + if got := nextRetryTime(anime, after); !got.Equal(want) { + t.Fatalf("nextRetryTime(after) = %s, want %s", got, want) + } +} + +func assertEpisode(t *testing.T, got domain.CanonicalEpisode, number int, title string, sub bool, dub bool, subOnly bool, filler bool, recap bool) { + t.Helper() + if got.Number != number || got.Title != title || got.HasSub != sub || got.HasDub != dub || got.SubOnly != subOnly || got.Filler != filler || got.Recap != recap { + t.Fatalf("episode = %+v, want number=%d title=%q sub=%t dub=%t subOnly=%t filler=%t recap=%t", got, number, title, sub, dub, subOnly, filler, recap) + } +}