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__/components/flock-logged-in-quote-form....

533 lines
16 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 {
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("调度:During pickup window / NEED delivery 常可选;其余高级项按件数>5或总重>5000解锁", async () => {
const mod = await import("@/components/flock/flock-logged-in-quote-form");
expect(mod.flockSchedulingWeightLockedHint()).toMatch(
/件数大于 5.*总重大于 5000/,
);
expect(mod.isFlockSchedulingOptionLocked(5, 5000, true)).toBe(true);
expect(mod.isFlockSchedulingOptionLocked(6, 200, true)).toBe(false);
expect(mod.isFlockSchedulingOptionLocked(2, 5001, true)).toBe(false);
expect(mod.isFlockSchedulingOptionLocked(1, 1, false)).toBe(false);
// 官网:与 Standard 一样常可选
expect(
mod.FLOCK_PICKUP_SERVICES.find((s) => s.id === "during_window")
?.weightLocked,
).toBe(false);
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);
// 官网灰色:HAVE / NEED pickup、During delivery、HAVE delivery、Must arrive by
expect(
mod.FLOCK_PICKUP_SERVICES.find((s) => s.id === "have_appointment")
?.weightLocked,
).toBe(true);
expect(
mod.FLOCK_PICKUP_SERVICES.find((s) => s.id === "need_appointment")
?.weightLocked,
).toBe(true);
expect(
mod.FLOCK_DELIVERY_SERVICES.find((s) => s.id === "during_window")
?.weightLocked,
).toBe(true);
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("预设时段");
expect(
mod.FLOCK_PICKUP_SERVICES.find((s) => s.id === "need_appointment")
?.detail,
).toMatch(/协调预约/);
expect(mod.flockSchedulingPickupPanelId("standard_fcfs")).toBeNull();
expect(mod.flockSchedulingPickupPanelId("during_window")).toBe(
"during_window",
);
expect(mod.flockSchedulingPickupPanelId("have_appointment")).toBe(
"have_appointment",
);
expect(mod.flockSchedulingPickupPanelId("need_appointment")).toBeNull();
expect(mod.flockSchedulingDeliveryPanelId("need_appointment")).toBeNull();
expect(mod.flockSchedulingDeliveryPanelId("standard_fcfs")).toBe(
"standard_call_before",
);
expect(mod.flockSchedulingDeliveryPanelId("must_arrive_by")).toBe(
"must_arrive_by",
);
expect(mod.flockSchedulingShowDeliveryCallBefore("standard_fcfs")).toBe(
true,
);
expect(mod.flockSchedulingShowDeliveryCallBefore("during_window")).toBe(
false,
);
expect(mod.flockSchedulingShowDeliveryCallBefore("need_appointment")).toBe(
false,
);
expect(mod.flockSchedulingShowDeliveryCallBefore("must_arrive_by")).toBe(
false,
);
expect(mod.flockSchedulingShowPickupCallBefore("standard_fcfs")).toBe(true);
expect(mod.flockSchedulingShowPickupCallBefore("during_window")).toBe(
false,
);
});
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("件数>5 或总重>5000 时 map 透传 load_bars / straps", () => {
const base = {
mode: "quick" as const,
pickupDate: "2026-07-16",
pickupZip: "60611",
pickupType: "business_with_dock" as const,
pickupLiftgate: false,
pickupInside: false,
pickupPalletJack: false,
deliveryZip: "78701",
deliveryType: "business_without_dock" as const,
deliveryLiftgate: false,
deliveryInside: false,
deliveryPalletJack: false,
additionalServices: [] as const,
vehicleTypes: ["dry_van"] as const,
pickupService: "standard_fcfs",
deliveryService: "standard_fcfs",
callBeforePickup: false,
callBeforeDelivery: false,
additionalInsurance: false,
};
const light = mapFlockLoggedInToApiInput({
...base,
items: [
{
quantity: 6,
packagingType: "pallets_48x40",
lengthIn: 48,
widthIn: 40,
heightIn: 48,
totalWeightLb: 200,
freightClass: "density",
description: "papers",
stackable: true,
turnable: false,
},
],
loadBars: 2,
straps: 4,
});
expect(light.load_bars).toBe(2);
expect(light.straps).toBe(4);
});
it("额外保险:是 + 货值透传;否不带货值", () => {
const baseItems = [
{
quantity: 2,
packagingType: "pallets_48x40" as const,
lengthIn: 48,
widthIn: 40,
heightIn: 48,
totalWeightLb: 1000,
freightClass: "70" as const,
description: "papers",
stackable: true,
turnable: false,
},
];
const common = {
mode: "quick" as const,
pickupDate: "2026-07-16",
pickupZip: "60611",
pickupType: "business_with_dock" as const,
pickupLiftgate: false,
pickupInside: false,
pickupPalletJack: false,
deliveryZip: "78701",
deliveryType: "business_without_dock" as const,
deliveryLiftgate: false,
deliveryInside: false,
deliveryPalletJack: false,
items: baseItems,
additionalServices: [] as [],
vehicleTypes: ["dry_van"] as ["dry_van"],
pickupService: "standard_fcfs",
deliveryService: "standard_fcfs",
callBeforePickup: false,
callBeforeDelivery: false,
};
const yes = mapFlockLoggedInToApiInput({
...common,
additionalInsurance: true,
shipmentValueUsd: 25000,
});
expect(yes.additional_insurance).toBe(true);
expect(yes.shipment_value_usd).toBe(25000);
const noMapped = mapFlockLoggedInToApiInput({
...common,
additionalInsurance: false,
shipmentValueUsd: 25000,
});
expect(noMapped.additional_insurance).toBe(false);
expect(noMapped.shipment_value_usd).toBeUndefined();
});
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);
});
});