You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chajia/__tests__/api/flock-hold-routes.test.ts

134 lines
4.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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/flock/hold-service", () => ({
declineFlockQuoteHold: vi.fn(),
continueFlockQuoteHold: vi.fn(),
}));
import { parseServiceAuth, assertCustomerMatch } from "@/lib/api/auth-context";
import { POST as declinePost } from "@/app/api/quotes/flock-hold/decline/route";
import { POST as continuePost } from "@/app/api/quotes/flock-hold/continue/route";
import {
continueFlockQuoteHold,
declineFlockQuoteHold,
} from "@/modules/flock/hold-service";
import { FLOCK_HOLD_MSG } from "@/lib/constants/flock-quote-hold";
const SESSION = "flock_q1";
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("flock-hold continue / decline API", () => {
beforeEach(() => {
vi.clearAllMocks();
authOk();
});
it("decline:缺 session → 400 中文", async () => {
const res = await declinePost(
jsonReq("http://localhost/api/quotes/flock-hold/decline", {
customer_id: "CUST_001",
quote_id: "q1",
}),
);
expect(res.status).toBe(400);
const body = await res.json();
expect(body.code).not.toBe(0);
expect(String(body.message)).toMatch(/询价会话|会话标识|Required/);
});
it("decline:非法 JSON → 400", async () => {
const res = await declinePost(
new Request("http://localhost/api/quotes/flock-hold/decline", {
method: "POST",
headers: { "content-type": "application/json" },
body: "{",
}),
);
expect(res.status).toBe(400);
});
it("decline:成功 → released", async () => {
vi.mocked(declineFlockQuoteHold).mockResolvedValue({ released: true });
const res = await declinePost(
jsonReq("http://localhost/api/quotes/flock-hold/decline", {
customer_id: "CUST_001",
quote_id: "q1",
quote_session_id: SESSION,
}),
);
const body = await res.json();
expect(body.code).toBe(0);
expect(body.data.released).toBe(true);
});
it("continue:成功 → filling", async () => {
vi.mocked(continueFlockQuoteHold).mockResolvedValue({ status: "filling" });
const res = await continuePost(
jsonReq("http://localhost/api/quotes/flock-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:60s 超时业务错误 → 400 中文", async () => {
vi.mocked(continueFlockQuoteHold).mockRejectedValue(
new Error(FLOCK_HOLD_MSG.decisionTimeoutApi),
);
const res = await continuePost(
jsonReq("http://localhost/api/quotes/flock-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).toBe(FLOCK_HOLD_MSG.decisionTimeoutApi);
});
it("continue:5min 超时 → 400 中文含 5 分钟", async () => {
vi.mocked(continueFlockQuoteHold).mockRejectedValue(
new Error(FLOCK_HOLD_MSG.totalTimeoutApi),
);
const res = await continuePost(
jsonReq("http://localhost/api/quotes/flock-hold/continue", {
customer_id: "CUST_001",
quote_id: "q1",
quote_session_id: SESSION,
}),
);
const body = await res.json();
expect(body.message).toMatch(/5 分钟/);
});
});