import test from 'node:test'; import assert from 'node:assert/strict'; import { createStreamPlaybackMetadataStore, matchRequestedStreamPlaybackMetadata, toAnimeBrowserPlaybackState, toAnilistMediaGuess, toJimakuMediaInfo, } from './stream-playback-metadata'; import type { AnimeStreamMetadata } from '../../anime-bridge/episode-metadata'; function metadata(overrides: Partial = {}): AnimeStreamMetadata { return { sourceId: '9001', animeUrl: '/anime/mushoku', episodeUrl: '/watch/ep-4', mediaPath: 'http://127.0.0.1:41234/video/abc.m3u8', statsPath: 'animebrowser://9001/%2Fanime%2Fmushoku/%2Fwatch%2Fep-4', seriesTitle: 'Mushoku Tensei: Jobless Reincarnation', seasonNumber: 3, episodeNumber: 4, episodeTitle: null, displayTitle: 'Mushoku Tensei: Jobless Reincarnation S03E04', ...overrides, }; } test('browser playback state keeps the source episode identity and drops other media', () => { assert.deepEqual(toAnimeBrowserPlaybackState(metadata()), { sourceId: '9001', animeUrl: '/anime/mushoku', episodeUrl: '/watch/ep-4', }); assert.equal(toAnimeBrowserPlaybackState(null), null); }); test('the store answers for the stream URL and for the stats path', () => { const store = createStreamPlaybackMetadataStore(); const current = metadata(); store.set(current); assert.equal(store.match(current.mediaPath), current); assert.equal(store.match(current.statsPath), current); assert.equal(store.match(` ${current.mediaPath} `), current); }); test('the store stops answering once the player moves on', () => { const store = createStreamPlaybackMetadataStore(); store.set(metadata()); assert.equal(store.match('/home/user/Videos/local.mkv'), null); assert.equal(store.match(null), null); assert.equal(store.match(''), null); store.clear(); assert.equal(store.match(metadata().mediaPath), null); }); test('the store keeps metadata for more than one resolved playlist entry', () => { const store = createStreamPlaybackMetadataStore(); const first = metadata(); const second = metadata({ mediaPath: 'http://127.0.0.1:41234/video/def.m3u8', statsPath: 'animebrowser://9001/%2Fanime%2Fmushoku/%2Fwatch%2Fep-5', episodeNumber: 5, }); store.set(first); store.set(second); assert.equal(store.match(first.mediaPath), first); assert.equal(store.match(second.mediaPath), second); }); test('an explicit target path does not inherit the current stream metadata', () => { const store = createStreamPlaybackMetadataStore(); const current = metadata(); store.set(current); assert.equal( matchRequestedStreamPlaybackMetadata(store, '/home/user/Videos/other.mkv', current.mediaPath), null, ); assert.equal(matchRequestedStreamPlaybackMetadata(store, null, current.mediaPath), current); }); test('toJimakuMediaInfo prefills the modals with the source-reported fields', () => { assert.deepEqual(toJimakuMediaInfo(metadata()), { title: 'Mushoku Tensei: Jobless Reincarnation', season: 3, episode: 4, confidence: 'high', filename: 'Mushoku Tensei: Jobless Reincarnation S03E04', rawTitle: 'Mushoku Tensei: Jobless Reincarnation S03E04', }); }); test('toJimakuMediaInfo drops to low confidence when there is no episode', () => { const info = toJimakuMediaInfo(metadata({ episodeNumber: null, seasonNumber: null })); assert.equal(info.episode, null); assert.equal(info.confidence, 'low'); assert.equal(info.title, 'Mushoku Tensei: Jobless Reincarnation'); }); test('toJimakuMediaInfo reports low confidence when a fractional episode is omitted', () => { const info = toJimakuMediaInfo(metadata({ episodeNumber: 6.5 })); assert.equal(info.episode, null); assert.equal(info.confidence, 'low'); }); test('toAnilistMediaGuess reports the stream fields verbatim', () => { assert.deepEqual(toAnilistMediaGuess(metadata()), { title: 'Mushoku Tensei: Jobless Reincarnation', season: 3, episode: 4, source: 'stream', }); }); test('toAnilistMediaGuess declines a special so the caller can fall back', () => { // AniList progress counts whole episodes; a 6.5 special is not one of them. assert.equal(toAnilistMediaGuess(metadata({ episodeNumber: 6.5 })), null); assert.equal(toAnilistMediaGuess(metadata({ episodeNumber: null })), null); assert.equal(toAnilistMediaGuess(metadata({ seriesTitle: '' })), null); });