import { BASE_URL, TEST_DIR } from "../helpers.ts"; import { assertEquals, assertFalse, assertStringIncludes } from "@std/assert"; import { Application } from "@oak/oak"; import { routeStaticFilesFrom } from "../../lib/static.ts"; async function handle( app: Application, path: string, headers: HeadersInit = {}, ) { const res = await app.handle(new Request(`${BASE_URL}${path}`, { headers })); if (!res) throw new Error("no response"); return { res, text: await res.text() }; } Deno.test("routeStaticFilesFrom: index, SPA fallback, cache rules, precompressed files", async () => { const root = `${TEST_DIR}/static-${crypto.randomUUID()}`; await Deno.mkdir(`${root}/assets`, { recursive: true }); await Deno.writeTextFile( `${root}/index.html`, `__SITE_NAME____BANDCAMP_PLAYER__`, ); const js = "console.log('app');".repeat(50); await Deno.writeTextFile(`${root}/assets/app-abc123.js`, js); const br = new Uint8Array([1, 2, 3]); await Deno.writeFile(`${root}/assets/app-abc123.js.br`, br); await Deno.writeTextFile(`${root}/robots.txt`, "User-agent: *"); const app = new Application(); app.use(routeStaticFilesFrom([root])); const index = await handle(app, "/"); assertEquals(index.res.headers.get("cache-control"), "no-cache"); assertEquals( index.text, "gerbeurembed", ); const spa = await handle(app, "/users/someone"); assertEquals(spa.res.status, 200); assertEquals(spa.text, index.text); // No Accept-Encoding header: the plain file, not the .br sibling. const asset = await handle(app, "/assets/app-abc123.js"); assertEquals(asset.text, js); assertEquals(asset.res.headers.get("content-encoding"), null); assertStringIncludes(asset.res.headers.get("cache-control")!, "immutable"); assertStringIncludes( asset.res.headers.get("cache-control")!, "max-age=31536000", ); assertStringIncludes(asset.res.headers.get("vary")!, "Accept-Encoding"); const compressed = await handle(app, "/assets/app-abc123.js", { "Accept-Encoding": "br, gzip", }); assertEquals(compressed.res.headers.get("content-encoding"), "br"); assertEquals(compressed.text, "\x01\x02\x03"); // the .br file's bytes const plain = await handle(app, "/robots.txt"); assertEquals(plain.text, "User-agent: *"); assertFalse( (plain.res.headers.get("cache-control") ?? "").includes("immutable"), ); // A chunk from an older build 404s rather than being answered with the index. const stale = await handle(app, "/assets/app-old999.js"); assertEquals(stale.res.status, 404); assertFalse(stale.text.includes("")); assertEquals( (await handle(app, "/emojibase/17.0.0/missing.json")).res.status, 404, ); });