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.
16 import {initializeUnitTest} from 'lexical/__tests__/utils';
17 import {$createHeadingNode, $isHeadingNode, HeadingNode} from "@lexical/rich-text/LexicalHeadingNode";
19 const editorConfig = Object.freeze({
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('');
43 expect(() => new HeadingNode('h1')).toThrow();
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>',
54 headingNode.createDOM({
62 headingNode.createDOM({
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>');
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);
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>',
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());
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>',
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);
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>',
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());
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>',
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();
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>',
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());
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>',
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);
166 test('$isHeadingNode()', async () => {
167 const {editor} = testEnv;
168 await editor.update(() => {
169 const headingNode = new HeadingNode('h1');
170 expect($isHeadingNode(headingNode)).toBe(true);
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);
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>`,
188 await editor.update(() => {
189 const result = headingNode.insertNewAfter();
190 expect(result).toBeInstanceOf(ParagraphNode);
191 expect(result.getDirection()).toEqual(headingNode.getDirection());
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>`,