diff options
Diffstat (limited to 'src/lib/Media/Anime/Airing/classify.test.ts')
| -rw-r--r-- | src/lib/Media/Anime/Airing/classify.test.ts | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/src/lib/Media/Anime/Airing/classify.test.ts b/src/lib/Media/Anime/Airing/classify.test.ts new file mode 100644 index 00000000..cad08b43 --- /dev/null +++ b/src/lib/Media/Anime/Airing/classify.test.ts @@ -0,0 +1,153 @@ +import { describe, expect, it } from 'vitest'; +import settings from '$stores/settings'; +import type { Media } from '$lib/Data/AniList/media'; +import { season } from '$lib/Media/Anime/season'; +import { hasDueEpisodes, getAnimeEpisodeState } from '$lib/Media/Anime/Airing/classify'; +import { injectAiringTime } from '$lib/Media/Anime/Airing/Subtitled/match'; +import type { SubsPlease } from '$lib/Media/Anime/Airing/Subtitled/subsPlease'; + +const toScheduleTime = (epochSeconds: number) => { + const date = new Date(epochSeconds * 1000); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + + return `${hours}:${minutes}`; +}; + +const baseMedia = (id: number): Media => + ({ + id, + idMal: id, + status: 'RELEASING', + type: 'ANIME', + episodes: 12, + chapters: 0, + volumes: 0, + duration: 24, + format: 'TV', + title: { + romaji: `Fixture Show ${id}`, + english: `Fixture Show ${id}`, + native: `Fixture Show ${id}` + }, + nextAiringEpisode: { + episode: 8, + airingAt: Math.floor(Date.now() / 1000) + 24 * 60 * 60 + }, + synonyms: [], + mediaListEntry: { + progress: 6, + progressVolumes: 0, + status: 'CURRENT', + score: 0, + repeat: 0, + startedAt: { + year: 2025, + month: 1, + day: 1 + }, + completedAt: { + year: 0, + month: 0, + day: 0 + }, + createdAt: 0, + updatedAt: 0, + customLists: {} + }, + startDate: { + year: 2025, + month: 1 + }, + endDate: { + year: 2025, + month: 12 + }, + coverImage: { + extraLarge: 'https://example.com/cover-xl.jpg', + medium: 'https://example.com/cover-md.jpg' + }, + tags: [], + genres: [], + season: season(), + isAdult: false, + relations: { + edges: [] + } + }) as Media; + +const regressionIds = [192507, 189259, 198767]; + +describe('anime episode classification', () => { + it('prefers nativeEpisode for due/upcoming classification', () => { + const media = baseMedia(192507); + + media.nextAiringEpisode = { + episode: 7, + nativeEpisode: 8, + airingAt: Math.floor(Date.now() / 1000) + 6 * 60 * 60, + nativeAiringAt: Math.floor(Date.now() / 1000) + 18 * 60 * 60 + }; + + const state = getAnimeEpisodeState(media); + + expect(state.airedEpisodes).toBe(7); + expect(hasDueEpisodes(media)).toBe(true); + }); + + it('treats stale native release data as aired for due detection', () => { + const media = baseMedia(189259); + + media.nextAiringEpisode = { + episode: 9, + airingAt: Math.floor(Date.now() / 1000) + 72 * 60 * 60, + nativeAiringAt: Math.floor(Date.now() / 1000) - 60 * 60 + }; + + const state = getAnimeEpisodeState(media); + + expect(state.airedEpisodes).toBe(9); + expect(hasDueEpisodes(media)).toBe(true); + }); +}); + +describe('native countdown toggle parity', () => { + for (const id of regressionIds) { + it(`keeps media ${id} due with native countdown on/off`, () => { + const media = baseMedia(id); + const subtitledAiringAt = Math.floor(Date.now() / 1000) + 24 * 60 * 60; + const nativeAiringAt = subtitledAiringAt + 12 * 60 * 60; + const nativeAiringDate = new Date(nativeAiringAt * 1000); + const airingDay = nativeAiringDate.toLocaleString('en-US', { weekday: 'long' }); + const subsPlease = { + tz: 'America/Los_Angeles', + schedule: { + [airingDay]: [ + { + title: media.title.romaji, + page: '', + image_url: '', + time: toScheduleTime(subtitledAiringAt) + } + ] + } + } as unknown as SubsPlease; + + media.nextAiringEpisode = { + episode: 8, + airingAt: nativeAiringAt + }; + + settings.setKey('displayNativeCountdown', true); + + const nativeOnly = injectAiringTime(media, subsPlease); + + settings.setKey('displayNativeCountdown', false); + + const subtitled = injectAiringTime(media, subsPlease); + + expect(hasDueEpisodes(nativeOnly)).toBe(true); + expect(hasDueEpisodes(subtitled)).toBe(true); + }); + } +}); |