diff --git a/packages/playwright-core/src/server/injected/recorder.ts b/packages/playwright-core/src/server/injected/recorder.ts index c7ef824ee5..ac28dbe0be 100644 --- a/packages/playwright-core/src/server/injected/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder.ts @@ -41,6 +41,8 @@ interface RecorderTool { onInput?(event: Event): void; onKeyDown?(event: KeyboardEvent): void; onKeyUp?(event: KeyboardEvent): void; + onPointerDown?(event: PointerEvent): void; + onPointerUp?(event: PointerEvent): void; onMouseDown?(event: MouseEvent): void; onMouseUp?(event: MouseEvent): void; onMouseMove?(event: MouseEvent): void; @@ -76,6 +78,14 @@ class InspectTool implements RecorderTool { this._recorder.delegate.setSelector?.(this._hoveredModel ? this._hoveredModel.selector : ''); } + onPointerDown(event: PointerEvent) { + consumeEvent(event); + } + + onPointerUp(event: PointerEvent) { + consumeEvent(event); + } + onMouseDown(event: MouseEvent) { consumeEvent(event); } @@ -176,6 +186,20 @@ class RecordActionTool implements RecorderTool { }); } + onPointerDown(event: PointerEvent) { + if (this._shouldIgnoreMouseEvent(event)) + return; + if (!this._performingAction) + consumeEvent(event); + } + + onPointerUp(event: PointerEvent) { + if (this._shouldIgnoreMouseEvent(event)) + return; + if (!this._performingAction) + consumeEvent(event); + } + onMouseDown(event: MouseEvent) { if (this._shouldIgnoreMouseEvent(event)) return; @@ -785,6 +809,8 @@ export class Recorder { addEventListener(this.document, 'input', event => this._onInput(event), true), addEventListener(this.document, 'keydown', event => this._onKeyDown(event as KeyboardEvent), true), addEventListener(this.document, 'keyup', event => this._onKeyUp(event as KeyboardEvent), true), + addEventListener(this.document, 'pointerdown', event => this._onPointerDown(event as PointerEvent), true), + addEventListener(this.document, 'pointerup', event => this._onPointerUp(event as PointerEvent), true), addEventListener(this.document, 'mousedown', event => this._onMouseDown(event as MouseEvent), true), addEventListener(this.document, 'mouseup', event => this._onMouseUp(event as MouseEvent), true), addEventListener(this.document, 'mousemove', event => this._onMouseMove(event as MouseEvent), true), @@ -857,6 +883,22 @@ export class Recorder { this._currentTool.onDragStart?.(event); } + private _onPointerDown(event: PointerEvent) { + if (!event.isTrusted) + return; + if (this._ignoreOverlayEvent(event)) + return; + this._currentTool.onPointerDown?.(event); + } + + private _onPointerUp(event: PointerEvent) { + if (!event.isTrusted) + return; + if (this._ignoreOverlayEvent(event)) + return; + this._currentTool.onPointerUp?.(event); + } + private _onMouseDown(event: MouseEvent) { if (!event.isTrusted) return; diff --git a/tests/library/inspector/cli-codegen-3.spec.ts b/tests/library/inspector/cli-codegen-3.spec.ts index 2c6af8be0a..91fae58192 100644 --- a/tests/library/inspector/cli-codegen-3.spec.ts +++ b/tests/library/inspector/cli-codegen-3.spec.ts @@ -527,4 +527,35 @@ test.describe('cli codegen', () => { expect.soft(sources.get('C#')!.text).toContain(` await page.GetByLabel("Coun\\"try").ClickAsync();`); }); + + test('should consume pointer events', async ({ page, openRecorder }) => { + const recorder = await openRecorder(); + + await recorder.setContentAndWait(` + + + `); + + await recorder.hoverOverElement('button'); + expect(await page.evaluate('log')).toEqual(['pointermove', 'mousemove']); + + const [message] = await Promise.all([ + page.waitForEvent('console', msg => msg.type() !== 'error'), + recorder.waitForOutput('JavaScript', 'click'), + recorder.trustedClick(), + ]); + expect(message.text()).toBe('clicked'); + expect(await page.evaluate('log')).toEqual([ + 'pointermove', 'mousemove', + 'pointermove', 'mousemove', + 'pointerdown', 'mousedown', + 'pointerup', 'mouseup', + 'click', + ]); + }); });