import { describe, it, expect, vi, beforeEach } from "vitest"; import { createRequest, createRouteContext, parseJsonResponse } from "@/__tests__/helpers/api-test-utils"; import { TEST_ROOM_DATA } from "@/__tests__/helpers/fixtures"; vi.mock("@/lib/prisma", () => ({ prisma: {} })); vi.mock("@/lib/roomRepository", () => ({ atomicUpdateRoom: vi.fn(), })); vi.mock("@/lib/roomEvents", () => ({ notify: vi.fn(), })); import { POST } from "./route"; import { atomicUpdateRoom } from "@/lib/roomRepository"; const mockAtomicUpdate = vi.mocked(atomicUpdateRoom); beforeEach(() => { vi.clearAllMocks(); }); describe("POST /api/room/[id]/join", () => { it("joins a room successfully", async () => { mockAtomicUpdate.mockImplementation(async (_id, updater) => { const data = { ...TEST_ROOM_DATA, users: ["user-1"] }; return updater(data); }); const req = createRequest("/api/room/ROOM01/join", { method: "POST", body: { userId: "user-2" }, }); const ctx = createRouteContext({ id: "ROOM01" }); const res = await POST(req, ctx); const { status, data } = await parseJsonResponse(res); expect(status).toBe(200); expect(data.roomId).toBe("ROOM01"); expect(data.userCount).toBe(2); }); it("returns 403 when kicked", async () => { mockAtomicUpdate.mockImplementation(async (_id, updater) => { const data = { ...TEST_ROOM_DATA, kickedUsers: ["user-2"] }; return updater(data); }); const req = createRequest("/api/room/ROOM01/join", { method: "POST", body: { userId: "user-2" }, }); const ctx = createRouteContext({ id: "ROOM01" }); const res = await POST(req, ctx); expect(res.status).toBe(403); }); it("returns 403 when room is locked", async () => { mockAtomicUpdate.mockImplementation(async (_id, updater) => { const data = { ...TEST_ROOM_DATA, locked: true, users: ["user-1"] }; return updater(data); }); const req = createRequest("/api/room/ROOM01/join", { method: "POST", body: { userId: "user-2" }, }); const ctx = createRouteContext({ id: "ROOM01" }); const res = await POST(req, ctx); expect(res.status).toBe(403); }); it("returns 404 when room not found", async () => { mockAtomicUpdate.mockResolvedValue(null); const req = createRequest("/api/room/ABC123/join", { method: "POST", body: { userId: "user-1" }, }); const ctx = createRouteContext({ id: "ABC123" }); const res = await POST(req, ctx); expect(res.status).toBe(404); }); it("returns 401 when no userId", async () => { const req = createRequest("/api/room/ROOM01/join", { method: "POST", body: {}, }); const ctx = createRouteContext({ id: "ROOM01" }); const res = await POST(req, ctx); expect(res.status).toBe(401); }); it("returns 400 when room id format is invalid", async () => { const req = createRequest("/api/room/1234/join", { method: "POST", body: { userId: "user-1" }, }); const ctx = createRouteContext({ id: "1234" }); const res = await POST(req, ctx); expect(res.status).toBe(400); }); });