import { beforeEach, describe, expect, mock, test } from "bun:test"; const objects = new Map>(); const cached = new Map(); const r2Gets: string[] = []; function r2Object( key: string, bytes: Uint8Array, range?: { offset?: number; length?: number; suffix?: number }, ) { let body: Uint8Array = bytes; if (range && "offset" in range) body = bytes.slice(range.offset ?? 0, (range.offset ?? 0) + (range.length ?? bytes.length)); return { key, size: bytes.length, httpEtag: '"abc"', range, body: new Blob([body]).stream() }; } mock.module("cloudflare:workers", () => ({ waitUntil: (promise: Promise) => void promise, env: { BUCKET: { async get(key: string, options?: { range?: { offset?: number; length?: number } }) { r2Gets.push(key); const bytes = objects.get(key); return bytes ? r2Object(key, bytes, options?.range) : null; }, async head(key: string) { const bytes = objects.get(key); return bytes ? { key, size: bytes.length, httpEtag: '"abc"' } : null; }, }, }, })); (globalThis as unknown as { caches: unknown }).caches = { open: async () => ({ match: async (request: Request) => cached.get(request.url)?.clone(), put: async (key: string, response: Response) => void cached.set(key, response), }), }; const { handleVideoRoutes } = await import("./videos"); const call = (path: string, init?: RequestInit) => { const request = new Request(`https://forge.example.com${path}`, init); return handleVideoRoutes(request, new URL(request.url)); }; describe("handleVideoRoutes", () => { beforeEach(() => { objects.clear(); cached.clear(); r2Gets.length = 0; objects.set("videos/intro/v1/720/00000.m4s", new TextEncoder().encode("0123456789")); }); test("ignores unrelated paths and 404s malformed video paths", async () => { expect(await call("/settings")).toBeNull(); expect((await call("/videos/intro/v1/../../secrets"))?.status).toBe(404); }); test("serves from R2 with immutable headers, then from the cache", async () => { const first = await call("/videos/intro/v1/720/00000.m4s"); expect(first?.status).toBe(200); expect(first?.headers.get("content-type")).toBe("video/mp4"); expect(first?.headers.get("cache-control")).toContain("immutable"); expect(await first?.text()).toBe("0123456789"); await Bun.sleep(0); const second = await call("/videos/intro/v1/720/00000.m4s"); expect(await second?.text()).toBe("0123456789"); expect(r2Gets).toHaveLength(1); }); test("answers a ranged miss with 206 from R2", async () => { const response = await call("/videos/intro/v1/720/00000.m4s", { headers: { range: "bytes=2-4" } }); expect(response?.status).toBe(206); expect(response?.headers.get("content-range")).toBe("bytes 2-4/10"); expect(await response?.text()).toBe("234"); }); test("404s missing objects and rejects writes", async () => { expect((await call("/videos/intro/v1/master.m3u8"))?.status).toBe(404); expect((await call("/videos/intro/v1/master.m3u8", { method: "PUT" }))?.status).toBe(405); }); });