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.

126 lines
4.4 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 { 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);
});
});