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.
19 $createTestElementNode,
22 } from 'lexical/src/__tests__/utils';
24 import {$dfs} from '../..';
26 describe('LexicalNodeHelpers tests', () => {
27 initializeUnitTest((testEnv) => {
34 * DFS: R, P1, B1, T1, B2, T2, T3, P2, T4, T5, B3, T6
36 test('DFS node order', async () => {
37 const editor: LexicalEditor = testEnv.editor;
39 let expectedKeys: Array<{
44 await editor.update(() => {
45 const root = $getRoot();
47 const paragraph1 = $createParagraphNode();
48 const paragraph2 = $createParagraphNode();
50 const block1 = $createTestElementNode();
51 const block2 = $createTestElementNode();
52 const block3 = $createTestElementNode();
54 const text1 = $createTextNode('text1');
55 const text2 = $createTextNode('text2');
56 const text3 = $createTextNode('text3');
57 const text4 = $createTextNode('text4');
58 const text5 = $createTextNode('text5');
59 const text6 = $createTextNode('text6');
61 root.append(paragraph1, paragraph2);
62 paragraph1.append(block1, block2);
63 paragraph2.append(text4, text5);
65 text5.toggleFormat('bold'); // Prevent from merging with text 4
67 paragraph2.append(block3);
69 block2.append(text2, text3);
71 text3.toggleFormat('bold'); // Prevent from merging with text2
82 node: paragraph1.getKey(),
86 node: block1.getKey(),
94 node: block2.getKey(),
102 node: text3.getKey(),
106 node: paragraph2.getKey(),
110 node: text4.getKey(),
114 node: text5.getKey(),
118 node: block3.getKey(),
122 node: text6.getKey(),
127 editor.getEditorState().read(() => {
128 const expectedNodes = expectedKeys.map(({depth, node: nodeKey}) => ({
130 node: $getNodeByKey(nodeKey)!.getLatest(),
133 const first = expectedNodes[0];
134 const second = expectedNodes[1];
135 const last = expectedNodes[expectedNodes.length - 1];
136 const secondToLast = expectedNodes[expectedNodes.length - 2];
138 expect($dfs(first.node, last.node)).toEqual(expectedNodes);
139 expect($dfs(second.node, secondToLast.node)).toEqual(
140 expectedNodes.slice(1, expectedNodes.length - 1),
142 expect($dfs()).toEqual(expectedNodes);
143 expect($dfs($getRoot())).toEqual(expectedNodes);
147 test('DFS triggers getLatest()', async () => {
148 const editor: LexicalEditor = testEnv.editor;
151 let paragraphKey: string;
152 let block1Key: string;
153 let block2Key: string;
155 await editor.update(() => {
156 const root = $getRoot();
158 const paragraph = $createParagraphNode();
159 const block1 = $createTestElementNode();
160 const block2 = $createTestElementNode();
162 rootKey = root.getKey();
163 paragraphKey = paragraph.getKey();
164 block1Key = block1.getKey();
165 block2Key = block2.getKey();
167 root.append(paragraph);
168 paragraph.append(block1, block2);
171 await editor.update(() => {
172 const root = $getNodeByKey(rootKey);
173 const paragraph = $getNodeByKey(paragraphKey);
174 const block1 = $getNodeByKey(block1Key);
175 const block2 = $getNodeByKey(block2Key);
177 const block3 = $createTestElementNode();
178 invariant($isElementNode(block1));
180 block1.append(block3);
182 expect($dfs(root!)).toEqual([
185 node: root!.getLatest(),
189 node: paragraph!.getLatest(),
193 node: block1.getLatest(),
197 node: block3.getLatest(),
201 node: block2!.getLatest(),
207 test('DFS of empty ParagraphNode returns only itself', async () => {
208 const editor: LexicalEditor = testEnv.editor;
210 let paragraphKey: string;
212 await editor.update(() => {
213 const root = $getRoot();
215 const paragraph = $createParagraphNode();
216 const paragraph2 = $createParagraphNode();
217 const text = $createTextNode('test');
219 paragraphKey = paragraph.getKey();
221 paragraph2.append(text);
222 root.append(paragraph, paragraph2);
224 await editor.update(() => {
225 const paragraph = $getNodeByKey(paragraphKey)!;
227 expect($dfs(paragraph ?? undefined)).toEqual([
230 node: paragraph?.getLatest(),