import { describe, it, expect, mock, beforeEach } from "bun:test"; import { temporaryRoleService } from "@shared/modules/system/temp-role.service"; import { userTimers } from "@db/schema"; import { TimerType } from "@shared/lib/constants"; const mockDelete = mock(); const mockWhere = mock(); const mockFindMany = mock(); mockDelete.mockReturnValue({ where: mockWhere }); // Mock DrizzleClient mock.module("@shared/db/DrizzleClient", () => ({ DrizzleClient: { delete: mockDelete, query: { userTimers: { findMany: mockFindMany } } } })); // Mock AuroraClient const mockRemoveRole = mock(); const mockFetchMember = mock(); const mockFetchGuild = mock(); mock.module("@/lib/BotClient", () => ({ AuroraClient: { guilds: { fetch: mockFetchGuild } } })); mock.module("@shared/lib/env", () => ({ env: { DISCORD_GUILD_ID: "guild123" } })); describe("temporaryRoleService", () => { beforeEach(() => { mockDelete.mockClear(); mockWhere.mockClear(); mockFindMany.mockClear(); mockRemoveRole.mockClear(); mockFetchMember.mockClear(); mockFetchGuild.mockClear(); mockFetchGuild.mockResolvedValue({ members: { fetch: mockFetchMember } }); mockFetchMember.mockResolvedValue({ user: { tag: "TestUser#1234" }, roles: { remove: mockRemoveRole } }); }); it("should revoke expired roles and delete timers", async () => { // Mock findMany to return an expired role timer mockFindMany.mockResolvedValue([ { userId: 123n, type: TimerType.ACCESS, key: 'role_456', expiresAt: new Date(Date.now() - 1000), metadata: { roleId: '456' } } ]); const count = await temporaryRoleService.processExpiredRoles(); expect(count).toBe(1); expect(mockFetchGuild).toHaveBeenCalledWith("guild123"); expect(mockFetchMember).toHaveBeenCalledWith("123"); expect(mockRemoveRole).toHaveBeenCalledWith("456"); expect(mockDelete).toHaveBeenCalledWith(userTimers); }); it("should still delete the timer even if member is not found", async () => { mockFindMany.mockResolvedValue([ { userId: 999n, type: TimerType.ACCESS, key: 'role_789', expiresAt: new Date(Date.now() - 1000), metadata: {} } ]); // Mock member fetch failure mockFetchMember.mockRejectedValue(new Error("Member not found")); const count = await temporaryRoleService.processExpiredRoles(); expect(count).toBe(1); expect(mockRemoveRole).not.toHaveBeenCalled(); expect(mockDelete).toHaveBeenCalledWith(userTimers); }); it("should return 0 if no expired timers exist", async () => { mockFindMany.mockResolvedValue([]); const count = await temporaryRoleService.processExpiredRoles(); expect(count).toBe(0); expect(mockDelete).not.toHaveBeenCalled(); }); });