]> BookStack Code Mirror - bookstack/blobdiff - resources/js/wysiwyg/services/__tests__/keyboard-handling.test.ts
Lexical: Aligned new empty item behaviour for nested lists
[bookstack] / resources / js / wysiwyg / services / __tests__ / keyboard-handling.test.ts
index 14a1ea973a5903f78258e33d544057881a254c3d..736c3573c5b48bd18bf2e4c4cd5e9fdd03c7b19d 100644 (file)
 import {
-    createTestContext,
+    createTestContext, destroyFromContext,
     dispatchKeydownEventForNode,
     dispatchKeydownEventForSelectedNode,
-    initializeUnitTest
 } from "lexical/__tests__/utils";
 import {
     $createParagraphNode, $createTextNode,
-    $getRoot, LexicalNode,
-    ParagraphNode,
+    $getRoot, $getSelection, LexicalEditor, LexicalNode,
+    ParagraphNode, TextNode,
 } from "lexical";
 import {$createDetailsNode, DetailsNode} from "@lexical/rich-text/LexicalDetailsNode";
 import {registerKeyboardHandling} from "../keyboard-handling";
 import {registerRichText} from "@lexical/rich-text";
+import {EditorUiContext} from "../../ui/framework/core";
+import {$createListItemNode, $createListNode, ListItemNode, ListNode} from "@lexical/list";
 
 describe('Keyboard-handling service tests', () => {
-    initializeUnitTest((testEnv) => {
 
-        test('Details: down key on last lines creates new sibling node', () => {
-            const {editor} = testEnv;
+    let context!: EditorUiContext;
+    let editor!: LexicalEditor;
 
-            registerRichText(editor);
-            registerKeyboardHandling(createTestContext(testEnv));
+    beforeEach(() => {
+        context = createTestContext();
+        editor = context.editor;
+        registerRichText(editor);
+        registerKeyboardHandling(context);
+    });
 
-            let lastRootChild!: LexicalNode|null;
-            let detailsPara!: ParagraphNode;
+    afterEach(() => {
+        destroyFromContext(context);
+    });
 
-            editor.updateAndCommit(() => {
-                const root = $getRoot()
-                const details = $createDetailsNode();
-                detailsPara = $createParagraphNode();
-                details.append(detailsPara);
-                $getRoot().append(details);
-                detailsPara.select();
+    test('Details: down key on last lines creates new sibling node', () => {
+        let lastRootChild!: LexicalNode|null;
+        let detailsPara!: ParagraphNode;
 
-                lastRootChild = root.getLastChild();
-            });
+        editor.updateAndCommit(() => {
+            const root = $getRoot()
+            const details = $createDetailsNode();
+            detailsPara = $createParagraphNode();
+            details.append(detailsPara);
+            $getRoot().append(details);
+            detailsPara.select();
 
-            expect(lastRootChild).toBeInstanceOf(DetailsNode);
+            lastRootChild = root.getLastChild();
+        });
 
-            dispatchKeydownEventForNode(detailsPara, editor, 'ArrowDown');
-            editor.commitUpdates();
+        expect(lastRootChild).toBeInstanceOf(DetailsNode);
 
-            editor.getEditorState().read(() => {
-                lastRootChild = $getRoot().getLastChild();
-            });
+        dispatchKeydownEventForNode(detailsPara, editor, 'ArrowDown');
 
-            expect(lastRootChild).toBeInstanceOf(ParagraphNode);
+        editor.getEditorState().read(() => {
+            lastRootChild = $getRoot().getLastChild();
         });
 
-        test('Details: enter on last empy block creates new sibling node', () => {
-            const {editor} = testEnv;
+        expect(lastRootChild).toBeInstanceOf(ParagraphNode);
+    });
 
-            registerRichText(editor);
-            registerKeyboardHandling(createTestContext(testEnv));
+    test('Details: enter on last empty block creates new sibling node', () => {
+        registerRichText(editor);
 
-            let lastRootChild!: LexicalNode|null;
-            let detailsPara!: ParagraphNode;
+        let lastRootChild!: LexicalNode|null;
+        let detailsPara!: ParagraphNode;
 
-            editor.updateAndCommit(() => {
-                const root = $getRoot()
-                const details = $createDetailsNode();
-                const text = $createTextNode('Hello!');
-                detailsPara = $createParagraphNode();
-                detailsPara.append(text);
-                details.append(detailsPara);
-                $getRoot().append(details);
-                text.selectEnd();
+        editor.updateAndCommit(() => {
+            const root = $getRoot()
+            const details = $createDetailsNode();
+            const text = $createTextNode('Hello!');
+            detailsPara = $createParagraphNode();
+            detailsPara.append(text);
+            details.append(detailsPara);
+            $getRoot().append(details);
+            text.selectEnd();
 
-                lastRootChild = root.getLastChild();
-            });
+            lastRootChild = root.getLastChild();
+        });
 
-            expect(lastRootChild).toBeInstanceOf(DetailsNode);
+        expect(lastRootChild).toBeInstanceOf(DetailsNode);
 
-            dispatchKeydownEventForNode(detailsPara, editor, 'Enter');
-            editor.commitUpdates();
+        dispatchKeydownEventForNode(detailsPara, editor, 'Enter');
+        dispatchKeydownEventForSelectedNode(editor, 'Enter');
 
-            dispatchKeydownEventForSelectedNode(editor, 'Enter');
-            editor.commitUpdates();
+        let detailsChildren!: LexicalNode[];
+        let lastDetailsText!: string;
 
-            let detailsChildren!: LexicalNode[];
-            let lastDetailsText!: string;
+        editor.getEditorState().read(() => {
+            detailsChildren = (lastRootChild as DetailsNode).getChildren();
+            lastRootChild = $getRoot().getLastChild();
+            lastDetailsText = detailsChildren[0].getTextContent();
+        });
 
-            editor.getEditorState().read(() => {
-                detailsChildren = (lastRootChild as DetailsNode).getChildren();
-                lastRootChild = $getRoot().getLastChild();
-                lastDetailsText = detailsChildren[0].getTextContent();
-            });
+        expect(lastRootChild).toBeInstanceOf(ParagraphNode);
+        expect(detailsChildren).toHaveLength(1);
+        expect(lastDetailsText).toBe('Hello!');
+    });
+
+    test('Lists: tab on empty list item insets item', () => {
+
+        let list!: ListNode;
+        let listItemB!: ListItemNode;
+
+        editor.updateAndCommit(() => {
+            const root = $getRoot();
+            list = $createListNode('bullet');
+            const listItemA = $createListItemNode();
+            listItemA.append($createTextNode('Hello!'));
+            listItemB = $createListItemNode();
+            list.append(listItemA, listItemB);
+            root.append(list);
+            listItemB.selectStart();
+        });
 
-            expect(lastRootChild).toBeInstanceOf(ParagraphNode);
-            expect(detailsChildren).toHaveLength(1);
-            expect(lastDetailsText).toBe('Hello!');
+        dispatchKeydownEventForNode(listItemB, editor, 'Tab');
+
+        editor.getEditorState().read(() => {
+            const list = $getRoot().getChildren()[0] as ListNode;
+            const listChild = list.getChildren()[0] as ListItemNode;
+            const children = listChild.getChildren();
+            expect(children).toHaveLength(2);
+            expect(children[0]).toBeInstanceOf(TextNode);
+            expect(children[0].getTextContent()).toBe('Hello!');
+            expect(children[1]).toBeInstanceOf(ListNode);
+
+            const innerList = children[1] as ListNode;
+            const selectedNode = $getSelection()?.getNodes()[0];
+            expect(selectedNode).toBeInstanceOf(ListItemNode);
+            expect(selectedNode?.getKey()).toBe(innerList.getChildren()[0].getKey());
         });
     });
 });
\ No newline at end of file