feat(frontend): 编辑器内联工具箱——就地调生成器(含金手指),结果一键插入正文

Phase 1(写作工作台重构):编辑器「工具箱」按钮打开内联面板,不离开写作界面即可调用
全部生成器(含金手指——后端 golden-finger 早已齐全,此处首次露出)。复用 GeneratorRunner,
为其加可选 onInsertText:文本类产物(开篇/简介/续写/扩写等)点「插入正文」直接追加到章末,
可入库类仍走既有 ingest。useToolboxTools 客户端拉描述符(已单测)。润色/续写/工具箱三卡互斥。
This commit is contained in:
Yaojia Wang
2026-07-07 19:48:13 +02:00
parent 9195cf36f3
commit 04f4785292
5 changed files with 245 additions and 4 deletions

View File

@@ -0,0 +1,52 @@
// @vitest-environment jsdom
import { renderHook, waitFor } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { useToolboxTools } from "./useToolboxTools";
const get = vi.fn();
const toast = vi.fn();
vi.mock("@/lib/api/client", () => ({
api: { GET: (...a: unknown[]) => get(...a) },
}));
vi.mock("@/components/Toast", () => ({ useToast: () => toast }));
describe("useToolboxTools", () => {
beforeEach(() => {
get.mockReset();
toast.mockReset();
});
afterEach(() => vi.clearAllMocks());
it("加载成功拉全量描述符status=ready", async () => {
const tools = [{ key: "golden-finger", title: "金手指生成器", is_legacy: false }];
get.mockResolvedValue({ data: { tools }, error: null });
const { result } = renderHook(() => useToolboxTools());
await waitFor(() => expect(result.current.status).toBe("ready"));
expect(result.current.tools).toEqual(tools);
expect(get).toHaveBeenCalledWith("/skills/toolbox", {});
expect(toast).not.toHaveBeenCalled();
});
it("data.tools 缺省时回退空数组", async () => {
get.mockResolvedValue({ data: { tools: null }, error: null });
const { result } = renderHook(() => useToolboxTools());
await waitFor(() => expect(result.current.status).toBe("ready"));
expect(result.current.tools).toEqual([]);
});
it("后端 errorstatus=error、弹错误 toast", async () => {
get.mockResolvedValue({ data: null, error: { detail: "boom" } });
const { result } = renderHook(() => useToolboxTools());
await waitFor(() => expect(result.current.status).toBe("error"));
expect(toast).toHaveBeenCalledWith(expect.any(String), "error");
});
it("请求抛异常status=error、弹网络异常 toast", async () => {
get.mockRejectedValue(new Error("network down"));
const { result } = renderHook(() => useToolboxTools());
await waitFor(() => expect(result.current.status).toBe("error"));
expect(toast).toHaveBeenCalledWith("工具箱加载异常,请检查网络。", "error");
});
});