]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/lexical/rich-text/__tests__/unit/LexicalHeadingNode.test.ts
Merge pull request #5917 from BookStackApp/copy_references
[bookstack] / resources / js / wysiwyg / lexical / rich-text / __tests__ / unit / LexicalHeadingNode.test.ts
1 /**
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  *
7  */
8
9 import {
10   $createTextNode,
11   $getRoot,
12   $getSelection,
13   ParagraphNode,
14   RangeSelection,
15 } from 'lexical';
16 import {initializeUnitTest} from 'lexical/__tests__/utils';
17 import {$createHeadingNode, $isHeadingNode, HeadingNode} from "@lexical/rich-text/LexicalHeadingNode";
18
19 const editorConfig = Object.freeze({
20   namespace: '',
21   theme: {
22     heading: {
23       h1: 'my-h1-class',
24       h2: 'my-h2-class',
25       h3: 'my-h3-class',
26       h4: 'my-h4-class',
27       h5: 'my-h5-class',
28       h6: 'my-h6-class',
29     },
30   },
31 });
32
33 describe('LexicalHeadingNode tests', () => {
34   initializeUnitTest((testEnv) => {
35     test('HeadingNode.constructor', async () => {
36       const {editor} = testEnv;
37       await editor.update(() => {
38         const headingNode = new HeadingNode('h1');
39         expect(headingNode.getType()).toBe('heading');
40         expect(headingNode.getTag()).toBe('h1');
41         expect(headingNode.getTextContent()).toBe('');
42       });
43       expect(() => new HeadingNode('h1')).toThrow();
44     });
45
46     test('HeadingNode.createDOM()', async () => {
47       const {editor} = testEnv;
48       await editor.update(() => {
49         const headingNode = new HeadingNode('h1');
50         expect(headingNode.createDOM(editorConfig).outerHTML).toBe(
51           '<h1 class="my-h1-class"></h1>',
52         );
53         expect(
54           headingNode.createDOM({
55             namespace: '',
56             theme: {
57               heading: {},
58             },
59           }).outerHTML,
60         ).toBe('<h1></h1>');
61         expect(
62           headingNode.createDOM({
63             namespace: '',
64             theme: {},
65           }).outerHTML,
66         ).toBe('<h1></h1>');
67       });
68     });
69
70     test('HeadingNode.updateDOM()', async () => {
71       const {editor} = testEnv;
72       await editor.update(() => {
73         const headingNode = new HeadingNode('h1');
74         const domElement = headingNode.createDOM(editorConfig);
75         expect(domElement.outerHTML).toBe('<h1 class="my-h1-class"></h1>');
76         const newHeadingNode = new HeadingNode('h2');
77         const result = newHeadingNode.updateDOM(headingNode, domElement);
78         expect(result).toBe(false);
79         expect(domElement.outerHTML).toBe('<h1 class="my-h1-class"></h1>');
80       });
81     });
82
83     test('HeadingNode.insertNewAfter() empty', async () => {
84       const {editor} = testEnv;
85       let headingNode: HeadingNode;
86       await editor.update(() => {
87         const root = $getRoot();
88         headingNode = new HeadingNode('h1');
89         root.append(headingNode);
90       });
91       expect(testEnv.outerHTML).toBe(
92         '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><h1><br></h1></div>',
93       );
94       await editor.update(() => {
95         const selection = $getSelection() as RangeSelection;
96         const result = headingNode.insertNewAfter(selection);
97         expect(result).toBeInstanceOf(ParagraphNode);
98         expect(result.getDirection()).toEqual(headingNode.getDirection());
99       });
100       expect(testEnv.outerHTML).toBe(
101         '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><h1><br></h1><p><br></p></div>',
102       );
103     });
104
105     test('HeadingNode.insertNewAfter() middle', async () => {
106       const {editor} = testEnv;
107       let headingNode: HeadingNode;
108       await editor.update(() => {
109         const root = $getRoot();
110         headingNode = new HeadingNode('h1');
111         const headingTextNode = $createTextNode('hello world');
112         root.append(headingNode.append(headingTextNode));
113         headingTextNode.select(5, 5);
114       });
115       expect(testEnv.outerHTML).toBe(
116         '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><h1><span data-lexical-text="true">hello world</span></h1></div>',
117       );
118       await editor.update(() => {
119         const selection = $getSelection() as RangeSelection;
120         const result = headingNode.insertNewAfter(selection);
121         expect(result).toBeInstanceOf(HeadingNode);
122         expect(result.getDirection()).toEqual(headingNode.getDirection());
123       });
124       expect(testEnv.outerHTML).toBe(
125         '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><h1><span data-lexical-text="true">hello world</span></h1><h1><br></h1></div>',
126       );
127     });
128
129     test('HeadingNode.insertNewAfter() end', async () => {
130       const {editor} = testEnv;
131       let headingNode: HeadingNode;
132       await editor.update(() => {
133         const root = $getRoot();
134         headingNode = new HeadingNode('h1');
135         const headingTextNode1 = $createTextNode('hello');
136         const headingTextNode2 = $createTextNode(' world');
137         headingTextNode2.setFormat('bold');
138         root.append(headingNode.append(headingTextNode1, headingTextNode2));
139         headingTextNode2.selectEnd();
140       });
141       expect(testEnv.outerHTML).toBe(
142         '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><h1><span data-lexical-text="true">hello</span><strong data-lexical-text="true"> world</strong></h1></div>',
143       );
144       await editor.update(() => {
145         const selection = $getSelection() as RangeSelection;
146         const result = headingNode.insertNewAfter(selection);
147         expect(result).toBeInstanceOf(ParagraphNode);
148         expect(result.getDirection()).toEqual(headingNode.getDirection());
149       });
150       expect(testEnv.outerHTML).toBe(
151         '<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><h1><span data-lexical-text="true">hello</span><strong data-lexical-text="true"> world</strong></h1><p><br></p></div>',
152       );
153     });
154
155     test('$createHeadingNode()', async () => {
156       const {editor} = testEnv;
157       await editor.update(() => {
158         const headingNode = new HeadingNode('h1');
159         const createdHeadingNode = $createHeadingNode('h1');
160         expect(headingNode.__type).toEqual(createdHeadingNode.__type);
161         expect(headingNode.__parent).toEqual(createdHeadingNode.__parent);
162         expect(headingNode.__key).not.toEqual(createdHeadingNode.__key);
163       });
164     });
165
166     test('$isHeadingNode()', async () => {
167       const {editor} = testEnv;
168       await editor.update(() => {
169         const headingNode = new HeadingNode('h1');
170         expect($isHeadingNode(headingNode)).toBe(true);
171       });
172     });
173
174     test('creates a h2 with text and can insert a new paragraph after', async () => {
175       const {editor} = testEnv;
176       let headingNode: HeadingNode;
177       const text = 'hello world';
178       await editor.update(() => {
179         const root = $getRoot();
180         headingNode = new HeadingNode('h2');
181         root.append(headingNode);
182         const textNode = $createTextNode(text);
183         headingNode.append(textNode);
184       });
185       expect(testEnv.outerHTML).toBe(
186         `<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><h2><span data-lexical-text="true">${text}</span></h2></div>`,
187       );
188       await editor.update(() => {
189         const result = headingNode.insertNewAfter();
190         expect(result).toBeInstanceOf(ParagraphNode);
191         expect(result.getDirection()).toEqual(headingNode.getDirection());
192       });
193       expect(testEnv.outerHTML).toBe(
194         `<div contenteditable="true" style="user-select: text; white-space: pre-wrap; word-break: break-word;" data-lexical-editor="true"><h2><span data-lexical-text="true">${text}</span></h2><p><br></p></div>`,
195       );
196     });
197   });
198 });