// tests/background/webm-remux-deps.test.ts // // Plan 01-08 Task 1: SW-compatibility + presence contract for the two new // runtime dependencies that the WebM remux pipeline rests on. Pins the // architectural commitment that landed in CONTEXT.md amendment D-14-remux: // - `ts-ebml` ^3.0.2 (MIT, parses each VideoSegment's EBML structure) // - `webm-muxer` ^5.1.4 (MIT, writes the single-EBML-headered output) // // Both libraries were surveyed in `.planning/debug/d13-multi-ebml-concat- // unplayable.md` (Evidence/library-survey, lines 380-410). They are pure // JS, pure ESM/CJS, and were grep-verified at survey time to contain no // hard DOM-global references on the hot path. Chrome's service-worker // runtime (where `remuxSegments()` will execute) does not provide // `window` or `document`; this test pins that compat at the // devDependency-import surface so a future bump that accidentally adds // a DOM global is caught at test time rather than at runtime in a // production SW. // // Test 1 asserts named-export presence (RED until `npm install` lands). // Test 2 asserts both libraries load under default Node globals without // referencing `window` or `document` synchronously at import time. // // Skip discipline: none — these are pure import-shape tests, no external // binaries, no fixtures. Vitest's default Node environment is sufficient. import { describe, it, expect, beforeEach, afterEach } from 'vitest'; interface GlobalSnapshot { window: unknown; document: unknown; hadWindow: boolean; hadDocument: boolean; } /** * Capture the current values of `window` and `document` on `globalThis` * so they can be restored after a test that deletes them. Vitest's * `vi.stubGlobal` is not used here because we want to assert the * absence of the globals at import time, not just stub them. * * @returns Snapshot the caller passes back to {@link restoreGlobals}. */ function snapshotGlobals(): GlobalSnapshot { const g = globalThis as unknown as Record; return { window: g.window, document: g.document, hadWindow: 'window' in g, hadDocument: 'document' in g, }; } /** * Restore the globals captured by {@link snapshotGlobals}. Idempotent. * * @param snap - Snapshot returned by {@link snapshotGlobals}. */ function restoreGlobals(snap: GlobalSnapshot): void { const g = globalThis as unknown as Record; if (snap.hadWindow) { g.window = snap.window; } else { delete g.window; } if (snap.hadDocument) { g.document = snap.document; } else { delete g.document; } } describe('webm-remux dependencies (Plan 01-08 Task 1)', () => { it('exports Muxer + ArrayBufferTarget + Decoder', async () => { // Dynamic import so a missing package surfaces as a precise test // failure ("Cannot find module 'webm-muxer'") rather than a Vitest // collection error that hides which dependency is the cause. const webmMuxer = await import('webm-muxer'); expect(webmMuxer.Muxer).toBeDefined(); expect(webmMuxer.ArrayBufferTarget).toBeDefined(); const tsEbml = await import('ts-ebml'); expect(tsEbml.Decoder).toBeDefined(); }); describe('loads under default Node globals without DOM-global ReferenceErrors', () => { let snap: GlobalSnapshot; beforeEach(() => { snap = snapshotGlobals(); const g = globalThis as unknown as Record; delete g.window; delete g.document; }); afterEach(() => { restoreGlobals(snap); }); it('webm-muxer + ts-ebml do not throw on import when window/document are absent', async () => { // The Chrome service-worker runtime provides neither `window` nor // `document`. If either library's published dist references one // of these synchronously at module evaluation time (e.g. a UMD // wrapper falling through to `window`), the import below would // throw a ReferenceError and this test would fail with a clear // signal. // // ts-ebml's UMD wrapper does contain a `typeof window` check // with a `self`/`global` fallback per the d13 library survey // — `typeof` does NOT throw on undeclared identifiers per // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof // so the fallback path resolves cleanly. // // webm-muxer is documented zero-DOM-ref. let webmMuxerError: unknown = null; try { await import('webm-muxer'); } catch (e) { webmMuxerError = e; } expect( webmMuxerError, `webm-muxer threw at import time without window/document: ${String(webmMuxerError)}`, ).toBeNull(); let tsEbmlError: unknown = null; try { await import('ts-ebml'); } catch (e) { tsEbmlError = e; } expect( tsEbmlError, `ts-ebml threw at import time without window/document: ${String(tsEbmlError)}`, ).toBeNull(); }); }); });