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.
mail-yubao/tests/unit/resolve-confirm-instruction...

138 lines
4.6 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 {
extractInstructionsFromMail,
resolveConfirmInstruction,
shouldForceForecastUnit,
} from "@/services/parse/resolve-confirm-instruction";
import type { MailInstructionUnit } from "@/services/parse/split-instructions";
function unit(
partial: Partial<MailInstructionUnit> &
Pick<MailInstructionUnit, "id" | "uiKind">,
): MailInstructionUnit {
return {
mailType: "NEW_CONTAINER",
label: partial.uiKind,
summary: "",
keywords: [],
source: "body_segment",
segmentIndex: 0,
isCurrent: false,
segmentText: "",
...partial,
};
}
describe("resolveConfirmInstruction", () => {
const forecast = unit({
id: "forecast-body_segment-5-派送单请查收",
uiKind: "forecast",
isCurrent: false,
});
const transfer = unit({
id: "transfer-body_segment-0-新增转仓",
uiKind: "transfer",
mailType: "TRANSFER",
isCurrent: true,
});
it("selects the requested instruction even when it is historical forecast", () => {
const resolved = resolveConfirmInstruction({
units: [transfer, forecast],
instructionId: forecast.id,
});
expect(resolved.reason).toBe("ok");
expect(resolved.unit?.id).toBe(forecast.id);
expect(resolved.unit?.uiKind).toBe("forecast");
});
it("does not infer from mail main type when instruction_id is missing and multiple units exist", () => {
const resolved = resolveConfirmInstruction({
units: [transfer, forecast],
});
expect(resolved.reason).toBe("missing_id");
expect(resolved.unit).toBeNull();
expect(resolved.candidates.map((u) => u.uiKind)).toEqual([
"transfer",
"forecast",
]);
});
it("auto-selects the only pending confirmable unit", () => {
const resolved = resolveConfirmInstruction({
units: [forecast],
});
expect(resolved.reason).toBe("ok");
expect(resolved.unit?.id).toBe(forecast.id);
});
it("keeps an already-imported unit visible as readonly", () => {
const resolved = resolveConfirmInstruction({
units: [forecast],
instructionId: forecast.id,
lineage: {
instruction_state: {
[forecast.id]: { status: "IMPORTED", importedAt: "2026-08-17" },
},
},
});
expect(resolved.reason).toBe("already_imported");
expect(resolved.unit?.id).toBe(forecast.id);
});
});
describe("extractInstructionsFromMail forceForecast parity", () => {
it("mail100-style DO + 整柜直送 subject still yields forecast unit", () => {
const mail = {
subject:
"Fw: Fw:回复:柜号:TRHU8524770+提单号:EGLV143661466958+封号:EMCEJJ0635+YWZD+不带车架+整柜直送",
body_text: "TRHU8524770 DO请查收",
attachments: [{ filename: "TRHU8524770-DO-1.pdf" }],
parse_result: {
container_header: { F_ContainerNo: "TRHU8524770" },
mail_record: { kind: "BL_FORECAST" },
},
};
expect(shouldForceForecastUnit(mail)).toBe(true);
const units = extractInstructionsFromMail(mail);
expect(units.some((u) => u.uiKind === "do_upload")).toBe(true);
const forecast = units.find((u) => u.uiKind === "forecast");
expect(forecast).toBeTruthy();
expect(forecast!.id).toMatch(/^forecast-record-/);
const resolved = resolveConfirmInstruction({
units,
instructionId: forecast!.id,
});
expect(resolved.reason).toBe("ok");
expect(resolved.unit?.uiKind).toBe("forecast");
});
it("forces forecast from 整柜直送 subject even without mail_record", () => {
const units = extractInstructionsFromMail({
subject:
"回复:柜号:TRHU8524770+提单号:EGLV143661466958+YWZD+不带车架+整柜直送",
body_text: "DO请查收",
attachments: [{ filename: "TRHU8524770-DO-1.pdf" }],
});
expect(units.some((u) => u.uiKind === "forecast")).toBe(true);
expect(units.some((u) => u.uiKind === "do_upload")).toBe(true);
});
it("does not force forecast for work-order mail that only has container in subject", () => {
const mail = {
subject: "Fw: 转发:TIIU8073522-90022",
body_text:
"主题 TIIU8073522-90022\nBAZUS001787430-90022 4PX 预约码: ==CNF26070717",
mail_type: "WORK_ORDER",
attachments: [] as Array<{ filename: string }>,
parse_result: {
container_header: { F_ContainerNo: "TIIU8073522" },
mail_record: { kind: "WORK_ORDER" },
},
};
expect(shouldForceForecastUnit(mail)).toBe(false);
const units = extractInstructionsFromMail(mail);
expect(units.some((u) => u.uiKind === "forecast")).toBe(false);
});
});