import { describe, expect, it } from "vitest"; import { AXEL_QUOTE_BODY, AXEL_QUOTE_URL, } from "@/__tests__/fixtures/axel-quote"; import { decodeAxelQuoteBodyLenient, decodeQuoteDetailsParam, decodeQuotePayloads, decodeEmbeddedJsonBodies, } from "@/workers/rpa/quote-capture/payload-decode"; import { formatPinnedTelemetry, isJsonNetworkCandidate, parsePinnedQuoteApiPatterns, } from "@/workers/rpa/quote-capture/constants"; import { assertQuoteContract, inspectQuoteContract, satisfiesQuoteContract, } from "@/workers/rpa/quote-capture/quote-contract-guard"; import { validateQuoteSchema } from "@/workers/rpa/quote-capture/quote-schema-validator"; import type { QuoteCaptureSignals } from "@/workers/rpa/quote-capture/types"; import { RpaError } from "@/modules/rpa/errors"; const validRatesBody = { rates: { standard: { lowest: { price: 612.72, transitDays: "5 business days" }, fastest: { price: 694.02, transitDays: "3 business days" }, }, guaranteed: { lowest: { price: 800, transitDays: "5 business days" }, fastest: { price: 900, transitDays: "2 business days" }, }, }, }; describe("quote contract guard", () => { it("满足 rates.standard.lowest + rates.standard.fastest + rates.guaranteed", () => { expect(satisfiesQuoteContract(validRatesBody)).toBe(true); }); it("缺少 rates.guaranteed 时 fail", () => { const result = inspectQuoteContract({ rates: { standard: { lowest: { price: 1 }, fastest: { price: 2 }, }, }, }); expect(result.ok).toBe(false); if (!result.ok) { expect(result.violations.some((v) => v.path.includes("guaranteed"))).toBe( true, ); } }); it("缺少 fastest 时 fail", () => { const result = inspectQuoteContract({ rates: { standard: { lowest: { price: 1 } }, guaranteed: { lowest: { price: 2 } }, }, }); expect(result.ok).toBe(false); }); it("assertQuoteContract 抛 RPA_DATA_INVALID", () => { expect(() => assertQuoteContract({ foo: 1 }, "test-url")).toThrow(RpaError); }); it("接受 rates.fastest 顶层", () => { expect( satisfiesQuoteContract({ rates: { standard: { lowest: { price: 10 } }, fastest: { price: 20, transitDays: "2d" }, guaranteed: { lowest: { price: 30 } }, }, }), ).toBe(true); }); it("接受 axel guaranteed.bestValue 作为 guaranteed 定价(阶段0 录证)", () => { expect(satisfiesQuoteContract(AXEL_QUOTE_BODY)).toBe(true); }); }); describe("isJsonNetworkCandidate", () => { it("JSON 响应通过(与 URL 路径无关)", () => { expect( isJsonNetworkCandidate( "https://any-host.example/unknown-path", "application/json", ), ).toBe(true); }); it("忽略 segment 静态埋点", () => { expect( isJsonNetworkCandidate( "https://api.segment.io/v1/track", "application/json", ), ).toBe(false); }); }); describe("pinned telemetry", () => { it("parsePinnedQuoteApiPatterns 仅用于校准日志", () => { process.env.MOTHERSHIP_QUOTE_API_URL_PATTERNS = "api.mothership.com/quotes"; expect( formatPinnedTelemetry("https://api.mothership.com/quotes/x"), ).toBe("pinned=match"); expect(formatPinnedTelemetry("https://other.example/x")).toBe("pinned=miss"); delete process.env.MOTHERSHIP_QUOTE_API_URL_PATTERNS; }); it("未配置 pinned 时 telemetry 提示未配置", () => { delete process.env.MOTHERSHIP_QUOTE_API_URL_PATTERNS; expect(formatPinnedTelemetry("https://x")).toBe("pinned=未配置"); }); }); describe("decodeQuoteDetailsParam", () => { it("解码 URL 编码 JSON(诊断用,非报价路径)", () => { const inner = JSON.stringify({ pickupLocation: { city: "Denver", zip: "80203" }, freight: { quantity: 2, weightLbs: 500 }, }); const encoded = encodeURIComponent(inner); expect(decodeQuoteDetailsParam(encoded)).toMatchObject({ pickupLocation: { city: "Denver" }, }); }); }); describe("decodeQuotePayloads", () => { function signals(overrides: Partial): QuoteCaptureSignals { return { contractPayloads: [], jsonPayloads: [], resultUrl: "https://www.mothership.com/", ...overrides, }; } it("data.rates 嵌套解析标准 Tab 档位", () => { const result = decodeQuotePayloads( signals({ contractPayloads: [ { url: "https://api.example/graphql", body: { data: { rates: validRatesBody.rates } }, }, ], }), ); expect(result?.items).toHaveLength(4); }); it("契约响应解析标准 Tab 档位", () => { const result = decodeQuotePayloads( signals({ contractPayloads: [ { url: "https://any.example/rates", body: validRatesBody }, ], }), ); expect(result?.source).toBe("contract"); expect(result?.items).toHaveLength(4); expect( result?.items.find( (i) => i.serviceLevel === "standard" && i.rateOption === "lowest", )?.rawFreight, ).toBe(612.72); }); it("axel/quote 响应解析全部档位(标准 3 + guaranteed.bestValue)", () => { const decoded = decodeQuotePayloads( signals({ contractPayloads: [{ url: AXEL_QUOTE_URL, body: AXEL_QUOTE_BODY }], }), ); const items = validateQuoteSchema(decoded!.items); expect(items).toHaveLength(4); expect( items.find( (i) => i.serviceLevel === "standard" && i.rateOption === "bestValue", )?.rawFreight, ).toBe(576.24); expect( items.find( (i) => i.serviceLevel === "standard" && i.rateOption === "lowest", )?.rawFreight, ).toBe(428.48); expect( items.find( (i) => i.serviceLevel === "standard" && i.rateOption === "fastest", )?.transitDays, ).toBe("Est. 3 business days"); expect( items.find( (i) => i.serviceLevel === "guaranteed" && i.rateOption === "bestValue", )?.rawFreight, ).toBe(814.15); }); it("2+2 动态档位:仅返回 API 存在的四档", () => { const body = { data: { rates: { standard: { lowest: { finalPrice: 100, days: 4, serviceType: "lowest" }, fastest: { finalPrice: 120, days: 2, serviceType: "fastest" }, }, guaranteed: { lowest: { finalPrice: 200, days: 3, serviceType: "lowest" }, bestValue: { finalPrice: 220, days: 2, serviceType: "bestValue" }, }, }, }, }; const items = validateQuoteSchema( decodeQuotePayloads( signals({ contractPayloads: [{ url: AXEL_QUOTE_URL, body }], }), )!.items, ); expect(items).toHaveLength(4); }); it("基线 UI 截图五档:标准 3 + 保证送达 2(finalPrice)", () => { const body = { data: { rates: { standard: { lowest: { finalPrice: 287.23, days: 4, serviceType: "lowest" }, bestValue: { finalPrice: 345, days: 3, serviceType: "bestValue" }, fastest: { finalPrice: 369.72, days: 2, serviceType: "fastest" }, }, guaranteed: { lowest: { finalPrice: 457.36, days: 3, serviceType: "lowest" }, bestValue: { finalPrice: 480.37, days: 2, serviceType: "bestValue" }, }, }, availableRates: {}, }, }; const decoded = decodeQuotePayloads( signals({ contractPayloads: [{ url: AXEL_QUOTE_URL, body }], }), ); const items = validateQuoteSchema(decoded!.items); expect(items).toHaveLength(5); expect(items.find((i) => i.serviceLevel === "standard" && i.rateOption === "lowest")?.rawFreight).toBe(287.23); expect(items.find((i) => i.serviceLevel === "standard" && i.rateOption === "bestValue")?.rawFreight).toBe(345); expect(items.find((i) => i.serviceLevel === "standard" && i.rateOption === "fastest")?.rawFreight).toBe(369.72); expect(items.find((i) => i.serviceLevel === "guaranteed" && i.rateOption === "lowest")?.rawFreight).toBe(457.36); expect(items.find((i) => i.serviceLevel === "guaranteed" && i.rateOption === "bestValue")?.rawFreight).toBe(480.37); }); it("availableRates extended 不覆盖 UI 叶节点 finalPrice", () => { const body = { data: { rates: { standard: { lowest: { id: "rate_x", finalPrice: 287.23, price: 478.46, days: 4, serviceType: "lowest", }, fastest: { id: "rate_y", finalPrice: 369.72, price: 2069.46, days: 2, serviceType: "fastest", }, bestValue: { id: "rate_z", finalPrice: 345, price: 500, days: 3, serviceType: "bestValue", }, }, guaranteed: { lowest: { finalPrice: 457.36, days: 3, serviceType: "lowest" }, bestValue: { finalPrice: 480.37, days: 2, serviceType: "bestValue" }, }, }, availableRates: { rate_x: { price: 478.46, serviceType: "customRate", serviceLevel: "standard", }, }, }, }; const decoded = decodeQuotePayloads( signals({ contractPayloads: [{ url: "https://services.mothership.com/axel/quote", body }], }), ); const items = validateQuoteSchema(decoded!.items); expect(items).toHaveLength(5); expect( items.find((i) => i.serviceLevel === "standard" && i.rateOption === "lowest")?.rawFreight, ).toBe(287.23); expect( items.find((i) => i.serviceLevel === "standard" && i.rateOption === "fastest")?.rawFreight, ).toBe(369.72); expect( items.find((i) => i.serviceLevel === "standard" && i.rateOption === "bestValue")?.rawFreight, ).toBe(345); expect( items.find((i) => i.serviceLevel === "guaranteed" && i.rateOption === "lowest")?.rawFreight, ).toBe(457.36); }); it("rates 已声明 UI 槽位时禁止 customRate 推断伪档位(3+1)", () => { const body = { data: { rates: { standard: { lowest: { finalPrice: 310.01, days: 8, serviceType: "lowest" }, bestValue: { finalPrice: 566.33, days: 5, serviceType: "bestValue" }, fastest: { finalPrice: 768.88, days: 4, serviceType: "fastest" }, }, guaranteed: { bestValue: { finalPrice: 698.81, days: 5, serviceType: "bestValue" }, }, }, availableRates: { junk_g1: { finalPrice: 704.38, days: 5, serviceLevel: "guaranteed", serviceType: "customRate", carrierInfo: { name: "TForce" }, }, junk_g2: { finalPrice: 566.33, days: 2, serviceLevel: "standard", serviceType: "customRate", carrierInfo: { name: "Daylight Transport" }, }, junk_g3: { finalPrice: 650.99, days: 6, serviceLevel: "standard", serviceType: "customRate", carrierInfo: { name: "Roadrunner Transportation Service" }, }, }, }, }; const items = validateQuoteSchema(decodeAxelQuoteBodyLenient(body)!); expect(items).toHaveLength(4); expect( items.find( (i) => i.serviceLevel === "guaranteed" && i.rateOption === "lowest", ), ).toBeUndefined(); expect( items.find( (i) => i.serviceLevel === "guaranteed" && i.rateOption === "fastest", ), ).toBeUndefined(); expect( items.find( (i) => i.serviceLevel === "standard" && i.rateOption === "lowest", )?.rawFreight, ).toBe(310.01); }); it("rates 声明 bestValue 槽位且叶节点为空时从 availableRates 补全", () => { const body = { data: { rates: { standard: { lowest: { finalPrice: 503.98, days: 4, serviceType: "lowest" }, fastest: { finalPrice: 597.89, days: 2, serviceType: "fastest" }, bestValue: {}, }, guaranteed: { bestValue: { finalPrice: 954.25, days: 2, serviceType: "bestValue" }, }, }, availableRates: { rate_bv: { finalPrice: 545.5, days: 3, serviceLevel: "standard", serviceType: "bestValue", }, }, }, }; const items = validateQuoteSchema(decodeAxelQuoteBodyLenient(body)!); expect(items).toHaveLength(4); expect( items.find( (i) => i.serviceLevel === "standard" && i.rateOption === "bestValue", )?.rawFreight, ).toBe(545.5); }); it("rates.standard.fastest 为 id 引用时从 availableRates 解析", () => { const body = { data: { rates: { standard: { lowest: { finalPrice: 310.01, days: 8, serviceType: "lowest" }, bestValue: { finalPrice: 566.33, days: 5, serviceType: "bestValue" }, fastest: { id: "rate_fast" }, }, guaranteed: { bestValue: { finalPrice: 698.81, days: 5, serviceType: "bestValue" }, }, }, availableRates: { rate_fast: { finalPrice: 768.88, days: 4, serviceLevel: "standard", serviceType: "fastest", carrierInfo: { name: "XPO Logistics" }, }, }, }, }; const items = validateQuoteSchema(decodeAxelQuoteBodyLenient(body)!); expect(items).toHaveLength(4); expect( items.find( (i) => i.serviceLevel === "standard" && i.rateOption === "fastest", )?.rawFreight, ).toBe(768.88); }); it("standard 缺 fastest 键时从 availableRates 显式 serviceType 补档", () => { const body = { data: { rates: { standard: { lowest: { finalPrice: 310.01, days: 8, serviceType: "lowest" }, bestValue: { finalPrice: 566.33, days: 5, serviceType: "bestValue" }, }, guaranteed: { bestValue: { finalPrice: 698.81, days: 5, serviceType: "bestValue" }, }, }, availableRates: { rate_fast: { finalPrice: 768.88, days: 4, serviceLevel: "standard", serviceType: "fastest", }, }, }, }; const items = validateQuoteSchema(decodeAxelQuoteBodyLenient(body)!); expect( items.find( (i) => i.serviceLevel === "standard" && i.rateOption === "fastest", )?.rawFreight, ).toBe(768.88); }); it("无契约响应返回 null", () => { expect(decodeQuotePayloads(signals({}))).toBeNull(); }); it("不满足契约且无法 lenient 解码时返回 null", () => { expect( decodeQuotePayloads( signals({ contractPayloads: [ { url: "https://x", body: { rates: { standard: { lowest: { price: 1 } } } } }, ], }), ), ).toBeNull(); }); it("sign-up-quote 页 axel/quote 契约不全时走 lenient", () => { const body = { data: { rates: { standard: {}, guaranteed: {}, dedicated: {} }, availableRates: { rate_a: { finalPrice: 612.72, price: 600, days: 3, serviceLevel: "standard", serviceType: "customRate", }, rate_b: { finalPrice: 890.12, price: 880, days: 2, serviceLevel: "standard", serviceType: "customRate", }, }, }, }; const decoded = decodeQuotePayloads( signals({ resultUrl: "https://www.mothership.com/sign-up-quote?quote-details=abc", contractPayloads: [ { url: "https://services.mothership.com/axel/quote", body }, ], }), ); expect(decoded?.source).toBe("lenient"); expect( decoded?.items.find( (i) => i.serviceLevel === "standard" && i.rateOption === "lowest", )?.rawFreight, ).toBe(612.72); }); }); describe("decodeEmbeddedJsonBodies", () => { it("已废弃,始终返回 null", () => { expect(decodeEmbeddedJsonBodies([{ rates: validRatesBody }])).toBeNull(); }); }); describe("decodeAxelQuoteBodyLenient", () => { it("rates 缺 standard/lowest 时从 availableRates customRate 推断", () => { const body = { data: { rates: { standard: {}, guaranteed: {}, dedicated: {}, }, availableRates: { rate_a: { finalPrice: 927.48, price: 922.49, days: 3, serviceLevel: "standard", serviceType: "customRate", carrierInfo: { name: "ABF Freight" }, }, rate_b: { finalPrice: 1100.12, price: 1095.13, days: 2, serviceLevel: "standard", serviceType: "customRate", carrierInfo: { name: "Saia" }, }, }, }, }; const items = decodeAxelQuoteBodyLenient(body); expect(items).not.toBeNull(); expect( items!.find((i) => i.serviceLevel === "standard" && i.rateOption === "lowest") ?.rawTotal, ).toBe(927.48); expect( items!.find((i) => i.serviceLevel === "standard" && i.rateOption === "fastest") ?.rawTotal, ).toBe(1100.12); }); });