F4:新 lib/errors/messages.ts —— friendlyError(code, fallback) 把错误码映射为 中文文案 + 可选「去设置提供商」动作;覆盖后端 ErrorCode + 前端 NETWORK/ STREAM_FAILED;未知码回退原 message。写作页与审稿页错误块改用之,不再暴露 raw error code。+4 vitest。 F3:写作页工具条字数计数器流式时显示「生成中… N 字」+ 朱砂脉冲 (motion-safe:animate-pulse,尊重 prefers-reduced-motion),停后回「字数 N」。 纯 text.length,无后端改动。 前端门禁绿:lint/typecheck/vitest 171/build。无契约变更。
29 lines
1.1 KiB
TypeScript
29 lines
1.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { friendlyError } from "./messages";
|
|
|
|
describe("friendlyError", () => {
|
|
it("maps LLM_UNAVAILABLE to copy + a settings action", () => {
|
|
const e = friendlyError("LLM_UNAVAILABLE", "fallback exhausted");
|
|
expect(e.text).toContain("未连接");
|
|
expect(e.actionHref).toBe("/settings/providers");
|
|
expect(e.actionLabel).toBe("去设置提供商");
|
|
});
|
|
|
|
it("maps NETWORK to friendly copy without leaking raw message", () => {
|
|
const e = friendlyError("NETWORK", "TypeError: Failed to fetch");
|
|
expect(e.text).toBe("网络中断,请检查连接后重试。");
|
|
expect(e.actionHref).toBeUndefined();
|
|
});
|
|
|
|
it("falls back to the raw message for an unknown code", () => {
|
|
const e = friendlyError("WEIRD_CODE", "something specific happened");
|
|
expect(e.text).toBe("something specific happened");
|
|
});
|
|
|
|
it("uses generic copy when code is unknown and no message given", () => {
|
|
expect(friendlyError(undefined).text).toBe("出错了,请稍后重试。");
|
|
expect(friendlyError("WEIRD_CODE", " ").text).toBe("出错了,请稍后重试。");
|
|
});
|
|
});
|