puppeteer: Cmd+A doesn't select all on Mac

There are two types of shortcuts: those handled by OS and those handled by Chrome

  • Alt-Tab is an example of a native shortcut
  • Shift-Left is an example of Chrome-handled shortcut

Puppeteer doesn’t emulate native shortcuts because native shortcuts depend on the active window, which is out of control for puppeteer.

Certain shortcuts, such as “select all”, are handled differently on different platforms:

  • On Win and Linux, Ctrl-A is handled by Chrome, and puppeteer does emulate this
  • On OS X, ⌘-A is handled by OS X, and puppeteer doesn’t emulate this

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 17 (2 by maintainers)

Commits related to this issue

Most upvoted comments

You can solve your problem by clicking 3 times in a row and then deleting your text. await input.click({ clickCount: 3 }); await page.keyboard.press("Backspace");

This is still a problem in my testing. I’d think the issue should be reopened.

In the meantime, what’s worked for me as a viable alternative for “select all” is:

await page.evaluate( () => document.execCommand( 'selectall', false, null ) );

I’m also having an issue with simulating command click:

 await page.keyboard.down('Meta');
 await page.click('a');
 await page.keyboard.up('Meta');

It doesn’t open a new tab.

The workaround with selectall should be good-enough for the most usecases.

Expanding on my previous comment, it ultimately wasn’t quite enough for our application which included more advanced handling to preventDefault the Cmd+A behavior under some conditions.

The full implementation ended up being just a bit more complex:

/**
 * 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,
			} ),
		);
	} );
}

I get it that you can’t hijack Alt on Linux/Windows machines but you CAN do this on a Mac (it’s the Option key on a mac).

Likewise, on a Mac you can easily create browser behavior that uses the Option key, javascript that recognizes when the Option key is pressed, etc.

I feel like it would make more sense to have this be platform-dependent, right now the implemention on Mac is limited by windows/Linux compatibility issues that shouldn’t affect it.

Even in the name of this bug it says “on the mac” so I’m not sure why it’s closed, the problems cited for reasons for closing this bug aren’t really relevant to the Mac.

Command + v is not working on mac also, but i find a solution, https://stackoverflow.com/questions/11750447/performing-a-copy-and-paste-with-selenium-2#answer-41046276 . in my mac, i confirmed that it works.

I’m also having an issue with simulating a paste from clipboard. tried

 await this.page.keyboard.down('ControlLeft');
 await this.page.keyboard.down('V');

 await this.page.keyboard.up('V');
  await this.page.keyboard.up('ControlLeft');

You can solve your problem by clicking 3 times in a row and then deleting your text. await input.click({ clickCount: 3 }); await page.keyboard.press("Backspace");

This works for me, just change params from clickCount to count

await elementHandle.click({ count: 3 }) await page.keyboard.press(‘Backspace’)