|
|
import { describe, expect, it } from "vitest";
|
|
|
import { RpaError } from "@/modules/rpa/errors";
|
|
|
import { RpaDataInvalidError } from "@/modules/quote/types";
|
|
|
import {
|
|
|
formatQuoteErrorMessage,
|
|
|
isChineseUserFacingMessage,
|
|
|
resolveQuoteFailureCode,
|
|
|
resolveQuoteFailureMessage,
|
|
|
toChineseUserFacingMessage,
|
|
|
translateKnownEnglishPhrases,
|
|
|
} from "@/modules/quote/quote-error-messages";
|
|
|
|
|
|
describe("quote-error-messages", () => {
|
|
|
it("RpaError 保留细分 error_code", () => {
|
|
|
expect(
|
|
|
resolveQuoteFailureCode(
|
|
|
new RpaError("ADDRESS_SUGGESTION_NOT_FOUND", "未找到地址"),
|
|
|
),
|
|
|
).toBe("ADDRESS_SUGGESTION_NOT_FOUND");
|
|
|
});
|
|
|
|
|
|
it("技术英文原文不直出,回退中文默认", () => {
|
|
|
const msg = resolveQuoteFailureMessage(
|
|
|
new RpaError(
|
|
|
"STRUCT_CHANGE",
|
|
|
"locator.waitFor: Timeout 15000ms exceeded",
|
|
|
),
|
|
|
"QUOTE_ENTRY_UNAVAILABLE",
|
|
|
);
|
|
|
expect(msg).toMatch(/自动化操作超时|报价入口/);
|
|
|
expect(msg).not.toMatch(/locator\.waitFor/i);
|
|
|
});
|
|
|
|
|
|
it("Playwright 超时译为具体中文原因,不再吞成通用「暂时无法获取」", () => {
|
|
|
const msg = toChineseUserFacingMessage(
|
|
|
"locator.waitFor: Timeout 30000ms exceeded.\nCall log:\n - waiting for getByTestId('ship-create-continue-button')",
|
|
|
"QUOTE_UNAVAILABLE",
|
|
|
);
|
|
|
expect(msg).toContain("自动化操作超时");
|
|
|
expect(msg).toContain("创建货件/报价表单控件");
|
|
|
expect(msg).not.toBe("暂时无法获取报价,请稍后重试");
|
|
|
});
|
|
|
|
|
|
it("RpaDataInvalidError 映射为 RPA_DATA_INVALID 并保留中文原因", () => {
|
|
|
expect(resolveQuoteFailureCode(new RpaDataInvalidError("缺少标准档报价"))).toBe(
|
|
|
"RPA_DATA_INVALID",
|
|
|
);
|
|
|
expect(
|
|
|
resolveQuoteFailureMessage(
|
|
|
new RpaDataInvalidError("缺少标准档报价"),
|
|
|
"RPA_DATA_INVALID",
|
|
|
),
|
|
|
).toMatch(/标准档|报价/);
|
|
|
});
|
|
|
|
|
|
it("含 rate-card 的中文业务句仍可展示", () => {
|
|
|
expect(
|
|
|
isChineseUserFacingMessage("登录态 rate-card 未能解析出承运商报价"),
|
|
|
).toBe(true);
|
|
|
expect(
|
|
|
toChineseUserFacingMessage(
|
|
|
"登录态 rate-card 未能解析出承运商报价",
|
|
|
"RPA_DATA_INVALID",
|
|
|
),
|
|
|
).toContain("承运商报价");
|
|
|
});
|
|
|
|
|
|
it("合格中文原文保留", () => {
|
|
|
expect(
|
|
|
formatQuoteErrorMessage("QUOTE_UNAVAILABLE", "该线路暂无可用运力,请换地址"),
|
|
|
).toBe("该线路暂无可用运力,请换地址");
|
|
|
});
|
|
|
|
|
|
it("formatQuoteErrorMessage 按 code 回退", () => {
|
|
|
expect(formatQuoteErrorMessage("QUOTE_TIMEOUT")).toContain("420 秒");
|
|
|
});
|
|
|
|
|
|
it("PROVIDER_LOGIN_FAILED 统一用户文案", () => {
|
|
|
expect(
|
|
|
resolveQuoteFailureCode(
|
|
|
new RpaError("PROVIDER_LOGIN_FAILED", "内部细节"),
|
|
|
),
|
|
|
).toBe("PROVIDER_LOGIN_FAILED");
|
|
|
expect(
|
|
|
resolveQuoteFailureMessage(
|
|
|
new RpaError("SESSION_EXPIRED", "仍停在登录页,账密可能错误"),
|
|
|
"SESSION_EXPIRED",
|
|
|
),
|
|
|
).toContain("即时保存更新");
|
|
|
expect(formatQuoteErrorMessage("PROVIDER_LOGIN_FAILED")).toContain(
|
|
|
"账号或密码可能不正确",
|
|
|
);
|
|
|
expect(
|
|
|
formatQuoteErrorMessage(
|
|
|
"RPA_DATA_INVALID",
|
|
|
"FLOCK_LOGIN_FAILED:账号或密码错误",
|
|
|
),
|
|
|
).toContain("即时保存更新");
|
|
|
});
|
|
|
|
|
|
it("英文官网文案译为中文", () => {
|
|
|
expect(translateKnownEnglishPhrases("No rates found")).toBe(
|
|
|
"未找到可用报价",
|
|
|
);
|
|
|
expect(
|
|
|
toChineseUserFacingMessage("No carriers available for this lane", "CARRIER_NO_CAPACITY"),
|
|
|
).toBe("该线路暂无可用运力");
|
|
|
});
|
|
|
|
|
|
it("附加服务 appointment 超时译为可读中文,不再吞成通用文案", () => {
|
|
|
const msg = toChineseUserFacingMessage(
|
|
|
"locator.waitFor: Timeout 8000ms exceeded.\nCall log:\n - waiting for getByTestId('address-book-accessorials-option-appointment').first() to be visible",
|
|
|
"QUOTE_UNAVAILABLE",
|
|
|
);
|
|
|
expect(msg).toContain("自动化操作超时");
|
|
|
expect(msg).toMatch(/预约|附加服务/);
|
|
|
expect(msg).not.toBe("暂时无法获取报价,请稍后重试");
|
|
|
});
|
|
|
|
|
|
it("附加服务不可用业务文案原样保留", () => {
|
|
|
const raw =
|
|
|
"派送附加服务「appointment」在官网下拉中不可用或未展开(可见选项:liftgate)。请取消该附加服务后重试,或确认地址类型是否支持。";
|
|
|
expect(toChineseUserFacingMessage(raw, "CARRIER_NO_CAPACITY")).toBe(raw);
|
|
|
});
|
|
|
});
|