From c6d154f9c42f95b6cdd42fb28da4f6355105e490 Mon Sep 17 00:00:00 2001 From: Mattias Wallander Date: Mon, 13 Nov 2023 17:58:46 +0100 Subject: [PATCH] feat: Add support for dispatching device motion events (#28067) References #27887. --- .../src/server/injected/injectedScript.ts | 17 ++++++++++- tests/assets/device-motion.html | 28 +++++++++++++++++++ tests/page/page-dispatchevent.spec.ts | 22 +++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 tests/assets/device-motion.html diff --git a/packages/playwright-core/src/server/injected/injectedScript.ts b/packages/playwright-core/src/server/injected/injectedScript.ts index 13a35cdb53..fe0affdab4 100644 --- a/packages/playwright-core/src/server/injected/injectedScript.ts +++ b/packages/playwright-core/src/server/injected/injectedScript.ts @@ -71,6 +71,10 @@ interface WebKitLegacyDeviceOrientationEvent extends DeviceOrientationEvent { readonly initDeviceOrientationEvent: (type: string, bubbles: boolean, cancelable: boolean, alpha: number, beta: number, gamma: number, absolute: boolean) => void; } +interface WebKitLegacyDeviceMotionEvent extends DeviceMotionEvent { + readonly initDeviceMotionEvent: (type: string, bubbles: boolean, cancelable: boolean, acceleration: DeviceMotionEventAcceleration, accelerationIncludingGravity: DeviceMotionEventAcceleration, rotationRate: DeviceMotionEventRotationRate, interval: number) => void; +} + export class InjectedScript { private _engines: Map; _evaluator: SelectorEvaluatorImpl; @@ -1049,6 +1053,15 @@ export class InjectedScript { event.initDeviceOrientationEvent(type, bubbles, cancelable, alpha, beta, gamma, absolute); } break; + case 'devicemotion': + try { + event = new DeviceMotionEvent(type, eventInit); + } catch { + const { bubbles, cancelable, acceleration, accelerationIncludingGravity, rotationRate, interval } = eventInit as {bubbles: boolean, cancelable: boolean, acceleration: DeviceMotionEventAcceleration, accelerationIncludingGravity: DeviceMotionEventAcceleration, rotationRate: DeviceMotionEventRotationRate, interval: number}; + event = this.document.createEvent('DeviceMotionEvent') as WebKitLegacyDeviceMotionEvent; + event.initDeviceMotionEvent(type, bubbles, cancelable, acceleration, accelerationIncludingGravity, rotationRate, interval); + } + break; default: event = new Event(type, eventInit); break; } node.dispatchEvent(event); @@ -1380,7 +1393,7 @@ function oneLine(s: string): string { return s.replace(/\n/g, '↵').replace(/\t/g, '⇆'); } -const eventType = new Map([ +const eventType = new Map([ ['auxclick', 'mouse'], ['click', 'mouse'], ['dblclick', 'mouse'], @@ -1431,6 +1444,8 @@ const eventType = new Map + + + + Device motion test + + + + + + + diff --git a/tests/page/page-dispatchevent.spec.ts b/tests/page/page-dispatchevent.spec.ts index 44dfa90592..a6562b5976 100644 --- a/tests/page/page-dispatchevent.spec.ts +++ b/tests/page/page-dispatchevent.spec.ts @@ -193,3 +193,25 @@ it('should dispatch absolute device orientation event', async ({ page, server, i expect(await page.evaluate('gamma')).toBe(30); expect(await page.evaluate('absolute')).toBeTruthy(); }); + +it('should dispatch device motion event', async ({ page, server, isAndroid }) => { + it.skip(isAndroid, 'DeviceOrientationEvent is only available in a secure context. While Androids loopback is not treated as secure.'); + await page.goto(server.PREFIX + '/device-motion.html'); + await page.locator('html').dispatchEvent('devicemotion', { + acceleration: { x: 10, y: 20, z: 30 }, + accelerationIncludingGravity: { x: 15, y: 25, z: 35 }, + rotationRate: { alpha: 5, beta: 10, gamma: 15 }, + interval: 16, + }); + expect(await page.evaluate('result')).toBe('Moved'); + expect(await page.evaluate('acceleration.x')).toBe(10); + expect(await page.evaluate('acceleration.y')).toBe(20); + expect(await page.evaluate('acceleration.z')).toBe(30); + expect(await page.evaluate('accelerationIncludingGravity.x')).toBe(15); + expect(await page.evaluate('accelerationIncludingGravity.y')).toBe(25); + expect(await page.evaluate('accelerationIncludingGravity.z')).toBe(35); + expect(await page.evaluate('rotationRate.alpha')).toBe(5); + expect(await page.evaluate('rotationRate.beta')).toBe(10); + expect(await page.evaluate('rotationRate.gamma')).toBe(15); + expect(await page.evaluate('interval')).toBe(16); +});