import { describe, expect, it } from "vitest"; import { FLOCK_ADDITIONAL_SERVICES, FLOCK_DEFAULT_VEHICLES, FLOCK_FREIGHT_CLASSES, FLOCK_LOCATION_TYPES, FLOCK_PACKAGING_TYPES, FLOCK_VEHICLE_TYPES, getFlockLocationAccessorials, mapFlockLoggedInToApiInput, validateFlockLoggedInCargoLine, type FlockLoggedInQuotePayload, } from "@/components/flock/flock-logged-in-quote-form"; import { FLOCK_VALIDATION_MESSAGES } from "@/lib/constants/flock-limits"; describe("flock logged-in quote form constants", () => { it("地点类型恰 12 项且无虚构 Grocery/Prison 等", () => { const ids = FLOCK_LOCATION_TYPES.map((x) => x.id); expect(ids).toHaveLength(12); expect(ids).toEqual( expect.arrayContaining([ "business_with_dock", "business_without_dock", "limited_school", "limited_airport", "limited_military", "trade_show", "residential", "limited_other", ]), ); expect(ids).not.toContain("limited_grocery"); expect(ids).not.toContain("limited_mini_storage"); expect(ids).not.toContain("limited_prison"); expect(ids).not.toContain("limited_utility"); }); it("地点类型含 Business / School / Airport / Trade Show 等", () => { const ids = FLOCK_LOCATION_TYPES.map((x) => x.id); expect(ids).toEqual( expect.arrayContaining([ "business_with_dock", "business_without_dock", "limited_school", "limited_airport", "trade_show", "residential", ]), ); }); it("调度选项按总重 >5000 动态启用", async () => { const mod = await import("@/components/flock/flock-logged-in-quote-form"); expect(mod.flockSchedulingWeightLockedHint()).toBe( "整票总重须大于 5000 lb 才可选用", ); expect( mod.isFlockSchedulingOptionLocked(4000, true), ).toBe(true); expect( mod.isFlockSchedulingOptionLocked(5001, true), ).toBe(false); expect( mod.isFlockSchedulingOptionLocked(4000, false), ).toBe(false); expect( mod.FLOCK_PICKUP_SERVICES.find((s) => s.id === "during_window") ?.weightLocked, ).toBe(true); expect( mod.FLOCK_PICKUP_SERVICES.find((s) => s.id === "standard_fcfs") ?.weightLocked, ).toBe(false); expect( mod.FLOCK_DELIVERY_SERVICES.find((s) => s.id === "need_appointment") ?.weightLocked, ).toBe(false); expect( mod.FLOCK_DELIVERY_SERVICES.find((s) => s.id === "must_arrive_by") ?.weightLocked, ).toBe(true); expect(mod.FLOCK_SCHEDULING_TIME_OPTIONS[0]).toBe("12:00 am"); expect( mod.FLOCK_PICKUP_SERVICES.find((s) => s.id === "during_window")?.detail, ).toContain("预设时段"); }); it("mapFlockLoggedInToApiInput 透传调度子字段", () => { const payload: FlockLoggedInQuotePayload = { mode: "quick", pickupDate: "2026-07-16", pickupZip: "60611", pickupType: "business_with_dock", pickupLiftgate: false, pickupInside: false, pickupPalletJack: false, deliveryZip: "78701", deliveryType: "business_without_dock", deliveryLiftgate: false, deliveryInside: false, deliveryPalletJack: false, items: [ { quantity: 4, packagingType: "pallets_48x40", lengthIn: 48, widthIn: 40, heightIn: 48, totalWeightLb: 6000, freightClass: "100", description: "papers", stackable: true, turnable: false, }, ], additionalServices: [], vehicleTypes: ["dry_van"], pickupService: "during_window", deliveryService: "must_arrive_by", pickupWindowStartTime: "8:00 am", pickupWindowEndTime: "5:00 pm", deliveryMustArriveByDate: "2026-07-20", callForDeliveryAppointment: true, callBeforePickup: false, callBeforeDelivery: false, additionalInsurance: false, }; const mapped = mapFlockLoggedInToApiInput(payload); expect(mapped.pickup_service).toBe("during_window"); expect(mapped.pickup_window_start_time).toBe("8:00 am"); expect(mapped.pickup_window_end_time).toBe("5:00 pm"); expect(mapped.delivery_service).toBe("must_arrive_by"); expect(mapped.delivery_must_arrive_by_date).toBe("2026-07-20"); expect(mapped.call_for_delivery_appointment).toBe(true); }); it("mapFlockLoggedInToApiInput 总重 ≤5000 时强制关闭提货前致电", () => { const payload: FlockLoggedInQuotePayload = { mode: "quick", pickupDate: "2026-07-16", pickupZip: "60611", pickupType: "business_with_dock", pickupLiftgate: false, pickupInside: false, pickupPalletJack: false, deliveryZip: "78701", deliveryType: "business_without_dock", deliveryLiftgate: false, deliveryInside: false, deliveryPalletJack: false, items: [ { quantity: 4, packagingType: "pallets_48x40", lengthIn: 48, widthIn: 40, heightIn: 48, totalWeightLb: 1000, freightClass: "100", description: "papers", stackable: true, turnable: false, }, ], additionalServices: [], vehicleTypes: ["dry_van"], pickupService: "standard_fcfs", deliveryService: "standard_fcfs", callBeforePickup: true, callBeforeDelivery: false, additionalInsurance: false, }; expect(mapFlockLoggedInToApiInput(payload).call_before_pickup).toBe(false); payload.items[0]!.totalWeightLb = 6000; expect(mapFlockLoggedInToApiInput(payload).call_before_pickup).toBe(true); }); it("各地点类型附加选项矩阵对齐官网截图", () => { expect(getFlockLocationAccessorials("business_without_dock")).toEqual({ liftgate: true, inside: true, palletJack: true, }); expect(getFlockLocationAccessorials("residential")).toEqual({ liftgate: true, inside: true, palletJack: false, }); expect(getFlockLocationAccessorials("limited_construction")).toEqual({ liftgate: true, inside: false, palletJack: true, }); expect(getFlockLocationAccessorials("trade_show")).toEqual({ liftgate: false, inside: false, palletJack: true, }); expect(getFlockLocationAccessorials("limited_worship")).toEqual({ liftgate: true, inside: true, palletJack: false, }); expect(getFlockLocationAccessorials("business_with_dock")).toEqual({ liftgate: false, inside: false, palletJack: false, }); }); it("官网提示文案中文齐全", async () => { const tips = await import("@/components/flock/flock-logged-in-quote-form"); expect(tips.FLOCK_LOCATION_TIP_ITEMS).toHaveLength(7); expect(tips.FLOCK_ADDITIONAL_SERVICE_TIP_ITEMS).toHaveLength(5); expect(tips.FLOCK_VEHICLE_TIP_ITEMS).toHaveLength(4); expect(tips.FLOCK_FREIGHT_CLASS_TIP).toContain("件数"); expect(tips.FLOCK_INSURANCE_YES_TIP).toContain("责任限额"); expect(tips.FLOCK_NMFC_NOTICE).toContain("NMFC"); }); it("货物尺寸与重量硬限同 FLOCK_LIMITS", () => { const ok = validateFlockLoggedInCargoLine({ quantity: 2, lengthIn: 48, widthIn: 40, heightIn: 48, totalWeightLb: 1000, description: "ok", }); expect(ok).toEqual({}); expect( validateFlockLoggedInCargoLine({ quantity: 1, lengthIn: 637, widthIn: 40, heightIn: 48, totalWeightLb: 100, description: "x", }).len, ).toBe(FLOCK_VALIDATION_MESSAGES.length); expect( validateFlockLoggedInCargoLine({ quantity: 1, lengthIn: 48, widthIn: 103, heightIn: 48, totalWeightLb: 100, description: "x", }).wid, ).toBe(FLOCK_VALIDATION_MESSAGES.width); expect( validateFlockLoggedInCargoLine({ quantity: 1, lengthIn: 48, widthIn: 40, heightIn: 109, totalWeightLb: 100, description: "x", }).hei, ).toBe(FLOCK_VALIDATION_MESSAGES.height); expect( validateFlockLoggedInCargoLine({ quantity: 1, lengthIn: 48, widthIn: 40, heightIn: 48, totalWeightLb: 45_001, description: "x", }).wt, ).toBe(FLOCK_VALIDATION_MESSAGES.totalWeight); }); it("包装类型含标准托盘尺寸", () => { const ids = FLOCK_PACKAGING_TYPES.map((x) => x.id); expect(ids).toEqual( expect.arrayContaining([ "pallets_48x40", "pallets_48x48", "pallets_60x48", "pallets_custom", ]), ); const p48 = FLOCK_PACKAGING_TYPES.find((p) => p.id === "pallets_48x40"); expect(p48?.length).toBe(48); expect(p48?.width).toBe(40); }); it("货运等级含密度计算与数值档", () => { expect(FLOCK_FREIGHT_CLASSES[0]).toBe("density"); expect(FLOCK_FREIGHT_CLASSES).toEqual( expect.arrayContaining(["50", "70", "100", "500"]), ); }); it("附加服务与车型对齐截图", () => { expect(FLOCK_ADDITIONAL_SERVICES.map((s) => s.id)).toEqual([ "blind_shipment", "food_grade", "load_to_ride", "temperature_control", "unloading", ]); expect(FLOCK_VEHICLE_TYPES.map((v) => v.id)).toEqual([ "box_truck", "dry_van", "refrigerated", "sprinter", ]); expect([...FLOCK_DEFAULT_VEHICLES]).toEqual([ "box_truck", "dry_van", "refrigerated", ]); }); it("mapFlockLoggedInToApiInput 汇总首行尺寸与多行数量/重量", () => { const payload: FlockLoggedInQuotePayload = { mode: "quick", pickupDate: "2026-07-16", pickupZip: "60611", pickupType: "business_with_dock", pickupLiftgate: false, pickupInside: false, pickupPalletJack: false, deliveryZip: "78701", deliveryType: "business_without_dock", deliveryLiftgate: true, deliveryInside: false, deliveryPalletJack: false, items: [ { quantity: 2, packagingType: "pallets_48x40", lengthIn: 48, widthIn: 40, heightIn: 50, totalWeightLb: 500, freightClass: "100", description: "papers", stackable: true, turnable: false, }, { quantity: 1, packagingType: "boxes", lengthIn: 20, widthIn: 20, heightIn: 20, totalWeightLb: 100, freightClass: "70", description: "parts", stackable: false, turnable: false, }, ], additionalServices: ["blind_shipment"], vehicleTypes: ["box_truck", "dry_van"], pickupService: "standard_fcfs", deliveryService: "standard_fcfs", callBeforePickup: false, callBeforeDelivery: false, additionalInsurance: false, }; const mapped = mapFlockLoggedInToApiInput(payload); expect(mapped.pickup_date).toBe("07/16/2026"); expect(mapped.pickup_zip).toBe("60611"); expect(mapped.delivery_zip).toBe("78701"); expect(mapped.pallet_count).toBe(3); expect(mapped.total_weight).toEqual({ value: 600, unit: "lb" }); expect(mapped.dimensions).toEqual({ length: 48, width: 40, height: 50, unit: "in", }); expect(mapped.form_mode).toBe("logged_in_quick"); expect(mapped.packaging_type).toBe("pallets_48x40"); expect(mapped.freight_class).toBe("100"); expect(mapped.description).toBe("papers"); expect(mapped.stackable).toBe(true); expect(mapped.additional_services).toEqual(["blind_shipment"]); expect(mapped.vehicle_types).toEqual(["box_truck", "dry_van"]); expect(mapped.delivery_liftgate).toBe(true); expect(mapped.pickup_liftgate).toBe(false); }); });