diff --git a/packages/e2e-test-utils/src/login-user.js b/packages/e2e-test-utils/src/login-user.js index 8c7063ee940cb3..d06878d69186ed 100644 --- a/packages/e2e-test-utils/src/login-user.js +++ b/packages/e2e-test-utils/src/login-user.js @@ -1,4 +1,3 @@ - /** * Internal dependencies */ diff --git a/packages/e2e-test-utils/src/press-key-with-modifier.js b/packages/e2e-test-utils/src/press-key-with-modifier.js index e20100ba54e5f7..59f5c8330672ec 100644 --- a/packages/e2e-test-utils/src/press-key-with-modifier.js +++ b/packages/e2e-test-utils/src/press-key-with-modifier.js @@ -8,6 +8,78 @@ import { capitalize } from 'lodash'; */ import { modifiers, SHIFT, ALT, CTRL } from '@wordpress/keycodes'; +/** + * Emulates a Ctrl+A SelectAll key combination by dispatching custom keyboard + * events and using the results of those events to determine whether to call + * `document.execCommand( 'selectall' );`. This is necessary because Puppeteer + * does not emulate Ctrl+A SelectAll in macOS. Events are dispatched to ensure + * that any `Event#preventDefault` which would have normally occurred in the + * application as a result of Ctrl+A is respected. + * + * @link https://github.com/GoogleChrome/puppeteer/issues/1313 + * @link https://w3c.github.io/uievents/tools/key-event-viewer.html + * + * @return {Promise} Promise resolving once the SelectAll emulation completes. + */ +async function emulateSelectAll() { + await page.evaluate( () => { + const isMac = /Mac|iPod|iPhone|iPad/.test( window.navigator.platform ); + + document.activeElement.dispatchEvent( + new KeyboardEvent( 'keydown', { + bubbles: true, + cancelable: true, + key: isMac ? 'Meta' : 'Control', + code: isMac ? 'MetaLeft' : 'ControlLeft', + location: window.KeyboardEvent.DOM_KEY_LOCATION_LEFT, + getModifierState: ( keyArg ) => keyArg === ( isMac ? 'Meta' : 'Control' ), + ctrlKey: ! isMac, + metaKey: isMac, + charCode: 0, + keyCode: isMac ? 93 : 17, + which: isMac ? 93 : 17, + } ) + ); + + const preventableEvent = new KeyboardEvent( 'keydown', { + bubbles: true, + cancelable: true, + key: 'a', + code: 'KeyA', + location: window.KeyboardEvent.DOM_KEY_LOCATION_STANDARD, + getModifierState: ( keyArg ) => keyArg === ( isMac ? 'Meta' : 'Control' ), + ctrlKey: ! isMac, + metaKey: isMac, + charCode: 0, + keyCode: 65, + which: 65, + } ); + + const wasPrevented = ( + ! document.activeElement.dispatchEvent( preventableEvent ) || + preventableEvent.defaultPrevented + ); + + if ( ! wasPrevented ) { + document.execCommand( 'selectall', false, null ); + } + + document.activeElement.dispatchEvent( + new KeyboardEvent( 'keyup', { + bubbles: true, + cancelable: true, + key: isMac ? 'Meta' : 'Control', + code: isMac ? 'MetaLeft' : 'ControlLeft', + location: window.KeyboardEvent.DOM_KEY_LOCATION_LEFT, + getModifierState: () => false, + charCode: 0, + keyCode: isMac ? 93 : 17, + which: isMac ? 93 : 17, + } ), + ); + } ); +} + /** * Performs a key press with modifier (Shift, Control, Meta, Alt), where each modifier * is normalized to platform-specific modifier. @@ -16,6 +88,10 @@ import { modifiers, SHIFT, ALT, CTRL } from '@wordpress/keycodes'; * @param {string} key Key to press while modifier held. */ export async function pressKeyWithModifier( modifier, key ) { + if ( modifier.toLowerCase() === 'primary' && key.toLowerCase() === 'a' ) { + return await emulateSelectAll(); + } + const isAppleOS = () => process.platform === 'darwin'; const overWrittenModifiers = { ...modifiers, diff --git a/packages/e2e-tests/specs/block-hierarchy-navigation.test.js b/packages/e2e-tests/specs/block-hierarchy-navigation.test.js index eb23d8fba8c267..c53adb01730bd3 100644 --- a/packages/e2e-tests/specs/block-hierarchy-navigation.test.js +++ b/packages/e2e-tests/specs/block-hierarchy-navigation.test.js @@ -98,11 +98,8 @@ describe( 'Navigating the block hierarchy', () => { await openBlockNavigator(); await page.keyboard.press( 'Space' ); - // Replace its content - // note Cmd/Ctrl + A doesn't work on Mac with Pupetter right now - // https://github.com/GoogleChrome/puppeteer/issues/1313 - await pressKeyTimes( 'ArrowRight', textString.length ); - await pressKeyTimes( 'Backspace', textString.length ); + // Replace its content. + await pressKeyWithModifier( 'primary', 'a' ); await page.keyboard.type( 'and I say hello' ); expect( await getEditedPostContent() ).toMatchSnapshot();