panatgithub_AnkiHeadingSync/src/application/errors/PluginUserError.test.ts
2026-04-27 19:54:49 +08:00

83 lines
No EOL
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as obsidian from "obsidian";
import { afterEach, describe, expect, it, vi } from "vitest";
import { PluginUserError, renderPluginFileFailure, renderPluginFileFailuresInline, renderUnknownUserFacingError, renderUserFacingMessage, renderUserMessage } from "./PluginUserError";
describe("PluginUserError", () => {
afterEach(() => {
vi.restoreAllMocks();
});
it("renders plugin-owned errors in English", () => {
vi.spyOn(obsidian, "getLanguage").mockReturnValue("en");
const error = new PluginUserError("errors.currentFileOutOfScope", { filePath: "notes/example.md" });
expect(renderUserMessage(error)).toBe("The current file is outside the plugin scope: notes/example.md");
});
it("renders plugin-owned errors in Simplified Chinese", () => {
vi.spyOn(obsidian, "getLanguage").mockReturnValue("zh");
const error = new PluginUserError("errors.currentFileOutOfScope", { filePath: "notes/example.md" });
expect(renderUserMessage(error)).toBe("当前文件不在插件作用范围内notes/example.md");
});
it("renders scope-not-configured errors in English and Chinese", () => {
vi.spyOn(obsidian, "getLanguage").mockReturnValue("en");
expect(renderUserMessage(new PluginUserError("errors.runScopeNotConfigured"))).toBe(
"Run scope is not configured. In include mode, select at least one folder before syncing.",
);
vi.spyOn(obsidian, "getLanguage").mockReturnValue("zh");
expect(renderUserMessage(new PluginUserError("errors.runScopeNotConfigured"))).toBe(
"运行范围尚未配置。当前是 include 模式,请至少选择一个文件夹后再同步。",
);
});
it("renders write-back failure summaries with localized detail lines", () => {
vi.spyOn(obsidian, "getLanguage").mockReturnValue("zh");
const error = new PluginUserError(
"errors.writeBack.summary",
{ fileCount: 2 },
{
failures: [
{ filePath: "a.md", key: "errors.writeBack.missingSourceContent" },
{ filePath: "b.md", rawMessage: "permission denied" },
],
},
);
expect(renderUserMessage(error)).toBe([
"Markdown 标记写回失败,共 2 个文件。",
"a.md: 缺少用于写回标记的扫描源码内容。",
"b.md: permission denied",
].join("\n"));
});
it("renders raw and keyed user-facing messages plus inline failure lists", () => {
vi.spyOn(obsidian, "getLanguage").mockReturnValue("en");
expect(renderUserFacingMessage({ key: "notice.failedSavePluginSettings" })).toBe("Failed to save plugin settings.");
expect(renderUserFacingMessage({ rawMessage: "raw failure" })).toBe("raw failure");
expect(renderPluginFileFailure({ filePath: "a.md", key: "errors.markerRemoval.markdownFileNotFound" })).toBe("Markdown file was not found.");
expect(renderPluginFileFailuresInline([
{ filePath: "a.md", key: "errors.markerRemoval.markdownFileNotFound" },
{ filePath: "b.md", rawMessage: "permission denied" },
])).toBe("a.md (Markdown file was not found.), b.md (permission denied)");
});
it("falls back to raw error messages for unknown errors", () => {
vi.spyOn(obsidian, "getLanguage").mockReturnValue("zh");
expect(renderUnknownUserFacingError(new Error("socket closed"), "notice.vaultSyncFailed")).toBe("socket closed");
});
it("falls back to a translated default when the value is not an Error", () => {
vi.spyOn(obsidian, "getLanguage").mockReturnValue("en");
expect(renderUnknownUserFacingError(null, "notice.vaultSyncFailed")).toBe("Vault sync failed.");
});
});