import { describe, it, expect, vi, beforeEach } from "vitest"; import { prismaMock, resetPrismaMock } from "@/__tests__/helpers/prisma-mock"; import { createRequest, parseJsonResponse } from "@/__tests__/helpers/api-test-utils"; import { TEST_USER } from "@/__tests__/helpers/fixtures"; vi.mock("@/lib/blindbox", () => ({ requireMembership: vi.fn().mockResolvedValue({}), })); import { POST } from "./route"; const mockCtx = { params: Promise.resolve({}) }; beforeEach(() => { resetPrismaMock(); }); describe("POST /api/blindbox/draw", () => { it("draws a random idea", async () => { prismaMock.$transaction.mockImplementation(async (fn: (tx: unknown) => Promise) => { const tx = { blindBoxIdea: { findMany: vi.fn().mockResolvedValue([{ id: "idea-1" }]), updateMany: vi.fn().mockResolvedValue({ count: 1 }), findUnique: vi.fn().mockResolvedValue({ id: "idea-1", content: "去公园", createdAt: new Date(), user: { id: "user-2", username: "submitter", avatar: "🐶" }, drawnBy: { id: "user-1", username: "drawer", avatar: "🐱" }, }), }, }; return fn(tx); }); const req = createRequest("/api/blindbox/draw", { method: "POST", body: { roomId: "bb-room-1", userId: "user-1" }, }); const res = await POST(req, mockCtx); const { status, data } = await parseJsonResponse(res); expect(status).toBe(200); expect(data.id).toBe("idea-1"); expect(data.content).toBe("去公园"); expect(data.submitter).toBeDefined(); expect(data.drawnBy).toBeDefined(); }); it("returns 404 when pool is empty", async () => { prismaMock.$transaction.mockImplementation(async (fn: (tx: unknown) => Promise) => { const tx = { blindBoxIdea: { findMany: vi.fn().mockResolvedValue([]), updateMany: vi.fn(), findUnique: vi.fn(), }, }; return fn(tx); }); const req = createRequest("/api/blindbox/draw", { method: "POST", body: { roomId: "bb-room-1", userId: "user-1" }, }); const res = await POST(req, mockCtx); expect(res.status).toBe(404); }); it("returns 409 on race condition (count=0)", async () => { prismaMock.$transaction.mockImplementation(async (fn: (tx: unknown) => Promise) => { const tx = { blindBoxIdea: { findMany: vi.fn().mockResolvedValue([{ id: "idea-1" }]), updateMany: vi.fn().mockResolvedValue({ count: 0 }), findUnique: vi.fn(), }, }; return fn(tx); }); const req = createRequest("/api/blindbox/draw", { method: "POST", body: { roomId: "bb-room-1", userId: "user-1" }, }); const res = await POST(req, mockCtx); expect(res.status).toBe(409); }); it("returns 400 when roomId is missing", async () => { const req = createRequest("/api/blindbox/draw", { method: "POST", body: { userId: "user-1" }, }); const res = await POST(req, mockCtx); expect(res.status).toBe(400); }); });