import { beforeEach, describe, expect, it, vi } from "vitest"; import { generateQuoteId, handleQuoteIdConflict, isQuoteIdUniqueConflict, } from "@/modules/quote/quote-id"; import { QuoteIdConflictError } from "@/modules/quote/types"; vi.mock("@/lib/prisma", () => ({ prisma: { quoteRecord: { findFirst: vi.fn(), }, auditLog: { create: vi.fn(), }, }, })); import { prisma } from "@/lib/prisma"; const mockedFindFirst = vi.mocked(prisma.quoteRecord.findFirst); const mockedAuditCreate = vi.mocked(prisma.auditLog.create); describe("generateQuoteId", () => { beforeEach(() => { mockedFindFirst.mockReset(); }); it("首日生成 _0001", async () => { mockedFindFirst.mockResolvedValue(null); const id = await generateQuoteId(); expect(id).toMatch(/^QTE_\d{8}_0001$/); }); it("递增序号", async () => { mockedFindFirst.mockResolvedValue({ quoteId: "QTE_20260616_0005", } as never); const id = await generateQuoteId(); expect(id).toMatch(/_0006$/); }); }); describe("isQuoteIdUniqueConflict", () => { it("P2002 quote_id → true", () => { expect( isQuoteIdUniqueConflict({ code: "P2002", meta: { target: ["quote_id"] }, }), ).toBe(true); }); it("其他错误 → false", () => { expect(isQuoteIdUniqueConflict({ code: "P2002", meta: { target: ["email"] } })).toBe(false); }); }); describe("handleQuoteIdConflict", () => { it("写 audit 并抛 QuoteIdConflictError", async () => { mockedAuditCreate.mockResolvedValue({} as never); await expect( handleQuoteIdConflict("QTE_20260616_0001", "CUST_001"), ).rejects.toThrow(QuoteIdConflictError); expect(mockedAuditCreate).toHaveBeenCalled(); }); });