fix: dispatch touch events in webkit (#34250)
This commit is contained in:
parent
7ee7e018fa
commit
edfbab2a79
|
|
@ -13,10 +13,6 @@ If your web application relies on [pointer events](https://developer.mozilla.org
|
||||||
|
|
||||||
You can dispatch touch events to the page using [`method: Locator.dispatchEvent`]. [Touch](https://developer.mozilla.org/en-US/docs/Web/API/Touch) points can be passed as arguments, see examples below.
|
You can dispatch touch events to the page using [`method: Locator.dispatchEvent`]. [Touch](https://developer.mozilla.org/en-US/docs/Web/API/Touch) points can be passed as arguments, see examples below.
|
||||||
|
|
||||||
:::note
|
|
||||||
The examples work only in Chromium and Firefox, as the [`Touch()`](https://developer.mozilla.org/en-US/docs/Web/API/Touch/Touch) constructor is not supported in WebKit.
|
|
||||||
:::
|
|
||||||
|
|
||||||
#### Emulating pan gesture
|
#### Emulating pan gesture
|
||||||
|
|
||||||
In the example below, we emulate pan gesture that is expected to move the map. The app under test only uses `clientX/clientY` coordinates of the touch point, so we initialize just that. In a more complex scenario you may need to also set `pageX/pageY/screenX/screenY`, if your app needs them.
|
In the example below, we emulate pan gesture that is expected to move the map. The app under test only uses `clientX/clientY` coordinates of the touch point, so we initialize just that. In a more complex scenario you may need to also set `pageX/pageY/screenX/screenY`, if your app needs them.
|
||||||
|
|
|
||||||
|
|
@ -1016,11 +1016,37 @@ export class InjectedScript {
|
||||||
case 'mouse': event = new MouseEvent(type, eventInit); break;
|
case 'mouse': event = new MouseEvent(type, eventInit); break;
|
||||||
case 'keyboard': event = new KeyboardEvent(type, eventInit); break;
|
case 'keyboard': event = new KeyboardEvent(type, eventInit); break;
|
||||||
case 'touch': {
|
case 'touch': {
|
||||||
|
// WebKit does not support Touch constructor, but has deprecated createTouch and createTouchList methods.
|
||||||
|
if (this._browserName === 'webkit') {
|
||||||
|
const createTouch = (t: any) => {
|
||||||
|
if (t instanceof Touch)
|
||||||
|
return t;
|
||||||
|
// createTouch does not accept clientX/clientY, so we have to use pageX/pageY.
|
||||||
|
let pageX = t.pageX;
|
||||||
|
if (pageX === undefined && t.clientX !== undefined)
|
||||||
|
pageX = t.clientX + (this.document.scrollingElement?.scrollLeft || 0);
|
||||||
|
let pageY = t.pageY;
|
||||||
|
if (pageY === undefined && t.clientY !== undefined)
|
||||||
|
pageY = t.clientY + (this.document.scrollingElement?.scrollTop || 0);
|
||||||
|
return (this.document as any).createTouch(this.window, t.target ?? node, t.identifier, pageX, pageY, t.screenX, t.screenY, t.radiusX, t.radiusY, t.rotationAngle, t.force);
|
||||||
|
};
|
||||||
|
const createTouchList = (touches: any) => {
|
||||||
|
if (touches instanceof TouchList || !touches)
|
||||||
|
return touches;
|
||||||
|
return (this.document as any).createTouchList(...touches.map(createTouch));
|
||||||
|
};
|
||||||
|
eventInit.target ??= node;
|
||||||
|
eventInit.touches = createTouchList(eventInit.touches);
|
||||||
|
eventInit.targetTouches = createTouchList(eventInit.targetTouches);
|
||||||
|
eventInit.changedTouches = createTouchList(eventInit.changedTouches);
|
||||||
|
event = new TouchEvent(type, eventInit);
|
||||||
|
} else {
|
||||||
eventInit.target ??= node;
|
eventInit.target ??= node;
|
||||||
eventInit.touches = eventInit.touches?.map((t: any) => t instanceof Touch ? t : new Touch({ ...t, target: t.target ?? node }));
|
eventInit.touches = eventInit.touches?.map((t: any) => t instanceof Touch ? t : new Touch({ ...t, target: t.target ?? node }));
|
||||||
eventInit.targetTouches = eventInit.targetTouches?.map((t: any) => t instanceof Touch ? t : new Touch({ ...t, target: t.target ?? node }));
|
eventInit.targetTouches = eventInit.targetTouches?.map((t: any) => t instanceof Touch ? t : new Touch({ ...t, target: t.target ?? node }));
|
||||||
eventInit.changedTouches = eventInit.changedTouches?.map((t: any) => t instanceof Touch ? t : new Touch({ ...t, target: t.target ?? node }));
|
eventInit.changedTouches = eventInit.changedTouches?.map((t: any) => t instanceof Touch ? t : new Touch({ ...t, target: t.target ?? node }));
|
||||||
event = new TouchEvent(type, eventInit);
|
event = new TouchEvent(type, eventInit);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'pointer': event = new PointerEvent(type, eventInit); break;
|
case 'pointer': event = new PointerEvent(type, eventInit); break;
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import { contextTest as it, expect } from '../config/browserTest';
|
||||||
it.use({ hasTouch: true });
|
it.use({ hasTouch: true });
|
||||||
|
|
||||||
it('should support touch points in touch event arguments', async ({ page, server, browserName }) => {
|
it('should support touch points in touch event arguments', async ({ page, server, browserName }) => {
|
||||||
it.fixme(browserName === 'webkit', 'WebKit does not have Touch constructor');
|
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
await page.setContent(`
|
await page.setContent(`
|
||||||
<div data-testid='outer' style="position: absolute; width: 120px; height: 120px; background-color: red;">
|
<div data-testid='outer' style="position: absolute; width: 120px; height: 120px; background-color: red;">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue