import { beforeEach, describe, expect, mock, test } from "bun:test"; import { scopedTestState } from "./scoped.test-helper"; const kv = new Map(); mock.module("cloudflare:workers", () => ({ env: { SECRETS_KEY: "k".repeat(40), PUBLIC_URL: "https://forge.test", SITES_DOMAIN: "sites.test", KV: { get: async (key: string) => kv.get(key) ?? null, put: async (key: string, value: string) => void kv.set(key, value), delete: async (key: string) => void kv.delete(key), }, }, waitUntil: () => undefined, })); mock.module("./directory", () => ({ forgetSiteDirectory: async () => undefined })); const scoped = scopedTestState(); scoped.install(); const unpublished: string[] = []; const actualDeploy = await import("./deploy"); mock.module("./deploy", () => ({ ...actualDeploy, assertLabelFree: async () => undefined, loadSiteById: async () => null, unpublishSite: async (id: string) => void unpublished.push(id), activateSiteDeployment: async () => "active", failSiteDeployment: async () => undefined, insertDeployment: async () => ({ id: "d" }), })); mock.module("./scratch-git", () => ({ assertScratchRepoTransferable: async () => undefined, createScratchRepo: async () => undefined, sweepOrphanScratchRepos: async () => undefined, transferScratchRepo: async () => undefined, })); const { backfillScratchExpiry, sweepScratchSites } = await import("./scratch"); const { scratchExpiryKey } = await import("./scratch-core"); const NOW = Date.now(); function scratch(id: string, expiresAt: number): void { scoped.site({ id, scratch: 1, claim_token_hash: `h-${id}`, expires_at: expiresAt }); scoped.register("site_claim", `h-${id}`, `site:${id}`); } beforeEach(() => { kv.clear(); scoped.reset(); unpublished.length = 0; }); describe("scratch expiry", () => { test("the sweep reads only queued expired sites and drops entries of claimed ones", async () => { scratch("old", NOW - 1000); scratch("live", NOW + 60_000); scratch("claimed", NOW - 2000); await backfillScratchExpiry(); expect(scoped.locate("scratch_expiry", scratchExpiryKey(NOW + 60_000, "live"))).toBe("site:live"); scoped.repo("site:claimed").run("UPDATE sites SET scratch = 0, expires_at = NULL WHERE id = 'claimed'"); expect(await sweepScratchSites()).toBe(1); expect(unpublished).toEqual(["old"]); expect(scoped.locate("scratch_expiry", scratchExpiryKey(NOW - 1000, "old"))).toBeNull(); expect(scoped.locate("scratch_expiry", scratchExpiryKey(NOW - 2000, "claimed"))).toBeNull(); expect(scoped.locate("scratch_expiry", scratchExpiryKey(NOW + 60_000, "live"))).toBe("site:live"); }); });