]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/lexical/list/__tests__/unit/utils.test.ts
1fa327379b91bab0cab43c4a3a6de32503f0bd79
[bookstack] / resources / js / wysiwyg / lexical / list / __tests__ / unit / utils.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 import {$createParagraphNode, $getRoot} from 'lexical';
9 import {initializeUnitTest} from 'lexical/src/__tests__/utils';
10
11 import {$createListItemNode, $createListNode} from '../..';
12 import {$getListDepth, $getTopListNode, $isLastItemInList} from '../../utils';
13
14 describe('Lexical List Utils tests', () => {
15   initializeUnitTest((testEnv) => {
16     test('getListDepth should return the 1-based depth of a list with one levels', async () => {
17       const editor = testEnv.editor;
18
19       editor.update(() => {
20         // Root
21         //   |- ListNode
22         const root = $getRoot();
23
24         const topListNode = $createListNode('bullet');
25
26         root.append(topListNode);
27
28         const result = $getListDepth(topListNode);
29
30         expect(result).toEqual(1);
31       });
32     });
33
34     test('getListDepth should return the 1-based depth of a list with two levels', async () => {
35       const editor = testEnv.editor;
36
37       await editor.update(() => {
38         // Root
39         //   |- ListNode
40         //         |- ListItemNode
41         //         |- ListItemNode
42         //         |- ListNode
43         //               |- ListItemNode
44         const root = $getRoot();
45
46         const topListNode = $createListNode('bullet');
47         const secondLevelListNode = $createListNode('bullet');
48
49         const listItem1 = $createListItemNode();
50         const listItem2 = $createListItemNode();
51         const listItem3 = $createListItemNode();
52
53         root.append(topListNode);
54
55         topListNode.append(listItem1);
56         topListNode.append(listItem2);
57         topListNode.append(secondLevelListNode);
58
59         secondLevelListNode.append(listItem3);
60
61         const result = $getListDepth(secondLevelListNode);
62
63         expect(result).toEqual(2);
64       });
65     });
66
67     test('getListDepth should return the 1-based depth of a list with five levels', async () => {
68       const editor = testEnv.editor;
69
70       await editor.update(() => {
71         // Root
72         //   |- ListNode
73         //        |- ListItemNode
74         //             |- ListNode
75         //                  |- ListItemNode
76         //                       |- ListNode
77         //                            |- ListItemNode
78         //                                 |- ListNode
79         //                                     |- ListItemNode
80         //                                          |- ListNode
81         const root = $getRoot();
82
83         const topListNode = $createListNode('bullet');
84         const listNode2 = $createListNode('bullet');
85         const listNode3 = $createListNode('bullet');
86         const listNode4 = $createListNode('bullet');
87         const listNode5 = $createListNode('bullet');
88
89         const listItem1 = $createListItemNode();
90         const listItem2 = $createListItemNode();
91         const listItem3 = $createListItemNode();
92         const listItem4 = $createListItemNode();
93
94         root.append(topListNode);
95
96         topListNode.append(listItem1);
97
98         listItem1.append(listNode2);
99         listNode2.append(listItem2);
100         listItem2.append(listNode3);
101         listNode3.append(listItem3);
102         listItem3.append(listNode4);
103         listNode4.append(listItem4);
104         listItem4.append(listNode5);
105
106         const result = $getListDepth(listNode5);
107
108         expect(result).toEqual(5);
109       });
110     });
111
112     test('getTopListNode should return the top list node when the list is a direct child of the RootNode', async () => {
113       const editor = testEnv.editor;
114
115       await editor.update(() => {
116         // Root
117         //   |- ListNode
118         //         |- ListItemNode
119         //         |- ListItemNode
120         //         |- ListNode
121         //               |- ListItemNode
122         const root = $getRoot();
123
124         const topListNode = $createListNode('bullet');
125         const secondLevelListNode = $createListNode('bullet');
126
127         const listItem1 = $createListItemNode();
128         const listItem2 = $createListItemNode();
129         const listItem3 = $createListItemNode();
130
131         root.append(topListNode);
132
133         topListNode.append(listItem1);
134         topListNode.append(listItem2);
135         topListNode.append(secondLevelListNode);
136         secondLevelListNode.append(listItem3);
137
138         const result = $getTopListNode(listItem3);
139         expect(result.getKey()).toEqual(topListNode.getKey());
140       });
141     });
142
143     test('getTopListNode should return the top list node when the list is not a direct child of the RootNode', async () => {
144       const editor = testEnv.editor;
145
146       await editor.update(() => {
147         // Root
148         // |- ParagraphNode
149         //     |- ListNode
150         //        |- ListItemNode
151         //        |- ListItemNode
152         //           |- ListNode
153         //              |- ListItemNode
154         const root = $getRoot();
155
156         const paragraphNode = $createParagraphNode();
157         const topListNode = $createListNode('bullet');
158         const secondLevelListNode = $createListNode('bullet');
159
160         const listItem1 = $createListItemNode();
161         const listItem2 = $createListItemNode();
162         const listItem3 = $createListItemNode();
163         root.append(paragraphNode);
164         paragraphNode.append(topListNode);
165         topListNode.append(listItem1);
166         topListNode.append(listItem2);
167         topListNode.append(secondLevelListNode);
168         secondLevelListNode.append(listItem3);
169
170         const result = $getTopListNode(listItem3);
171         expect(result.getKey()).toEqual(topListNode.getKey());
172       });
173     });
174
175     test('getTopListNode should return the top list node when the list item is deeply nested.', async () => {
176       const editor = testEnv.editor;
177
178       await editor.update(() => {
179         // Root
180         // |- ParagraphNode
181         //     |- ListNode
182         //        |- ListItemNode
183         //           |- ListNode
184         //              |- ListItemNode
185         //                  |- ListNode
186         //                      |- ListItemNode
187         //        |- ListItemNode
188         const root = $getRoot();
189
190         const paragraphNode = $createParagraphNode();
191         const topListNode = $createListNode('bullet');
192         const secondLevelListNode = $createListNode('bullet');
193         const thirdLevelListNode = $createListNode('bullet');
194
195         const listItem1 = $createListItemNode();
196         const listItem2 = $createListItemNode();
197         const listItem3 = $createListItemNode();
198         const listItem4 = $createListItemNode();
199         root.append(paragraphNode);
200         paragraphNode.append(topListNode);
201         topListNode.append(listItem1);
202         listItem1.append(secondLevelListNode);
203         secondLevelListNode.append(listItem2);
204         listItem2.append(thirdLevelListNode);
205         thirdLevelListNode.append(listItem3);
206         topListNode.append(listItem4);
207
208         const result = $getTopListNode(listItem4);
209         expect(result.getKey()).toEqual(topListNode.getKey());
210       });
211     });
212
213     test('isLastItemInList should return true if the listItem is the last in a nested list.', async () => {
214       const editor = testEnv.editor;
215
216       await editor.update(() => {
217         // Root
218         //   |- ListNode
219         //      |- ListItemNode
220         //         |- ListNode
221         //            |- ListItemNode
222         //                |- ListNode
223         //                    |- ListItemNode
224         const root = $getRoot();
225
226         const topListNode = $createListNode('bullet');
227         const secondLevelListNode = $createListNode('bullet');
228         const thirdLevelListNode = $createListNode('bullet');
229
230         const listItem1 = $createListItemNode();
231         const listItem2 = $createListItemNode();
232         const listItem3 = $createListItemNode();
233
234         root.append(topListNode);
235
236         topListNode.append(listItem1);
237         listItem1.append(secondLevelListNode);
238         secondLevelListNode.append(listItem2);
239         listItem2.append(thirdLevelListNode);
240         thirdLevelListNode.append(listItem3);
241
242         const result = $isLastItemInList(listItem3);
243
244         expect(result).toEqual(true);
245       });
246     });
247
248     test('isLastItemInList should return true if the listItem is the last in a non-nested list.', async () => {
249       const editor = testEnv.editor;
250
251       await editor.update(() => {
252         // Root
253         //   |- ListNode
254         //      |- ListItemNode
255         //      |- ListItemNode
256         const root = $getRoot();
257
258         const topListNode = $createListNode('bullet');
259
260         const listItem1 = $createListItemNode();
261         const listItem2 = $createListItemNode();
262
263         root.append(topListNode);
264
265         topListNode.append(listItem1);
266         topListNode.append(listItem2);
267
268         const result = $isLastItemInList(listItem2);
269
270         expect(result).toEqual(true);
271       });
272     });
273
274     test('isLastItemInList should return false if the listItem is not the last in a nested list.', async () => {
275       const editor = testEnv.editor;
276
277       await editor.update(() => {
278         // Root
279         //   |- ListNode
280         //      |- ListItemNode
281         //         |- ListNode
282         //            |- ListItemNode
283         //                |- ListNode
284         //                    |- ListItemNode
285         const root = $getRoot();
286
287         const topListNode = $createListNode('bullet');
288         const secondLevelListNode = $createListNode('bullet');
289         const thirdLevelListNode = $createListNode('bullet');
290
291         const listItem1 = $createListItemNode();
292         const listItem2 = $createListItemNode();
293         const listItem3 = $createListItemNode();
294
295         root.append(topListNode);
296
297         topListNode.append(listItem1);
298         listItem1.append(secondLevelListNode);
299         secondLevelListNode.append(listItem2);
300         listItem2.append(thirdLevelListNode);
301         thirdLevelListNode.append(listItem3);
302
303         const result = $isLastItemInList(listItem2);
304
305         expect(result).toEqual(false);
306       });
307     });
308
309     test('isLastItemInList should return true if the listItem is not the last in a non-nested list.', async () => {
310       const editor = testEnv.editor;
311
312       await editor.update(() => {
313         // Root
314         //   |- ListNode
315         //      |- ListItemNode
316         //      |- ListItemNode
317         const root = $getRoot();
318
319         const topListNode = $createListNode('bullet');
320
321         const listItem1 = $createListItemNode();
322         const listItem2 = $createListItemNode();
323
324         root.append(topListNode);
325
326         topListNode.append(listItem1);
327         topListNode.append(listItem2);
328
329         const result = $isLastItemInList(listItem1);
330
331         expect(result).toEqual(false);
332       });
333     });
334   });
335 });