From a891e98bfca7f31301d302256eda3e56e3c61ce8 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Thu, 21 Nov 2024 17:48:45 -0700 Subject: [PATCH] fix(richtext-lexical): slash menu from + button did not trigger item select action (#9420) Fixes a bug I introduced through https://github.com/payloadcms/payload/pull/9396 and adds an e2e test --- .../LexicalMenu.tsx | 37 +++++----- .../collections/Lexical/e2e/main/e2e.spec.ts | 67 +++++++++++++++++++ 2 files changed, 84 insertions(+), 20 deletions(-) diff --git a/packages/richtext-lexical/src/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/LexicalMenu.tsx b/packages/richtext-lexical/src/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/LexicalMenu.tsx index 728fb4c51a6..2095c5aa3db 100644 --- a/packages/richtext-lexical/src/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/LexicalMenu.tsx +++ b/packages/richtext-lexical/src/lexical/plugins/SlashMenu/LexicalTypeaheadMenuPlugin/LexicalMenu.tsx @@ -254,26 +254,23 @@ export function LexicalMenu({ (selectedItem: SlashMenuItem) => { close() - editor.update( - () => { - const textNodeContainingQuery = - resolution.match != null && shouldSplitNodeWithQuery - ? $splitNodeContainingQuery(resolution.match) - : null - - if (textNodeContainingQuery) { - textNodeContainingQuery.remove() - } - }, - { - onUpdate() { - selectedItem.onSelect({ - editor, - queryString: resolution.match ? resolution.match.matchingString : '', - }) - }, - }, - ) + editor.update(() => { + const textNodeContainingQuery = + resolution.match != null && shouldSplitNodeWithQuery + ? $splitNodeContainingQuery(resolution.match) + : null + + if (textNodeContainingQuery) { + textNodeContainingQuery.remove() + } + }) + + setTimeout(() => { + selectedItem.onSelect({ + editor, + queryString: resolution.match ? resolution.match.matchingString : '', + }) + }, 0) }, [editor, shouldSplitNodeWithQuery, resolution.match, close], ) diff --git a/test/fields/collections/Lexical/e2e/main/e2e.spec.ts b/test/fields/collections/Lexical/e2e/main/e2e.spec.ts index a5a96a29c32..7d98c382b51 100644 --- a/test/fields/collections/Lexical/e2e/main/e2e.spec.ts +++ b/test/fields/collections/Lexical/e2e/main/e2e.spec.ts @@ -1068,6 +1068,73 @@ describe('lexicalMain', () => { await expect(page.locator('#blocks-row-1 .section-title__input')).toHaveValue('1') // block name }) + test('ensure blocks can be created from plus button', async () => { + await navigateToLexicalFields() + const richTextField = page.locator('.rich-text-lexical').first() + await richTextField.scrollIntoViewIfNeeded() + await expect(richTextField).toBeVisible() + // Wait until there at least 10 blocks visible in that richtext field - thus wait for it to be fully loaded + await expect(page.locator('.rich-text-lexical').nth(2).locator('.lexical-block')).toHaveCount( + 10, + ) + await expect(page.locator('.shimmer-effect')).toHaveCount(0) + + // click contenteditable + await richTextField.locator('.ContentEditable__root').first().click() + + const lastParagraph = richTextField.locator('p').first() + await lastParagraph.scrollIntoViewIfNeeded() + await expect(lastParagraph).toBeVisible() + + /** + * Create new upload node + */ + // type / to open the slash menu + await lastParagraph.click() + // hover over the last paragraph to make the plus button visible + await lastParagraph.hover() + await wait(600) + //await richTextField.locator('.add-block-menu').first().click() + const plusButton = richTextField.locator('.add-block-menu').first() + + // hover over plusButton + await plusButton.hover() + await wait(100) + // click the plus button + await plusButton.click() + + await expect(richTextField.locator('.slash-menu-popup')).toBeVisible() + // click button with text "Text" + await richTextField.locator('.slash-menu-popup button').getByText('My Block').click() + + await expect(richTextField.locator('.lexical-block')).toHaveCount(1) + await richTextField.locator('#field-someTextRequired').first().fill('test') + + await saveDocAndAssert(page) + + await expect(async () => { + const lexicalDoc: LexicalField = ( + await payload.find({ + collection: lexicalFieldsSlug, + depth: 0, + overrideAccess: true, + where: { + title: { + equals: lexicalDocData.title, + }, + }, + }) + ).docs[0] as never + + const lexicalField: SerializedEditorState = lexicalDoc.lexicalRootEditor + + // @ts-expect-error no need to type this + await expect(lexicalField?.root?.children[1].fields.someTextRequired).toEqual('test') + }).toPass({ + timeout: POLL_TOPASS_TIMEOUT, + }) + }) + describe('localization', () => { test.skip('ensure simple localized lexical field works', async () => { await navigateToLexicalFields(true, true)