From 24ac097a639c0ef8c961bb5ed8a237e22c42eaae Mon Sep 17 00:00:00 2001 From: Ella Date: Fri, 6 Oct 2023 14:38:23 +0300 Subject: [PATCH] List: fix forward merging of nested list --- .../src/list-item/hooks/use-merge.js | 43 ++++++------- test/e2e/specs/editor/blocks/list.spec.js | 64 ++++++++++++------- 2 files changed, 62 insertions(+), 45 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 6b456a2a742bdb..cda1f0c02d3a88 100644 --- a/packages/block-library/src/list-item/hooks/use-merge.js +++ b/packages/block-library/src/list-item/hooks/use-merge.js @@ -76,6 +76,24 @@ export default function useMerge( clientId, onMerge ) { } return ( forward ) => { + function mergeWithNested( clientIdA, clientIdB ) { + registry.batch( () => { + // When merging a sub list item with a higher next list item, we + // also need to move any nested list items. Check if there's a + // listed list, and append its nested list items to the current + // list. + const [ nestedListClientId ] = getBlockOrder( clientIdB ); + if ( nestedListClientId ) { + moveBlocksToPosition( + getBlockOrder( nestedListClientId ), + nestedListClientId, + getBlockRootClientId( clientIdA ) + ); + } + mergeBlocks( clientIdA, clientIdB ); + } ); + } + if ( forward ) { const nextBlockClientId = getNextId( clientId ); @@ -87,14 +105,7 @@ export default function useMerge( clientId, onMerge ) { if ( getParentListItemId( nextBlockClientId ) ) { outdentListItem( nextBlockClientId ); } else { - registry.batch( () => { - moveBlocksToPosition( - getBlockOrder( nextBlockClientId ), - nextBlockClientId, - getPreviousBlockClientId( nextBlockClientId ) - ); - mergeBlocks( clientId, nextBlockClientId ); - } ); + mergeWithNested( clientId, nextBlockClientId ); } } else { // Merging is only done from the top level. For lowel levels, the @@ -104,21 +115,7 @@ export default function useMerge( clientId, onMerge ) { outdentListItem( clientId ); } else if ( previousBlockClientId ) { const trailingId = getTrailingId( previousBlockClientId ); - registry.batch( () => { - // 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 ); - } ); + mergeWithNested( trailingId, clientId ); } else { onMerge( forward ); } diff --git a/test/e2e/specs/editor/blocks/list.spec.js b/test/e2e/specs/editor/blocks/list.spec.js index f4396982bb997f..741e4a210d2f73 100644 --- a/test/e2e/specs/editor/blocks/list.spec.js +++ b/test/e2e/specs/editor/blocks/list.spec.js @@ -1361,11 +1361,8 @@ test.describe( 'List (@firefox)', () => { ` ); } ); - test( 'should merge two list items with nested lists', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { + test.describe( 'should merge two list items with nested lists', () => { + const start = { name: 'core/list', innerBlocks: [ { @@ -1399,22 +1396,8 @@ test.describe( 'List (@firefox)', () => { ], }, ], - } ); - - // 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( [ + }; + const end = [ { name: 'core/list', innerBlocks: [ @@ -1439,6 +1422,43 @@ test.describe( 'List (@firefox)', () => { }, ], }, - ] ); + ]; + + test( 'Backspace', async ( { editor, page } ) => { + await editor.insertBlock( start ); + + // Navigate to the start of 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( end ); + } ); + + test( 'Delete (forward)', async ( { editor, page } ) => { + await editor.insertBlock( start ); + + // Navigate to the end of the second 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( 'ArrowRight' ); + + await page.keyboard.press( 'Delete' ); + + // Test caret position. + await page.keyboard.type( '‸' ); + + await expect.poll( editor.getBlocks ).toMatchObject( end ); + } ); } ); } );