import { describe, test, expect, mock, beforeEach } from "bun:test"; // The memberCache module depends on constants (prisma + redis) which are mocked // in setup.ts. We can import the functions and test their pure-logic paths. import { resolveMemberName, setMemberCache, getMemberCache, resolveMember, } from "../../src/modules/cw-utils/members/memberCache"; import { Collection } from "@discordjs/collection"; import type { CWMember } from "../../src/modules/cw-utils/members/fetchAllMembers"; function buildTestMember(overrides: Partial = {}): CWMember { return { id: 10, identifier: "jroberts", firstName: "John", lastName: "Roberts", officeEmail: "john@test.com", inactiveFlag: false, _info: {}, ...overrides, }; } describe("memberCache", () => { beforeEach(async () => { // Reset cache to empty before each test await setMemberCache(new Collection()); }); describe("setMemberCache / getMemberCache", () => { test("stores and retrieves members", async () => { const members = new Collection(); members.set("jroberts", buildTestMember()); members.set( "asmith", buildTestMember({ id: 20, identifier: "asmith", firstName: "Alice", lastName: "Smith", }), ); await setMemberCache(members); const cached = await getMemberCache(); expect(cached.size).toBe(2); expect(cached.get("jroberts")?.firstName).toBe("John"); expect(cached.get("asmith")?.firstName).toBe("Alice"); }); test("empty cache returns empty collection", async () => { const cached = await getMemberCache(); // May be empty or hydrated from redis mock (which returns null) expect(cached.size).toBe(0); }); }); describe("resolveMemberName", () => { test("returns full name when member exists", async () => { const members = new Collection(); members.set("jroberts", buildTestMember()); await setMemberCache(members); expect(resolveMemberName("jroberts")).toBe("John Roberts"); }); test("returns raw identifier when member not found", () => { expect(resolveMemberName("unknown-user")).toBe("unknown-user"); }); test("falls back to identifier if name parts are empty", async () => { const members = new Collection(); members.set( "empty", buildTestMember({ identifier: "empty", firstName: "", lastName: "" }), ); await setMemberCache(members); expect(resolveMemberName("empty")).toBe("empty"); }); }); describe("resolveMember", () => { test("returns resolved member with local user id null when no local user", async () => { const members = new Collection(); members.set("jroberts", buildTestMember()); await setMemberCache(members); const resolved = await resolveMember("jroberts"); expect(resolved.identifier).toBe("jroberts"); expect(resolved.name).toBe("John Roberts"); expect(resolved.cwMemberId).toBe(10); // prisma.user.findFirst is mocked to return null expect(resolved.id).toBeNull(); }); test("returns fallback values when member not in cache", async () => { const resolved = await resolveMember("unknown"); expect(resolved.identifier).toBe("unknown"); expect(resolved.name).toBe("unknown"); expect(resolved.cwMemberId).toBeNull(); expect(resolved.id).toBeNull(); }); }); });