import { mkdirSync, writeFileSync } from "node:fs"; import { resolve } from "node:path"; import { expect, test } from "@playwright/test"; import { createServer, type ViteDevServer } from "vite"; const resources = new Map([ ["123e4567-e89b-42d3-a456-426614174001", "aaaaaaaa"], ["123e4567-e89b-42d3-a456-426614174002", "bbbbbbbb"], ["123e4567-e89b-42d3-a456-426614174003", "cccccccc"], ]); let vite: ViteDevServer; let webUrl: string; let publicFetchCount = 0; test.beforeAll(async () => { vite = await createServer({ configFile: false, plugins: [{ name: "wp0-06-public-assets", configureServer(server) { server.middlewares.use((request, response, next) => { const match = request.url?.match(/^\/api\/v1\/assets\/public\/[^/]+\/([0-9a-f-]+)$/i); if (!match) return next(); const body = resources.get(match[1] ?? ""); if (!body) { response.statusCode = 404; response.end(); return; } publicFetchCount += 1; response.setHeader("Cache-Control", "public, max-age=31536000, immutable"); response.setHeader("Content-Type", "application/octet-stream"); response.end(body); }); }, }], publicDir: resolve("apps/web/public"), root: process.cwd(), server: { host: "127.0.0.1", port: 0 }, }); await vite.listen(); const address = vite.httpServer?.address(); if (!address || typeof address === "string") throw new Error("Vite did not expose a test port."); webUrl = `http://127.0.0.1:${address.port}`; }); test.afterAll(async () => vite.close()); test("TDD-WP0-CACHE-001-public-lru enumerates isolated browser persistence", async ({ page }) => { publicFetchCount = 0; await page.goto(`${webUrl}/tests/e2e/fixtures/public-asset-cache.html`); await expect(page.locator("#status")).toHaveText("ready"); await page.reload(); await expect(page.locator("#status")).toHaveText("ready"); const result = await page.evaluate(async () => { const ids = [ "123e4567-e89b-42d3-a456-426614174001", "123e4567-e89b-42d3-a456-426614174002", "123e4567-e89b-42d3-a456-426614174003", ]; const descriptor = (resource_id: string, release_version: string) => ({ access_class: "public_release_asset" as const, cache_kind: "thumbnail" as const, release_version, resource_id, }); const cache = window.dadaCacheProbe.cache; await cache.clear(); const first = await cache.cache(descriptor(ids[0]!, "asset-20260727.1")); const second = await cache.cache(descriptor(ids[1]!, "asset-20260727.1")); await fetch(`/api/v1/assets/public/asset-20260727.1/${ids[0]}`); const third = await cache.cache(descriptor(ids[2]!, "asset-20260727.2")); const rejected = []; for (const [access_class, cache_kind] of [ ["internal_preview_asset", "thumbnail"], ["private_user_asset", "thumbnail"], ["public_release_asset", "project"], ["public_release_asset", "prompt"], ["public_release_asset", "verification_code"], ["public_release_asset", "session"], ["public_release_asset", "unsaved_edit"], ["public_release_asset", "user_download"], ]) { rejected.push(await cache.cache({ access_class, cache_kind, release_version: "asset-20260727.2", resource_id: ids[0] })); } const enumeration = await cache.inspect(); const registrations = await navigator.serviceWorker.getRegistrations(); return { enumeration, local_storage_keys: Object.keys(localStorage), rejected, results: [first, second, third], service_workers: registrations.map((item) => ({ active: item.active?.state, scope: item.scope, script_url: item.active?.scriptURL })), session_storage_keys: Object.keys(sessionStorage), }; }); expect(result.results[2]).toMatchObject({ evicted_resource_ids: ["123e4567-e89b-42d3-a456-426614174002"], status: "cached" }); expect(result.enumeration.policy.current_public_cache_bytes).toBe(16); expect(result.enumeration.policy.max_public_cache_bytes).toBe(20); expect(result.enumeration.entries.map((item: { resource_id: string }) => item.resource_id).sort()).toEqual([ "123e4567-e89b-42d3-a456-426614174001", "123e4567-e89b-42d3-a456-426614174003", ]); expect(result.enumeration.cache_keys).toHaveLength(2); expect(result.enumeration.indexed_db_names).toEqual(["dada-public-asset-cache-v1"]); expect(result.rejected).toEqual(Array.from({ length: 8 }, () => ({ status: "rejected_not_allowlisted" }))); expect(result.local_storage_keys).toEqual([]); expect(result.session_storage_keys).toEqual([]); expect(result.service_workers).toHaveLength(1); expect(publicFetchCount).toBe(3); const evidenceDirectory = process.env.DADA_EVIDENCE_DIR_CACHE; if (evidenceDirectory) { mkdirSync(evidenceDirectory, { recursive: true }); writeFileSync(resolve(evidenceDirectory, "cache-enumeration.json"), `${JSON.stringify({ business_database_calls: 0, public_network_fetches: publicFetchCount, ...result, }, null, 2)}\n`); writeFileSync(resolve(evidenceDirectory, "lru-trace.json"), `${JSON.stringify({ capacity_driver: { production_max_bytes: 157_286_400, test_max_bytes: 20 }, prewrite_eviction: true, results: result.results, }, null, 2)}\n`); } });