import { describe, expect, mock, test } from "bun:test"; const kv = new Map([["backfill:attachment-bytes", "done"]]); mock.module("cloudflare:workers", () => ({ env: { KV: { get: async (key: string) => kv.get(key) ?? null, put: async () => undefined } }, })); mock.module("./db", () => ({ all: async () => [], first: async () => null, run: async () => ({ meta: { changes: 0 } }), })); const { memoryScopes } = await import("./scoped-db/testing"); const scopes = memoryScopes(); mock.module("./scoped-db", () => scopes.module); const { attachmentUsage, forgetRepoAttachmentBytes, syncAttachmentBytes } = await import("./attachment-bytes"); function attach(repoId: string, id: string, owner: string, uploader: string, size: number): void { scopes .raw("repo", repoId) .query( `INSERT INTO attachments (id, owner_id, repo_id, uploader_id, name, content_type, size, r2_key, created_at) VALUES (?, ?, ?, ?, 'f', 'text/plain', ?, 'k', 0)`, ) .run(id, owner, repoId, uploader, size); } describe("attachment bytes", () => { test("quota totals come from the accounts' own entries, recomputed per repository", async () => { attach("r1", "a", "org", "alice", 100); attach("r2", "b", "org", "bob", 50); attach("r2", "c", "alice", "alice", 7); await syncAttachmentBytes("r1", ["org", "alice"]); await syncAttachmentBytes("r2", ["org", "alice", "bob"]); await syncAttachmentBytes("r2", ["org", "alice", "bob"]); expect(await attachmentUsage("org", "alice")).toEqual({ owner_total: 150, uploader_total: 107 }); await forgetRepoAttachmentBytes("r2"); expect(await attachmentUsage("org", "bob")).toEqual({ owner_total: 100, uploader_total: 0 }); }); });