// Covers §24's Storage section: sizes by repo and kind, kept tarballs with a delete each, and // orphan cleanup that touches only Kepr's own files. import { beforeAll, describe, expect, test } from "bun:test"; import { mkdir, writeFile } from "node:fs/promises"; import { dirname, join } from "node:path"; import { measureStorage } from "../src/admin/storage.ts"; import { openBucket } from "../src/bucket/reader.ts"; import { Browser, type Instance, instance } from "./browser.ts"; import { makeRepos, writeRelease } from "./fixture.ts"; describe("storage view (§24)", () => { let inst: Instance; let operator: Browser; let bucketDir: string; let save: string; const exists = (key: string) => Bun.file(join(bucketDir, key)).exists(); const put = async (key: string) => { await mkdir(dirname(join(bucketDir, key)), { recursive: true }); await writeFile(join(bucketDir, key), "x"); }; let generation = ""; const kept = () => `.kepr/tarballs/app/${generation}/${save}.tar.gz`; const orphans = [ ".kepr/tarballs/app/0-000000000000/aaaaaaaaaaaa.tar.gz", ".kepr/tarballs/gone/0-000000000000/aaaaaaaaaaaa.tar.gz", ".kepr/hidden/gone", ]; const unlisted = "app/releases/9.9.9/linux-x86_64/app"; beforeAll(async () => { const repos = await makeRepos(["app"]); bucketDir = repos.bucketDir; save = repos.saves.app as string; await writeRelease(bucketDir, "app", { version: "1.0.0", save, files: [{ platform: "linux-x86_64", name: "app", bytes: new Uint8Array(2048) }], }); inst = await instance(bucketDir); operator = new Browser(inst.app); await operator.signIn(); expect(await (await operator.get("/admin/storage")).text()).toContain("Not measured yet"); await operator.post("/admin/repos/app", { public: "1" }); expect((await inst.app.request(`/app/archive/${save}.tar.gz`)).status).toBe(200); const listed = new Bun.Glob(`.kepr/tarballs/app/*/${save}.tar.gz`).scanSync({ cwd: bucketDir, dot: true, }); generation = (Array.from(listed)[0] as string).split("/")[3] as string; for (const key of [...orphans, unlisted]) await put(key); await measure(); }); const measure = () => measureStorage({ bucket: openBucket({ kind: "folder", path: bucketDir }), kepr: inst.kepr, mirrorDir: join(inst.dataDir, "mirror"), }); test("shows each repo's history, builds and kept tarballs, and the orphans", async () => { const page = await (await operator.get("/admin/storage")).text(); expect(page).toMatch(/