diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index 69ef1ecba5..87685050ec 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -1210,6 +1210,9 @@ export class Frame extends SdkObject { // Note: do not perform locator handlers checkpoint to avoid moving the mouse in the middle of a drag operation. dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, false /* performActionPreChecks */, async handle => { return handle._retryPointerAction(progress, 'move and up', false, async point => { + // NOTE: Normal browsers emit usually a lot of dragover/mousemove events during drag'n + // drop operations. We want to emit minimal (2) to make Angular CDK work. + await this._page.mouse.move(point.x, point.y); await this._page.mouse.move(point.x, point.y); await this._page.mouse.up(); }, { diff --git a/tests/assets/drag-n-drop-manual.html b/tests/assets/drag-n-drop-manual.html new file mode 100644 index 0000000000..143b87ef9a --- /dev/null +++ b/tests/assets/drag-n-drop-manual.html @@ -0,0 +1,112 @@ + + + +
+

+ Select this element, drag it to the Drop Zone and then release the selection to move the element.

+
+
Drop Zone
+ + + diff --git a/tests/page/page-drag.spec.ts b/tests/page/page-drag.spec.ts index c227978f23..906e037d91 100644 --- a/tests/page/page-drag.spec.ts +++ b/tests/page/page-drag.spec.ts @@ -53,6 +53,25 @@ it.describe('Drag and drop', () => { ]); }); + it('should send the right events when using dragTo', async ({ server, page, browserName }) => { + await page.goto(server.PREFIX + '/drag-n-drop.html'); + const events = await trackEvents(await page.$('body')); + await page.locator('#source').dragTo(page.locator('#target')); + expect(await events.jsonValue()).toEqual([ + 'mousemove at 120;86', + 'mousedown at 120;86', + browserName === 'firefox' ? 'dragstart at 120;86' : 'mousemove at 240;350', + browserName === 'firefox' ? 'mousemove at 240;350' : 'dragstart at 120;86', + 'dragenter at 240;350', + // NOTE: Normal browsers emit usually a lot of dragover events during drag'n + // drop operations. We want to emit minimal (2) to make Angular CDK work. + 'dragover at 240;350', + 'dragover at 240;350', + 'drop at 240;350', + 'dragend', + ]); + }); + it('should not send dragover on the first mousemove', async ({ server, page, browserName }) => { it.fixme(browserName !== 'chromium'); @@ -293,6 +312,34 @@ it.describe('Drag and drop', () => { expect(await page.$eval('#target', target => target.contains(document.querySelector('#source')))).toBe(true); // could not find source in target }); + it('should work with manual drag\'n drop and emit correct mousemove events', { + annotation: { + type: 'issue', + description: 'https://github.com/microsoft/playwright/issues/34688', + } + }, async ({ page, server }) => { + await page.goto(server.PREFIX + '/drag-n-drop-manual.html'); + const events = await page.evaluateHandle(() => { + const events = []; + document.addEventListener('mousemove', (event: MouseEvent) => { + events.push({ + type: event.type, + x: event.clientX, + y: event.clientY, + }); + }); + return events; + }); + await page.dragAndDrop('#source', '#target'); + expect(await events.jsonValue()).toEqual([ + { type: 'mousemove', x: 120, y: 86 }, + // NOTE: Normal browsers emit usually a lot of mousemove events during drag'n + // drop operations. We want to emit minimal (2) to make Angular CDK work. + { type: 'mousemove', x: 240, y: 350 }, + { type: 'mousemove', x: 240, y: 350 }, + ]); + }); + it('should allow specifying the position', async ({ page, server }) => { await page.setContent(`