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.

110 lines
3.1 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 { Prisma } from "@prisma/client";
import type { QuoteRecord } from "@prisma/client";
import { describe, expect, it } from "vitest";
import {
serializeQuoteDetail,
serializeQuoteSummary,
} from "@/modules/quote/quote-serializer";
const BASE_RECORD: QuoteRecord = {
id: BigInt(1),
quoteId: "QTE_20260616_0001",
requestId: "550e8400-e29b-41d4-a716-446655440000",
customerId: "CUST_001",
cargoHash: "abc123",
status: "done",
sourceType: "cache",
isRealtime: true,
confidenceScore: null,
currency: "USD",
pickupJson: {},
deliveryJson: {},
weightLb: new Prisma.Decimal(500),
dimLIn: new Prisma.Decimal(48),
dimWIn: new Prisma.Decimal(40),
dimHIn: new Prisma.Decimal(48),
palletCount: 2,
cargoType: "general_freight",
quotesJson: [{ service_level: "standard" }],
markupPercent: new Prisma.Decimal(0),
validUntil: new Date(Date.now() + 60_000),
errorCode: null,
errorMessage: null,
ccCustomerId: null,
forecastId: null,
isDeleted: false,
createdAt: new Date(),
updatedAt: new Date(),
};
describe("serializeQuoteDetail", () => {
it("done + cache → confidence_score=0.95 + quotes", () => {
const result = serializeQuoteDetail(BASE_RECORD);
expect(result.status).toBe("done");
expect(result.confidence_score).toBe(0.95);
expect(result.source_type).toBe("cache");
expect(result.quotes).toHaveLength(1);
});
it("stale → confidence_score=0.70", () => {
const result = serializeQuoteDetail({
...BASE_RECORD,
sourceType: "stale",
isRealtime: false,
});
expect(result.confidence_score).toBe(0.7);
expect(result.is_realtime).toBe(false);
});
it("valid_until 过期 → status=expired不含 quotes", () => {
const result = serializeQuoteDetail({
...BASE_RECORD,
validUntil: new Date(Date.now() - 1_000),
});
expect(result.status).toBe("expired");
expect(result.quotes).toBeUndefined();
});
it("processing → 仅基础字段", () => {
const result = serializeQuoteDetail({
...BASE_RECORD,
status: "processing",
quotesJson: null,
validUntil: null,
});
expect(result.status).toBe("processing");
expect(result.quotes).toBeUndefined();
});
it("failed → error_code + error_message", () => {
const result = serializeQuoteDetail({
...BASE_RECORD,
status: "failed",
errorCode: "QUOTE_TIMEOUT",
errorMessage: null,
});
expect(result.status).toBe("failed");
expect(result.error_code).toBe("QUOTE_TIMEOUT");
expect(result.error_message).toContain("420 秒");
});
it("failed → 优先返回库内 error_message", () => {
const result = serializeQuoteDetail({
...BASE_RECORD,
status: "failed",
errorCode: "QUOTE_UNAVAILABLE",
errorMessage: "MotherShip 页面加载失败",
});
expect(result.error_message).toBe("MotherShip 页面加载失败");
});
});
describe("serializeQuoteSummary", () => {
it("历史摘要含关键字段", () => {
const result = serializeQuoteSummary(BASE_RECORD);
expect(result.quote_id).toBe("QTE_20260616_0001");
expect(result.pallet_count).toBe(2);
expect(result.created_at).toBeTruthy();
});
});