1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-08-07 23:03:00 +03:00

Lexical: Improved list tab handling, Improved test utils

- Made tab work on empty list items
- Improved select preservation on single list item tab
- Altered test context creation for more standard testing
This commit is contained in:
Dan Brown
2024-12-17 14:44:10 +00:00
parent e50cd33277
commit ace8af077d
4 changed files with 154 additions and 70 deletions

View File

@@ -1,95 +1,135 @@
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);
dispatchKeydownEventForNode(detailsPara, editor, 'ArrowDown');
editor.commitUpdates();
editor.getEditorState().read(() => {
lastRootChild = $getRoot().getLastChild();
});
expect(lastRootChild).toBeInstanceOf(ParagraphNode);
lastRootChild = root.getLastChild();
});
test('Details: enter on last empy block creates new sibling node', () => {
const {editor} = testEnv;
expect(lastRootChild).toBeInstanceOf(DetailsNode);
registerRichText(editor);
registerKeyboardHandling(createTestContext(testEnv));
dispatchKeydownEventForNode(detailsPara, editor, 'ArrowDown');
editor.commitUpdates();
let lastRootChild!: LexicalNode|null;
let detailsPara!: ParagraphNode;
editor.getEditorState().read(() => {
lastRootChild = $getRoot().getLastChild();
});
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();
expect(lastRootChild).toBeInstanceOf(ParagraphNode);
});
lastRootChild = root.getLastChild();
});
test('Details: enter on last empty block creates new sibling node', () => {
registerRichText(editor);
expect(lastRootChild).toBeInstanceOf(DetailsNode);
let lastRootChild!: LexicalNode|null;
let detailsPara!: ParagraphNode;
dispatchKeydownEventForNode(detailsPara, editor, 'Enter');
editor.commitUpdates();
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();
dispatchKeydownEventForSelectedNode(editor, 'Enter');
editor.commitUpdates();
lastRootChild = root.getLastChild();
});
let detailsChildren!: LexicalNode[];
let lastDetailsText!: string;
expect(lastRootChild).toBeInstanceOf(DetailsNode);
editor.getEditorState().read(() => {
detailsChildren = (lastRootChild as DetailsNode).getChildren();
lastRootChild = $getRoot().getLastChild();
lastDetailsText = detailsChildren[0].getTextContent();
});
dispatchKeydownEventForNode(detailsPara, editor, 'Enter');
editor.commitUpdates();
expect(lastRootChild).toBeInstanceOf(ParagraphNode);
expect(detailsChildren).toHaveLength(1);
expect(lastDetailsText).toBe('Hello!');
dispatchKeydownEventForSelectedNode(editor, 'Enter');
editor.commitUpdates();
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.commitUpdates();
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());
});
});
});