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,
);
});