@wordpress/e2e-test-utils-playwright
Version:
End-To-End (E2E) test utils for WordPress.
8 lines (7 loc) • 9.09 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../src/page-utils/press-keys.ts"],
"sourcesContent": ["/**\n * External dependencies\n */\nimport { capitalCase } from 'change-case';\nimport type { Page } from '@playwright/test';\n\n/**\n * Internal dependencies\n */\nimport type { PageUtils } from './';\nimport { modifiers as baseModifiers, SHIFT, ALT, CTRL } from './keycodes';\n\nlet clipboardDataHolder: {\n\t'text/plain': string;\n\t'text/html': string;\n\t'rich-text': string;\n} = {\n\t'text/plain': '',\n\t'text/html': '',\n\t'rich-text': '',\n};\n\n/**\n * Sets the clipboard data that can be pasted with\n * `pressKeys( 'primary+v' )`.\n *\n * @param this\n * @param clipboardData\n * @param clipboardData.plainText\n * @param clipboardData.html\n */\nexport function setClipboardData(\n\tthis: PageUtils,\n\t{ plainText = '', html = '' }\n) {\n\tclipboardDataHolder = {\n\t\t'text/plain': plainText,\n\t\t'text/html': html,\n\t\t'rich-text': '',\n\t};\n}\n\nasync function emulateClipboard( page: Page, type: 'copy' | 'cut' | 'paste' ) {\n\tconst output = await page.evaluate(\n\t\t( [ _type, _clipboardData ] ) => {\n\t\t\tconst canvasDoc =\n\t\t\t\t// @ts-ignore\n\t\t\t\tdocument.activeElement?.contentDocument ?? document;\n\t\t\tconst event = new ClipboardEvent( _type, {\n\t\t\t\tbubbles: true,\n\t\t\t\tcancelable: true,\n\t\t\t\tclipboardData: new DataTransfer(),\n\t\t\t} );\n\n\t\t\tif ( ! event.clipboardData ) {\n\t\t\t\tthrow new Error( 'ClipboardEvent.clipboardData is null' );\n\t\t\t}\n\n\t\t\tif ( _type === 'paste' ) {\n\t\t\t\tevent.clipboardData.setData(\n\t\t\t\t\t'text/plain',\n\t\t\t\t\t_clipboardData[ 'text/plain' ]\n\t\t\t\t);\n\t\t\t\tevent.clipboardData.setData(\n\t\t\t\t\t'text/html',\n\t\t\t\t\t_clipboardData[ 'text/html' ]\n\t\t\t\t);\n\t\t\t\tevent.clipboardData.setData(\n\t\t\t\t\t'rich-text',\n\t\t\t\t\t_clipboardData[ 'rich-text' ]\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst selection = canvasDoc.defaultView.getSelection()!;\n\t\t\t\tconst plainText = selection.toString();\n\t\t\t\tlet html = plainText;\n\t\t\t\tif ( selection.rangeCount ) {\n\t\t\t\t\tconst range = selection.getRangeAt( 0 );\n\t\t\t\t\tconst fragment = range.cloneContents();\n\t\t\t\t\thtml = Array.from( fragment.childNodes )\n\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t( node ) =>\n\t\t\t\t\t\t\t\t( node as Element ).outerHTML ??\n\t\t\t\t\t\t\t\t( node as Element ).nodeValue\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.join( '' );\n\t\t\t\t}\n\t\t\t\tevent.clipboardData.setData( 'text/plain', plainText );\n\t\t\t\tevent.clipboardData.setData( 'text/html', html );\n\t\t\t}\n\n\t\t\tcanvasDoc.activeElement.dispatchEvent( event );\n\n\t\t\tif ( _type === 'paste' ) {\n\t\t\t\treturn event.defaultPrevented;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t'text/plain': event.clipboardData.getData( 'text/plain' ),\n\t\t\t\t'text/html': event.clipboardData.getData( 'text/html' ),\n\t\t\t\t'rich-text': event.clipboardData.getData( 'rich-text' ),\n\t\t\t};\n\t\t},\n\t\t[ type, clipboardDataHolder ] as const\n\t);\n\n\tif ( typeof output === 'object' ) {\n\t\tclipboardDataHolder = output;\n\t}\n\n\tif ( output === false ) {\n\t\t// Emulate paste by typing the clipboard content, which works across all\n\t\t// elements and documents (keyboard.type does uses the nested active\n\t\t// element automatically).\n\t\tawait page.keyboard.type( clipboardDataHolder[ 'text/plain' ] );\n\t}\n}\n\nconst isAppleOS = () => process.platform === 'darwin';\n\nconst isWebkit = ( page: Page ) =>\n\tpage.context().browser()!.browserType().name() === 'webkit';\n\nconst browserCache = new WeakMap();\nconst getHasNaturalTabNavigation = async ( page: Page ) => {\n\tif ( ! isAppleOS() || ! isWebkit( page ) ) {\n\t\treturn true;\n\t}\n\tif ( browserCache.has( page.context().browser()! ) ) {\n\t\treturn browserCache.get( page.context().browser()! );\n\t}\n\tconst testPage = await page.context().newPage();\n\tawait testPage.setContent( `<button>1</button><button>2</button>` );\n\tawait testPage.getByText( '1' ).focus();\n\tawait testPage.keyboard.press( 'Tab' );\n\tconst featureDetected = await testPage\n\t\t.getByText( '2' )\n\t\t.evaluate( ( node ) => node === document.activeElement );\n\tbrowserCache.set( page.context().browser()!, featureDetected );\n\tawait testPage.close();\n\treturn featureDetected;\n};\n\ntype Options = {\n\ttimes?: number;\n\tdelay?: number;\n};\n\nconst modifiers = {\n\t...baseModifiers,\n\tshiftAlt: ( _isApple: () => boolean ) =>\n\t\t_isApple() ? [ SHIFT, ALT ] : [ SHIFT, CTRL ],\n};\n\nexport async function pressKeys(\n\tthis: PageUtils,\n\tkey: string,\n\t{ times, ...pressOptions }: Options = {}\n) {\n\tconst hasNaturalTabNavigation = await getHasNaturalTabNavigation(\n\t\tthis.page\n\t);\n\n\tlet command: () => Promise< void >;\n\n\tif ( key.toLowerCase() === 'primary+c' ) {\n\t\tcommand = () => emulateClipboard( this.page, 'copy' );\n\t} else if ( key.toLowerCase() === 'primary+x' ) {\n\t\tcommand = () => emulateClipboard( this.page, 'cut' );\n\t} else if ( key.toLowerCase() === 'primary+v' ) {\n\t\tcommand = () => emulateClipboard( this.page, 'paste' );\n\t} else {\n\t\tconst keys = key.split( '+' ).flatMap( ( keyCode ) => {\n\t\t\tif ( Object.prototype.hasOwnProperty.call( modifiers, keyCode ) ) {\n\t\t\t\treturn modifiers[ keyCode as keyof typeof modifiers ](\n\t\t\t\t\tisAppleOS\n\t\t\t\t).map( ( modifier ) =>\n\t\t\t\t\tmodifier === CTRL ? 'Control' : capitalCase( modifier )\n\t\t\t\t);\n\t\t\t} else if ( keyCode === 'Tab' && ! hasNaturalTabNavigation ) {\n\t\t\t\treturn [ 'Alt', 'Tab' ];\n\t\t\t}\n\t\t\treturn keyCode;\n\t\t} );\n\t\tconst normalizedKeys = keys.join( '+' );\n\t\tcommand = () => this.page.keyboard.press( normalizedKeys );\n\t}\n\n\ttimes = times ?? 1;\n\tfor ( let i = 0; i < times; i += 1 ) {\n\t\tawait command();\n\n\t\tif ( times > 1 && pressOptions.delay ) {\n\t\t\tawait this.page.waitForTimeout( pressOptions.delay );\n\t\t}\n\t}\n}\n"],
"mappings": "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",
"names": ["baseModifiers"]
}