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