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__/lib/flock/freight-class-density.test.ts

136 lines
4.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 { describe, expect, it } from "vitest";
import {
computeFreightDensity,
densityPcfToFreightClass,
formatFreightClassDensityTip,
formatNmfcDensityClassChartZh,
freightClassDensityMismatchMessage,
NMFC_DENSITY_CLASS_BANDS,
NMFC_NON_DENSITY_FREIGHT_CLASSES,
} from "@/lib/flock/freight-class-density";
describe("freight-class-density(NMFTA 2025 十三档,对齐 Flock)", () => {
it("官网样例:6×48×40×48、2000lb → 320 ft³ / 6.25 PCF → Class 125", () => {
const d = computeFreightDensity({
lengthIn: 48,
widthIn: 40,
heightIn: 48,
quantity: 6,
totalWeightLb: 2000,
});
expect(d).not.toBeNull();
expect(d!.cubicFeet).toBeCloseTo(320, 2);
expect(d!.densityPcf).toBeCloseTo(6.25, 2);
expect(d!.suggestedClass).toBe("125");
expect(d!.rangeLabelZh).toBe("6 – <8");
expect(formatFreightClassDensityTip(d)).toContain("基于密度的货运等级:125");
});
it("官网样例:2×48×40×48、5000lb → ~46.88 PCF → Class 55", () => {
const d = computeFreightDensity({
lengthIn: 48,
widthIn: 40,
heightIn: 48,
quantity: 2,
totalWeightLb: 5000,
});
expect(d!.suggestedClass).toBe("55");
expect(d!.densityPcf).toBeCloseTo(46.875, 2);
});
it("十三档边界全部对齐 NMFTA「X but less than Y」", () => {
const cases: Array<[number, string]> = [
[0.5, "400"],
[0.999, "400"],
[1, "300"],
[1.999, "300"],
[2, "250"],
[3.999, "250"],
[4, "175"],
[5.999, "175"],
[6, "125"],
[7.999, "125"],
[8, "100"],
[9.999, "100"],
[10, "92.5"],
[11.999, "92.5"],
[12, "85"],
[14.999, "85"],
[15, "70"],
[22.499, "70"],
[22.5, "65"],
[29.999, "65"],
[30, "60"],
[34.999, "60"],
[35, "55"],
[49.999, "55"],
[50, "50"],
[100, "50"],
];
for (const [pcf, expected] of cases) {
expect(densityPcfToFreightClass(pcf), `pcf=${pcf}`).toBe(expected);
}
});
it("密度推算绝不会落到商品条件档 77.5/110/150/200/500", () => {
const densClasses = new Set(
NMFC_DENSITY_CLASS_BANDS.map((b) => b.freightClass),
);
for (const c of NMFC_NON_DENSITY_FREIGHT_CLASSES) {
expect(densClasses.has(c)).toBe(false);
}
// 扫一圈常见 PCF,结果必须在十三档内
for (let p = 0.1; p <= 60; p += 0.37) {
const c = densityPcfToFreightClass(p);
expect(c).not.toBeNull();
expect(densClasses.has(c!)).toBe(true);
expect(
(NMFC_NON_DENSITY_FREIGHT_CLASSES as readonly string[]).includes(c!),
).toBe(false);
}
});
it("体积↑或重量↓ → 等级数字↑(用户感知:参数越「稀」等级越高)", () => {
const base = {
lengthIn: 48,
widthIn: 40,
heightIn: 48,
quantity: 1,
totalWeightLb: 1000,
};
const dense = computeFreightDensity(base)!; // ~18.75 → 70
const bulkier = computeFreightDensity({ ...base, heightIn: 96 })!; // 体积翻倍
const lighter = computeFreightDensity({ ...base, totalWeightLb: 200 })!;
expect(Number(bulkier.suggestedClass)).toBeGreaterThan(
Number(dense.suggestedClass),
);
expect(Number(lighter.suggestedClass)).toBeGreaterThan(
Number(dense.suggestedClass),
);
});
it("分档表文案含全部十三档与非密度档说明", () => {
const chart = formatNmfcDensityClassChartZh();
for (const b of NMFC_DENSITY_CLASS_BANDS) {
expect(chart).toContain(`等级 ${b.freightClass}`);
}
expect(chart).toContain("77.5");
expect(formatFreightClassDensityTip(null)).toContain("总体积");
});
it("手选与推算不一致才提示", () => {
const d = computeFreightDensity({
lengthIn: 48,
widthIn: 40,
heightIn: 48,
quantity: 6,
totalWeightLb: 2000,
});
expect(freightClassDensityMismatchMessage("100", d)).toMatch(
/请选择货运等级 125/,
);
expect(freightClassDensityMismatchMessage("125", d)).toBeNull();
expect(freightClassDensityMismatchMessage("density", d)).toBeNull();
});
});