/** * DTP-17 — CDN reversed-ID URL convention. */ import { describe, expect, it } from "@suaveplan/testing/runner"; import type { CdnFallbackConfig } from "../src/index.js"; import { buildCdnChunkUrl, DEFAULT_CDN_LEVELS, DEFAULT_CDN_PADDING, } from "../src/index.js"; const BASE: CdnFallbackConfig = { baseUrl: "https://chunks.example.com", pathScheme: "reverse-id", levels: DEFAULT_CDN_LEVELS, padding: DEFAULT_CDN_PADDING, }; describe("DTP-17 — reverse-id URL convention", () => { it("URL builder produces correct path for various levels and padding values", { timeout: 5000, }, () => { const url = buildCdnChunkUrl(BASE, "abcdef1234567890", 47); expect(url).toBe( "https://chunks.example.com/0/9/8/abcdef1234567890_000000047.chunk" ); }); it("levels override changes the directory depth", { timeout: 5000 }, () => { const url = buildCdnChunkUrl( { ...BASE, levels: 1 }, "abcdef1234567890", 0 ); expect(url).toBe( "https://chunks.example.com/0/abcdef1234567890_000000000.chunk" ); }); it("levels=0 produces no directory prefix", { timeout: 5000 }, () => { const url = buildCdnChunkUrl({ ...BASE, levels: 0 }, "abcdef", 0); expect(url).toBe("https://chunks.example.com/abcdef_000000000.chunk"); }); it("padding override affects chunk-id zero-padding", { timeout: 5000, }, () => { const url = buildCdnChunkUrl( { ...BASE, padding: 4 }, "abcdef1234567890", 12 ); expect(url).toBe( "https://chunks.example.com/0/9/8/abcdef1234567890_0012.chunk" ); }); it("trailing slash on baseUrl is stripped", { timeout: 5000 }, () => { const url = buildCdnChunkUrl( { ...BASE, baseUrl: "https://chunks.example.com/" }, "abcdef1234567890", 1 ); expect(url.startsWith("https://chunks.example.com/0/9/8/")).toBe(true); }); it("identical inputs produce byte-identical URLs", { timeout: 5000, }, () => { const a = buildCdnChunkUrl(BASE, "abcdef", 99); const b = buildCdnChunkUrl(BASE, "abcdef", 99); expect(a).toBe(b); }); it("rejects empty fileId", { timeout: 5000 }, () => { expect(() => buildCdnChunkUrl(BASE, "", 0)).toThrow(); }); it("rejects negative chunkId", { timeout: 5000 }, () => { expect(() => buildCdnChunkUrl(BASE, "abcdef", -1)).toThrow(); }); it("rejects non-integer chunkId", { timeout: 5000 }, () => { expect(() => buildCdnChunkUrl(BASE, "abcdef", 1.5)).toThrow(); }); it("rejects negative levels", { timeout: 5000 }, () => { expect(() => buildCdnChunkUrl({ ...BASE, levels: -1 }, "abcdef", 0) ).toThrow(); }); it("rejects non-integer levels", { timeout: 5000 }, () => { expect(() => buildCdnChunkUrl({ ...BASE, levels: 1.5 }, "abcdef", 0) ).toThrow(); }); it("rejects levels > fileId length", { timeout: 5000 }, () => { expect(() => buildCdnChunkUrl({ ...BASE, levels: 10 }, "abc", 0) ).toThrow(); }); it("rejects negative padding", { timeout: 5000 }, () => { expect(() => buildCdnChunkUrl({ ...BASE, padding: -1 }, "abcdef", 0) ).toThrow(); }); it("rejects non-integer padding", { timeout: 5000 }, () => { expect(() => buildCdnChunkUrl({ ...BASE, padding: 1.5 }, "abcdef", 0) ).toThrow(); }); });