]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/services/__tests__/keyboard-handling.test.ts
0ab6935fb1ac5effb4ebc5bd6280571f04671b87
[bookstack] / resources / js / wysiwyg / services / __tests__ / keyboard-handling.test.ts
1 import {
2     createTestContext, destroyFromContext,
3     dispatchKeydownEventForNode,
4     dispatchKeydownEventForSelectedNode,
5 } from "lexical/__tests__/utils";
6 import {
7     $createParagraphNode, $createTextNode,
8     $getRoot, $getSelection, LexicalEditor, LexicalNode,
9     ParagraphNode, TextNode,
10 } from "lexical";
11 import {$createDetailsNode, DetailsNode} from "@lexical/rich-text/LexicalDetailsNode";
12 import {registerKeyboardHandling} from "../keyboard-handling";
13 import {registerRichText} from "@lexical/rich-text";
14 import {EditorUiContext} from "../../ui/framework/core";
15 import {$createListItemNode, $createListNode, ListItemNode, ListNode} from "@lexical/list";
16
17 describe('Keyboard-handling service tests', () => {
18
19     let context!: EditorUiContext;
20     let editor!: LexicalEditor;
21
22     beforeEach(() => {
23         context = createTestContext();
24         editor = context.editor;
25         registerRichText(editor);
26         registerKeyboardHandling(context);
27     });
28
29     afterEach(() => {
30         destroyFromContext(context);
31     });
32
33     test('Details: down key on last lines creates new sibling node', () => {
34         let lastRootChild!: LexicalNode|null;
35         let detailsPara!: ParagraphNode;
36
37         editor.updateAndCommit(() => {
38             const root = $getRoot()
39             const details = $createDetailsNode();
40             detailsPara = $createParagraphNode();
41             details.append(detailsPara);
42             $getRoot().append(details);
43             detailsPara.select();
44
45             lastRootChild = root.getLastChild();
46         });
47
48         expect(lastRootChild).toBeInstanceOf(DetailsNode);
49
50         dispatchKeydownEventForNode(detailsPara, editor, 'ArrowDown');
51         editor.commitUpdates();
52
53         editor.getEditorState().read(() => {
54             lastRootChild = $getRoot().getLastChild();
55         });
56
57         expect(lastRootChild).toBeInstanceOf(ParagraphNode);
58     });
59
60     test('Details: enter on last empty block creates new sibling node', () => {
61         registerRichText(editor);
62
63         let lastRootChild!: LexicalNode|null;
64         let detailsPara!: ParagraphNode;
65
66         editor.updateAndCommit(() => {
67             const root = $getRoot()
68             const details = $createDetailsNode();
69             const text = $createTextNode('Hello!');
70             detailsPara = $createParagraphNode();
71             detailsPara.append(text);
72             details.append(detailsPara);
73             $getRoot().append(details);
74             text.selectEnd();
75
76             lastRootChild = root.getLastChild();
77         });
78
79         expect(lastRootChild).toBeInstanceOf(DetailsNode);
80
81         dispatchKeydownEventForNode(detailsPara, editor, 'Enter');
82         editor.commitUpdates();
83
84         dispatchKeydownEventForSelectedNode(editor, 'Enter');
85         editor.commitUpdates();
86
87         let detailsChildren!: LexicalNode[];
88         let lastDetailsText!: string;
89
90         editor.getEditorState().read(() => {
91             detailsChildren = (lastRootChild as DetailsNode).getChildren();
92             lastRootChild = $getRoot().getLastChild();
93             lastDetailsText = detailsChildren[0].getTextContent();
94         });
95
96         expect(lastRootChild).toBeInstanceOf(ParagraphNode);
97         expect(detailsChildren).toHaveLength(1);
98         expect(lastDetailsText).toBe('Hello!');
99     });
100
101     test('Lists: tab on empty list item insets item', () => {
102
103         let list!: ListNode;
104         let listItemB!: ListItemNode;
105
106         editor.updateAndCommit(() => {
107             const root = $getRoot();
108             list = $createListNode('bullet');
109             const listItemA = $createListItemNode();
110             listItemA.append($createTextNode('Hello!'));
111             listItemB = $createListItemNode();
112             list.append(listItemA, listItemB);
113             root.append(list);
114             listItemB.selectStart();
115         });
116
117         dispatchKeydownEventForNode(listItemB, editor, 'Tab');
118         editor.commitUpdates();
119
120         editor.getEditorState().read(() => {
121             const list = $getRoot().getChildren()[0] as ListNode;
122             const listChild = list.getChildren()[0] as ListItemNode;
123             const children = listChild.getChildren();
124             expect(children).toHaveLength(2);
125             expect(children[0]).toBeInstanceOf(TextNode);
126             expect(children[0].getTextContent()).toBe('Hello!');
127             expect(children[1]).toBeInstanceOf(ListNode);
128
129             const innerList = children[1] as ListNode;
130             const selectedNode = $getSelection()?.getNodes()[0];
131             expect(selectedNode).toBeInstanceOf(ListItemNode);
132             expect(selectedNode?.getKey()).toBe(innerList.getChildren()[0].getKey());
133         });
134     });
135 });