diff --git a/packages/dom/src/dom.js b/packages/dom/src/dom.js index 26f2985e5c48b..75f2d10311345 100644 --- a/packages/dom/src/dom.js +++ b/packages/dom/src/dom.js @@ -180,9 +180,15 @@ export function isVerticalEdge( container, isReverse ) { return false; } - const buffer = rangeRect.height / 2; const editableRect = container.getBoundingClientRect(); + // Calculate a buffer that is half the line height. In some browsers, the + // selection rectangle may not fill the entire height of the line, so we add + // half the line height to the selection rectangle to ensure that it is well + // over its line boundary. + const { lineHeight } = window.getComputedStyle( container ); + const buffer = parseInt( lineHeight, 10 ) / 2; + // Too low. if ( isReverse && rangeRect.top - buffer > editableRect.top ) { return false; diff --git a/packages/e2e-tests/specs/__snapshots__/multi-block-selection.test.js.snap b/packages/e2e-tests/specs/__snapshots__/multi-block-selection.test.js.snap new file mode 100644 index 0000000000000..3634f485a83ee --- /dev/null +++ b/packages/e2e-tests/specs/__snapshots__/multi-block-selection.test.js.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Multi-block selection should only trigger multi-selection when at the end 1`] = ` +" +

1.

+ + + +

+" +`; diff --git a/packages/e2e-tests/specs/multi-block-selection.test.js b/packages/e2e-tests/specs/multi-block-selection.test.js index 3f1fb30370ef6..5a83abc74036d 100644 --- a/packages/e2e-tests/specs/multi-block-selection.test.js +++ b/packages/e2e-tests/specs/multi-block-selection.test.js @@ -6,6 +6,8 @@ import { insertBlock, createNewPost, pressKeyWithModifier, + pressKeyTimes, + getEditedPostContent, } from '@wordpress/e2e-test-utils'; describe( 'Multi-block selection', () => { @@ -137,4 +139,30 @@ describe( 'Multi-block selection', () => { const speakTextContent = await page.$eval( '#a11y-speak-assertive', ( element ) => element.textContent ); expect( speakTextContent.trim() ).toEqual( '3 blocks selected.' ); } ); + + // See #14448: an incorrect buffer may trigger multi-selection too soon. + it( 'should only trigger multi-selection when at the end', async () => { + // Create a paragraph with four lines. + await clickBlockAppender(); + await page.keyboard.type( '1.' ); + await pressKeyWithModifier( 'shift', 'Enter' ); + await page.keyboard.type( '2.' ); + await pressKeyWithModifier( 'shift', 'Enter' ); + await page.keyboard.type( '3.' ); + await pressKeyWithModifier( 'shift', 'Enter' ); + await page.keyboard.type( '4.' ); + // Create a second block. + await page.keyboard.press( 'Enter' ); + // Move to the middle of the first line. + await pressKeyTimes( 'ArrowUp', 4 ); + await page.keyboard.press( 'ArrowRight' ); + // Select mid line one to mid line four. + await pressKeyWithModifier( 'shift', 'ArrowDown' ); + await pressKeyWithModifier( 'shift', 'ArrowDown' ); + await pressKeyWithModifier( 'shift', 'ArrowDown' ); + // Delete the text to see if the selection was correct. + await page.keyboard.press( 'Backspace' ); + + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); } );