Lexical: Added tests to cover recent changes
Some checks failed
test-js / build (push) Has been cancelled

Also updated list tests to new test process.
This commit is contained in:
Dan Brown
2025-03-28 18:29:00 +00:00
parent 9bfcadd95f
commit bb44334224
4 changed files with 240 additions and 196 deletions

View File

@ -37,6 +37,7 @@ import {QuoteNode} from "@lexical/rich-text/LexicalQuoteNode";
import {DetailsNode} from "@lexical/rich-text/LexicalDetailsNode"; import {DetailsNode} from "@lexical/rich-text/LexicalDetailsNode";
import {EditorUiContext} from "../../../../ui/framework/core"; import {EditorUiContext} from "../../../../ui/framework/core";
import {EditorUIManager} from "../../../../ui/framework/manager"; import {EditorUIManager} from "../../../../ui/framework/manager";
import {ImageNode} from "@lexical/rich-text/LexicalImageNode";
type TestEnv = { type TestEnv = {
readonly container: HTMLDivElement; readonly container: HTMLDivElement;
@ -484,6 +485,9 @@ export function createTestContext(): EditorUiContext {
const editor = createTestEditor({ const editor = createTestEditor({
namespace: 'testing', namespace: 'testing',
theme: {}, theme: {},
nodes: [
ImageNode,
]
}); });
editor.setRootElement(editorDOM); editor.setRootElement(editorDOM);

View File

@ -6,7 +6,7 @@
* *
*/ */
import {ParagraphNode, TextNode} from 'lexical'; import {ParagraphNode, TextNode} from 'lexical';
import {initializeUnitTest} from 'lexical/__tests__/utils'; import {createTestContext} from 'lexical/__tests__/utils';
import { import {
$createListItemNode, $createListItemNode,
@ -16,6 +16,7 @@ import {
ListItemNode, ListItemNode,
ListNode, ListNode,
} from '../..'; } from '../..';
import {$htmlToBlockNodes} from "../../../../utils/nodes";
const editorConfig = Object.freeze({ const editorConfig = Object.freeze({
namespace: '', namespace: '',
@ -46,9 +47,8 @@ const editorConfig = Object.freeze({
}); });
describe('LexicalListNode tests', () => { describe('LexicalListNode tests', () => {
initializeUnitTest((testEnv) => {
test('ListNode.constructor', async () => { test('ListNode.constructor', async () => {
const {editor} = testEnv; const {editor} = createTestContext();
await editor.update(() => { await editor.update(() => {
const listNode = $createListNode('bullet', 1); const listNode = $createListNode('bullet', 1);
@ -62,7 +62,7 @@ describe('LexicalListNode tests', () => {
}); });
test('ListNode.getTag()', async () => { test('ListNode.getTag()', async () => {
const {editor} = testEnv; const {editor} = createTestContext();
await editor.update(() => { await editor.update(() => {
const ulListNode = $createListNode('bullet', 1); const ulListNode = $createListNode('bullet', 1);
@ -75,7 +75,7 @@ describe('LexicalListNode tests', () => {
}); });
test('ListNode.createDOM()', async () => { test('ListNode.createDOM()', async () => {
const {editor} = testEnv; const {editor} = createTestContext();
await editor.update(() => { await editor.update(() => {
const listNode = $createListNode('bullet', 1); const listNode = $createListNode('bullet', 1);
@ -100,7 +100,7 @@ describe('LexicalListNode tests', () => {
}); });
test('ListNode.createDOM() correctly applies classes to a nested ListNode', async () => { test('ListNode.createDOM() correctly applies classes to a nested ListNode', async () => {
const {editor} = testEnv; const {editor} = createTestContext();
await editor.update(() => { await editor.update(() => {
const listNode1 = $createListNode('bullet'); const listNode1 = $createListNode('bullet');
@ -181,7 +181,7 @@ describe('LexicalListNode tests', () => {
}); });
test('ListNode.updateDOM()', async () => { test('ListNode.updateDOM()', async () => {
const {editor} = testEnv; const {editor} = createTestContext();
await editor.update(() => { await editor.update(() => {
const listNode = $createListNode('bullet', 1); const listNode = $createListNode('bullet', 1);
@ -206,7 +206,7 @@ describe('LexicalListNode tests', () => {
}); });
test('ListNode.append() should properly transform a ListItemNode', async () => { test('ListNode.append() should properly transform a ListItemNode', async () => {
const {editor} = testEnv; const {editor} = createTestContext();
await editor.update(() => { await editor.update(() => {
const listNode = new ListNode('bullet', 1); const listNode = new ListNode('bullet', 1);
@ -223,7 +223,7 @@ describe('LexicalListNode tests', () => {
}); });
test('ListNode.append() should properly transform a ListNode', async () => { test('ListNode.append() should properly transform a ListNode', async () => {
const {editor} = testEnv; const {editor} = createTestContext();
await editor.update(() => { await editor.update(() => {
const listNode = new ListNode('bullet', 1); const listNode = new ListNode('bullet', 1);
@ -245,7 +245,7 @@ describe('LexicalListNode tests', () => {
}); });
test('ListNode.append() should properly transform a ParagraphNode', async () => { test('ListNode.append() should properly transform a ParagraphNode', async () => {
const {editor} = testEnv; const {editor} = createTestContext();
await editor.update(() => { await editor.update(() => {
const listNode = new ListNode('bullet', 1); const listNode = new ListNode('bullet', 1);
@ -261,7 +261,7 @@ describe('LexicalListNode tests', () => {
}); });
test('$createListNode()', async () => { test('$createListNode()', async () => {
const {editor} = testEnv; const {editor} = createTestContext();
await editor.update(() => { await editor.update(() => {
const listNode = $createListNode('bullet', 1); const listNode = $createListNode('bullet', 1);
@ -275,7 +275,7 @@ describe('LexicalListNode tests', () => {
}); });
test('$isListNode()', async () => { test('$isListNode()', async () => {
const {editor} = testEnv; const {editor} = createTestContext();
await editor.update(() => { await editor.update(() => {
const listNode = $createListNode('bullet', 1); const listNode = $createListNode('bullet', 1);
@ -285,7 +285,7 @@ describe('LexicalListNode tests', () => {
}); });
test('$createListNode() with tag name (backward compatibility)', async () => { test('$createListNode() with tag name (backward compatibility)', async () => {
const {editor} = testEnv; const {editor} = createTestContext();
await editor.update(() => { await editor.update(() => {
const numberList = $createListNode('number', 1); const numberList = $createListNode('number', 1);
@ -294,5 +294,17 @@ describe('LexicalListNode tests', () => {
expect(bulletList.__listType).toBe('bullet'); expect(bulletList.__listType).toBe('bullet');
}); });
}); });
test('importDOM handles old editor expected task list format', async () => {
const {editor} = createTestContext();
let list!: ListNode;
editor.update(() => {
const nodes = $htmlToBlockNodes(editor, `<ul><li class="task-list-item"><input checked="" disabled="" type="checkbox"> A</li></ul>`);
list = nodes[0] as ListNode;
});
expect(list).toBeInstanceOf(ListNode);
expect(list.getListType()).toBe('check');
}); });
}); });

View File

@ -1,7 +1,7 @@
import { import {
createTestContext, destroyFromContext, createTestContext, destroyFromContext,
dispatchKeydownEventForNode, dispatchKeydownEventForNode,
dispatchKeydownEventForSelectedNode, dispatchKeydownEventForSelectedNode, expectNodeShapeToMatch,
} from "lexical/__tests__/utils"; } from "lexical/__tests__/utils";
import { import {
$createParagraphNode, $createTextNode, $createParagraphNode, $createTextNode,
@ -13,6 +13,7 @@ import {registerKeyboardHandling} from "../keyboard-handling";
import {registerRichText} from "@lexical/rich-text"; import {registerRichText} from "@lexical/rich-text";
import {EditorUiContext} from "../../ui/framework/core"; import {EditorUiContext} from "../../ui/framework/core";
import {$createListItemNode, $createListNode, ListItemNode, ListNode} from "@lexical/list"; import {$createListItemNode, $createListNode, ListItemNode, ListNode} from "@lexical/list";
import {$createImageNode, ImageNode} from "@lexical/rich-text/LexicalImageNode";
describe('Keyboard-handling service tests', () => { describe('Keyboard-handling service tests', () => {
@ -127,4 +128,34 @@ describe('Keyboard-handling service tests', () => {
expect(selectedNode?.getKey()).toBe(innerList.getChildren()[0].getKey()); 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'}
],
}]);
});
}); });

View File

@ -79,7 +79,6 @@ function focusAdjacentOrInsertForSingleSelectNode(editor: LexicalEditor, event:
const nearestBlock = $getNearestNodeBlockParent(node) || node; const nearestBlock = $getNearestNodeBlockParent(node) || node;
let target = after ? nearestBlock.getNextSibling() : nearestBlock.getPreviousSibling(); let target = after ? nearestBlock.getNextSibling() : nearestBlock.getPreviousSibling();
requestAnimationFrame(() => {
editor.update(() => { editor.update(() => {
if (!target) { if (!target) {
target = $createParagraphNode(); target = $createParagraphNode();
@ -92,8 +91,6 @@ function focusAdjacentOrInsertForSingleSelectNode(editor: LexicalEditor, event:
target.selectStart(); target.selectStart();
}); });
});
return true; return true;
} }