From 9ea082b961dacd5ba128e0f92c68b6efdced21e0 Mon Sep 17 00:00:00 2001 From: Faisal Ahmed Date: Fri, 9 Feb 2024 22:00:54 +0600 Subject: [PATCH] "Multiple use" block validation logic improvement [with Playwright] (#57576) * Multiple use block validation logic improvement See: #38502 * Added playwright as the testing library * Moved 'validate-multiple-use' test to 'test/e2e/specs/editor/variou' dir * renamed test file * Fix: issues with block insertion for testing * Rewrite test cases by playwright role api * Fix iframe locator issue * Update playwright locators by 'getByRole' * Using 'clickBlockOptionsMenuItem' function * Apply comment wording improvements Co-authored-by: Ben Dwyer --------- Co-authored-by: Delowar Hossain Co-authored-by: Dave Smith Co-authored-by: Ben Dwyer --- .../src/hooks/validate-multiple-use/index.js | 31 ++++++++++++++-- .../various/validate-multiple-use.spec.js | 36 +++++++++++++++++++ 2 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 test/e2e/specs/editor/various/validate-multiple-use.spec.js diff --git a/packages/edit-post/src/hooks/validate-multiple-use/index.js b/packages/edit-post/src/hooks/validate-multiple-use/index.js index 31444a86467c70..bf771f45220362 100644 --- a/packages/edit-post/src/hooks/validate-multiple-use/index.js +++ b/packages/edit-post/src/hooks/validate-multiple-use/index.js @@ -15,6 +15,33 @@ import { addFilter } from '@wordpress/hooks'; import { __ } from '@wordpress/i18n'; import { compose, createHigherOrderComponent } from '@wordpress/compose'; +/** + * Recursively find very first block of an specific block type. + * + * @param {Object[]} blocks List of blocks. + * @param {string} name Block name to search. + * + * @return {Object|undefined} Return block object or undefined. + */ +function findFirstOfSameType( blocks, name ) { + if ( ! Array.isArray( blocks ) || ! blocks.length ) { + return; + } + + for ( const block of blocks ) { + if ( block.name === name ) { + return block; + } + + // Search inside innerBlocks. + const firstBlock = findFirstOfSameType( block.innerBlocks, name ); + + if ( firstBlock ) { + return firstBlock; + } + } +} + const enhance = compose( /** * For blocks whose block type doesn't support `multiple`, provides the @@ -39,9 +66,7 @@ const enhance = compose( // Otherwise, only pass `originalBlockClientId` if it refers to a different // block from the current one. const blocks = select( blockEditorStore ).getBlocks(); - const firstOfSameType = blocks.find( - ( { name } ) => block.name === name - ); + const firstOfSameType = findFirstOfSameType( blocks, block.name ); const isInvalid = firstOfSameType && firstOfSameType.clientId !== block.clientId; return { diff --git a/test/e2e/specs/editor/various/validate-multiple-use.spec.js b/test/e2e/specs/editor/various/validate-multiple-use.spec.js new file mode 100644 index 00000000000000..4ab455d22cf299 --- /dev/null +++ b/test/e2e/specs/editor/various/validate-multiple-use.spec.js @@ -0,0 +1,36 @@ +/** + * WordPress dependencies + */ + +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +test.describe( 'Validate multiple use', () => { + test.beforeEach( async ( { admin } ) => { + await admin.createNewPost(); + } ); + + test( 'should display correct number of warning messages', async ( { + editor, + pageUtils, + } ) => { + // Insert a block with the `multiple` feature enabled, such as `core/more` + await editor.insertBlock( { + name: 'core/more', + } ); + + // Group the block + await pageUtils.pressKeys( 'primary+a' ); + await editor.clickBlockOptionsMenuItem( 'Group' ); + + // Duplicate the block + await pageUtils.pressKeys( 'primary+a' ); + await editor.clickBlockOptionsMenuItem( 'Duplicate' ); + + // Check if warning is visible + await expect( + editor.canvas.getByRole( 'button', { + name: 'Find original', + } ) + ).toBeVisible(); + } ); +} );