161 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
import {
 | 
						|
    createTestContext, destroyFromContext,
 | 
						|
    dispatchKeydownEventForNode,
 | 
						|
    dispatchKeydownEventForSelectedNode, expectNodeShapeToMatch,
 | 
						|
} from "lexical/__tests__/utils";
 | 
						|
import {
 | 
						|
    $createParagraphNode, $createTextNode,
 | 
						|
    $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";
 | 
						|
import {$createImageNode, ImageNode} from "@lexical/rich-text/LexicalImageNode";
 | 
						|
 | 
						|
describe('Keyboard-handling service tests', () => {
 | 
						|
 | 
						|
    let context!: EditorUiContext;
 | 
						|
    let editor!: LexicalEditor;
 | 
						|
 | 
						|
    beforeEach(() => {
 | 
						|
        context = createTestContext();
 | 
						|
        editor = context.editor;
 | 
						|
        registerRichText(editor);
 | 
						|
        registerKeyboardHandling(context);
 | 
						|
    });
 | 
						|
 | 
						|
    afterEach(() => {
 | 
						|
        destroyFromContext(context);
 | 
						|
    });
 | 
						|
 | 
						|
    test('Details: down key on last lines creates new sibling node', () => {
 | 
						|
        let lastRootChild!: LexicalNode|null;
 | 
						|
        let detailsPara!: ParagraphNode;
 | 
						|
 | 
						|
        editor.updateAndCommit(() => {
 | 
						|
            const root = $getRoot()
 | 
						|
            const details = $createDetailsNode();
 | 
						|
            detailsPara = $createParagraphNode();
 | 
						|
            details.append(detailsPara);
 | 
						|
            $getRoot().append(details);
 | 
						|
            detailsPara.select();
 | 
						|
 | 
						|
            lastRootChild = root.getLastChild();
 | 
						|
        });
 | 
						|
 | 
						|
        expect(lastRootChild).toBeInstanceOf(DetailsNode);
 | 
						|
 | 
						|
        dispatchKeydownEventForNode(detailsPara, editor, 'ArrowDown');
 | 
						|
 | 
						|
        editor.getEditorState().read(() => {
 | 
						|
            lastRootChild = $getRoot().getLastChild();
 | 
						|
        });
 | 
						|
 | 
						|
        expect(lastRootChild).toBeInstanceOf(ParagraphNode);
 | 
						|
    });
 | 
						|
 | 
						|
    test('Details: enter on last empty block creates new sibling node', () => {
 | 
						|
        registerRichText(editor);
 | 
						|
 | 
						|
        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();
 | 
						|
 | 
						|
            lastRootChild = root.getLastChild();
 | 
						|
        });
 | 
						|
 | 
						|
        expect(lastRootChild).toBeInstanceOf(DetailsNode);
 | 
						|
 | 
						|
        dispatchKeydownEventForNode(detailsPara, editor, 'Enter');
 | 
						|
        dispatchKeydownEventForSelectedNode(editor, 'Enter');
 | 
						|
 | 
						|
        let detailsChildren!: LexicalNode[];
 | 
						|
        let lastDetailsText!: string;
 | 
						|
 | 
						|
        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();
 | 
						|
        });
 | 
						|
 | 
						|
        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());
 | 
						|
        });
 | 
						|
    });
 | 
						|
 | 
						|
    test('Images: up on selected image creates new paragraph if none above', () => {
 | 
						|
        let image!: ImageNode;
 | 
						|
        editor.updateAndCommit(() => {
 | 
						|
            const root = $getRoot();
 | 
						|
            const imageWrap = $createParagraphNode();
 | 
						|
            image = $createImageNode('https://example.com/cat.png');
 | 
						|
            imageWrap.append(image);
 | 
						|
            root.append(imageWrap);
 | 
						|
            image.select();
 | 
						|
        });
 | 
						|
 | 
						|
        expectNodeShapeToMatch(editor, [{
 | 
						|
            type: 'paragraph',
 | 
						|
            children: [
 | 
						|
                {type: 'image'}
 | 
						|
            ],
 | 
						|
        }]);
 | 
						|
 | 
						|
        dispatchKeydownEventForNode(image, editor, 'ArrowUp');
 | 
						|
 | 
						|
        expectNodeShapeToMatch(editor, [{
 | 
						|
            type: 'paragraph',
 | 
						|
        }, {
 | 
						|
            type: 'paragraph',
 | 
						|
            children: [
 | 
						|
                {type: 'image'}
 | 
						|
            ],
 | 
						|
        }]);
 | 
						|
    });
 | 
						|
}); |