import { beforeEach, describe, expect, it, vi } from "vitest"; import { appRouter } from "./routers"; import * as db from "./db"; import type { TrpcContext } from "./_core/context"; vi.mock("./db", () => ({ findInspectionTaskByModelAndName: vi.fn(async () => undefined), createInspectionTaskWithDefaults: vi.fn(async (data) => ({ task: { id: 1, modelId: data.modelId, inspectionObjectId: data.inspectionObjectId, name: data.name, inspector: data.inspector ?? null, notes: data.notes ?? null, status: data.status, createdAt: new Date(), updatedAt: new Date(), completedAt: null }, pointcloudFile: { id: 11, taskId: 1 }, cadFile: { id: 12, taskId: 1 }, })), })); type AuthenticatedUser = NonNullable; function createAuthContext(): TrpcContext { const user: AuthenticatedUser = { id: 1, username: "test-user", passwordHash: null, email: "test@example.com", name: "Test User", role: "admin", isActive: 1, mustChangePassword: 0, sessionVersion: 0, createdAt: new Date(), updatedAt: new Date(), lastLoginAt: new Date(), }; return { user, req: { protocol: "https", headers: {}, } as TrpcContext["req"], res: { clearCookie: vi.fn(), } as unknown as TrpcContext["res"], }; } describe("inspection task router", () => { beforeEach(() => { vi.clearAllMocks(); vi.mocked(db.findInspectionTaskByModelAndName).mockResolvedValue(undefined); }); it("trims name and creates a task in created status", async () => { const ctx = createAuthContext(); const caller = appRouter.createCaller(ctx); const result = await caller.inspectionTask.create({ modelId: 1, inspectionObjectId: 9, name: " 首检任务 ", }); expect(result.task.status).toBe("created"); expect(db.findInspectionTaskByModelAndName).toHaveBeenCalledWith(1, "首检任务"); expect(db.createInspectionTaskWithDefaults).toHaveBeenCalledWith({ modelId: 1, inspectionObjectId: 9, name: "首检任务", inspector: null, notes: null, status: "created", }); }); it("returns CONFLICT when the same model already has the task name", async () => { vi.mocked(db.findInspectionTaskByModelAndName).mockResolvedValueOnce({ id: 1, modelId: 1, inspectionObjectId: 9, name: "首检任务", inspector: null, notes: null, status: "created", createdAt: new Date(), updatedAt: new Date(), completedAt: null, }); const ctx = createAuthContext(); const caller = appRouter.createCaller(ctx); await expect(caller.inspectionTask.create({ modelId: 1, inspectionObjectId: 9, name: "首检任务", })).rejects.toMatchObject({ code: "CONFLICT", message: "该车型下已存在同名检测任务。", }); expect(db.createInspectionTaskWithDefaults).not.toHaveBeenCalled(); }); it("returns CONFLICT when the database unique key rejects a concurrent duplicate", async () => { vi.mocked(db.createInspectionTaskWithDefaults).mockRejectedValueOnce({ code: "ER_DUP_ENTRY", errno: 1062, message: "Duplicate entry '1-首检任务' for key 'uk_inspection_tasks_model_name'", }); const ctx = createAuthContext(); const caller = appRouter.createCaller(ctx); await expect(caller.inspectionTask.create({ modelId: 1, inspectionObjectId: 9, name: "首检任务", })).rejects.toMatchObject({ code: "CONFLICT", message: "该车型下已存在同名检测任务。", }); }); });