import { describe, it, expect, vi } from "vitest"; import { createForumRecord } from "../lib/steps/create-forum.js"; describe("createForumRecord", () => { const forumDid = "did:plc:testforum"; function mockDb() { return { insert: vi.fn().mockReturnValue({ values: vi.fn().mockResolvedValue(undefined), }), } as any; } // XRPC "RecordNotFound" error mimics @atproto/api behavior function recordNotFoundError() { const err = Object.assign(new Error("Record not found"), { status: 400, error: "RecordNotFound", }); return err; } function mockAgent(overrides: Record = {}) { return { com: { atproto: { repo: { getRecord: vi.fn().mockRejectedValue(recordNotFoundError()), createRecord: vi.fn().mockResolvedValue({ data: { uri: `at://${forumDid}/space.atbb.forum.forum/self`, cid: "bafytest" }, }), ...overrides, }, }, }, } as any; } it("creates forum record and inserts into DB when it does not exist", async () => { const db = mockDb(); const agent = mockAgent(); const result = await createForumRecord(db, agent, forumDid, { name: "My Forum", description: "A test forum", }); expect(result.created).toBe(true); expect(result.cid).toBe("bafytest"); expect(result.uri).toContain("space.atbb.forum.forum/self"); expect(agent.com.atproto.repo.createRecord).toHaveBeenCalledWith( expect.objectContaining({ repo: forumDid, collection: "space.atbb.forum.forum", rkey: "self", record: expect.objectContaining({ $type: "space.atbb.forum.forum", name: "My Forum", description: "A test forum", }), }) ); // Verify DB insertion expect(db.insert).toHaveBeenCalled(); }); it("skips creation when forum record already exists", async () => { const db = mockDb(); const agent = mockAgent({ getRecord: vi.fn().mockResolvedValue({ data: { uri: `at://${forumDid}/space.atbb.forum.forum/self`, cid: "bafyexisting", value: { name: "Existing Forum" }, }, }), }); const result = await createForumRecord(db, agent, forumDid, { name: "My Forum", }); expect(result.created).toBe(false); expect(result.skipped).toBe(true); expect(result.cid).toBe("bafyexisting"); expect(agent.com.atproto.repo.createRecord).not.toHaveBeenCalled(); // No DB insertion when skipped expect(db.insert).not.toHaveBeenCalled(); }); it("throws when PDS write fails", async () => { const db = mockDb(); const agent = mockAgent({ createRecord: vi.fn().mockRejectedValue(new Error("PDS write failed")), }); await expect( createForumRecord(db, agent, forumDid, { name: "My Forum" }) ).rejects.toThrow("PDS write failed"); }); it("re-throws non-RecordNotFound errors from getRecord", async () => { const db = mockDb(); const agent = mockAgent({ getRecord: vi.fn().mockRejectedValue(new Error("Network timeout")), }); await expect( createForumRecord(db, agent, forumDid, { name: "My Forum" }) ).rejects.toThrow("Network timeout"); // Should never attempt createRecord expect(agent.com.atproto.repo.createRecord).not.toHaveBeenCalled(); }); });