61 lines
2.6 KiB
TypeScript
61 lines
2.6 KiB
TypeScript
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { afterEach, describe, expect, test } from "vitest";
|
|
|
|
import {
|
|
__resetStaticAssetMetadataCacheForTests,
|
|
createStaticEtag,
|
|
getStaticAssetMetadata,
|
|
getStaticCacheControl,
|
|
isStaticAssetNotModified,
|
|
selectStaticRepresentation,
|
|
} from "./static-assets";
|
|
|
|
const temporaryDirectories: string[] = [];
|
|
|
|
afterEach(async () => {
|
|
__resetStaticAssetMetadataCacheForTests();
|
|
await Promise.all(temporaryDirectories.splice(0).map((directory) => rm(directory, { force: true, recursive: true })));
|
|
});
|
|
|
|
async function createAssetFixture() {
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), "hivegrid-static-"));
|
|
temporaryDirectories.push(directory);
|
|
const filePath = path.join(directory, "asset.js");
|
|
await Promise.all([writeFile(filePath, "identity"), writeFile(`${filePath}.br`, "br"), writeFile(`${filePath}.gz`, "gzip")]);
|
|
return filePath;
|
|
}
|
|
|
|
describe("static asset metadata", () => {
|
|
test("selects the highest-quality available precompressed representation", async () => {
|
|
const metadata = await getStaticAssetMetadata(await createAssetFixture());
|
|
expect(metadata).not.toBeNull();
|
|
expect(selectStaticRepresentation(metadata!, "gzip;q=1, br;q=0.5").encoding).toBe("gzip");
|
|
expect(selectStaticRepresentation(metadata!, "gzip;q=0, br").encoding).toBe("br");
|
|
expect(selectStaticRepresentation(metadata!, undefined).encoding).toBe("identity");
|
|
});
|
|
|
|
test("uses representation-specific validators and honours conditional requests", async () => {
|
|
const metadata = await getStaticAssetMetadata(await createAssetFixture());
|
|
const representation = selectStaticRepresentation(metadata!, "br");
|
|
const etag = createStaticEtag(representation);
|
|
expect(etag).toContain("-br");
|
|
expect(isStaticAssetNotModified({ etag, ifNoneMatch: etag, mtimeMs: representation.stat.mtimeMs })).toBe(true);
|
|
expect(isStaticAssetNotModified({ etag, ifNoneMatch: 'W/"different"', mtimeMs: representation.stat.mtimeMs })).toBe(false);
|
|
expect(
|
|
isStaticAssetNotModified({
|
|
etag,
|
|
ifModifiedSince: new Date(representation.stat.mtimeMs + 1_000).toUTCString(),
|
|
mtimeMs: representation.stat.mtimeMs,
|
|
})
|
|
).toBe(true);
|
|
});
|
|
|
|
test("gives revisioned locales immutable caching and unversioned locales a short revalidation window", () => {
|
|
expect(getStaticCacheControl("/assets/app-hash.js", false)).toContain("immutable");
|
|
expect(getStaticCacheControl("/locales/de/common.json", true)).toContain("immutable");
|
|
expect(getStaticCacheControl("/locales/de/common.json", false)).toContain("must-revalidate");
|
|
});
|
|
});
|