2 * Copyright (c) Meta Platforms, Inc. and affiliates.
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
11 $createRangeSelection,
19 } from 'lexical/__tests__/utils';
28 const editorConfig = Object.freeze({
32 listitem: 'my-listItem-item-class',
34 listitem: 'my-nested-list-listItem-class',
40 describe('LexicalListItemNode tests', () => {
41 initializeUnitTest((testEnv) => {
42 test('ListItemNode.constructor', async () => {
43 const {editor} = testEnv;
45 await editor.update(() => {
46 const listItemNode = new ListItemNode();
48 expect(listItemNode.getType()).toBe('listitem');
50 expect(listItemNode.getTextContent()).toBe('');
53 expect(() => new ListItemNode()).toThrow();
56 test('ListItemNode.createDOM()', async () => {
57 const {editor} = testEnv;
59 await editor.update(() => {
60 const listItemNode = new ListItemNode();
63 listItemNode.createDOM(editorConfig).outerHTML,
65 <li class="my-listItem-item-class" value="1"></li>
70 listItemNode.createDOM({
81 describe('ListItemNode.updateDOM()', () => {
82 test('base', async () => {
83 const {editor} = testEnv;
85 await editor.update(() => {
86 const listItemNode = new ListItemNode();
88 const domElement = listItemNode.createDOM(editorConfig);
93 <li class="my-listItem-item-class" value="1"></li>
96 const newListItemNode = new ListItemNode();
98 const result = newListItemNode.updateDOM(
104 expect(result).toBe(false);
107 domElement.outerHTML,
109 <li class="my-listItem-item-class" value="1"></li>
115 test('nested list', async () => {
116 const {editor} = testEnv;
118 await editor.update(() => {
119 const parentListNode = new ListNode('bullet', 1);
120 const parentlistItemNode = new ListItemNode();
122 parentListNode.append(parentlistItemNode);
123 const domElement = parentlistItemNode.createDOM(editorConfig);
126 domElement.outerHTML,
128 <li class="my-listItem-item-class" value="1"></li>
131 const nestedListNode = new ListNode('bullet', 1);
132 nestedListNode.append(new ListItemNode());
133 parentlistItemNode.append(nestedListNode);
134 const result = parentlistItemNode.updateDOM(
140 expect(result).toBe(false);
143 domElement.outerHTML,
146 class="my-listItem-item-class my-nested-list-listItem-class"
154 describe('ListItemNode.replace()', () => {
155 let listNode: ListNode;
156 let listItemNode1: ListItemNode;
157 let listItemNode2: ListItemNode;
158 let listItemNode3: ListItemNode;
160 beforeEach(async () => {
161 const {editor} = testEnv;
163 await editor.update(() => {
164 const root = $getRoot();
165 listNode = new ListNode('bullet', 1);
166 listItemNode1 = new ListItemNode();
168 listItemNode1.append(new TextNode('one'));
169 listItemNode2 = new ListItemNode();
171 listItemNode2.append(new TextNode('two'));
172 listItemNode3 = new ListItemNode();
174 listItemNode3.append(new TextNode('three'));
175 root.append(listNode);
176 listNode.append(listItemNode1, listItemNode2, listItemNode3);
183 contenteditable="true"
184 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
185 data-lexical-editor="true">
187 <li dir="ltr" value="1">
188 <span data-lexical-text="true">one</span>
190 <li dir="ltr" value="2">
191 <span data-lexical-text="true">two</span>
193 <li dir="ltr" value="3">
194 <span data-lexical-text="true">three</span>
202 test('another list item node', async () => {
203 const {editor} = testEnv;
205 await editor.update(() => {
206 const newListItemNode = new ListItemNode();
208 newListItemNode.append(new TextNode('bar'));
209 listItemNode1.replace(newListItemNode);
216 contenteditable="true"
217 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
218 data-lexical-editor="true">
220 <li dir="ltr" value="1">
221 <span data-lexical-text="true">bar</span>
223 <li dir="ltr" value="2">
224 <span data-lexical-text="true">two</span>
226 <li dir="ltr" value="3">
227 <span data-lexical-text="true">three</span>
235 test('first list item with a non list item node', async () => {
236 const {editor} = testEnv;
238 await editor.update(() => {
246 contenteditable="true"
247 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
248 data-lexical-editor="true">
250 <li dir="ltr" value="1">
251 <span data-lexical-text="true">one</span>
253 <li dir="ltr" value="2">
254 <span data-lexical-text="true">two</span>
256 <li dir="ltr" value="3">
257 <span data-lexical-text="true">three</span>
264 await editor.update(() => {
265 const paragraphNode = $createParagraphNode();
266 listItemNode1.replace(paragraphNode);
273 contenteditable="true"
274 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
275 data-lexical-editor="true">
278 <li dir="ltr" value="1">
279 <span data-lexical-text="true">two</span>
281 <li dir="ltr" value="2">
282 <span data-lexical-text="true">three</span>
290 test('last list item with a non list item node', async () => {
291 const {editor} = testEnv;
293 await editor.update(() => {
294 const paragraphNode = $createParagraphNode();
295 listItemNode3.replace(paragraphNode);
302 contenteditable="true"
303 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
304 data-lexical-editor="true">
306 <li dir="ltr" value="1">
307 <span data-lexical-text="true">one</span>
309 <li dir="ltr" value="2">
310 <span data-lexical-text="true">two</span>
319 test('middle list item with a non list item node', async () => {
320 const {editor} = testEnv;
322 await editor.update(() => {
323 const paragraphNode = $createParagraphNode();
324 listItemNode2.replace(paragraphNode);
331 contenteditable="true"
332 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
333 data-lexical-editor="true">
335 <li dir="ltr" value="1">
336 <span data-lexical-text="true">one</span>
341 <li dir="ltr" value="1">
342 <span data-lexical-text="true">three</span>
350 test('the only list item with a non list item node', async () => {
351 const {editor} = testEnv;
353 await editor.update(() => {
354 listItemNode2.remove();
355 listItemNode3.remove();
362 contenteditable="true"
363 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
364 data-lexical-editor="true">
366 <li dir="ltr" value="1">
367 <span data-lexical-text="true">one</span>
374 await editor.update(() => {
375 const paragraphNode = $createParagraphNode();
376 listItemNode1.replace(paragraphNode);
383 contenteditable="true"
384 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
385 data-lexical-editor="true">
393 describe('ListItemNode.remove()', () => {
397 test('siblings are not nested', async () => {
398 const {editor} = testEnv;
401 await editor.update(() => {
402 const root = $getRoot();
403 const parent = new ListNode('bullet', 1);
405 const A_listItem = new ListItemNode();
406 A_listItem.append(new TextNode('A'));
408 x = new ListItemNode();
409 x.append(new TextNode('x'));
411 const B_listItem = new ListItemNode();
412 B_listItem.append(new TextNode('B'));
414 parent.append(A_listItem, x, B_listItem);
422 contenteditable="true"
423 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
424 data-lexical-editor="true">
426 <li dir="ltr" value="1">
427 <span data-lexical-text="true">A</span>
429 <li dir="ltr" value="2">
430 <span data-lexical-text="true">x</span>
432 <li dir="ltr" value="3">
433 <span data-lexical-text="true">B</span>
440 await editor.update(() => x.remove());
446 contenteditable="true"
447 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
448 data-lexical-editor="true">
450 <li dir="ltr" value="1">
451 <span data-lexical-text="true">A</span>
453 <li dir="ltr" value="2">
454 <span data-lexical-text="true">B</span>
465 test('the previous sibling is nested', async () => {
466 const {editor} = testEnv;
469 await editor.update(() => {
470 const root = $getRoot();
471 const parent = new ListNode('bullet', 1);
473 const A_listItem = new ListItemNode();
474 const A_nestedList = new ListNode('bullet', 1);
475 const A_nestedListItem = new ListItemNode();
476 A_listItem.append(A_nestedList);
477 A_nestedList.append(A_nestedListItem);
478 A_nestedListItem.append(new TextNode('A'));
480 x = new ListItemNode();
481 x.append(new TextNode('x'));
483 const B_listItem = new ListItemNode();
484 B_listItem.append(new TextNode('B'));
486 parent.append(A_listItem, x, B_listItem);
494 contenteditable="true"
495 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
496 data-lexical-editor="true">
500 <li dir="ltr" value="1">
501 <span data-lexical-text="true">A</span>
505 <li dir="ltr" value="1">
506 <span data-lexical-text="true">x</span>
508 <li dir="ltr" value="2">
509 <span data-lexical-text="true">B</span>
516 await editor.update(() => x.remove());
522 contenteditable="true"
523 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
524 data-lexical-editor="true">
528 <li dir="ltr" value="1">
529 <span data-lexical-text="true">A</span>
533 <li dir="ltr" value="1">
534 <span data-lexical-text="true">B</span>
545 test('the next sibling is nested', async () => {
546 const {editor} = testEnv;
549 await editor.update(() => {
550 const root = $getRoot();
551 const parent = new ListNode('bullet', 1);
553 const A_listItem = new ListItemNode();
554 A_listItem.append(new TextNode('A'));
556 x = new ListItemNode();
557 x.append(new TextNode('x'));
559 const B_listItem = new ListItemNode();
560 const B_nestedList = new ListNode('bullet', 1);
561 const B_nestedListItem = new ListItemNode();
562 B_listItem.append(B_nestedList);
563 B_nestedList.append(B_nestedListItem);
564 B_nestedListItem.append(new TextNode('B'));
566 parent.append(A_listItem, x, B_listItem);
574 contenteditable="true"
575 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
576 data-lexical-editor="true">
578 <li dir="ltr" value="1">
579 <span data-lexical-text="true">A</span>
581 <li dir="ltr" value="2">
582 <span data-lexical-text="true">x</span>
586 <li dir="ltr" value="1">
587 <span data-lexical-text="true">B</span>
596 await editor.update(() => x.remove());
602 contenteditable="true"
603 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
604 data-lexical-editor="true">
606 <li dir="ltr" value="1">
607 <span data-lexical-text="true">A</span>
611 <li dir="ltr" value="1">
612 <span data-lexical-text="true">B</span>
625 test('both siblings are nested', async () => {
626 const {editor} = testEnv;
629 await editor.update(() => {
630 const root = $getRoot();
631 const parent = new ListNode('bullet', 1);
633 const A_listItem = new ListItemNode();
634 const A_nestedList = new ListNode('bullet', 1);
635 const A_nestedListItem = new ListItemNode();
636 A_listItem.append(A_nestedList);
637 A_nestedList.append(A_nestedListItem);
638 A_nestedListItem.append(new TextNode('A'));
640 x = new ListItemNode();
641 x.append(new TextNode('x'));
643 const B_listItem = new ListItemNode();
644 const B_nestedList = new ListNode('bullet', 1);
645 const B_nestedListItem = new ListItemNode();
646 B_listItem.append(B_nestedList);
647 B_nestedList.append(B_nestedListItem);
648 B_nestedListItem.append(new TextNode('B'));
650 parent.append(A_listItem, x, B_listItem);
658 contenteditable="true"
659 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
660 data-lexical-editor="true">
664 <li dir="ltr" value="1">
665 <span data-lexical-text="true">A</span>
669 <li dir="ltr" value="1">
670 <span data-lexical-text="true">x</span>
674 <li dir="ltr" value="1">
675 <span data-lexical-text="true">B</span>
684 await editor.update(() => x.remove());
690 contenteditable="true"
691 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
692 data-lexical-editor="true">
696 <li dir="ltr" value="1">
697 <span data-lexical-text="true">A</span>
699 <li dir="ltr" value="2">
700 <span data-lexical-text="true">B</span>
714 test('the previous sibling is nested deeper than the next sibling', async () => {
715 const {editor} = testEnv;
718 await editor.update(() => {
719 const root = $getRoot();
720 const parent = new ListNode('bullet', 1);
722 const A_listItem = new ListItemNode();
723 const A_nestedList = new ListNode('bullet', 1);
724 const A_nestedListItem1 = new ListItemNode();
725 const A_nestedListItem2 = new ListItemNode();
726 const A_deeplyNestedList = new ListNode('bullet', 1);
727 const A_deeplyNestedListItem = new ListItemNode();
728 A_listItem.append(A_nestedList);
729 A_nestedList.append(A_nestedListItem1);
730 A_nestedList.append(A_nestedListItem2);
731 A_nestedListItem1.append(new TextNode('A1'));
732 A_nestedListItem2.append(A_deeplyNestedList);
733 A_deeplyNestedList.append(A_deeplyNestedListItem);
734 A_deeplyNestedListItem.append(new TextNode('A2'));
736 x = new ListItemNode();
737 x.append(new TextNode('x'));
739 const B_listItem = new ListItemNode();
740 const B_nestedList = new ListNode('bullet', 1);
741 const B_nestedlistItem = new ListItemNode();
742 B_listItem.append(B_nestedList);
743 B_nestedList.append(B_nestedlistItem);
744 B_nestedlistItem.append(new TextNode('B'));
746 parent.append(A_listItem, x, B_listItem);
754 contenteditable="true"
755 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
756 data-lexical-editor="true">
760 <li dir="ltr" value="1">
761 <span data-lexical-text="true">A1</span>
765 <li dir="ltr" value="1">
766 <span data-lexical-text="true">A2</span>
772 <li dir="ltr" value="1">
773 <span data-lexical-text="true">x</span>
777 <li dir="ltr" value="1">
778 <span data-lexical-text="true">B</span>
787 await editor.update(() => x.remove());
793 contenteditable="true"
794 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
795 data-lexical-editor="true">
799 <li dir="ltr" value="1">
800 <span data-lexical-text="true">A1</span>
804 <li dir="ltr" value="1">
805 <span data-lexical-text="true">A2</span>
809 <li dir="ltr" value="2">
810 <span data-lexical-text="true">B</span>
824 test('the next sibling is nested deeper than the previous sibling', async () => {
825 const {editor} = testEnv;
828 await editor.update(() => {
829 const root = $getRoot();
830 const parent = new ListNode('bullet', 1);
832 const A_listItem = new ListItemNode();
833 const A_nestedList = new ListNode('bullet', 1);
834 const A_nestedListItem = new ListItemNode();
835 A_listItem.append(A_nestedList);
836 A_nestedList.append(A_nestedListItem);
837 A_nestedListItem.append(new TextNode('A'));
839 x = new ListItemNode();
840 x.append(new TextNode('x'));
842 const B_listItem = new ListItemNode();
843 const B_nestedList = new ListNode('bullet', 1);
844 const B_nestedListItem1 = new ListItemNode();
845 const B_nestedListItem2 = new ListItemNode();
846 const B_deeplyNestedList = new ListNode('bullet', 1);
847 const B_deeplyNestedListItem = new ListItemNode();
848 B_listItem.append(B_nestedList);
849 B_nestedList.append(B_nestedListItem1);
850 B_nestedList.append(B_nestedListItem2);
851 B_nestedListItem1.append(B_deeplyNestedList);
852 B_nestedListItem2.append(new TextNode('B2'));
853 B_deeplyNestedList.append(B_deeplyNestedListItem);
854 B_deeplyNestedListItem.append(new TextNode('B1'));
856 parent.append(A_listItem, x, B_listItem);
864 contenteditable="true"
865 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
866 data-lexical-editor="true">
870 <li dir="ltr" value="1">
871 <span data-lexical-text="true">A</span>
875 <li dir="ltr" value="1">
876 <span data-lexical-text="true">x</span>
882 <li dir="ltr" value="1">
883 <span data-lexical-text="true">B1</span>
887 <li dir="ltr" value="1">
888 <span data-lexical-text="true">B2</span>
897 await editor.update(() => x.remove());
903 contenteditable="true"
904 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
905 data-lexical-editor="true">
909 <li dir="ltr" value="1">
910 <span data-lexical-text="true">A</span>
914 <li dir="ltr" value="1">
915 <span data-lexical-text="true">B1</span>
919 <li dir="ltr" value="2">
920 <span data-lexical-text="true">B2</span>
935 test('both siblings are deeply nested', async () => {
936 const {editor} = testEnv;
939 await editor.update(() => {
940 const root = $getRoot();
941 const parent = new ListNode('bullet', 1);
943 const A_listItem = new ListItemNode();
944 const A_nestedList = new ListNode('bullet', 1);
945 const A_nestedListItem1 = new ListItemNode();
946 const A_nestedListItem2 = new ListItemNode();
947 const A_deeplyNestedList = new ListNode('bullet', 1);
948 const A_deeplyNestedListItem = new ListItemNode();
949 A_listItem.append(A_nestedList);
950 A_nestedList.append(A_nestedListItem1);
951 A_nestedList.append(A_nestedListItem2);
952 A_nestedListItem1.append(new TextNode('A1'));
953 A_nestedListItem2.append(A_deeplyNestedList);
954 A_deeplyNestedList.append(A_deeplyNestedListItem);
955 A_deeplyNestedListItem.append(new TextNode('A2'));
957 x = new ListItemNode();
958 x.append(new TextNode('x'));
960 const B_listItem = new ListItemNode();
961 const B_nestedList = new ListNode('bullet', 1);
962 const B_nestedListItem1 = new ListItemNode();
963 const B_nestedListItem2 = new ListItemNode();
964 const B_deeplyNestedList = new ListNode('bullet', 1);
965 const B_deeplyNestedListItem = new ListItemNode();
966 B_listItem.append(B_nestedList);
967 B_nestedList.append(B_nestedListItem1);
968 B_nestedList.append(B_nestedListItem2);
969 B_nestedListItem1.append(B_deeplyNestedList);
970 B_nestedListItem2.append(new TextNode('B2'));
971 B_deeplyNestedList.append(B_deeplyNestedListItem);
972 B_deeplyNestedListItem.append(new TextNode('B1'));
974 parent.append(A_listItem, x, B_listItem);
982 contenteditable="true"
983 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
984 data-lexical-editor="true">
988 <li dir="ltr" value="1">
989 <span data-lexical-text="true">A1</span>
993 <li dir="ltr" value="1">
994 <span data-lexical-text="true">A2</span>
1000 <li dir="ltr" value="1">
1001 <span data-lexical-text="true">x</span>
1007 <li dir="ltr" value="1">
1008 <span data-lexical-text="true">B1</span>
1012 <li dir="ltr" value="1">
1013 <span data-lexical-text="true">B2</span>
1022 await editor.update(() => x.remove());
1024 expectHtmlToBeEqual(
1028 contenteditable="true"
1029 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
1030 data-lexical-editor="true">
1034 <li dir="ltr" value="1">
1035 <span data-lexical-text="true">A1</span>
1039 <li dir="ltr" value="1">
1040 <span data-lexical-text="true">A2</span>
1042 <li dir="ltr" value="2">
1043 <span data-lexical-text="true">B1</span>
1047 <li dir="ltr" value="2">
1048 <span data-lexical-text="true">B2</span>
1059 describe('ListItemNode.insertNewAfter(): non-empty list items', () => {
1060 let listNode: ListNode;
1061 let listItemNode1: ListItemNode;
1062 let listItemNode2: ListItemNode;
1063 let listItemNode3: ListItemNode;
1065 beforeEach(async () => {
1066 const {editor} = testEnv;
1068 await editor.update(() => {
1069 const root = $getRoot();
1070 listNode = new ListNode('bullet', 1);
1071 listItemNode1 = new ListItemNode();
1073 listItemNode2 = new ListItemNode();
1075 listItemNode3 = new ListItemNode();
1077 root.append(listNode);
1078 listNode.append(listItemNode1, listItemNode2, listItemNode3);
1079 listItemNode1.append(new TextNode('one'));
1080 listItemNode2.append(new TextNode('two'));
1081 listItemNode3.append(new TextNode('three'));
1084 expectHtmlToBeEqual(
1088 contenteditable="true"
1089 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
1090 data-lexical-editor="true">
1092 <li dir="ltr" value="1">
1093 <span data-lexical-text="true">one</span>
1095 <li dir="ltr" value="2">
1096 <span data-lexical-text="true">two</span>
1098 <li dir="ltr" value="3">
1099 <span data-lexical-text="true">three</span>
1107 test('first list item', async () => {
1108 const {editor} = testEnv;
1110 await editor.update(() => {
1111 listItemNode1.insertNewAfter($createRangeSelection());
1114 expectHtmlToBeEqual(
1118 contenteditable="true"
1119 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
1120 data-lexical-editor="true">
1122 <li dir="ltr" value="1">
1123 <span data-lexical-text="true">one</span>
1125 <li value="2"><br /></li>
1126 <li dir="ltr" value="3">
1127 <span data-lexical-text="true">two</span>
1129 <li dir="ltr" value="4">
1130 <span data-lexical-text="true">three</span>
1138 test('last list item', async () => {
1139 const {editor} = testEnv;
1141 await editor.update(() => {
1142 listItemNode3.insertNewAfter($createRangeSelection());
1145 expectHtmlToBeEqual(
1149 contenteditable="true"
1150 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
1151 data-lexical-editor="true">
1153 <li dir="ltr" value="1">
1154 <span data-lexical-text="true">one</span>
1156 <li dir="ltr" value="2">
1157 <span data-lexical-text="true">two</span>
1159 <li dir="ltr" value="3">
1160 <span data-lexical-text="true">three</span>
1162 <li value="4"><br /></li>
1169 test('middle list item', async () => {
1170 const {editor} = testEnv;
1172 await editor.update(() => {
1173 listItemNode3.insertNewAfter($createRangeSelection());
1176 expectHtmlToBeEqual(
1180 contenteditable="true"
1181 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
1182 data-lexical-editor="true">
1184 <li dir="ltr" value="1">
1185 <span data-lexical-text="true">one</span>
1187 <li dir="ltr" value="2">
1188 <span data-lexical-text="true">two</span>
1190 <li dir="ltr" value="3">
1191 <span data-lexical-text="true">three</span>
1193 <li value="4"><br /></li>
1200 test('the only list item', async () => {
1201 const {editor} = testEnv;
1203 await editor.update(() => {
1204 listItemNode2.remove();
1205 listItemNode3.remove();
1208 expectHtmlToBeEqual(
1212 contenteditable="true"
1213 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
1214 data-lexical-editor="true">
1216 <li dir="ltr" value="1">
1217 <span data-lexical-text="true">one</span>
1224 await editor.update(() => {
1225 listItemNode1.insertNewAfter($createRangeSelection());
1228 expectHtmlToBeEqual(
1232 contenteditable="true"
1233 style="user-select: text; white-space: pre-wrap; word-break: break-word;"
1234 data-lexical-editor="true">
1236 <li dir="ltr" value="1">
1237 <span data-lexical-text="true">one</span>
1239 <li value="2"><br /></li>
1247 test('$createListItemNode()', async () => {
1248 const {editor} = testEnv;
1250 await editor.update(() => {
1251 const listItemNode = new ListItemNode();
1253 const createdListItemNode = $createListItemNode();
1255 expect(listItemNode.__type).toEqual(createdListItemNode.__type);
1256 expect(listItemNode.__parent).toEqual(createdListItemNode.__parent);
1257 expect(listItemNode.__key).not.toEqual(createdListItemNode.__key);
1261 test('$isListItemNode()', async () => {
1262 const {editor} = testEnv;
1264 await editor.update(() => {
1265 const listItemNode = new ListItemNode();
1267 expect($isListItemNode(listItemNode)).toBe(true);
1271 describe('ListItemNode.setIndent()', () => {
1272 let listNode: ListNode;
1273 let listItemNode1: ListItemNode;
1274 let listItemNode2: ListItemNode;
1276 beforeEach(async () => {
1277 const {editor} = testEnv;
1279 await editor.update(() => {
1280 const root = $getRoot();
1281 listNode = new ListNode('bullet', 1);
1282 listItemNode1 = new ListItemNode();
1284 listItemNode2 = new ListItemNode();
1286 root.append(listNode);
1287 listNode.append(listItemNode1, listItemNode2);
1288 listItemNode1.append(new TextNode('one'));
1289 listItemNode2.append(new TextNode('two'));
1292 it('indents and outdents list item', async () => {
1293 const {editor} = testEnv;
1295 await editor.update(() => {
1296 listItemNode1.setIndent(3);
1299 await editor.update(() => {
1300 expect(listItemNode1.getIndent()).toBe(3);
1303 expectHtmlToBeEqual(
1304 editor.getRootElement()!.innerHTML,
1313 <li dir="ltr" value="1">
1314 <span data-lexical-text="true">one</span>
1322 <li dir="ltr" value="1">
1323 <span data-lexical-text="true">two</span>
1329 await editor.update(() => {
1330 listItemNode1.setIndent(0);
1333 await editor.update(() => {
1334 expect(listItemNode1.getIndent()).toBe(0);
1337 expectHtmlToBeEqual(
1338 editor.getRootElement()!.innerHTML,
1341 <li dir="ltr" value="1">
1342 <span data-lexical-text="true">one</span>
1344 <li dir="ltr" value="2">
1345 <span data-lexical-text="true">two</span>
1352 it('handles fractional indent values', async () => {
1353 const {editor} = testEnv;
1355 await editor.update(() => {
1356 listItemNode1.setIndent(0.5);
1359 await editor.update(() => {
1360 expect(listItemNode1.getIndent()).toBe(0);