|
|
import { describe, expect, it } from "vitest";
|
|
|
import {
|
|
|
classifyCcFailure,
|
|
|
conflictCheckOperatorMessage,
|
|
|
describeCcFailureForOperator,
|
|
|
formatCcCause,
|
|
|
formatImapSkipReason,
|
|
|
formatMailLastError,
|
|
|
formatOAuthCallbackError,
|
|
|
formatOperatorError,
|
|
|
} from "@/constants/error-copy";
|
|
|
|
|
|
describe("formatOperatorError", () => {
|
|
|
it("translates last_error machine codes", () => {
|
|
|
expect(formatMailLastError("NO_SHIPMENT_ROWS")).toMatch(/未解析到货件/);
|
|
|
expect(formatMailLastError("NO_SUPPORTED_SPREADSHEET")).toMatch(/表格附件/);
|
|
|
expect(formatMailLastError("NO_BODY_NO_ATTACHMENT")).toMatch(/没有正文/);
|
|
|
expect(formatMailLastError("ATTACHMENT_TOO_LARGE")).toMatch(/过大/);
|
|
|
expect(formatMailLastError("MIME_PARSE_ERROR")).toMatch(/格式损坏/);
|
|
|
expect(formatMailLastError("missing_columns:仓库ID")).toMatch(/缺列/);
|
|
|
expect(formatMailLastError("INVALID_CONTAINER_NO:TRHU8524770")).toMatch(
|
|
|
/TRHU8524770/,
|
|
|
);
|
|
|
});
|
|
|
|
|
|
it("does not show Unauthorized / Invalid body to operators", () => {
|
|
|
expect(formatOperatorError("Unauthorized", "UNAUTHORIZED")).toMatch(/登录/);
|
|
|
expect(formatOperatorError("Unauthorized")).toMatch(/CarrierCentral|权限/);
|
|
|
expect(formatOperatorError("Invalid body")).toMatch(/提交内容|必填/);
|
|
|
expect(formatOperatorError("Mail not found")).toMatch(/邮件/);
|
|
|
expect(formatMailLastError("Unauthorized")).not.toMatch(/Unauthorized/i);
|
|
|
expect(formatMailLastError("Invalid body")).not.toMatch(/Invalid/i);
|
|
|
});
|
|
|
|
|
|
it("translates CC transport failures", () => {
|
|
|
expect(formatCcCause("CC request timeout")).toMatch(/超时/);
|
|
|
expect(formatCcCause("CC request failed")).toMatch(/无法连接/);
|
|
|
expect(formatCcCause("CC save failed with code 400")).toMatch(
|
|
|
/集装箱数据导入|拒绝|400/,
|
|
|
);
|
|
|
expect(formatCcCause("GetContainerList timeout")).toMatch(
|
|
|
/集装箱列表|超时/,
|
|
|
);
|
|
|
expect(formatMailLastError("CC_WRITE_OFF")).toMatch(/未开启/);
|
|
|
expect(formatMailLastError("WO_MOCK_OK")).toMatch(/模拟|未写入/);
|
|
|
expect(formatMailLastError("WO_MOCK_OK")).not.toMatch(/操作失败/);
|
|
|
expect(formatMailLastError("XFER_MOCK_OK")).toMatch(/模拟|未写入/);
|
|
|
expect(formatMailLastError("DO_MOCK_OK")).toMatch(/模拟|未写入/);
|
|
|
expect(formatCcCause("Unauthorized")).not.toMatch(/Unauthorized/i);
|
|
|
});
|
|
|
|
|
|
it("keeps CC Chinese info even when it embeds FBACode / charset lists", () => {
|
|
|
const raw =
|
|
|
"第60行的FBACode是空值或者只输入了正常英文字符[_- ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz]以外的字符。";
|
|
|
const out = formatCcCause(raw);
|
|
|
expect(out).toMatch(/第60行/);
|
|
|
expect(out).toMatch(/目的代码/);
|
|
|
expect(out).not.toMatch(/请稍后重试或到 CC 核对/);
|
|
|
});
|
|
|
|
|
|
it("keeps already-Chinese messages", () => {
|
|
|
expect(formatOperatorError("邮件不存在")).toBe("邮件不存在");
|
|
|
expect(formatOperatorError("柜号必填")).toBe("柜号必填");
|
|
|
});
|
|
|
|
|
|
it("rewrites English embedded in Chinese", () => {
|
|
|
expect(
|
|
|
formatOperatorError("查柜失败:GetContainerList timeout,默认降级工单"),
|
|
|
).toMatch(/集装箱列表|超时/);
|
|
|
});
|
|
|
|
|
|
it("keeps Chinese packing-list errors that mention Excel/xlsx", () => {
|
|
|
expect(
|
|
|
formatOperatorError(
|
|
|
"解析装箱表失败,请确认文件为有效的 Excel(xlsx)",
|
|
|
"PARSE_FAILED",
|
|
|
),
|
|
|
).toMatch(/装箱表|Excel|xlsx/);
|
|
|
expect(
|
|
|
formatOperatorError(
|
|
|
"未能从表格解析出货件行,请确认是卡派清单等含「渠道/件数/仓库」表头的 xlsx",
|
|
|
"PARSE_FAILED",
|
|
|
),
|
|
|
).toMatch(/货件行|卡派清单/);
|
|
|
});
|
|
|
|
|
|
it("maps OAuth and IMAP skip reasons", () => {
|
|
|
expect(formatOAuthCallbackError("missing_code")).toMatch(/授权码/);
|
|
|
expect(formatImapSkipReason("no_credentials")).toMatch(/邮箱/);
|
|
|
expect(formatImapSkipReason("SKIP_BLACKLIST")).toMatch(/黑名单/);
|
|
|
});
|
|
|
|
|
|
it("classifies conflict check failures for operators", () => {
|
|
|
expect(classifyCcFailure("CC_LOGIN_FAILED:账户或密码错误")).toBe("login");
|
|
|
expect(classifyCcFailure("访问次数限制,请稍后再试")).toBe("rate_limit");
|
|
|
expect(classifyCcFailure("GetContainerList timeout")).toBe("timeout");
|
|
|
expect(
|
|
|
conflictCheckOperatorMessage("login", "CC_LOGIN_FAILED:401"),
|
|
|
).toMatch(/账号|密码/);
|
|
|
expect(conflictCheckOperatorMessage("rate_limit")).toMatch(/每分钟|60/);
|
|
|
});
|
|
|
|
|
|
it("maps CC login credential errors", () => {
|
|
|
expect(formatCcCause("CC_CREDENTIALS_MISSING")).toMatch(/未配置/);
|
|
|
expect(formatCcCause("CC_LOGIN_FAILED:账户或密码错误")).toMatch(/密码/);
|
|
|
});
|
|
|
|
|
|
it("describeCcFailureForOperator exposes kind and message", () => {
|
|
|
const login = describeCcFailureForOperator("CC_LOGIN_FAILED:账户或密码错误");
|
|
|
expect(login.kind).toBe("login");
|
|
|
expect(login.kindLabel).toMatch(/登录/);
|
|
|
expect(login.message).toMatch(/账号|密码/);
|
|
|
|
|
|
const validation = describeCcFailureForOperator(
|
|
|
"以下字段未填写,不能保存:柜型",
|
|
|
);
|
|
|
expect(validation.kind).toBe("validation");
|
|
|
expect(validation.message).toMatch(/柜型|40HQ/);
|
|
|
});
|
|
|
});
|