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.
8 import {ParagraphNode, TextNode} from 'lexical';
9 import {initializeUnitTest} from 'lexical/__tests__/utils';
20 const editorConfig = Object.freeze({
24 ol: 'my-ol-list-class',
34 ul: 'my-ul-list-class',
48 describe('LexicalListNode tests', () => {
49 initializeUnitTest((testEnv) => {
50 test('ListNode.constructor', async () => {
51 const {editor} = testEnv;
53 await editor.update(() => {
54 const listNode = $createListNode('bullet', 1);
55 expect(listNode.getType()).toBe('list');
56 expect(listNode.getTag()).toBe('ul');
57 expect(listNode.getTextContent()).toBe('');
61 expect(() => $createListNode()).toThrow();
64 test('ListNode.getTag()', async () => {
65 const {editor} = testEnv;
67 await editor.update(() => {
68 const ulListNode = $createListNode('bullet', 1);
69 expect(ulListNode.getTag()).toBe('ul');
70 const olListNode = $createListNode('number', 1);
71 expect(olListNode.getTag()).toBe('ol');
72 const checkListNode = $createListNode('check', 1);
73 expect(checkListNode.getTag()).toBe('ul');
77 test('ListNode.createDOM()', async () => {
78 const {editor} = testEnv;
80 await editor.update(() => {
81 const listNode = $createListNode('bullet', 1);
82 expect(listNode.createDOM(editorConfig).outerHTML).toBe(
83 '<ul class="my-ul-list-class my-ul-list-class-1"></ul>',
102 test('ListNode.createDOM() correctly applies classes to a nested ListNode', async () => {
103 const {editor} = testEnv;
105 await editor.update(() => {
106 const listNode1 = $createListNode('bullet');
107 const listNode2 = $createListNode('bullet');
108 const listNode3 = $createListNode('bullet');
109 const listNode4 = $createListNode('bullet');
110 const listNode5 = $createListNode('bullet');
111 const listNode6 = $createListNode('bullet');
112 const listNode7 = $createListNode('bullet');
114 const listItem1 = $createListItemNode();
115 const listItem2 = $createListItemNode();
116 const listItem3 = $createListItemNode();
117 const listItem4 = $createListItemNode();
119 listNode1.append(listItem1);
120 listItem1.append(listNode2);
121 listNode2.append(listItem2);
122 listItem2.append(listNode3);
123 listNode3.append(listItem3);
124 listItem3.append(listNode4);
125 listNode4.append(listItem4);
126 listNode4.append(listNode5);
127 listNode5.append(listNode6);
128 listNode6.append(listNode7);
130 expect(listNode1.createDOM(editorConfig).outerHTML).toBe(
131 '<ul class="my-ul-list-class my-ul-list-class-1"></ul>',
134 listNode1.createDOM({
142 listNode1.createDOM({
147 expect(listNode2.createDOM(editorConfig).outerHTML).toBe(
148 '<ul class="my-ul-list-class my-ul-list-class-2"></ul>',
150 expect(listNode3.createDOM(editorConfig).outerHTML).toBe(
151 '<ul class="my-ul-list-class my-ul-list-class-3"></ul>',
153 expect(listNode4.createDOM(editorConfig).outerHTML).toBe(
154 '<ul class="my-ul-list-class my-ul-list-class-4"></ul>',
156 expect(listNode5.createDOM(editorConfig).outerHTML).toBe(
157 '<ul class="my-ul-list-class my-ul-list-class-5"></ul>',
159 expect(listNode6.createDOM(editorConfig).outerHTML).toBe(
160 '<ul class="my-ul-list-class my-ul-list-class-6"></ul>',
162 expect(listNode7.createDOM(editorConfig).outerHTML).toBe(
163 '<ul class="my-ul-list-class my-ul-list-class-7"></ul>',
166 listNode5.createDOM({
170 ...editorConfig.theme.list,
172 'my-ul-list-class-1',
173 'my-ul-list-class-2',
174 'my-ul-list-class-3',
179 ).toBe('<ul class="my-ul-list-class my-ul-list-class-2"></ul>');
183 test('ListNode.updateDOM()', async () => {
184 const {editor} = testEnv;
186 await editor.update(() => {
187 const listNode = $createListNode('bullet', 1);
188 const domElement = listNode.createDOM(editorConfig);
190 expect(domElement.outerHTML).toBe(
191 '<ul class="my-ul-list-class my-ul-list-class-1"></ul>',
194 const newListNode = $createListNode('number', 1);
195 const result = newListNode.updateDOM(
201 expect(result).toBe(true);
202 expect(domElement.outerHTML).toBe(
203 '<ul class="my-ul-list-class my-ul-list-class-1"></ul>',
208 test('ListNode.append() should properly transform a ListItemNode', async () => {
209 const {editor} = testEnv;
211 await editor.update(() => {
212 const listNode = new ListNode('bullet', 1);
213 const listItemNode = new ListItemNode();
214 const textNode = new TextNode('Hello');
216 listItemNode.append(textNode);
217 const nodesToAppend = [listItemNode];
219 expect(listNode.append(...nodesToAppend)).toBe(listNode);
220 expect(listNode.getFirstChild()).toBe(listItemNode);
221 expect(listNode.getFirstChild()?.getTextContent()).toBe('Hello');
225 test('ListNode.append() should properly transform a ListNode', async () => {
226 const {editor} = testEnv;
228 await editor.update(() => {
229 const listNode = new ListNode('bullet', 1);
230 const nestedListNode = new ListNode('bullet', 1);
231 const listItemNode = new ListItemNode();
232 const textNode = new TextNode('Hello');
234 listItemNode.append(textNode);
235 nestedListNode.append(listItemNode);
237 const nodesToAppend = [nestedListNode];
239 expect(listNode.append(...nodesToAppend)).toBe(listNode);
240 expect($isListItemNode(listNode.getFirstChild())).toBe(true);
241 expect(listNode.getFirstChild<ListItemNode>()!.getFirstChild()).toBe(
247 test('ListNode.append() should properly transform a ParagraphNode', async () => {
248 const {editor} = testEnv;
250 await editor.update(() => {
251 const listNode = new ListNode('bullet', 1);
252 const paragraph = new ParagraphNode();
253 const textNode = new TextNode('Hello');
254 paragraph.append(textNode);
255 const nodesToAppend = [paragraph];
257 expect(listNode.append(...nodesToAppend)).toBe(listNode);
258 expect($isListItemNode(listNode.getFirstChild())).toBe(true);
259 expect(listNode.getFirstChild()?.getTextContent()).toBe('Hello');
263 test('$createListNode()', async () => {
264 const {editor} = testEnv;
266 await editor.update(() => {
267 const listNode = $createListNode('bullet', 1);
268 const createdListNode = $createListNode('bullet');
270 expect(listNode.__type).toEqual(createdListNode.__type);
271 expect(listNode.__parent).toEqual(createdListNode.__parent);
272 expect(listNode.__tag).toEqual(createdListNode.__tag);
273 expect(listNode.__key).not.toEqual(createdListNode.__key);
277 test('$isListNode()', async () => {
278 const {editor} = testEnv;
280 await editor.update(() => {
281 const listNode = $createListNode('bullet', 1);
283 expect($isListNode(listNode)).toBe(true);
287 test('$createListNode() with tag name (backward compatibility)', async () => {
288 const {editor} = testEnv;
290 await editor.update(() => {
291 const numberList = $createListNode('number', 1);
292 const bulletList = $createListNode('bullet', 1);
293 expect(numberList.__listType).toBe('number');
294 expect(bulletList.__listType).toBe('bullet');