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 main 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});