From d6b114de7489ca4df591a79b312671555b9e4e14 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 6 May 2026 00:25:43 +0100 Subject: [PATCH] Lexical: Added some test coverage for shortcut handling Updates existing keydown test helper to accept other event options. --- .../lexical/core/__tests__/utils/index.ts | 15 ++- .../services/__tests__/shortcuts.test.ts | 91 +++++++++++++++++++ 2 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 resources/js/wysiwyg/services/__tests__/shortcuts.test.ts diff --git a/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts b/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts index ab54bdb31..a30c86fcc 100644 --- a/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts +++ b/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts @@ -837,22 +837,31 @@ function formatHtml(s: string): string { return s.replace(/>\s+<').replace(/\s*\n\s*/g, ' ').trim(); } -export function dispatchKeydownEventForNode(node: LexicalNode, editor: LexicalEditor, key: string) { +interface TestKeyboardEventOptions { + ctrlKey?: boolean; + altKey?: boolean; + shiftKey?: boolean; + metaKey?: boolean; + keyCode?: number; +} + +export function dispatchKeydownEventForNode(node: LexicalNode, editor: LexicalEditor, key: string, options: TestKeyboardEventOptions = {}) { const nodeDomEl = editor.getElementByKey(node.getKey()); const event = new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key, + ...options, }); nodeDomEl?.dispatchEvent(event); editor.commitUpdates(); } -export function dispatchKeydownEventForSelectedNode(editor: LexicalEditor, key: string) { +export function dispatchKeydownEventForSelectedNode(editor: LexicalEditor, key: string, options: TestKeyboardEventOptions = {}) { editor.getEditorState().read((): void => { const node = $getSelection()?.getNodes()[0] || null; if (node) { - dispatchKeydownEventForNode(node, editor, key); + dispatchKeydownEventForNode(node, editor, key, options); } }); } diff --git a/resources/js/wysiwyg/services/__tests__/shortcuts.test.ts b/resources/js/wysiwyg/services/__tests__/shortcuts.test.ts new file mode 100644 index 000000000..f7e7298e8 --- /dev/null +++ b/resources/js/wysiwyg/services/__tests__/shortcuts.test.ts @@ -0,0 +1,91 @@ +import { + createTestContext, destroyFromContext, + dispatchKeydownEventForSelectedNode, expectEditorStateJSONPropToEqual, +} from "lexical/__tests__/utils"; +import { + $createParagraphNode, $createTextNode, + $getRoot, IS_BOLD, LexicalEditor, +} from "lexical"; +import {registerRichText} from "@lexical/rich-text"; +import {EditorUiContext} from "../../ui/framework/core"; +import {registerShortcuts} from "../shortcuts"; + +describe('Keyboard-handling service tests', () => { + + let context!: EditorUiContext; + let editor!: LexicalEditor; + + beforeEach(() => { + context = createTestContext(); + editor = context.editor; + registerRichText(editor); + registerShortcuts(context, true); + }); + + afterEach(() => { + destroyFromContext(context); + }); + + test('Basic block format shortcuts works', () => { + editor.updateAndCommit(() => { + const p = $createParagraphNode(); + p.append($createTextNode('Hello World')) + $getRoot().append(p); + p.select(); + }); + + dispatchKeydownEventForSelectedNode(editor, '1', {ctrlKey: true}); + + expectEditorStateJSONPropToEqual(editor, '0.type', 'heading'); + expectEditorStateJSONPropToEqual(editor, '0.tag', 'h2'); + + dispatchKeydownEventForSelectedNode(editor, '2', {ctrlKey: true}); + + expectEditorStateJSONPropToEqual(editor, '0.type', 'heading'); + expectEditorStateJSONPropToEqual(editor, '0.tag', 'h3'); + + dispatchKeydownEventForSelectedNode(editor, 'd', {ctrlKey: true}); + + expectEditorStateJSONPropToEqual(editor, '0.type', 'paragraph'); + expectEditorStateJSONPropToEqual(editor, '0.0.text', 'Hello World'); + }); + + test('Basic bold format shortcut works', () => { + editor.updateAndCommit(() => { + const p = $createParagraphNode(); + const text = $createTextNode('Hello World'); + p.append(text) + $getRoot().append(p); + text.select(0, 5); + }); + + // Toggle bold for selection + dispatchKeydownEventForSelectedNode(editor, 'b', {ctrlKey: true}); + expectEditorStateJSONPropToEqual(editor, '0.0.format', IS_BOLD); + expectEditorStateJSONPropToEqual(editor, '0.1.format', 0); + + // Untoggle bold for selection + dispatchKeydownEventForSelectedNode(editor, 'b', {ctrlKey: true}); + expectEditorStateJSONPropToEqual(editor, '0.0.format', 0); + }); + + test('Basic bold format shortcut works when using cyrillic equivalent keys', () => { + editor.updateAndCommit(() => { + const p = $createParagraphNode(); + const text = $createTextNode('Hello World'); + p.append(text) + $getRoot().append(p); + text.select(0, 5); + }); + + // Toggle bold for selection + dispatchKeydownEventForSelectedNode(editor, 'и', {ctrlKey: true, keyCode: 66}); + expectEditorStateJSONPropToEqual(editor, '0.0.format', IS_BOLD); + expectEditorStateJSONPropToEqual(editor, '0.1.format', 0); + + // Untoggle bold for selection + dispatchKeydownEventForSelectedNode(editor, 'и', {ctrlKey: true, keyCode: 66}); + expectEditorStateJSONPropToEqual(editor, '0.0.format', 0); + }); + +});