3ccd1262f9
基于 Vitest 搭建测试基础设施,覆盖后端纯函数、API 路由、 前端 hooks、UI 组件和页面级集成测试。
96 lines
3.0 KiB
TypeScript
96 lines
3.0 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
import { createRequest, createRouteContext, parseJsonResponse } from "@/__tests__/helpers/api-test-utils";
|
|
import { TEST_ROOM_DATA, TEST_RESTAURANT, TEST_RESTAURANT_2 } from "@/__tests__/helpers/fixtures";
|
|
|
|
vi.mock("@/lib/prisma", () => ({ prisma: {} }));
|
|
|
|
vi.mock("@/lib/store", () => ({
|
|
atomicUpdateRoom: vi.fn(),
|
|
}));
|
|
|
|
vi.mock("@/lib/roomEvents", () => ({
|
|
notify: vi.fn(),
|
|
}));
|
|
|
|
import { POST } from "./route";
|
|
import { atomicUpdateRoom } from "@/lib/store";
|
|
|
|
const mockAtomicUpdate = vi.mocked(atomicUpdateRoom);
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe("POST /api/room/[id]/reset", () => {
|
|
it("resets the room (clears likes/swipeCounts/match)", async () => {
|
|
mockAtomicUpdate.mockImplementation(async (_id, updater) => {
|
|
const data = structuredClone(TEST_ROOM_DATA);
|
|
data.likes = { "rest-1": ["user-1"] };
|
|
data.swipeCounts = { "user-1": 3 };
|
|
data.match = "rest-1";
|
|
const result = updater(data);
|
|
expect(result.likes).toEqual({});
|
|
expect(result.swipeCounts).toEqual({});
|
|
expect(result.match).toBeNull();
|
|
return result;
|
|
});
|
|
|
|
const req = createRequest("/api/room/ROOM01/reset", {
|
|
method: "POST",
|
|
body: { userId: "user-1" },
|
|
});
|
|
const ctx = createRouteContext({ id: "ROOM01" });
|
|
const res = await POST(req, ctx);
|
|
const { status, data } = await parseJsonResponse(res);
|
|
|
|
expect(status).toBe(200);
|
|
expect(data.ok).toBe(true);
|
|
});
|
|
|
|
it("filters restaurants when restaurantIds provided", async () => {
|
|
mockAtomicUpdate.mockImplementation(async (_id, updater) => {
|
|
const data = structuredClone(TEST_ROOM_DATA);
|
|
const result = updater(data);
|
|
expect(result.restaurants).toHaveLength(1);
|
|
expect(result.restaurants[0].id).toBe(TEST_RESTAURANT.id);
|
|
return result;
|
|
});
|
|
|
|
const req = createRequest("/api/room/ROOM01/reset", {
|
|
method: "POST",
|
|
body: { userId: "user-1", restaurantIds: [TEST_RESTAURANT.id] },
|
|
});
|
|
const ctx = createRouteContext({ id: "ROOM01" });
|
|
await POST(req, ctx);
|
|
});
|
|
|
|
it("returns 403 when not a member or creator", async () => {
|
|
mockAtomicUpdate.mockImplementation(async (_id, updater) => {
|
|
const data = structuredClone(TEST_ROOM_DATA);
|
|
data.users = ["other-user"];
|
|
data.creatorId = "other-user";
|
|
return updater(data);
|
|
});
|
|
|
|
const req = createRequest("/api/room/ROOM01/reset", {
|
|
method: "POST",
|
|
body: { userId: "user-1" },
|
|
});
|
|
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/NONEXIST/reset", {
|
|
method: "POST",
|
|
body: { userId: "user-1" },
|
|
});
|
|
const ctx = createRouteContext({ id: "NONEXIST" });
|
|
const res = await POST(req, ctx);
|
|
expect(res.status).toBe(404);
|
|
});
|
|
});
|