Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing: Reimplement pressKeyWithModifier to emulate Cmd+A in macOS #14243

Merged
merged 3 commits into from
Apr 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/e2e-test-utils/src/login-user.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/**
* Internal dependencies
*/
Expand Down
76 changes: 76 additions & 0 deletions packages/e2e-test-utils/src/press-key-with-modifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this emulation be limited to macOS?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this emulation be limited to macOS?

I'd thought about it, and while true that it doesn't need to occur outside macOS, I'd thought to avoid divergent implementations. The main downside is that, at least currently, emulateSelectAll has to do its own platform detection to determine Meta vs. Control as modifier, which wouldn't be necessary if only applying the emulation specific to macOS.

}

const isAppleOS = () => process.platform === 'darwin';
const overWrittenModifiers = {
...modifiers,
Expand Down
7 changes: 2 additions & 5 deletions packages/e2e-tests/specs/block-hierarchy-navigation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down