import { describe, it, expect, mock, beforeEach, spyOn } from "bun:test"; import { cleanupService } from "./cleanup.service"; import { lootdrops, userTimers, userQuests } from "@/db/schema"; import { config } from "@/lib/config"; const mockDelete = mock(); const mockReturning = mock(); const mockWhere = mock(); const mockFindMany = mock(); mockDelete.mockReturnValue({ where: mockWhere }); mockWhere.mockReturnValue({ returning: mockReturning }); // Mock DrizzleClient mock.module("@/lib/DrizzleClient", () => ({ DrizzleClient: { delete: mockDelete, query: { userTimers: { findMany: mockFindMany } } } })); // Mock AuroraClient mock.module("@/lib/BotClient", () => ({ AuroraClient: { guilds: { fetch: mock().mockResolvedValue({ members: { fetch: mock().mockResolvedValue({ user: { tag: "TestUser#1234" }, roles: { remove: mock().mockResolvedValue({}) } }) } }) } } })); // Mock Config mock.module("@/lib/config", () => ({ config: { system: { cleanup: { intervalMs: 86400000, questArchiveDays: 30 } } } })); describe("cleanupService", () => { beforeEach(() => { mockDelete.mockClear(); mockWhere.mockClear(); mockReturning.mockClear(); mockFindMany.mockClear(); }); it("cleanupLootdrops should delete expired unclaimed lootdrops", async () => { mockReturning.mockResolvedValue([{ id: "msg1" }, { id: "msg2" }]); const count = await cleanupService.cleanupLootdrops(); expect(count).toBe(2); expect(mockDelete).toHaveBeenCalledWith(lootdrops); }); it("cleanupTimers should delete expired timers and handle roles", async () => { // Mock findMany for expired ACCESS timers mockFindMany.mockResolvedValue([ { userId: 123n, type: 'ACCESS', key: 'role_456', metadata: { roleId: '456' } } ]); // Mock returning for bulk delete mockReturning.mockResolvedValue([{ userId: 789n }]); // One other timer const count = await cleanupService.cleanupTimers(); // 1 from findMany + 1 from bulk delete (simplified mock behavior) expect(count).toBe(2); expect(mockDelete).toHaveBeenCalledWith(userTimers); }); it("cleanupQuests should delete old completed quests", async () => { mockReturning.mockResolvedValue([{ userId: 123n }]); const count = await cleanupService.cleanupQuests(); expect(count).toBe(1); expect(mockDelete).toHaveBeenCalledWith(userQuests); }); it("runAll should run all cleanup tasks and log stats", async () => { const spyLootdrops = spyOn(cleanupService, 'cleanupLootdrops').mockResolvedValue(1); const spyTimers = spyOn(cleanupService, 'cleanupTimers').mockResolvedValue(2); const spyQuests = spyOn(cleanupService, 'cleanupQuests').mockResolvedValue(3); await cleanupService.runAll(); expect(spyLootdrops).toHaveBeenCalled(); expect(spyTimers).toHaveBeenCalled(); expect(spyQuests).toHaveBeenCalled(); spyLootdrops.mockRestore(); spyTimers.mockRestore(); spyQuests.mockRestore(); }); });