111 lines
3.8 KiB
TypeScript
111 lines
3.8 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import {
|
|
createMindmapAdapterProjectionEndpoint,
|
|
createMindmapCommandApplyEndpoint,
|
|
executeMindmapCommandApply,
|
|
executeMindmapCommandApplyAndRefreshProjection,
|
|
executeMindmapDataPutAndRefreshProjection,
|
|
isMindmapAdapterProjection,
|
|
requestMindmapAdapterProjection,
|
|
} from "./leptos-mindmap-adapter";
|
|
import { createFallbackMindmapAdapterProjection } from "./simple-mind-map-bridge";
|
|
|
|
describe("leptos-mindmap adapter projection", () => {
|
|
it("识别 adapter projection contract", () => {
|
|
const projection = createFallbackMindmapAdapterProjection({ mindmapId: "mind_1" });
|
|
expect(isMindmapAdapterProjection(projection)).toBe(true);
|
|
expect(isMindmapAdapterProjection({ ...projection, runtime: "other" })).toBe(false);
|
|
});
|
|
|
|
it("构建 simple_mind_map_scene 查询 endpoint", () => {
|
|
expect(createMindmapAdapterProjectionEndpoint("doc 1", "mind/1")).toBe(
|
|
"/api/mindmap/doc%201/mind%2F1?view=simple_mind_map_scene&queryName=mindmap.simple_mind_map_scene.get",
|
|
);
|
|
expect(createMindmapCommandApplyEndpoint("doc 1", "mind/1")).toBe(
|
|
"/api/mindmap/doc%201/mind%2F1",
|
|
);
|
|
});
|
|
|
|
it("从 result wrapper 中读取 projection", async () => {
|
|
const projection = createFallbackMindmapAdapterProjection({ mindmapId: "mind_1" });
|
|
const fetcher = vi.fn(async () => ({
|
|
ok: true,
|
|
json: async () => ({ result: projection }),
|
|
})) as unknown as typeof fetch;
|
|
|
|
await expect(
|
|
requestMindmapAdapterProjection({
|
|
documentId: "doc_1",
|
|
mindmapId: "mind_1",
|
|
fetcher,
|
|
}),
|
|
).resolves.toEqual(projection);
|
|
});
|
|
|
|
it("command apply 成功后可刷新 adapter projection", async () => {
|
|
const projection = createFallbackMindmapAdapterProjection({ mindmapId: "mind_1", kernelRevision: 12 });
|
|
const fetcher = vi
|
|
.fn()
|
|
.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({ ok: true, kernelRevision: 11 }),
|
|
})
|
|
.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({ result: projection }),
|
|
}) as unknown as typeof fetch;
|
|
|
|
await expect(
|
|
executeMindmapCommandApplyAndRefreshProjection({
|
|
documentId: "doc_1",
|
|
mindmapId: "mind_1",
|
|
commands: [{ type: "updateText", mindmapId: "mind_1", nodeId: "root", text: "新标题" }],
|
|
projectionRevision: 10,
|
|
fetcher,
|
|
}),
|
|
).resolves.toEqual(projection);
|
|
expect(fetcher).toHaveBeenNthCalledWith(
|
|
1,
|
|
"/api/mindmap/doc_1/mind_1",
|
|
expect.objectContaining({
|
|
method: "POST",
|
|
body: expect.stringContaining('"commandName":"mindmap.command.apply"'),
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("command apply 失败时抛出可定位 command_failed 错误", async () => {
|
|
const fetcher = vi.fn(async () => ({
|
|
ok: false,
|
|
status: 409,
|
|
json: async () => ({ error: "revision_conflict" }),
|
|
})) as unknown as typeof fetch;
|
|
|
|
await expect(
|
|
executeMindmapCommandApply({
|
|
documentId: "doc_1",
|
|
mindmapId: "mind_1",
|
|
commands: [{ type: "deleteNode", mindmapId: "mind_1", nodeId: "node_1" }],
|
|
fetcher,
|
|
}),
|
|
).rejects.toMatchObject({ code: "command_failed", status: 409, message: "command_failed:409:revision_conflict" });
|
|
});
|
|
|
|
it("data put 失败时透出 route 错误细节", async () => {
|
|
const fetcher = vi.fn(async () => ({
|
|
ok: false,
|
|
status: 400,
|
|
json: async () => ({ error: "mindmap_put_failed", details: ["missing_root_uid"] }),
|
|
})) as unknown as typeof fetch;
|
|
|
|
await expect(
|
|
executeMindmapDataPutAndRefreshProjection({
|
|
documentId: "doc_1",
|
|
mindmapId: "mind_1",
|
|
data: { data: { text: "中心主题" }, children: [] },
|
|
fetcher,
|
|
}),
|
|
).rejects.toMatchObject({ code: "command_failed", status: 400, message: "command_failed:400:mindmap_put_failed" });
|
|
});
|
|
});
|