ai-chatbot/tests/routes/flow-board-topic-details.test.ts

80 lines
2.3 KiB
TypeScript

import { expect, test } from "@playwright/test";
import { normalizeFlowBoardSnapshot } from "@/app/api/flow-board/_utils";
import {
getSafeTopicHref,
getTopicDetails,
patchTopicDetails,
} from "@/lib/flow-board/topic-details";
test("topic notes, labels, links and resources survive snapshot serialization", () => {
const topic = {
id: "topic",
type: "mindmap",
xmind: {
notes: { plain: { content: "第一行\n第二行" } },
labels: ["标签一", "标签二"],
href: "https://example.com",
topicLinkId: "target",
attachment: {
name: "spec.txt",
url: "data:application/octet-stream;base64,eA==",
mimeType: "application/octet-stream",
},
},
data: {
image: { url: "data:image/png;base64,eA==", width: 32, height: 32 },
},
};
const snapshot = normalizeFlowBoardSnapshot(
JSON.parse(JSON.stringify({ children: [topic] }))
);
expect(snapshot.children[0]).toEqual(topic);
expect(getTopicDetails(topic)).toMatchObject({
notes: "第一行\n第二行",
labels: ["标签一", "标签二"],
topicLinkId: "target",
attachment: { name: "spec.txt" },
});
});
test("editing a note preserves image metadata and non-edited labels and links", () => {
const topic = {
id: "topic",
xmind: {
notes: { plain: { content: "旧备注" } },
labels: ["保留"],
image: { src: "xap:resources/a.png" },
href: "https://example.com",
markers: [{ markerId: "priority-1" }],
},
};
const metadata = patchTopicDetails(topic, { notes: "新备注" });
expect(metadata).toEqual({
...topic.xmind,
notes: { plain: { content: "新备注" } },
});
expect(
getTopicDetails({
...topic,
xmind: patchTopicDetails(topic, { notes: "" }),
}).notes
).toBe("");
});
test("links cannot execute script and external URLs require an allowed protocol", () => {
for (const value of [
"javascript:alert(1)",
"data:text/html,<script>x</script>",
"file:///etc/passwd",
"//example.com",
"xmind:#target",
])
expect(getSafeTopicHref(value)).toBeNull();
expect(getSafeTopicHref("https://example.com/a?q=b")).toBe(
"https://example.com/a?q=b"
);
expect(getSafeTopicHref("mailto:hello@example.com")).toBe(
"mailto:hello@example.com"
);
});