generated from nhcarrigan/template
5025948530
- Grant Elysian Discord role to players on OAuth login (new and returning) - Add inGuild flag to Player schema, seeded from role grant response - Connect Discord Gateway WebSocket to keep inGuild in sync on join/leave - Return inGuild from load endpoint; expose in game context - Show join community modal once per session when inGuild is false
129 lines
5.2 KiB
TypeScript
129 lines
5.2 KiB
TypeScript
/* 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"),
|
|
);
|
|
});
|
|
});
|
|
});
|