import { describe, expect, it } from 'vitest'; import { isManifestContentType, isManifestUrl, looksLikeManifest, MediaWatcher } from '../../src/background/capture/media.js'; describe('isManifestUrl', () => { it('matches .m3u8 and .mpd, query string included', () => { expect(isManifestUrl('https://cdn.example/video/master.m3u8')).toBe(true); expect(isManifestUrl('https://cdn.example/video/master.m3u8?token=abc')).toBe(true); expect(isManifestUrl('https://cdn.example/video/stream.mpd')).toBe(true); }); it('does not match an ordinary page or a segment file', () => { expect(isManifestUrl('https://example.com/watch?v=1')).toBe(false); expect(isManifestUrl('https://cdn.example/video/segment-001.ts')).toBe(false); }); it('is false on an unparseable URL rather than throwing', () => { expect(isManifestUrl('not a url')).toBe(false); }); }); describe('isManifestContentType', () => { it('matches HLS and DASH content types, ignoring a charset suffix', () => { expect(isManifestContentType('application/vnd.apple.mpegurl')).toBe(true); expect(isManifestContentType('application/dash+xml; charset=utf-8')).toBe(true); expect(isManifestContentType('application/x-mpegurl')).toBe(true); }); it('does not match ordinary types or missing headers', () => { expect(isManifestContentType('text/html')).toBe(false); expect(isManifestContentType(null)).toBe(false); expect(isManifestContentType(undefined)).toBe(false); }); }); describe('looksLikeManifest', () => { it('is true on either signal alone', () => { expect(looksLikeManifest('https://cdn.example/x.m3u8', 'text/plain')).toBe(true); expect(looksLikeManifest('https://cdn.example/x', 'application/dash+xml')).toBe(true); expect(looksLikeManifest('https://cdn.example/x', 'text/html')).toBe(false); }); }); describe('MediaWatcher', () => { function fakeWebRequest() { let listener: ((d: unknown) => void) | undefined; return { onHeadersReceived: { addListener: (cb: (d: unknown) => void) => { listener = cb; }, }, fire: (d: unknown) => listener?.(d), }; } it('reports a detected manifest with its response headers', () => { const wr = fakeWebRequest(); const detected: unknown[] = []; const watcher = new MediaWatcher((m) => detected.push(m)); watcher.attach(wr as never); wr.fire({ tabId: 7, url: 'https://cdn.example/master.m3u8', responseHeaders: [{ name: 'Content-Type', value: 'application/vnd.apple.mpegurl' }], }); expect(detected).toEqual([ { tabId: 7, url: 'https://cdn.example/master.m3u8', headers: [{ name: 'Content-Type', value: 'application/vnd.apple.mpegurl' }], }, ]); }); it('ignores a response that is not a manifest', () => { const wr = fakeWebRequest(); const detected: unknown[] = []; const watcher = new MediaWatcher((m) => detected.push(m)); watcher.attach(wr as never); wr.fire({ tabId: 7, url: 'https://example.com/page.html', responseHeaders: [{ name: 'Content-Type', value: 'text/html' }] }); expect(detected).toHaveLength(0); }); it('ignores requests with no associated tab', () => { const wr = fakeWebRequest(); const detected: unknown[] = []; const watcher = new MediaWatcher((m) => detected.push(m)); watcher.attach(wr as never); wr.fire({ tabId: -1, url: 'https://cdn.example/master.m3u8', responseHeaders: [] }); expect(detected).toHaveLength(0); }); it('reports the same (tab, url) manifest only once', () => { const wr = fakeWebRequest(); const detected: unknown[] = []; const watcher = new MediaWatcher((m) => detected.push(m)); watcher.attach(wr as never); const details = { tabId: 7, url: 'https://cdn.example/live.m3u8', responseHeaders: [] }; wr.fire(details); wr.fire(details); // HLS live-refresh re-requests the same manifest expect(detected).toHaveLength(1); }); });