]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/lexical/table/__tests__/unit/LexicalTableSelection.test.tsx
9e9dbac8131891400702e1f3184d30d144015e35
[bookstack] / resources / js / wysiwyg / lexical / table / __tests__ / unit / LexicalTableSelection.test.tsx
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
9 import {$createTableSelection} from '@lexical/table';
10 import {
11   $createParagraphNode,
12   $createTextNode,
13   $getRoot,
14   $setSelection,
15   EditorState,
16   type LexicalEditor,
17   ParagraphNode,
18   RootNode,
19   TextNode,
20 } from 'lexical';
21 import {createTestEditor} from 'lexical/__tests__/utils';
22 import {createRef, useEffect, useMemo} from 'react';
23 import {createRoot, Root} from 'react-dom/client';
24 import * as ReactTestUtils from 'lexical/shared/react-test-utils';
25
26 describe('table selection', () => {
27   let originalText: TextNode;
28   let parsedParagraph: ParagraphNode;
29   let parsedRoot: RootNode;
30   let parsedText: TextNode;
31   let paragraphKey: string;
32   let textKey: string;
33   let parsedEditorState: EditorState;
34   let reactRoot: Root;
35   let container: HTMLDivElement | null = null;
36   let editor: LexicalEditor | null = null;
37
38   beforeEach(() => {
39     container = document.createElement('div');
40     reactRoot = createRoot(container);
41     document.body.appendChild(container);
42   });
43
44   function useLexicalEditor(
45     rootElementRef: React.RefObject<HTMLDivElement>,
46     onError?: () => void,
47   ) {
48     const editorInHook = useMemo(
49       () =>
50         createTestEditor({
51           nodes: [],
52           onError: onError || jest.fn(),
53           theme: {
54             text: {
55               bold: 'editor-text-bold',
56               italic: 'editor-text-italic',
57               underline: 'editor-text-underline',
58             },
59           },
60         }),
61       [onError],
62     );
63
64     useEffect(() => {
65       const rootElement = rootElementRef.current;
66
67       editorInHook.setRootElement(rootElement);
68     }, [rootElementRef, editorInHook]);
69
70     return editorInHook;
71   }
72
73   function init(onError?: () => void) {
74     const ref = createRef<HTMLDivElement>();
75
76     function TestBase() {
77       editor = useLexicalEditor(ref, onError);
78
79       return <div ref={ref} contentEditable={true} />;
80     }
81
82     ReactTestUtils.act(() => {
83       reactRoot.render(<TestBase />);
84     });
85   }
86
87   async function update(fn: () => void) {
88     editor!.update(fn);
89
90     return Promise.resolve().then();
91   }
92
93   beforeEach(async () => {
94     init();
95
96     await update(() => {
97       const paragraph = $createParagraphNode();
98       originalText = $createTextNode('Hello world');
99       const selection = $createTableSelection();
100       selection.set(
101         originalText.getKey(),
102         originalText.getKey(),
103         originalText.getKey(),
104       );
105       $setSelection(selection);
106       paragraph.append(originalText);
107       $getRoot().append(paragraph);
108     });
109
110     const stringifiedEditorState = JSON.stringify(
111       editor!.getEditorState().toJSON(),
112     );
113
114     parsedEditorState = editor!.parseEditorState(stringifiedEditorState);
115     parsedEditorState.read(() => {
116       parsedRoot = $getRoot();
117       parsedParagraph = parsedRoot.getFirstChild()!;
118       paragraphKey = parsedParagraph.getKey();
119       parsedText = parsedParagraph.getFirstChild()!;
120       textKey = parsedText.getKey();
121     });
122   });
123
124   it('Parses the nodes of a stringified editor state', async () => {
125     expect(parsedRoot).toEqual({
126       __cachedText: null,
127       __dir: 'ltr',
128       __first: paragraphKey,
129       __format: 0,
130       __indent: 0,
131       __key: 'root',
132       __last: paragraphKey,
133       __next: null,
134       __parent: null,
135       __prev: null,
136       __size: 1,
137       __style: '',
138       __type: 'root',
139     });
140     expect(parsedParagraph).toEqual({
141       __dir: 'ltr',
142       __first: textKey,
143       __format: 0,
144       __indent: 0,
145       __key: paragraphKey,
146       __last: textKey,
147       __next: null,
148       __parent: 'root',
149       __prev: null,
150       __size: 1,
151       __style: '',
152       __textFormat: 0,
153       __textStyle: '',
154       __type: 'paragraph',
155     });
156     expect(parsedText).toEqual({
157       __detail: 0,
158       __format: 0,
159       __key: textKey,
160       __mode: 0,
161       __next: null,
162       __parent: paragraphKey,
163       __prev: null,
164       __style: '',
165       __text: 'Hello world',
166       __type: 'text',
167     });
168   });
169
170   it('Parses the text content of the editor state', async () => {
171     expect(parsedEditorState.read(() => $getRoot().__cachedText)).toBe(null);
172     expect(parsedEditorState.read(() => $getRoot().getTextContent())).toBe(
173       'Hello world',
174     );
175   });
176 });