WIP! A BB-style forum, on the ATmosphere! We're still working... we'll be back soon when we have something to show off!
node typescript hono htmx atproto
at root/atb-56-theme-caching-layer 110 lines 3.7 kB view raw
1import { describe, it, expect, vi } from "vitest"; 2import { seedDefaultRoles, DEFAULT_ROLES } from "../lib/steps/seed-roles.js"; 3 4describe("seedDefaultRoles", () => { 5 const forumDid = "did:plc:testforum"; 6 7 function mockDb(existingRoleNames: string[] = []) { 8 const existingQueue = [...existingRoleNames]; 9 let roleIdCounter = 1n; 10 11 return { 12 select: vi.fn().mockReturnValue({ 13 from: vi.fn().mockReturnValue({ 14 where: vi.fn().mockReturnValue({ 15 limit: vi.fn().mockImplementation(() => { 16 const roleName = existingQueue.shift(); 17 if (roleName) { 18 return [{ 19 name: roleName, 20 did: forumDid, 21 rkey: roleName.toLowerCase(), 22 cid: `bafyexisting-${roleName.toLowerCase()}`, 23 }]; 24 } 25 return []; 26 }), 27 }), 28 }), 29 }), 30 insert: vi.fn().mockImplementation(() => { 31 const id = roleIdCounter++; 32 // values() returns a Promise (for rolePermissions inserts that are awaited directly) 33 // but also has a .returning() method (for role inserts) 34 const resolvedPromise = Promise.resolve(undefined); 35 const valuesResult = Object.assign(resolvedPromise, { 36 returning: vi.fn().mockResolvedValue([{ id }]), 37 }); 38 return { 39 values: vi.fn().mockReturnValue(valuesResult), 40 }; 41 }), 42 } as any; 43 } 44 45 function mockAgent() { 46 let callCount = 0; 47 return { 48 com: { 49 atproto: { 50 repo: { 51 createRecord: vi.fn().mockImplementation(() => { 52 callCount++; 53 return Promise.resolve({ 54 data: { 55 uri: `at://${forumDid}/space.atbb.forum.role/tid${callCount}`, 56 cid: `bafynew${callCount}`, 57 }, 58 }); 59 }), 60 }, 61 }, 62 }, 63 } as any; 64 } 65 66 it("exports DEFAULT_ROLES with correct structure", () => { 67 expect(DEFAULT_ROLES).toHaveLength(4); 68 expect(DEFAULT_ROLES[0].name).toBe("Owner"); 69 expect(DEFAULT_ROLES[0].priority).toBe(0); 70 expect(DEFAULT_ROLES[3].name).toBe("Member"); 71 expect(DEFAULT_ROLES[3].priority).toBe(30); 72 }); 73 74 it("creates all roles on PDS and DB when none exist", async () => { 75 const db = mockDb(); 76 const agent = mockAgent(); 77 78 const result = await seedDefaultRoles(db, agent, forumDid); 79 80 expect(result.created).toBe(4); 81 expect(result.skipped).toBe(0); 82 expect(agent.com.atproto.repo.createRecord).toHaveBeenCalledTimes(4); 83 // Verify DB insertions: 4 role inserts + 4 rolePermissions inserts (one per role) 84 expect(db.insert).toHaveBeenCalledTimes(8); 85 // Verify returned role data 86 expect(result.roles).toHaveLength(4); 87 expect(result.roles[0].name).toBe("Owner"); 88 expect(result.roles[0].uri).toContain("space.atbb.forum.role/"); 89 expect(result.roles[0].cid).toBeTruthy(); 90 }); 91 92 it("skips existing roles and returns their data", async () => { 93 // Simulate Owner and Admin already existing 94 const db = mockDb(["Owner", "Admin"]); 95 const agent = mockAgent(); 96 97 const result = await seedDefaultRoles(db, agent, forumDid); 98 99 expect(result.skipped).toBe(2); 100 expect(result.created).toBe(2); 101 // All 4 roles should be in the return value 102 expect(result.roles).toHaveLength(4); 103 // Existing roles use data from DB 104 expect(result.roles[0].name).toBe("Owner"); 105 expect(result.roles[0].cid).toBe("bafyexisting-owner"); 106 // New roles use data from PDS response 107 expect(result.roles[2].name).toBe("Moderator"); 108 expect(result.roles[2].cid).toMatch(/^bafynew/); 109 }); 110});