|
|
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>): 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);
|
|
|
});
|
|
|
});
|