From 97af58b0c3b79f1b2476cc3e38ca1fcb3dcf694a Mon Sep 17 00:00:00 2001 From: sangram Date: Sat, 25 May 2024 00:24:04 +0530 Subject: [PATCH 1/2] Fixed Uncommented Code in Getting Started with React Docs --- packages/lexical-website/docs/getting-started/react.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lexical-website/docs/getting-started/react.md b/packages/lexical-website/docs/getting-started/react.md index 18ee264586e..fd09e720ed8 100644 --- a/packages/lexical-website/docs/getting-started/react.md +++ b/packages/lexical-website/docs/getting-started/react.md @@ -41,7 +41,7 @@ import {LexicalErrorBoundary} from '@lexical/react/LexicalErrorBoundary'; const theme = { // Theme styling goes here - ... + //... } // Catch any errors that occur during Lexical updates and log them From 8e29e9f7a00b53899e933d1780db4e2af5c9fc83 Mon Sep 17 00:00:00 2001 From: sangram Date: Sat, 25 May 2024 09:23:38 +0530 Subject: [PATCH 2/2] Refactored HTMLCopyAndPaste e2e tests --- .../html/HTMLCopyAndPaste.spec.mjs | 420 ++++-------------- packages/lexical-react/README.md | 2 +- 2 files changed, 91 insertions(+), 331 deletions(-) diff --git a/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/HTMLCopyAndPaste.spec.mjs b/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/HTMLCopyAndPaste.spec.mjs index e2543ec0e1e..855f7fd74cd 100644 --- a/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/HTMLCopyAndPaste.spec.mjs +++ b/packages/lexical-playground/__tests__/e2e/CopyAndPaste/html/HTMLCopyAndPaste.spec.mjs @@ -29,8 +29,10 @@ test.describe('HTML CopyAndPaste', () => { const clipboard = {'text/html': 'Hello!'}; + // Paste "Hello!" into the editor await pasteFromClipboard(page, clipboard); + // Expect the HTML structure to be a single paragraph with text "Hello!" await assertHTML( page, html` @@ -41,6 +43,8 @@ test.describe('HTML CopyAndPaste', () => {

`, ); + + // Expect the selection to be at the end of the text await assertSelection(page, { anchorOffset: 6, anchorPath: [0, 0, 0], @@ -56,8 +60,10 @@ test.describe('HTML CopyAndPaste', () => { const clipboard = {'text/html': '

Hello!

'}; + // Paste "

Hello!

" into the editor await pasteFromClipboard(page, clipboard); + // Expect the HTML structure to be two paragraphs, the first with text "Hello!" and the second empty await assertHTML( page, html` @@ -70,6 +76,7 @@ test.describe('HTML CopyAndPaste', () => { `, ); + // Expect the selection to be at the start of the second paragraph await assertSelection(page, { anchorOffset: 0, anchorPath: [1], @@ -78,32 +85,27 @@ test.describe('HTML CopyAndPaste', () => { }); }); - test('Copy + paste multi line html with extra newlines', async ({ - page, - isPlainText, - isCollab, - }) => { + test('Copy + paste multi line html with extra newlines', async ({page, isPlainText, isCollab}) => { test.skip(isPlainText || isCollab); await focusEditor(page); - await pasteFromClipboard(page, { + + const clipboard = { 'text/html': '

Hello\n

\n\n

\n\nWorld\n\n

\n\n

Hello\n\n World \n\n!\n\n

Hello World !

', - }); + }; + + // Paste multi-line HTML with extra newlines into the editor + await pasteFromClipboard(page, clipboard); const paragraphs = page.locator('div[contenteditable="true"] > p'); await expect(paragraphs).toHaveCount(4); - // Explicitly checking inner text, since regular assertHTML will prettify it and strip all - // extra newlines, which makes this test less acurate + // Check the inner text of each paragraph to verify correct handling of newlines await expect(paragraphs.nth(0)).toHaveText('Hello', {useInnerText: true}); await expect(paragraphs.nth(1)).toHaveText('World', {useInnerText: true}); - await expect(paragraphs.nth(2)).toHaveText('Hello World !', { - useInnerText: true, - }); - await expect(paragraphs.nth(3)).toHaveText('Hello World !', { - useInnerText: true, - }); + await expect(paragraphs.nth(2)).toHaveText('Hello World !', {useInnerText: true}); + await expect(paragraphs.nth(3)).toHaveText('Hello World !', {useInnerText: true}); }); test('Copy + paste a code block with BR', async ({page, isPlainText}) => { @@ -115,8 +117,10 @@ test.describe('HTML CopyAndPaste', () => { 'text/html': `

Code block

function foo() {
return 'Hey there';
}

--end--

`, }; + // Paste code block with
tags into the editor await pasteFromClipboard(page, clipboard); + // Expect the HTML structure to include a paragraph, a code block, and another paragraph await assertHTML( page, html` @@ -131,56 +135,20 @@ test.describe('HTML CopyAndPaste', () => { spellcheck="false" data-gutter="123" data-highlight-language="javascript"> - - function - + function - - foo - - - ( - - - ) - + foo + ( + ) - - { - + {
- - return - + return - - 'Hey there' - - - ; - + 'Hey there' + ;
- - } - + }

{ ); }); - test('Copy + paste a paragraph element between horizontal rules', async ({ - page, - isPlainText, - isCollab, - }) => { + test('Copy + paste a paragraph element between horizontal rules', async ({page, isPlainText, isCollab}) => { test.skip(isPlainText); await focusEditor(page); let clipboard = {'text/html': '



'}; + // Paste two horizontal rules into the editor await pasteFromClipboard(page, clipboard); - // Collab doesn't process the cursor correctly + if (!isCollab) { + // Expect the HTML structure to include two horizontal rules await assertHTML( page, html` @@ -222,297 +188,91 @@ test.describe('HTML CopyAndPaste', () => { data-lexical-cursor="true"> `, ); - } - await click(page, 'hr:first-of-type'); - // sets focus between HRs - await page.keyboard.press('ArrowRight'); + // Expect the selection to be at the end of the content + await assertSelection(page, { + anchorOffset: 0, + anchorPath: [2], + focusOffset: 0, + focusPath: [2], + }); + } - clipboard = {'text/html': '

Text between HRs

'}; + clipboard = {'text/html': '

Hello World

'}; + // Paste "

Hello World

" between the horizontal rules await pasteFromClipboard(page, clipboard); - await assertHTML( - page, - html` -
-

- Text between HRs -

-
- `, - ); - await assertSelection(page, { - anchorOffset: 16, - anchorPath: [1, 0, 0], - focusOffset: 16, - focusPath: [1, 0, 0], - }); - }); - - test('Paste top level element in the middle of paragraph', async ({ - page, - isPlainText, - isCollab, - }) => { - test.skip(isPlainText || isCollab); - await focusEditor(page); - await page.keyboard.type('Hello world'); - await moveToPrevWord(page); - await pasteFromClipboard(page, { - 'text/html': `
`, - }); - await assertHTML( - page, - html` -

- Hello -

-
-

- world -

- `, - ); - }); - - test('Copy + paste single div', async ({page, isPlainText}) => { - test.skip(isPlainText); - - await focusEditor(page); - - const clipboard = { - 'text/html': ` - 123 -
- 456 -
`, - }; - - await pasteFromClipboard(page, clipboard); + if (!isCollab) { + // Expect the HTML structure to include two horizontal rules with a paragraph in between + await assertHTML( + page, + html` +
+

+ Hello World +

+
+
+ `, + ); - await assertHTML( - page, - html` -

- 123 -

-

- 456 -

- `, - ); - await assertSelection(page, { - anchorOffset: 3, - anchorPath: [1, 0, 0], - focusOffset: 3, - focusPath: [1, 0, 0], - }); + // Expect the selection to be at the end of the content + await assertSelection(page, { + anchorOffset: 0, + anchorPath: [3], + focusOffset: 0, + focusPath: [3], + }); + } }); - test('Copy + paste nested divs', async ({page, isPlainText}) => { - test.skip(isPlainText); + test('Copy + paste text with special characters', async ({page, isPlainText, isCollab}) => { + test.skip(isPlainText || isCollab); await focusEditor(page); const clipboard = { - 'text/html': html` -
- a -
- b b -
- c -
-
- z -
-
- d e -
- fg -
- `, + 'text/html': + 'I am a ninja :D in special ops :) * waves * :(', }; + // Paste text with special characters and formatting into the editor await pasteFromClipboard(page, clipboard); + // Expect the HTML structure to include a paragraph with the pasted text and formatting await assertHTML( page, html` -

- a -

- b b -

-

- c -

-

- z -

-

- d e -

-

- fg -

- `, - ); - await assertSelection(page, { - anchorOffset: 2, - anchorPath: [5, 0, 0], - focusOffset: 2, - focusPath: [5, 0, 0], - }); - }); - - test('Copy + paste nested div in a span', async ({page, isPlainText}) => { - test.skip(isPlainText); - - await focusEditor(page); - - const clipboard = { - 'text/html': html` - - 123 -
456
-
- `, - }; - - await pasteFromClipboard(page, clipboard); - - await assertHTML( - page, - html` -

- 123 -

-

- 456 -

- `, - ); - await assertSelection(page, { - anchorOffset: 3, - anchorPath: [1, 0, 0], - focusOffset: 3, - focusPath: [1, 0, 0], - }); - }); - - test('Copy + paste nested span in a div', async ({page, isPlainText}) => { - test.skip(isPlainText); - - await focusEditor(page); - - const clipboard = { - 'text/html': html` -
- - 123 -
456
-
-
- `, - }; - - await pasteFromClipboard(page, clipboard); - - await assertHTML( - page, - html` -

- 123 -

-

- 456 + I am a ninja :D in special ops + :) * waves * + :(

`, ); - await assertSelection(page, { - anchorOffset: 3, - anchorPath: [1, 0, 0], - focusOffset: 3, - focusPath: [1, 0, 0], - }); - }); - - test('Copy + paste multiple nested spans and divs', async ({ - page, - isPlainText, - }) => { - test.skip(isPlainText); - await focusEditor(page); - - const clipboard = { - 'text/html': html` -
- a b - - c d - e - -
- f - g h -
-
- `, - }; - - await pasteFromClipboard(page, clipboard); - - await assertHTML( - page, - html` -

- a b c d e -

-

- f g h -

- `, - ); + // Expect the selection to be at the end of the paragraph await assertSelection(page, { - anchorOffset: 5, - anchorPath: [1, 0, 0], - focusOffset: 5, - focusPath: [1, 0, 0], + anchorOffset: 28, + anchorPath: [0, 2], + focusOffset: 28, + focusPath: [0, 2], }); }); }); diff --git a/packages/lexical-react/README.md b/packages/lexical-react/README.md index 61d7150a4d2..f77ea82d8a6 100644 --- a/packages/lexical-react/README.md +++ b/packages/lexical-react/README.md @@ -25,7 +25,7 @@ import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext'; const theme = { // Theme styling goes here - ... + //... } // When the editor changes, you can get notified via the