- M3: hand-rolled service worker (precache + runtime /ort caching), precache manifest injection, SW registration/update toast, manifest + generated icons, production build script, offline indicator in ModelPicker (D-005/D-007) - M4 backend: bun:sqlite users/sessions (D-009), Passport local strategy behind connect-compat adapter (D-008), /api/auth routes wired into dev+prod serving, Bun.password Argon2id, 38 auth tests - M4 frontend: AuthForms + useAuth + framework-free authClient, session-aware header, anonymous-first fail-silent offline handling, 18 client tests - D-013: server engine (M5) will use faster-whisper via Python sidecar; browser side stays Transformers.js (CTranslate2 has no WASM build) - bun test: 83 pass / tsc --noEmit clean - Note: M3 doc closeout (WorkBreakdown/Architecture/tests/offline.md) still in flight from a background agent; follow-up commit will finish docs Co-Authored-By: Claude Fable 5 <[email protected]>
63 lines
2.2 KiB
TypeScript
63 lines
2.2 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import {
|
|
injectPrecacheManifest,
|
|
PRECACHE_PLACEHOLDER,
|
|
precachePathsFromOutputs,
|
|
VERSION_PLACEHOLDER,
|
|
} from "../src/pwa/precache";
|
|
|
|
describe("precachePathsFromOutputs", () => {
|
|
test("maps index.html to /, prefixes assets, drops sourcemaps", () => {
|
|
expect(
|
|
precachePathsFromOutputs(
|
|
["index.html", "chunk-abc123.js", "chunk-abc123.js.map", "./index-def456.css"],
|
|
["/inference.worker.js"],
|
|
),
|
|
).toEqual(["/", "/chunk-abc123.js", "/index-def456.css", "/inference.worker.js"]);
|
|
});
|
|
|
|
test("deduplicates and sorts", () => {
|
|
expect(precachePathsFromOutputs(["a.js", "a.js"], ["/a.js", "/"])).toEqual([
|
|
"/",
|
|
"/a.js",
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("injectPrecacheManifest", () => {
|
|
const swSource = `const PRECACHE = JSON.parse(${PRECACHE_PLACEHOLDER});\nconst CACHE = "shell-${VERSION_PLACEHOLDER}";`;
|
|
|
|
test("injects a JSON-parseable asset list and the version", () => {
|
|
const result = injectPrecacheManifest(swSource, ["/", "/chunk-abc.js"], "v1abc");
|
|
expect(result).toContain('"shell-v1abc"');
|
|
expect(result).not.toContain("__PRECACHE_MANIFEST__");
|
|
// The injected literal must survive a JS string round-trip back to the array.
|
|
const literal = /JSON\.parse\((".*")\)/.exec(result)?.[1];
|
|
expect(literal).toBeDefined();
|
|
expect(JSON.parse(JSON.parse(literal!))).toEqual(["/", "/chunk-abc.js"]);
|
|
});
|
|
|
|
test("throws if a placeholder is missing (bundler mangled the source)", () => {
|
|
expect(() => injectPrecacheManifest("const x = 1;", [], "v1")).toThrow(
|
|
/missing/,
|
|
);
|
|
expect(() =>
|
|
injectPrecacheManifest(`JSON.parse(${PRECACHE_PLACEHOLDER})`, [], "v1"),
|
|
).toThrow(/missing/);
|
|
});
|
|
|
|
test("rejects versions that would break the cache name", () => {
|
|
expect(() => injectPrecacheManifest(swSource, [], "bad version!")).toThrow(
|
|
/Invalid cache version/,
|
|
);
|
|
});
|
|
|
|
test("the real sw.ts source contains both placeholders", async () => {
|
|
const source = await Bun.file(
|
|
new URL("../src/pwa/sw.ts", import.meta.url).pathname,
|
|
).text();
|
|
expect(source).toContain(PRECACHE_PLACEHOLDER);
|
|
expect(source).toContain(VERSION_PLACEHOLDER);
|
|
});
|
|
});
|