|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
|
|
vi.mock("@/lib/api/auth-context", () => ({
|
|
|
parseServiceAuth: vi.fn(),
|
|
|
assertCustomerMatch: vi.fn(),
|
|
|
}));
|
|
|
|
|
|
vi.mock("@/lib/api/rate-limit", () => ({
|
|
|
enforceRateLimits: vi.fn().mockResolvedValue(null),
|
|
|
}));
|
|
|
|
|
|
vi.mock("@/modules/mothership/refine-service", () => ({
|
|
|
declineMsRefineHold: vi.fn(),
|
|
|
continueMsRefineHold: vi.fn(),
|
|
|
submitMsRefineDetails: vi.fn(),
|
|
|
}));
|
|
|
|
|
|
import { parseServiceAuth, assertCustomerMatch } from "@/lib/api/auth-context";
|
|
|
import { POST as declinePost } from "@/app/api/quotes/refine-hold/decline/route";
|
|
|
import { POST as continuePost } from "@/app/api/quotes/refine-hold/continue/route";
|
|
|
import { POST as refineDetailsPost } from "@/app/api/quotes/refine-details/route";
|
|
|
import {
|
|
|
continueMsRefineHold,
|
|
|
declineMsRefineHold,
|
|
|
submitMsRefineDetails,
|
|
|
} from "@/modules/mothership/refine-service";
|
|
|
|
|
|
const SESSION = "00000000-0000-4000-8000-000000000001";
|
|
|
|
|
|
function authOk() {
|
|
|
vi.mocked(parseServiceAuth).mockResolvedValue({
|
|
|
authType: "service",
|
|
|
customerId: "CUST_001",
|
|
|
permissions: [],
|
|
|
} as never);
|
|
|
vi.mocked(assertCustomerMatch).mockImplementation(() => undefined);
|
|
|
}
|
|
|
|
|
|
function jsonReq(url: string, body: unknown) {
|
|
|
return new Request(url, {
|
|
|
method: "POST",
|
|
|
headers: { "content-type": "application/json" },
|
|
|
body: JSON.stringify(body),
|
|
|
});
|
|
|
}
|
|
|
|
|
|
describe("refine-hold / refine-details API", () => {
|
|
|
beforeEach(() => {
|
|
|
vi.clearAllMocks();
|
|
|
authOk();
|
|
|
});
|
|
|
|
|
|
it("decline:参数非法 → 400", async () => {
|
|
|
const res = await declinePost(
|
|
|
jsonReq("http://localhost/api/quotes/refine-hold/decline", {
|
|
|
customer_id: "CUST_001",
|
|
|
quote_id: "q1",
|
|
|
quote_session_id: "not-uuid",
|
|
|
}),
|
|
|
);
|
|
|
expect(res.status).toBe(400);
|
|
|
const body = await res.json();
|
|
|
expect(body.code).not.toBe(0);
|
|
|
});
|
|
|
|
|
|
it("decline:成功 → ok released", async () => {
|
|
|
vi.mocked(declineMsRefineHold).mockResolvedValue({ released: true });
|
|
|
const res = await declinePost(
|
|
|
jsonReq("http://localhost/api/quotes/refine-hold/decline", {
|
|
|
customer_id: "CUST_001",
|
|
|
quote_id: "q1",
|
|
|
quote_session_id: SESSION,
|
|
|
}),
|
|
|
);
|
|
|
expect(res.status).toBe(200);
|
|
|
const body = await res.json();
|
|
|
expect(body.code).toBe(0);
|
|
|
expect(body.data.released).toBe(true);
|
|
|
});
|
|
|
|
|
|
it("continue:成功 → filling", async () => {
|
|
|
vi.mocked(continueMsRefineHold).mockResolvedValue({ status: "filling" });
|
|
|
const res = await continuePost(
|
|
|
jsonReq("http://localhost/api/quotes/refine-hold/continue", {
|
|
|
customer_id: "CUST_001",
|
|
|
quote_id: "q1",
|
|
|
quote_session_id: SESSION,
|
|
|
}),
|
|
|
);
|
|
|
const body = await res.json();
|
|
|
expect(body.code).toBe(0);
|
|
|
expect(body.data.status).toBe("filling");
|
|
|
});
|
|
|
|
|
|
it("continue:业务超时 → 400 中文", async () => {
|
|
|
vi.mocked(continueMsRefineHold).mockRejectedValue(
|
|
|
new Error("确认窗口已超时,请重新询价"),
|
|
|
);
|
|
|
const res = await continuePost(
|
|
|
jsonReq("http://localhost/api/quotes/refine-hold/continue", {
|
|
|
customer_id: "CUST_001",
|
|
|
quote_id: "q1",
|
|
|
quote_session_id: SESSION,
|
|
|
}),
|
|
|
);
|
|
|
expect(res.status).toBe(400);
|
|
|
const body = await res.json();
|
|
|
expect(body.message).toMatch(/确认窗口已超时/);
|
|
|
});
|
|
|
|
|
|
it("refine-details:成功入队", async () => {
|
|
|
vi.mocked(submitMsRefineDetails).mockResolvedValue({
|
|
|
quote_id: "q1",
|
|
|
status: "processing",
|
|
|
});
|
|
|
const res = await refineDetailsPost(
|
|
|
jsonReq("http://localhost/api/quotes/refine-details", {
|
|
|
customer_id: "CUST_001",
|
|
|
quote_id: "q1",
|
|
|
quote_session_id: SESSION,
|
|
|
mothership_details: { pickup: { company_name: "Acme" } },
|
|
|
}),
|
|
|
);
|
|
|
const body = await res.json();
|
|
|
expect(body.code).toBe(0);
|
|
|
expect(body.data.status).toBe("processing");
|
|
|
});
|
|
|
|
|
|
it("refine-details:缺 quote_id → 校验失败", async () => {
|
|
|
const res = await refineDetailsPost(
|
|
|
jsonReq("http://localhost/api/quotes/refine-details", {
|
|
|
customer_id: "CUST_001",
|
|
|
quote_session_id: SESSION,
|
|
|
}),
|
|
|
);
|
|
|
expect(res.status).toBe(400);
|
|
|
});
|
|
|
});
|