2 createTestContext, destroyFromContext,
3 dispatchKeydownEventForNode,
4 dispatchKeydownEventForSelectedNode, expectNodeShapeToMatch,
5 } from "lexical/__tests__/utils";
7 $createParagraphNode, $createTextNode,
8 $getRoot, $getSelection, LexicalEditor, LexicalNode,
9 ParagraphNode, TextNode,
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 import {$createImageNode, ImageNode} from "@lexical/rich-text/LexicalImageNode";
18 describe('Keyboard-handling service tests', () => {
20 let context!: EditorUiContext;
21 let editor!: LexicalEditor;
24 context = createTestContext();
25 editor = context.editor;
26 registerRichText(editor);
27 registerKeyboardHandling(context);
31 destroyFromContext(context);
34 test('Details: down key on last lines creates new sibling node', () => {
35 let lastRootChild!: LexicalNode|null;
36 let detailsPara!: ParagraphNode;
38 editor.updateAndCommit(() => {
39 const root = $getRoot()
40 const details = $createDetailsNode();
41 detailsPara = $createParagraphNode();
42 details.append(detailsPara);
43 $getRoot().append(details);
46 lastRootChild = root.getLastChild();
49 expect(lastRootChild).toBeInstanceOf(DetailsNode);
51 dispatchKeydownEventForNode(detailsPara, editor, 'ArrowDown');
53 editor.getEditorState().read(() => {
54 lastRootChild = $getRoot().getLastChild();
57 expect(lastRootChild).toBeInstanceOf(ParagraphNode);
60 test('Details: enter on last empty block creates new sibling node', () => {
61 registerRichText(editor);
63 let lastRootChild!: LexicalNode|null;
64 let detailsPara!: ParagraphNode;
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);
76 lastRootChild = root.getLastChild();
79 expect(lastRootChild).toBeInstanceOf(DetailsNode);
81 dispatchKeydownEventForNode(detailsPara, editor, 'Enter');
82 dispatchKeydownEventForSelectedNode(editor, 'Enter');
84 let detailsChildren!: LexicalNode[];
85 let lastDetailsText!: string;
87 editor.getEditorState().read(() => {
88 detailsChildren = (lastRootChild as DetailsNode).getChildren();
89 lastRootChild = $getRoot().getLastChild();
90 lastDetailsText = detailsChildren[0].getTextContent();
93 expect(lastRootChild).toBeInstanceOf(ParagraphNode);
94 expect(detailsChildren).toHaveLength(1);
95 expect(lastDetailsText).toBe('Hello!');
98 test('Lists: tab on empty list item insets item', () => {
101 let listItemB!: ListItemNode;
103 editor.updateAndCommit(() => {
104 const root = $getRoot();
105 list = $createListNode('bullet');
106 const listItemA = $createListItemNode();
107 listItemA.append($createTextNode('Hello!'));
108 listItemB = $createListItemNode();
109 list.append(listItemA, listItemB);
111 listItemB.selectStart();
114 dispatchKeydownEventForNode(listItemB, editor, 'Tab');
116 editor.getEditorState().read(() => {
117 const list = $getRoot().getChildren()[0] as ListNode;
118 const listChild = list.getChildren()[0] as ListItemNode;
119 const children = listChild.getChildren();
120 expect(children).toHaveLength(2);
121 expect(children[0]).toBeInstanceOf(TextNode);
122 expect(children[0].getTextContent()).toBe('Hello!');
123 expect(children[1]).toBeInstanceOf(ListNode);
125 const innerList = children[1] as ListNode;
126 const selectedNode = $getSelection()?.getNodes()[0];
127 expect(selectedNode).toBeInstanceOf(ListItemNode);
128 expect(selectedNode?.getKey()).toBe(innerList.getChildren()[0].getKey());
132 test('Images: up on selected image creates new paragraph if none above', () => {
133 let image!: ImageNode;
134 editor.updateAndCommit(() => {
135 const root = $getRoot();
136 const imageWrap = $createParagraphNode();
137 image = $createImageNode('https://example.com/cat.png');
138 imageWrap.append(image);
139 root.append(imageWrap);
143 expectNodeShapeToMatch(editor, [{
150 dispatchKeydownEventForNode(image, editor, 'ArrowUp');
152 expectNodeShapeToMatch(editor, [{