Skip to content
File

Blob: tests/client/components/editor/extensions/page-mention-paste-guard.test.ts

typescript66 lines
1import { describe, expect, it } from "vitest";
2import { getSchema } from "@tiptap/core";
3import { StarterKit } from "@tiptap/starter-kit";
4import { Slice } from "@tiptap/pm/model";
5import { PageMentionNode } from "@/client/components/editor/extensions/page-mention/node";
6import { stripPageMentions } from "@/client/components/editor/extensions/page-mention/node";
7 
8const schema = getSchema([StarterKit.configure({ undoRedo: false }), PageMentionNode]);
9 
10function paragraphSlice(content: Array<{ type: string; text?: string; attrs?: Record<string, unknown> }>): Slice {
11 const doc = schema.nodeFromJSON({
12 type: "doc",
13 content: [{ type: "paragraph", content }],
14 });
15 return doc.slice(0, doc.content.size);
16}
17 
18function collectMentionPageIds(slice: Slice): string[] {
19 const ids: string[] = [];
20 slice.content.descendants((node) => {
21 if (node.type.name === "pageMention") {
22 const id = (node.attrs as { pageId?: string }).pageId;
23 if (id) ids.push(id);
24 }
25 return true;
26 });
27 return ids;
28}
29 
30describe("stripPageMentions", () => {
31 it("drops pageMention nodes and preserves surrounding inline content", () => {
32 const slice = paragraphSlice([
33 { type: "text", text: "hello " },
34 { type: "pageMention", attrs: { pageId: "page-123" } },
35 { type: "text", text: " world" },
36 ]);
37 
38 expect(collectMentionPageIds(slice)).toEqual(["page-123"]);
39 
40 const stripped = stripPageMentions(slice);
41 
42 expect(collectMentionPageIds(stripped)).toEqual([]);
43 expect(stripped.content.firstChild?.textContent).toBe("hello world");
44 });
45 
46 it("returns the original slice when no mentions are present", () => {
47 const slice = paragraphSlice([{ type: "text", text: "no mentions here" }]);
48 expect(stripPageMentions(slice)).toBe(slice);
49 });
50 
51 it("strips mentions nested inside other inline structures", () => {
52 const slice = paragraphSlice([
53 { type: "text", text: "outer " },
54 { type: "pageMention", attrs: { pageId: "p1" } },
55 { type: "text", text: " between " },
56 { type: "pageMention", attrs: { pageId: "p2" } },
57 { type: "text", text: " end" },
58 ]);
59 
60 const stripped = stripPageMentions(slice);
61 
62 expect(collectMentionPageIds(stripped)).toEqual([]);
63 expect(stripped.content.firstChild?.textContent).toBe("outer between end");
64 });
65});