From ab8ec235e44f2cd37938c506488eeb41d083e5be Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Wed, 26 Jul 2023 16:43:57 +0100 Subject: [PATCH] List: fix merging nested lists (#52949) --- .../src/list-item/hooks/use-merge.js | 17 ++-- test/e2e/specs/editor/blocks/list.spec.js | 81 +++++++++++++++++++ 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/list-item/hooks/use-merge.js b/packages/block-library/src/list-item/hooks/use-merge.js index 8c186b27f6dc9..da81fe0a7bfde 100644 --- a/packages/block-library/src/list-item/hooks/use-merge.js +++ b/packages/block-library/src/list-item/hooks/use-merge.js @@ -107,11 +107,18 @@ export default function useMerge( clientId, onMerge ) { } else if ( previousBlockClientId ) { const trailingId = getTrailingId( previousBlockClientId ); registry.batch( () => { - moveBlocksToPosition( - getBlockOrder( clientId ), - clientId, - previousBlockClientId - ); + // When merging a list item with a previous trailing list + // item, we also need to move any nested list items. First, + // check if there's a listed list. If there's a nested list, + // append its nested list items to the trailing list. + const [ nestedListClientId ] = getBlockOrder( clientId ); + if ( nestedListClientId ) { + moveBlocksToPosition( + getBlockOrder( nestedListClientId ), + nestedListClientId, + getBlockRootClientId( trailingId ) + ); + } mergeBlocks( trailingId, clientId ); } ); } else { diff --git a/test/e2e/specs/editor/blocks/list.spec.js b/test/e2e/specs/editor/blocks/list.spec.js index 41c846a975077..f51b559e61384 100644 --- a/test/e2e/specs/editor/blocks/list.spec.js +++ b/test/e2e/specs/editor/blocks/list.spec.js @@ -1367,4 +1367,85 @@ test.describe( 'List (@firefox)', () => { ` ); } ); + + test( 'should merge two list items with nested lists', async ( { + editor, + page, + } ) => { + await editor.insertBlock( { + name: 'core/list', + innerBlocks: [ + { + name: 'core/list-item', + attributes: { content: '1' }, + innerBlocks: [ + { + name: 'core/list', + innerBlocks: [ + { + name: 'core/list-item', + attributes: { content: 'a' }, + }, + ], + }, + ], + }, + { + name: 'core/list-item', + attributes: { content: '2' }, + innerBlocks: [ + { + name: 'core/list', + innerBlocks: [ + { + name: 'core/list-item', + attributes: { content: 'b' }, + }, + ], + }, + ], + }, + ], + } ); + + // Navigate to the third item. + await page.keyboard.press( 'ArrowDown' ); + await page.keyboard.press( 'ArrowDown' ); + await page.keyboard.press( 'ArrowDown' ); + await page.keyboard.press( 'ArrowDown' ); + await page.keyboard.press( 'ArrowDown' ); + await page.keyboard.press( 'ArrowDown' ); + + await page.keyboard.press( 'Backspace' ); + + // Test caret position. + await page.keyboard.type( '‸' ); + + await expect.poll( editor.getBlocks ).toMatchObject( [ + { + name: 'core/list', + innerBlocks: [ + { + name: 'core/list-item', + attributes: { content: '1' }, + innerBlocks: [ + { + name: 'core/list', + innerBlocks: [ + { + name: 'core/list-item', + attributes: { content: 'a‸2' }, + }, + { + name: 'core/list-item', + attributes: { content: 'b' }, + }, + ], + }, + ], + }, + ], + }, + ] ); + } ); } );