/* eslint-disable max-lines-per-function -- Test suites naturally have many cases */ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; vi.mock("../../src/db/client.js", () => ({ prisma: { player: { updateMany: vi.fn() }, }, })); vi.mock("../../src/services/logger.js", () => ({ logger: { error: vi.fn().mockResolvedValue(undefined), log: vi.fn().mockResolvedValue(undefined), }, })); import { prisma } from "../../src/db/client.js"; describe("gateway service", () => { const ORIGINAL_ENV = process.env; beforeEach(() => { process.env = { ...ORIGINAL_ENV }; vi.resetAllMocks(); }); afterEach(() => { process.env = ORIGINAL_ENV; }); describe("handleGuildMemberAdd", () => { it("sets inGuild to true for the matching guild", async () => { process.env["DISCORD_GUILD_ID"] = "guild123"; vi.mocked(prisma.player.updateMany).mockResolvedValueOnce({ count: 1 }); const { handleGuildMemberAdd } = await import("../../src/services/gateway.js"); await handleGuildMemberAdd("user123", "guild123"); expect(prisma.player.updateMany).toHaveBeenCalledWith({ data: { inGuild: true }, where: { discordId: "user123" }, }); }); it("no-ops when guild id does not match", async () => { process.env["DISCORD_GUILD_ID"] = "guild123"; const { handleGuildMemberAdd } = await import("../../src/services/gateway.js"); await handleGuildMemberAdd("user123", "other_guild"); expect(prisma.player.updateMany).not.toHaveBeenCalled(); }); it("no-ops when DISCORD_GUILD_ID env var is missing and guild does not match undefined", async () => { delete process.env["DISCORD_GUILD_ID"]; const { handleGuildMemberAdd } = await import("../../src/services/gateway.js"); await handleGuildMemberAdd("user123", "guild123"); expect(prisma.player.updateMany).not.toHaveBeenCalled(); }); it("logs error when prisma throws an Error", async () => { process.env["DISCORD_GUILD_ID"] = "guild123"; const dbError = new Error("DB failure"); vi.mocked(prisma.player.updateMany).mockRejectedValueOnce(dbError); const { handleGuildMemberAdd } = await import("../../src/services/gateway.js"); const { logger } = await import("../../src/services/logger.js"); await handleGuildMemberAdd("user123", "guild123"); expect(logger.error).toHaveBeenCalledWith("gateway_member_add", dbError); }); it("logs error when prisma throws a non-Error", async () => { process.env["DISCORD_GUILD_ID"] = "guild123"; vi.mocked(prisma.player.updateMany).mockRejectedValueOnce("raw error"); const { handleGuildMemberAdd } = await import("../../src/services/gateway.js"); const { logger } = await import("../../src/services/logger.js"); await handleGuildMemberAdd("user123", "guild123"); expect(logger.error).toHaveBeenCalledWith( "gateway_member_add", new Error("raw error"), ); }); }); describe("handleGuildMemberRemove", () => { it("sets inGuild to false for the matching guild", async () => { process.env["DISCORD_GUILD_ID"] = "guild123"; vi.mocked(prisma.player.updateMany).mockResolvedValueOnce({ count: 1 }); const { handleGuildMemberRemove } = await import("../../src/services/gateway.js"); await handleGuildMemberRemove("user123", "guild123"); expect(prisma.player.updateMany).toHaveBeenCalledWith({ data: { inGuild: false }, where: { discordId: "user123" }, }); }); it("no-ops when guild id does not match", async () => { process.env["DISCORD_GUILD_ID"] = "guild123"; const { handleGuildMemberRemove } = await import("../../src/services/gateway.js"); await handleGuildMemberRemove("user123", "other_guild"); expect(prisma.player.updateMany).not.toHaveBeenCalled(); }); it("no-ops when DISCORD_GUILD_ID env var is missing", async () => { delete process.env["DISCORD_GUILD_ID"]; const { handleGuildMemberRemove } = await import("../../src/services/gateway.js"); await handleGuildMemberRemove("user123", "guild123"); expect(prisma.player.updateMany).not.toHaveBeenCalled(); }); it("logs error when prisma throws an Error", async () => { process.env["DISCORD_GUILD_ID"] = "guild123"; const dbError = new Error("DB failure"); vi.mocked(prisma.player.updateMany).mockRejectedValueOnce(dbError); const { handleGuildMemberRemove } = await import("../../src/services/gateway.js"); const { logger } = await import("../../src/services/logger.js"); await handleGuildMemberRemove("user123", "guild123"); expect(logger.error).toHaveBeenCalledWith("gateway_member_remove", dbError); }); it("logs error when prisma throws a non-Error", async () => { process.env["DISCORD_GUILD_ID"] = "guild123"; vi.mocked(prisma.player.updateMany).mockRejectedValueOnce("raw error"); const { handleGuildMemberRemove } = await import("../../src/services/gateway.js"); const { logger } = await import("../../src/services/logger.js"); await handleGuildMemberRemove("user123", "guild123"); expect(logger.error).toHaveBeenCalledWith( "gateway_member_remove", new Error("raw error"), ); }); }); });